]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: PPC: Book3S Nested: Use explicit 4096 LPID maximum
authorNicholas Piggin <npiggin@gmail.com>
Sun, 23 Jan 2022 12:00:42 +0000 (22:00 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 13 May 2022 11:33:34 +0000 (21:33 +1000)
Rather than tie this to KVMPPC_NR_LPIDS which is becoming more dynamic,
fix it to 4096 (12-bits) explicitly for now.

kvmhv_get_nested() does not have to check against KVM_MAX_NESTED_GUESTS
because the L1 partition table registration hcall already did that, and
it checks against the partition table size.

This patch also puts all the partition table size calculations into the
same form, using 12 for the architected size field shift and 4 for the
shift corresponding to the partition table entry size.

Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-of-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220123120043.3586018-6-npiggin@gmail.com
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv_nested.c

index 29cabb0845f109af69fa45f085e0e1e1340e6263..2909a88acd163b3633626390e0eb36f0dcfd19f1 100644 (file)
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 #include <asm/kvm_book3s_asm.h>                /* for MAX_SMT_THREADS */
 #define KVM_MAX_VCPU_IDS       (MAX_SMT_THREADS * KVM_MAX_VCORES)
-#define KVM_MAX_NESTED_GUESTS  KVMPPC_NR_LPIDS
+
+/*
+ * Limit the nested partition table to 4096 entries (because that's what
+ * hardware supports). Both guest and host use this value.
+ */
+#define KVM_MAX_NESTED_GUESTS_SHIFT    12
 
 #else
 #define KVM_MAX_VCPU_IDS       KVM_MAX_VCPUS
index b19347fa207625356be822f5564d3affcef6b6f3..a2254390e74b57c8e93835d8a317bb9448c04b30 100644 (file)
@@ -266,7 +266,7 @@ int kvmppc_mmu_hv_init(void)
                        return -EINVAL;
                nr_lpids = 1UL << mmu_lpid_bits;
        } else {
-               nr_lpids = KVM_MAX_NESTED_GUESTS;
+               nr_lpids = 1UL << KVM_MAX_NESTED_GUESTS_SHIFT;
        }
 
        if (nr_lpids > KVMPPC_NR_LPIDS)
index 1eff969b095c21d85860e37c24bba4dc693bc96e..75169e0753cea0f68cd883a25143445d08f959c3 100644 (file)
@@ -439,10 +439,11 @@ long kvmhv_nested_init(void)
        if (!radix_enabled())
                return -ENODEV;
 
-       /* find log base 2 of KVMPPC_NR_LPIDS, rounding up */
-       ptb_order = __ilog2(KVMPPC_NR_LPIDS - 1) + 1;
-       if (ptb_order < 8)
-               ptb_order = 8;
+       /* Partition table entry is 1<<4 bytes in size, hence the 4. */
+       ptb_order = KVM_MAX_NESTED_GUESTS_SHIFT + 4;
+       /* Minimum partition table size is 1<<12 bytes */
+       if (ptb_order < 12)
+               ptb_order = 12;
        pseries_partition_tb = kmalloc(sizeof(struct patb_entry) << ptb_order,
                                       GFP_KERNEL);
        if (!pseries_partition_tb) {
@@ -450,7 +451,7 @@ long kvmhv_nested_init(void)
                return -ENOMEM;
        }
 
-       ptcr = __pa(pseries_partition_tb) | (ptb_order - 8);
+       ptcr = __pa(pseries_partition_tb) | (ptb_order - 12);
        rc = plpar_hcall_norets(H_SET_PARTITION_TABLE, ptcr);
        if (rc != H_SUCCESS) {
                pr_err("kvm-hv: Parent hypervisor does not support nesting (rc=%ld)\n",
@@ -534,16 +535,14 @@ long kvmhv_set_partition_table(struct kvm_vcpu *vcpu)
        long ret = H_SUCCESS;
 
        srcu_idx = srcu_read_lock(&kvm->srcu);
-       /*
-        * Limit the partition table to 4096 entries (because that's what
-        * hardware supports), and check the base address.
-        */
-       if ((ptcr & PRTS_MASK) > 12 - 8 ||
+       /* Check partition size and base address. */
+       if ((ptcr & PRTS_MASK) + 12 - 4 > KVM_MAX_NESTED_GUESTS_SHIFT ||
            !kvm_is_visible_gfn(vcpu->kvm, (ptcr & PRTB_MASK) >> PAGE_SHIFT))
                ret = H_PARAMETER;
        srcu_read_unlock(&kvm->srcu, srcu_idx);
        if (ret == H_SUCCESS)
                kvm->arch.l1_ptcr = ptcr;
+
        return ret;
 }
 
@@ -639,7 +638,7 @@ static void kvmhv_update_ptbl_cache(struct kvm_nested_guest *gp)
 
        ret = -EFAULT;
        ptbl_addr = (kvm->arch.l1_ptcr & PRTB_MASK) + (gp->l1_lpid << 4);
-       if (gp->l1_lpid < (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 8))) {
+       if (gp->l1_lpid < (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 12 - 4))) {
                int srcu_idx = srcu_read_lock(&kvm->srcu);
                ret = kvm_read_guest(kvm, ptbl_addr,
                                     &ptbl_entry, sizeof(ptbl_entry));
@@ -809,8 +808,7 @@ struct kvm_nested_guest *kvmhv_get_nested(struct kvm *kvm, int l1_lpid,
 {
        struct kvm_nested_guest *gp, *newgp;
 
-       if (l1_lpid >= KVM_MAX_NESTED_GUESTS ||
-           l1_lpid >= (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 12 - 4)))
+       if (l1_lpid >= (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 12 - 4)))
                return NULL;
 
        spin_lock(&kvm->mmu_lock);