KVM: PPC: Book3S HV: Add nested shadow page tables to debugfs
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 8 Oct 2018 05:31:17 +0000 (16:31 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 9 Oct 2018 05:04:27 +0000 (16:04 +1100)
This adds a list of valid shadow PTEs for each nested guest to
the 'radix' file for the guest in debugfs.  This can be useful for
debugging.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/kvm_book3s_64.h
arch/powerpc/kvm/book3s_64_mmu_radix.c
arch/powerpc/kvm/book3s_hv_nested.c

index 83d4def5f1ed3798ed5f05edd37d5e6068870bac..6d298145d564e84b42ac050e102b34437d95606a 100644 (file)
@@ -120,6 +120,7 @@ struct rmap_nested {
 struct kvm_nested_guest *kvmhv_get_nested(struct kvm *kvm, int l1_lpid,
                                          bool create);
 void kvmhv_put_nested(struct kvm_nested_guest *gp);
+int kvmhv_nested_next_lpid(struct kvm *kvm, int lpid);
 
 /* Encoding of first parameter for H_TLB_INVALIDATE */
 #define H_TLBIE_P1_ENC(ric, prs, r)    (___PPC_RIC(ric) | ___PPC_PRS(prs) | \
index ae0e3edd94bc327b5a7b94e2b5f2a8c371e6dc62..43b21e88c71667b4133ebb88587d1a199d4bb15b 100644 (file)
@@ -1002,6 +1002,7 @@ struct debugfs_radix_state {
        struct kvm      *kvm;
        struct mutex    mutex;
        unsigned long   gpa;
+       int             lpid;
        int             chars_left;
        int             buf_index;
        char            buf[128];
@@ -1043,6 +1044,7 @@ static ssize_t debugfs_radix_read(struct file *file, char __user *buf,
        struct kvm *kvm;
        unsigned long gpa;
        pgd_t *pgt;
+       struct kvm_nested_guest *nested;
        pgd_t pgd, *pgdp;
        pud_t pud, *pudp;
        pmd_t pmd, *pmdp;
@@ -1077,10 +1079,39 @@ static ssize_t debugfs_radix_read(struct file *file, char __user *buf,
        }
 
        gpa = p->gpa;
-       pgt = kvm->arch.pgtable;
-       while (len != 0 && gpa < RADIX_PGTABLE_RANGE) {
+       nested = NULL;
+       pgt = NULL;
+       while (len != 0 && p->lpid >= 0) {
+               if (gpa >= RADIX_PGTABLE_RANGE) {
+                       gpa = 0;
+                       pgt = NULL;
+                       if (nested) {
+                               kvmhv_put_nested(nested);
+                               nested = NULL;
+                       }
+                       p->lpid = kvmhv_nested_next_lpid(kvm, p->lpid);
+                       p->hdr = 0;
+                       if (p->lpid < 0)
+                               break;
+               }
+               if (!pgt) {
+                       if (p->lpid == 0) {
+                               pgt = kvm->arch.pgtable;
+                       } else {
+                               nested = kvmhv_get_nested(kvm, p->lpid, false);
+                               if (!nested) {
+                                       gpa = RADIX_PGTABLE_RANGE;
+                                       continue;
+                               }
+                               pgt = nested->shadow_pgtable;
+                       }
+               }
+               n = 0;
                if (!p->hdr) {
-                       n = scnprintf(p->buf, sizeof(p->buf),
+                       if (p->lpid > 0)
+                               n = scnprintf(p->buf, sizeof(p->buf),
+                                             "\nNested LPID %d: ", p->lpid);
+                       n += scnprintf(p->buf + n, sizeof(p->buf) - n,
                                      "pgdir: %lx\n", (unsigned long)pgt);
                        p->hdr = 1;
                        goto copy;
@@ -1146,6 +1177,8 @@ static ssize_t debugfs_radix_read(struct file *file, char __user *buf,
                }
        }
        p->gpa = gpa;
+       if (nested)
+               kvmhv_put_nested(nested);
 
  out:
        mutex_unlock(&p->mutex);
index 3f21f785bf0ae3505fbd72cc9e64791d5255747c..401d2ecbebc508ebfc04b228216a3b5429d11278 100644 (file)
@@ -1274,3 +1274,18 @@ long int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu)
        mutex_unlock(&gp->tlb_lock);
        return ret;
 }
+
+int kvmhv_nested_next_lpid(struct kvm *kvm, int lpid)
+{
+       int ret = -1;
+
+       spin_lock(&kvm->mmu_lock);
+       while (++lpid <= kvm->arch.max_nested_lpid) {
+               if (kvm->arch.nested_guests[lpid]) {
+                       ret = lpid;
+                       break;
+               }
+       }
+       spin_unlock(&kvm->mmu_lock);
+       return ret;
+}