aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2015-03-27 23:21:01 -0400
committerAlexander Graf <agraf@suse.de>2015-04-21 09:21:31 -0400
commite23a808b1681d398a983ebc51179efc51c4a1eaf (patch)
tree4dd8a7c2a9c5633c767a03ad8999bde471a55eda
parent6e0365b782739eb41b03bcfd23abeefacbf0817a (diff)
KVM: PPC: Book3S HV: Create debugfs file for each guest's HPT
This creates a debugfs directory for each HV guest (assuming debugfs is enabled in the kernel config), and within that directory, a file by which the contents of the guest's HPT (hashed page table) can be read. The directory is named vmnnnn, where nnnn is the PID of the process that created the guest. The file is named "htab". This is intended to help in debugging problems in the host's management of guest memory. The contents of the file consist of a series of lines like this: 3f48 4000d032bf003505 0000000bd7ff1196 00000003b5c71196 The first field is the index of the entry in the HPT, the second and third are the HPT entry, so the third entry contains the real page number that is mapped by the entry if the entry's valid bit is set. The fourth field is the guest's view of the second doubleword of the entry, so it contains the guest physical address. (The format of the second through fourth fields are described in the Power ISA and also in arch/powerpc/include/asm/mmu-hash64.h.) Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h2
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c136
-rw-r--r--arch/powerpc/kvm/book3s_hv.c12
-rw-r--r--virt/kvm/kvm_main.c1
5 files changed, 153 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 0789a0f50969..869c53fe02cd 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -436,6 +436,8 @@ static inline struct kvm_memslots *kvm_memslots_raw(struct kvm *kvm)
436 return rcu_dereference_raw_notrace(kvm->memslots); 436 return rcu_dereference_raw_notrace(kvm->memslots);
437} 437}
438 438
439extern void kvmppc_mmu_debugfs_init(struct kvm *kvm);
440
439#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ 441#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
440 442
441#endif /* __ASM_KVM_BOOK3S_64_H__ */ 443#endif /* __ASM_KVM_BOOK3S_64_H__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 015773f5bb33..f1d0bbc0f079 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -238,6 +238,8 @@ struct kvm_arch {
238 atomic_t hpte_mod_interest; 238 atomic_t hpte_mod_interest;
239 cpumask_t need_tlb_flush; 239 cpumask_t need_tlb_flush;
240 int hpt_cma_alloc; 240 int hpt_cma_alloc;
241 struct dentry *debugfs_dir;
242 struct dentry *htab_dentry;
241#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ 243#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
242#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE 244#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
243 struct mutex hpt_mutex; 245 struct mutex hpt_mutex;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 6c6825a7ae49..d6fe30835c58 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -27,6 +27,7 @@
27#include <linux/srcu.h> 27#include <linux/srcu.h>
28#include <linux/anon_inodes.h> 28#include <linux/anon_inodes.h>
29#include <linux/file.h> 29#include <linux/file.h>
30#include <linux/debugfs.h>
30 31
31#include <asm/tlbflush.h> 32#include <asm/tlbflush.h>
32#include <asm/kvm_ppc.h> 33#include <asm/kvm_ppc.h>
@@ -1490,6 +1491,141 @@ int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *ghf)
1490 return ret; 1491 return ret;
1491} 1492}
1492 1493
1494struct debugfs_htab_state {
1495 struct kvm *kvm;
1496 struct mutex mutex;
1497 unsigned long hpt_index;
1498 int chars_left;
1499 int buf_index;
1500 char buf[64];
1501};
1502
1503static int debugfs_htab_open(struct inode *inode, struct file *file)
1504{
1505 struct kvm *kvm = inode->i_private;
1506 struct debugfs_htab_state *p;
1507
1508 p = kzalloc(sizeof(*p), GFP_KERNEL);
1509 if (!p)
1510 return -ENOMEM;
1511
1512 kvm_get_kvm(kvm);
1513 p->kvm = kvm;
1514 mutex_init(&p->mutex);
1515 file->private_data = p;
1516
1517 return nonseekable_open(inode, file);
1518}
1519
1520static int debugfs_htab_release(struct inode *inode, struct file *file)
1521{
1522 struct debugfs_htab_state *p = file->private_data;
1523
1524 kvm_put_kvm(p->kvm);
1525 kfree(p);
1526 return 0;
1527}
1528
1529static ssize_t debugfs_htab_read(struct file *file, char __user *buf,
1530 size_t len, loff_t *ppos)
1531{
1532 struct debugfs_htab_state *p = file->private_data;
1533 ssize_t ret, r;
1534 unsigned long i, n;
1535 unsigned long v, hr, gr;
1536 struct kvm *kvm;
1537 __be64 *hptp;
1538
1539 ret = mutex_lock_interruptible(&p->mutex);
1540 if (ret)
1541 return ret;
1542
1543 if (p->chars_left) {
1544 n = p->chars_left;
1545 if (n > len)
1546 n = len;
1547 r = copy_to_user(buf, p->buf + p->buf_index, n);
1548 n -= r;
1549 p->chars_left -= n;
1550 p->buf_index += n;
1551 buf += n;
1552 len -= n;
1553 ret = n;
1554 if (r) {
1555 if (!n)
1556 ret = -EFAULT;
1557 goto out;
1558 }
1559 }
1560
1561 kvm = p->kvm;
1562 i = p->hpt_index;
1563 hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
1564 for (; len != 0 && i < kvm->arch.hpt_npte; ++i, hptp += 2) {
1565 if (!(be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)))
1566 continue;
1567
1568 /* lock the HPTE so it's stable and read it */
1569 preempt_disable();
1570 while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
1571 cpu_relax();
1572 v = be64_to_cpu(hptp[0]) & ~HPTE_V_HVLOCK;
1573 hr = be64_to_cpu(hptp[1]);
1574 gr = kvm->arch.revmap[i].guest_rpte;
1575 unlock_hpte(hptp, v);
1576 preempt_enable();
1577
1578 if (!(v & (HPTE_V_VALID | HPTE_V_ABSENT)))
1579 continue;
1580
1581 n = scnprintf(p->buf, sizeof(p->buf),
1582 "%6lx %.16lx %.16lx %.16lx\n",
1583 i, v, hr, gr);
1584 p->chars_left = n;
1585 if (n > len)
1586 n = len;
1587 r = copy_to_user(buf, p->buf, n);
1588 n -= r;
1589 p->chars_left -= n;
1590 p->buf_index = n;
1591 buf += n;
1592 len -= n;
1593 ret += n;
1594 if (r) {
1595 if (!ret)
1596 ret = -EFAULT;
1597 goto out;
1598 }
1599 }
1600 p->hpt_index = i;
1601
1602 out:
1603 mutex_unlock(&p->mutex);
1604 return ret;
1605}
1606
1607ssize_t debugfs_htab_write(struct file *file, const char __user *buf,
1608 size_t len, loff_t *ppos)
1609{
1610 return -EACCES;
1611}
1612
1613static const struct file_operations debugfs_htab_fops = {
1614 .owner = THIS_MODULE,
1615 .open = debugfs_htab_open,
1616 .release = debugfs_htab_release,
1617 .read = debugfs_htab_read,
1618 .write = debugfs_htab_write,
1619 .llseek = generic_file_llseek,
1620};
1621
1622void kvmppc_mmu_debugfs_init(struct kvm *kvm)
1623{
1624 kvm->arch.htab_dentry = debugfs_create_file("htab", 0400,
1625 kvm->arch.debugfs_dir, kvm,
1626 &debugfs_htab_fops);
1627}
1628
1493void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu) 1629void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
1494{ 1630{
1495 struct kvmppc_mmu *mmu = &vcpu->arch.mmu; 1631 struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index dde14fd64d8e..08f8617f4046 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -32,6 +32,7 @@
32#include <linux/page-flags.h> 32#include <linux/page-flags.h>
33#include <linux/srcu.h> 33#include <linux/srcu.h>
34#include <linux/miscdevice.h> 34#include <linux/miscdevice.h>
35#include <linux/debugfs.h>
35 36
36#include <asm/reg.h> 37#include <asm/reg.h>
37#include <asm/cputable.h> 38#include <asm/cputable.h>
@@ -2319,6 +2320,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
2319static int kvmppc_core_init_vm_hv(struct kvm *kvm) 2320static int kvmppc_core_init_vm_hv(struct kvm *kvm)
2320{ 2321{
2321 unsigned long lpcr, lpid; 2322 unsigned long lpcr, lpid;
2323 char buf[32];
2322 2324
2323 /* Allocate the guest's logical partition ID */ 2325 /* Allocate the guest's logical partition ID */
2324 2326
@@ -2359,6 +2361,14 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
2359 */ 2361 */
2360 kvm_hv_vm_activated(); 2362 kvm_hv_vm_activated();
2361 2363
2364 /*
2365 * Create a debugfs directory for the VM
2366 */
2367 snprintf(buf, sizeof(buf), "vm%d", current->pid);
2368 kvm->arch.debugfs_dir = debugfs_create_dir(buf, kvm_debugfs_dir);
2369 if (!IS_ERR_OR_NULL(kvm->arch.debugfs_dir))
2370 kvmppc_mmu_debugfs_init(kvm);
2371
2362 return 0; 2372 return 0;
2363} 2373}
2364 2374
@@ -2379,6 +2389,8 @@ static void kvmppc_free_vcores(struct kvm *kvm)
2379 2389
2380static void kvmppc_core_destroy_vm_hv(struct kvm *kvm) 2390static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
2381{ 2391{
2392 debugfs_remove_recursive(kvm->arch.debugfs_dir);
2393
2382 kvm_hv_vm_deactivated(); 2394 kvm_hv_vm_deactivated();
2383 2395
2384 kvmppc_free_vcores(kvm); 2396 kvmppc_free_vcores(kvm);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index d3fc9399062a..90977418aeb6 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -89,6 +89,7 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
89static __read_mostly struct preempt_ops kvm_preempt_ops; 89static __read_mostly struct preempt_ops kvm_preempt_ops;
90 90
91struct dentry *kvm_debugfs_dir; 91struct dentry *kvm_debugfs_dir;
92EXPORT_SYMBOL_GPL(kvm_debugfs_dir);
92 93
93static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, 94static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
94 unsigned long arg); 95 unsigned long arg);