KVM: PPC: Book3S HV: Make the guest hash table size configurable
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / powerpc / kvm / book3s_64_mmu_hv.c
index c3beaee..d03eb6f 100644 (file)
 
 /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
 #define MAX_LPID_970   63
-#define NR_LPIDS       (LPID_RSVD + 1)
-unsigned long lpid_inuse[BITS_TO_LONGS(NR_LPIDS)];
 
-long kvmppc_alloc_hpt(struct kvm *kvm)
+/* Power architecture requires HPT is at least 256kB */
+#define PPC_MIN_HPT_ORDER      18
+
+long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
 {
        unsigned long hpt;
-       unsigned long lpid;
        struct revmap_entry *rev;
        struct kvmppc_linear_info *li;
+       long order = kvm_hpt_order;
 
-       /* Allocate guest's hashed page table */
-       li = kvm_alloc_hpt();
-       if (li) {
-               /* using preallocated memory */
-               hpt = (ulong)li->base_virt;
-               kvm->arch.hpt_li = li;
-       } else {
-               /* using dynamic memory */
+       if (htab_orderp) {
+               order = *htab_orderp;
+               if (order < PPC_MIN_HPT_ORDER)
+                       order = PPC_MIN_HPT_ORDER;
+       }
+
+       /*
+        * If the user wants a different size from default,
+        * try first to allocate it from the kernel page allocator.
+        */
+       hpt = 0;
+       if (order != kvm_hpt_order) {
                hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|
-                                      __GFP_NOWARN, HPT_ORDER - PAGE_SHIFT);
+                                      __GFP_NOWARN, order - PAGE_SHIFT);
+               if (!hpt)
+                       --order;
        }
 
+       /* Next try to allocate from the preallocated pool */
        if (!hpt) {
-               pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n");
-               return -ENOMEM;
+               li = kvm_alloc_hpt();
+               if (li) {
+                       hpt = (ulong)li->base_virt;
+                       kvm->arch.hpt_li = li;
+                       order = kvm_hpt_order;
+               }
+       }
+
+       /* Lastly try successively smaller sizes from the page allocator */
+       while (!hpt && order > PPC_MIN_HPT_ORDER) {
+               hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|
+                                      __GFP_NOWARN, order - PAGE_SHIFT);
+               if (!hpt)
+                       --order;
        }
+
+       if (!hpt)
+               return -ENOMEM;
+
        kvm->arch.hpt_virt = hpt;
+       kvm->arch.hpt_order = order;
+       /* HPTEs are 2**4 bytes long */
+       kvm->arch.hpt_npte = 1ul << (order - 4);
+       /* 128 (2**7) bytes in each HPTEG */
+       kvm->arch.hpt_mask = (1ul << (order - 7)) - 1;
 
        /* Allocate reverse map array */
-       rev = vmalloc(sizeof(struct revmap_entry) * HPT_NPTE);
+       rev = vmalloc(sizeof(struct revmap_entry) * kvm->arch.hpt_npte);
        if (!rev) {
                pr_err("kvmppc_alloc_hpt: Couldn't alloc reverse map array\n");
                goto out_freehpt;
        }
        kvm->arch.revmap = rev;
+       kvm->arch.sdr1 = __pa(hpt) | (order - 18);
 
-       /* Allocate the guest's logical partition ID */
-       do {
-               lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS);
-               if (lpid >= NR_LPIDS) {
-                       pr_err("kvm_alloc_hpt: No LPIDs free\n");
-                       goto out_freeboth;
-               }
-       } while (test_and_set_bit(lpid, lpid_inuse));
+       pr_info("KVM guest htab at %lx (order %ld), LPID %x\n",
+               hpt, order, kvm->arch.lpid);
 
-       kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18);
-       kvm->arch.lpid = lpid;
-
-       pr_info("KVM guest htab at %lx, LPID %lx\n", hpt, lpid);
+       if (htab_orderp)
+               *htab_orderp = order;
        return 0;
 
- out_freeboth:
-       vfree(rev);
  out_freehpt:
-       free_pages(hpt, HPT_ORDER - PAGE_SHIFT);
+       if (kvm->arch.hpt_li)
+               kvm_release_hpt(kvm->arch.hpt_li);
+       else
+               free_pages(hpt, order - PAGE_SHIFT);
        return -ENOMEM;
 }
 
