@@ -207,8 +207,56 @@ static const struct file_operations kvm_ptdump_guest_fops = {
.release = kvm_ptdump_guest_close,
};
+static int kvm_pgtable_debugfs_show(struct seq_file *m, void *unused)
+{
+ const struct file *file = m->file;
+ struct kvm_pgtable *pgtable = m->private;
+
+ if (!strcmp(file_dentry(file)->d_iname, "ipa_range"))
+ seq_printf(m, "%2u\n", pgtable->ia_bits);
+ else if (!strcmp(file_dentry(file)->d_iname, "stage2_levels"))
+ seq_printf(m, "%1d\n", KVM_PGTABLE_LAST_LEVEL - pgtable->start_level + 1);
+ return 0;
+}
+
+static int kvm_pgtable_debugfs_open(struct inode *m, struct file *file)
+{
+ struct kvm *kvm = m->i_private;
+ struct kvm_pgtable *pgtable;
+ int ret;
+
+ if (!kvm_get_kvm_safe(kvm))
+ return -ENOENT;
+
+ pgtable = kvm->arch.mmu.pgt;
+
+ ret = single_open(file, kvm_pgtable_debugfs_show, pgtable);
+ if (ret < 0)
+ kvm_put_kvm(kvm);
+ return ret;
+}
+
+static int kvm_pgtable_debugfs_close(struct inode *m, struct file *file)
+{
+ struct kvm *kvm = m->i_private;
+
+ kvm_put_kvm(kvm);
+ return single_release(m, file);
+}
+
+static const struct file_operations kvm_pgtable_debugfs_fops = {
+ .open = kvm_pgtable_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = kvm_pgtable_debugfs_close,
+};
+
void kvm_ptdump_guest_register(struct kvm *kvm)
{
debugfs_create_file("stage2_page_tables", 0400, kvm->debugfs_dentry,
kvm, &kvm_ptdump_guest_fops);
+ debugfs_create_file("ipa_range", 0400, kvm->debugfs_dentry, kvm,
+ &kvm_pgtable_debugfs_fops);
+ debugfs_create_file("stage2_levels", 0400, kvm->debugfs_dentry,
+ kvm, &kvm_pgtable_debugfs_fops);
}
Make the start level and the IPA bits properties available in the virtual machine debugfs directory. Make sure that the KVM structure doesn't disappear behind our back and keep a reference to the KVM struct while these files are opened. Signed-off-by: Sebastian Ene <sebastianene@google.com> --- arch/arm64/kvm/ptdump.c | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)