On 20.03.15 10:39, Paul Mackerras wrote: > 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@xxxxxxxxx> > --- > arch/powerpc/include/asm/kvm_book3s_64.h | 2 + > arch/powerpc/include/asm/kvm_host.h | 2 + > arch/powerpc/kvm/book3s_64_mmu_hv.c | 136 +++++++++++++++++++++++++++++++ > arch/powerpc/kvm/book3s_hv.c | 12 +++ > virt/kvm/kvm_main.c | 1 + > 5 files changed, 153 insertions(+) > > diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h > index 0789a0f..869c53f 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) > return rcu_dereference_raw_notrace(kvm->memslots); > } > > +extern void kvmppc_mmu_debugfs_init(struct kvm *kvm); > + > #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ > > #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 015773f..f1d0bbc 100644 > --- a/arch/powerpc/include/asm/kvm_host.h > +++ b/arch/powerpc/include/asm/kvm_host.h > @@ -238,6 +238,8 @@ struct kvm_arch { > atomic_t hpte_mod_interest; > cpumask_t need_tlb_flush; > int hpt_cma_alloc; > + struct dentry *debugfs_dir; > + struct dentry *htab_dentry; > #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ > #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE > 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 6c6825a..d6fe308 100644 > --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c > +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c > @@ -27,6 +27,7 @@ > #include <linux/srcu.h> > #include <linux/anon_inodes.h> > #include <linux/file.h> > +#include <linux/debugfs.h> > > #include <asm/tlbflush.h> > #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) > return ret; > } > > +struct debugfs_htab_state { > + struct kvm *kvm; > + struct mutex mutex; > + unsigned long hpt_index; > + int chars_left; > + int buf_index; > + char buf[64]; > +}; > + > +static int debugfs_htab_open(struct inode *inode, struct file *file) > +{ > + struct kvm *kvm = inode->i_private; > + struct debugfs_htab_state *p; > + > + p = kzalloc(sizeof(*p), GFP_KERNEL); > + if (!p) > + return -ENOMEM; > + > + kvm_get_kvm(kvm); > + p->kvm = kvm; > + mutex_init(&p->mutex); > + file->private_data = p; > + > + return nonseekable_open(inode, file); > +} > + > +static int debugfs_htab_release(struct inode *inode, struct file *file) > +{ > + struct debugfs_htab_state *p = file->private_data; > + > + kvm_put_kvm(p->kvm); > + kfree(p); > + return 0; > +} > + > +static ssize_t debugfs_htab_read(struct file *file, char __user *buf, > + size_t len, loff_t *ppos) > +{ > + struct debugfs_htab_state *p = file->private_data; > + ssize_t ret, r; > + unsigned long i, n; > + unsigned long v, hr, gr; > + struct kvm *kvm; > + __be64 *hptp; > + > + ret = mutex_lock_interruptible(&p->mutex); > + if (ret) > + return ret; > + > + if (p->chars_left) { > + n = p->chars_left; > + if (n > len) > + n = len; > + r = copy_to_user(buf, p->buf + p->buf_index, n); > + n -= r; > + p->chars_left -= n; > + p->buf_index += n; > + buf += n; > + len -= n; > + ret = n; > + if (r) { > + if (!n) > + ret = -EFAULT; > + goto out; > + } > + } > + > + kvm = p->kvm; > + i = p->hpt_index; > + hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); > + for (; len != 0 && i < kvm->arch.hpt_npte; ++i, hptp += 2) { > + if (!(be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))) > + continue; > + > + /* lock the HPTE so it's stable and read it */ > + preempt_disable(); > + while (!try_lock_hpte(hptp, HPTE_V_HVLOCK)) > + cpu_relax(); > + v = be64_to_cpu(hptp[0]) & ~HPTE_V_HVLOCK; > + hr = be64_to_cpu(hptp[1]); > + gr = kvm->arch.revmap[i].guest_rpte; > + unlock_hpte(hptp, v); > + preempt_enable(); > + > + if (!(v & (HPTE_V_VALID | HPTE_V_ABSENT))) > + continue; > + > + n = scnprintf(p->buf, sizeof(p->buf), > + "%6lx %.16lx %.16lx %.16lx\n", > + i, v, hr, gr); > + p->chars_left = n; > + if (n > len) > + n = len; > + r = copy_to_user(buf, p->buf, n); > + n -= r; > + p->chars_left -= n; > + p->buf_index = n; > + buf += n; > + len -= n; > + ret += n; > + if (r) { > + if (!ret) > + ret = -EFAULT; > + goto out; > + } > + } > + p->hpt_index = i; > + > + out: > + mutex_unlock(&p->mutex); > + return ret; > +} > + > +ssize_t debugfs_htab_write(struct file *file, const char __user *buf, > + size_t len, loff_t *ppos) > +{ > + return -EACCES; > +} > + > +static const struct file_operations debugfs_htab_fops = { > + .owner = THIS_MODULE, > + .open = debugfs_htab_open, > + .release = debugfs_htab_release, > + .read = debugfs_htab_read, > + .write = debugfs_htab_write, > + .llseek = generic_file_llseek, > +}; > + > +void kvmppc_mmu_debugfs_init(struct kvm *kvm) > +{ > + kvm->arch.htab_dentry = debugfs_create_file("htab", 0400, > + kvm->arch.debugfs_dir, kvm, > + &debugfs_htab_fops); > +} > + > void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu) > { > struct kvmppc_mmu *mmu = &vcpu->arch.mmu; > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 7b7102a..6631b53 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -32,6 +32,7 @@ > #include <linux/page-flags.h> > #include <linux/srcu.h> > #include <linux/miscdevice.h> > +#include <linux/debugfs.h> > > #include <asm/reg.h> > #include <asm/cputable.h> > @@ -2307,6 +2308,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) > static int kvmppc_core_init_vm_hv(struct kvm *kvm) > { > unsigned long lpcr, lpid; > + char buf[32]; > > /* Allocate the guest's logical partition ID */ > > @@ -2347,6 +2349,14 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) > */ > kvm_hv_vm_activated(); > > + /* > + * Create a debugfs directory for the VM > + */ > + sprintf(buf, "vm%d", current->pid); The same comment stands here. I don't see how you could possibly overrun 32 bytes with vm%d, but I'd feel a lot safer if this was an snprintf. Alex -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html