+long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp)
+{
+       long err = -EBUSY;
+       long order;
+
+       mutex_lock(&kvm->lock);
+       if (kvm->arch.rma_setup_done) {
+               kvm->arch.rma_setup_done = 0;
+               /* order rma_setup_done vs. vcpus_running */
+               smp_mb();
+               if (atomic_read(&kvm->arch.vcpus_running)) {
+                       kvm->arch.rma_setup_done = 1;
+                       goto out;
+               }
+       }
+       if (kvm->arch.hpt_virt) {
+               order = kvm->arch.hpt_order;
+               /* Set the entire HPT to 0, i.e. invalid HPTEs */
+               memset((void *)kvm->arch.hpt_virt, 0, 1ul << order);
+               /*
+                * Set the whole last_vcpu array to an invalid vcpu number.
+                * This ensures that each vcpu will flush its TLB on next entry.
+                */
+               memset(kvm->arch.last_vcpu, 0xff, sizeof(kvm->arch.last_vcpu));
+               *htab_orderp = order;
+               err = 0;
+       } else {
+               err = kvmppc_alloc_hpt(kvm, htab_orderp);
+               order = *htab_orderp;
+       }
+ out:
+       mutex_unlock(&kvm->lock);
+       return err;
+}
+
 void kvmppc_free_hpt(struct kvm *kvm)
 {
-       clear_bit(kvm->arch.lpid, lpid_inuse);
+       kvmppc_free_lpid(kvm->arch.lpid);
        vfree(kvm->arch.revmap);
        if (kvm->arch.hpt_li)
                kvm_release_hpt(kvm->arch.hpt_li);
        else
-               free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+               free_pages(kvm->arch.hpt_virt,
+                          kvm->arch.hpt_order - PAGE_SHIFT);
 }
 
 /* Bits in first HPTE dword for pagesize 4k, 64k or 16M */
@@ -126,6 +185,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
        unsigned long psize;
        unsigned long hp0, hp1;
        long ret;
+       struct kvm *kvm = vcpu->kvm;
 
        psize = 1ul << porder;
        npages = memslot->npages >> (porder - PAGE_SHIFT);
@@ -134,8 +194,8 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
        if (npages > 1ul << (40 - porder))
                npages = 1ul << (40 - porder);
        /* Can't use more than 1 HPTE per HPTEG */
-       if (npages > HPT_NPTEG)
-               npages = HPT_NPTEG;
+       if (npages > kvm->arch.hpt_mask + 1)
+               npages = kvm->arch.hpt_mask + 1;
 
        hp0 = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
                HPTE_V_BOLTED | hpte0_pgsize_encoding(psize);
@@ -145,7 +205,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
        for (i = 0; i < npages; ++i) {
                addr = i << porder;
                /* can't use hpt_hash since va > 64 bits */
-               hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK;
+               hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & kvm->arch.hpt_mask;
                /*
                 * We assume that the hash table is empty and no
                 * vcpus are using it at this stage.  Since we create
@@ -171,8 +231,7 @@ int kvmppc_mmu_hv_init(void)
        if (!cpu_has_feature(CPU_FTR_HVMODE))
                return -EINVAL;
 
-       memset(lpid_inuse, 0, sizeof(lpid_inuse));
-
+       /* POWER7 has 10-bit LPIDs, PPC970 and e500mc have 6-bit LPIDs */
        if (cpu_has_feature(CPU_FTR_ARCH_206)) {
                host_lpid = mfspr(SPRN_LPID);   /* POWER7 */
                rsvd_lpid = LPID_RSVD;
@@ -181,9 +240,11 @@ int kvmppc_mmu_hv_init(void)
                rsvd_lpid = MAX_LPID_970;
        }
 
-       set_bit(host_lpid, lpid_inuse);
+       kvmppc_init_lpid(rsvd_lpid + 1);
+
+       kvmppc_claim_lpid(host_lpid);
        /* rsvd_lpid is reserved for use in partition switching */
-       set_bit(rsvd_lpid, lpid_inuse);
+       kvmppc_claim_lpid(rsvd_lpid);
 
        return 0;
 }
@@ -452,7 +513,7 @@ static int instruction_is_store(unsigned int instr)
 }
 
 static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
-                                 unsigned long gpa, int is_store)
+                                 unsigned long gpa, gva_t ea, int is_store)
 {
        int ret;
        u32 last_inst;
@@ -499,6 +560,7 @@ static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
         */
 
        vcpu->arch.paddr_accessed = gpa;
+       vcpu->arch.vaddr_accessed = ea;
        return kvmppc_emulate_mmio(run, vcpu);
 }
 
@@ -552,7 +614,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        /* No memslot means it's an emulated MMIO region */
        if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
                unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
-               return kvmppc_hv_emulate_mmio(run, vcpu, gpa,
+               return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
                                              dsisr & DSISR_ISSTORE);
        }