Re: [PATCH v3 04/14] KVM: PPC: Keep page physical addresses in per-slot arrays

2011-12-19 Thread Alexander Graf

On 12.12.2011, at 23:28, Paul Mackerras wrote:

> This allocates an array for each memory slot that is added to store
> the physical addresses of the pages in the slot.  This array is
> vmalloc'd and accessed in kvmppc_h_enter using real_vmalloc_addr().
> This allows us to remove the ram_pginfo field from the kvm_arch
> struct, and removes the 64GB guest RAM limit that we had.
> 
> We use the low-order bits of the array entries to store a flag
> indicating that we have done get_page on the corresponding page,
> and therefore need to call put_page when we are finished with the
> page.  Currently this is set for all pages except those in our
> special RMO regions.
> 
> Signed-off-by: Paul Mackerras 
> ---
> arch/powerpc/include/asm/kvm_host.h |9 ++-
> arch/powerpc/kvm/book3s_64_mmu_hv.c |   18 +++---
> arch/powerpc/kvm/book3s_hv.c|  114 +--
> arch/powerpc/kvm/book3s_hv_rm_mmu.c |   41 +++-
> 4 files changed, 107 insertions(+), 75 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_host.h 
> b/arch/powerpc/include/asm/kvm_host.h
> index 629df2e..7a17ab5 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -38,6 +38,7 @@
> #define KVM_MEMORY_SLOTS 32
> /* memory slots that does not exposed to userspace */
> #define KVM_PRIVATE_MEM_SLOTS 4
> +#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)
> 
> #ifdef CONFIG_KVM_MMIO
> #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
> @@ -175,25 +176,27 @@ struct revmap_entry {
>   unsigned long guest_rpte;
> };
> 
> +/* Low-order bits in kvm->arch.slot_phys[][] */
> +#define KVMPPC_GOT_PAGE  0x80
> +
> struct kvm_arch {
> #ifdef CONFIG_KVM_BOOK3S_64_HV
>   unsigned long hpt_virt;
>   struct revmap_entry *revmap;
> - unsigned long ram_npages;
>   unsigned long ram_psize;
>   unsigned long ram_porder;
> - struct kvmppc_pginfo *ram_pginfo;
>   unsigned int lpid;
>   unsigned int host_lpid;
>   unsigned long host_lpcr;
>   unsigned long sdr1;
>   unsigned long host_sdr1;
>   int tlbie_lock;
> - int n_rma_pages;
>   unsigned long lpcr;
>   unsigned long rmor;
>   struct kvmppc_rma_info *rma;
>   struct list_head spapr_tce_tables;
> + unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
> + int slot_npages[KVM_MEM_SLOTS_NUM];
>   unsigned short last_vcpu[NR_CPUS];
>   struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
> #endif /* CONFIG_KVM_BOOK3S_64_HV */
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c 
> b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> index 80ece8d..e4c6069 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> @@ -98,16 +98,16 @@ void kvmppc_free_hpt(struct kvm *kvm)
> void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
> {
>   unsigned long i;
> - unsigned long npages = kvm->arch.ram_npages;
> - unsigned long pfn;
> + unsigned long npages;
> + unsigned long pa;
>   unsigned long *hpte;
>   unsigned long hash;
>   unsigned long porder = kvm->arch.ram_porder;
>   struct revmap_entry *rev;
> - struct kvmppc_pginfo *pginfo = kvm->arch.ram_pginfo;
> + unsigned long *physp;
> 
> - if (!pginfo)
> - return;
> + physp = kvm->arch.slot_phys[mem->slot];
> + npages = kvm->arch.slot_npages[mem->slot];
> 
>   /* VRMA can't be > 1TB */
>   if (npages > 1ul << (40 - porder))
> @@ -117,9 +117,10 @@ void kvmppc_map_vrma(struct kvm *kvm, struct 
> kvm_userspace_memory_region *mem)
>   npages = HPT_NPTEG;
> 
>   for (i = 0; i < npages; ++i) {
> - pfn = pginfo[i].pfn;
> - if (!pfn)
> + pa = physp[i];
> + if (!pa)
>   break;
> + pa &= PAGE_MASK;
>   /* can't use hpt_hash since va > 64 bits */
>   hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK;
>   /*
> @@ -131,8 +132,7 @@ void kvmppc_map_vrma(struct kvm *kvm, struct 
> kvm_userspace_memory_region *mem)
>   hash = (hash << 3) + 7;
>   hpte = (unsigned long *) (kvm->arch.hpt_virt + (hash << 4));
>   /* HPTE low word - RPN, protection, etc. */
> - hpte[1] = (pfn << PAGE_SHIFT) | HPTE_R_R | HPTE_R_C |
> - HPTE_R_M | PP_RWXX;
> + hpte[1] = pa | HPTE_R_R | HPTE_R_C | HPTE_R_M | PP_RWXX;
>   smp_wmb();
>   hpte[0] = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
>   (i << (VRMA_PAGE_ORDER - 16)) | HPTE_V_BOLTED |
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index da7db14..86d3e4b 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -50,14 +50,6 @@
> #include 
> #include 
> 
> -/*
> - * For now, limit memory to 64GB and require it to be large pages.
> - * This value is chose

[PATCH v3 04/14] KVM: PPC: Keep page physical addresses in per-slot arrays

2011-12-12 Thread Paul Mackerras
This allocates an array for each memory slot that is added to store
the physical addresses of the pages in the slot.  This array is
vmalloc'd and accessed in kvmppc_h_enter using real_vmalloc_addr().
This allows us to remove the ram_pginfo field from the kvm_arch
struct, and removes the 64GB guest RAM limit that we had.

We use the low-order bits of the array entries to store a flag
indicating that we have done get_page on the corresponding page,
and therefore need to call put_page when we are finished with the
page.  Currently this is set for all pages except those in our
special RMO regions.

Signed-off-by: Paul Mackerras 
---
 arch/powerpc/include/asm/kvm_host.h |9 ++-
 arch/powerpc/kvm/book3s_64_mmu_hv.c |   18 +++---
 arch/powerpc/kvm/book3s_hv.c|  114 +--
 arch/powerpc/kvm/book3s_hv_rm_mmu.c |   41 +++-
 4 files changed, 107 insertions(+), 75 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h 
b/arch/powerpc/include/asm/kvm_host.h
index 629df2e..7a17ab5 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -38,6 +38,7 @@
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
+#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)
 
 #ifdef CONFIG_KVM_MMIO
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -175,25 +176,27 @@ struct revmap_entry {
unsigned long guest_rpte;
 };
 
+/* Low-order bits in kvm->arch.slot_phys[][] */
+#define KVMPPC_GOT_PAGE0x80
+
 struct kvm_arch {
 #ifdef CONFIG_KVM_BOOK3S_64_HV
unsigned long hpt_virt;
struct revmap_entry *revmap;
-   unsigned long ram_npages;
unsigned long ram_psize;
unsigned long ram_porder;
-   struct kvmppc_pginfo *ram_pginfo;
unsigned int lpid;
unsigned int host_lpid;
unsigned long host_lpcr;
unsigned long sdr1;
unsigned long host_sdr1;
int tlbie_lock;
-   int n_rma_pages;
unsigned long lpcr;
unsigned long rmor;
struct kvmppc_rma_info *rma;
struct list_head spapr_tce_tables;
+   unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
+   int slot_npages[KVM_MEM_SLOTS_NUM];
unsigned short last_vcpu[NR_CPUS];
struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c 
b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 80ece8d..e4c6069 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -98,16 +98,16 @@ void kvmppc_free_hpt(struct kvm *kvm)
 void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
 {
unsigned long i;
-   unsigned long npages = kvm->arch.ram_npages;
-   unsigned long pfn;
+   unsigned long npages;
+   unsigned long pa;
unsigned long *hpte;
unsigned long hash;
unsigned long porder = kvm->arch.ram_porder;
struct revmap_entry *rev;
-   struct kvmppc_pginfo *pginfo = kvm->arch.ram_pginfo;
+   unsigned long *physp;
 
-   if (!pginfo)
-   return;
+   physp = kvm->arch.slot_phys[mem->slot];
+   npages = kvm->arch.slot_npages[mem->slot];
 
/* VRMA can't be > 1TB */
if (npages > 1ul << (40 - porder))
@@ -117,9 +117,10 @@ void kvmppc_map_vrma(struct kvm *kvm, struct 
kvm_userspace_memory_region *mem)
npages = HPT_NPTEG;
 
for (i = 0; i < npages; ++i) {
-   pfn = pginfo[i].pfn;
-   if (!pfn)
+   pa = physp[i];
+   if (!pa)
break;
+   pa &= PAGE_MASK;
/* can't use hpt_hash since va > 64 bits */
hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK;
/*
@@ -131,8 +132,7 @@ void kvmppc_map_vrma(struct kvm *kvm, struct 
kvm_userspace_memory_region *mem)
hash = (hash << 3) + 7;
hpte = (unsigned long *) (kvm->arch.hpt_virt + (hash << 4));
/* HPTE low word - RPN, protection, etc. */
-   hpte[1] = (pfn << PAGE_SHIFT) | HPTE_R_R | HPTE_R_C |
-   HPTE_R_M | PP_RWXX;
+   hpte[1] = pa | HPTE_R_R | HPTE_R_C | HPTE_R_M | PP_RWXX;
smp_wmb();
hpte[0] = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
(i << (VRMA_PAGE_ORDER - 16)) | HPTE_V_BOLTED |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index da7db14..86d3e4b 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -50,14 +50,6 @@
 #include 
 #include 
 
-/*
- * For now, limit memory to 64GB and require it to be large pages.
- * This value is chosen because it makes the ram_pginfo array be
- * 64kB in size, which is about as large as we want to be trying
- * to allocate with kmalloc.
- */
-#define MAX_ME