Skip to content

Commit e23a808

Browse files
paulusmackagraf
authored andcommitted
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 <[email protected]> Signed-off-by: Alexander Graf <[email protected]>
1 parent 6e0365b commit e23a808

File tree

5 files changed

+153
-0
lines changed

5 files changed

+153
-0
lines changed

arch/powerpc/include/asm/kvm_book3s_64.h

+2
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ static inline struct kvm_memslots *kvm_memslots_raw(struct kvm *kvm)
436436
return rcu_dereference_raw_notrace(kvm->memslots);
437437
}
438438

439+
extern void kvmppc_mmu_debugfs_init(struct kvm *kvm);
440+
439441
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
440442

441443
#endif /* __ASM_KVM_BOOK3S_64_H__ */

arch/powerpc/include/asm/kvm_host.h

+2
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ struct kvm_arch {
238238
atomic_t hpte_mod_interest;
239239
cpumask_t need_tlb_flush;
240240
int hpt_cma_alloc;
241+
struct dentry *debugfs_dir;
242+
struct dentry *htab_dentry;
241243
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
242244
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
243245
struct mutex hpt_mutex;

arch/powerpc/kvm/book3s_64_mmu_hv.c

+136
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/srcu.h>
2828
#include <linux/anon_inodes.h>
2929
#include <linux/file.h>
30+
#include <linux/debugfs.h>
3031

3132
#include <asm/tlbflush.h>
3233
#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)
14901491
return ret;
14911492
}
14921493

1494+
struct 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+
1503+
static 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+
1520+
static 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+
1529+
static 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+
1607+
ssize_t debugfs_htab_write(struct file *file, const char __user *buf,
1608+
size_t len, loff_t *ppos)
1609+
{
1610+
return -EACCES;
1611+
}
1612+
1613+
static 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+
1622+
void 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+
14931629
void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
14941630
{
14951631
struct kvmppc_mmu *mmu = &vcpu->arch.mmu;

arch/powerpc/kvm/book3s_hv.c

+12
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/page-flags.h>
3333
#include <linux/srcu.h>
3434
#include <linux/miscdevice.h>
35+
#include <linux/debugfs.h>
3536

3637
#include <asm/reg.h>
3738
#include <asm/cputable.h>
@@ -2319,6 +2320,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
23192320
static int kvmppc_core_init_vm_hv(struct kvm *kvm)
23202321
{
23212322
unsigned long lpcr, lpid;
2323+
char buf[32];
23222324

23232325
/* Allocate the guest's logical partition ID */
23242326

@@ -2359,6 +2361,14 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
23592361
*/
23602362
kvm_hv_vm_activated();
23612363

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+
23622372
return 0;
23632373
}
23642374

@@ -2379,6 +2389,8 @@ static void kvmppc_free_vcores(struct kvm *kvm)
23792389

23802390
static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
23812391
{
2392+
debugfs_remove_recursive(kvm->arch.debugfs_dir);
2393+
23822394
kvm_hv_vm_deactivated();
23832395

23842396
kvmppc_free_vcores(kvm);

virt/kvm/kvm_main.c

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
8989
static __read_mostly struct preempt_ops kvm_preempt_ops;
9090

9191
struct dentry *kvm_debugfs_dir;
92+
EXPORT_SYMBOL_GPL(kvm_debugfs_dir);
9293

9394
static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
9495
unsigned long arg);

0 commit comments

Comments
 (0)