Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch kvm-arm64/nv-s2-debugfs into kvmarm-master/next

* kvm-arm64/nv-s2-debugfs:
: .
: Expand the stage-2 ptdump infrastructure to be able to display
: the content of the shadow s2 tables generated by nested virt.
:
: Patches courtesy of Wei-Lin Chang.
: .
KVM: arm64: ptdump: Initialize parser_state before pgtable walk
KVM: arm64: nv: Expose shadow page tables in debugfs
KVM: arm64: ptdump: Make KVM ptdump code s2 mmu aware

Signed-off-by: Marc Zyngier <maz@kernel.org>

+68 -30
+9
arch/arm64/include/asm/kvm_host.h
··· 217 217 */ 218 218 bool nested_stage2_enabled; 219 219 220 + #ifdef CONFIG_PTDUMP_STAGE2_DEBUGFS 221 + struct dentry *shadow_pt_debugfs_dentry; 222 + #endif 223 + 220 224 /* 221 225 * true when this MMU needs to be unmapped before being used for a new 222 226 * purpose. ··· 412 408 * the associated pKVM instance in the hypervisor. 413 409 */ 414 410 struct kvm_protected_vm pkvm; 411 + 412 + #ifdef CONFIG_PTDUMP_STAGE2_DEBUGFS 413 + /* Nested virtualization info */ 414 + struct dentry *debugfs_nv_dentry; 415 + #endif 415 416 }; 416 417 417 418 struct kvm_vcpu_fault_info {
+4
arch/arm64/include/asm/kvm_mmu.h
··· 393 393 394 394 #ifdef CONFIG_PTDUMP_STAGE2_DEBUGFS 395 395 void kvm_s2_ptdump_create_debugfs(struct kvm *kvm); 396 + void kvm_nested_s2_ptdump_create_debugfs(struct kvm_s2_mmu *mmu); 397 + void kvm_nested_s2_ptdump_remove_debugfs(struct kvm_s2_mmu *mmu); 396 398 #else 397 399 static inline void kvm_s2_ptdump_create_debugfs(struct kvm *kvm) {} 400 + static inline void kvm_nested_s2_ptdump_create_debugfs(struct kvm_s2_mmu *mmu) {} 401 + static inline void kvm_nested_s2_ptdump_remove_debugfs(struct kvm_s2_mmu *mmu) {} 398 402 #endif /* CONFIG_PTDUMP_STAGE2_DEBUGFS */ 399 403 400 404 #endif /* __ASSEMBLER__ */
+5 -1
arch/arm64/kvm/nested.c
··· 735 735 kvm->arch.nested_mmus_next = (i + 1) % kvm->arch.nested_mmus_size; 736 736 737 737 /* Make sure we don't forget to do the laundry */ 738 - if (kvm_s2_mmu_valid(s2_mmu)) 738 + if (kvm_s2_mmu_valid(s2_mmu)) { 739 + kvm_nested_s2_ptdump_remove_debugfs(s2_mmu); 739 740 s2_mmu->pending_unmap = true; 741 + } 740 742 741 743 /* 742 744 * The virtual VMID (modulo CnP) will be used as a key when matching ··· 751 749 s2_mmu->tlb_vttbr = vcpu_read_sys_reg(vcpu, VTTBR_EL2) & ~VTTBR_CNP_BIT; 752 750 s2_mmu->tlb_vtcr = vcpu_read_sys_reg(vcpu, VTCR_EL2); 753 751 s2_mmu->nested_stage2_enabled = vcpu_read_sys_reg(vcpu, HCR_EL2) & HCR_VM; 752 + 753 + kvm_nested_s2_ptdump_create_debugfs(s2_mmu); 754 754 755 755 out: 756 756 atomic_inc(&s2_mmu->refcnt);
+50 -29
arch/arm64/kvm/ptdump.c
··· 10 10 #include <linux/kvm_host.h> 11 11 #include <linux/seq_file.h> 12 12 13 + #include <asm/cpufeature.h> 13 14 #include <asm/kvm_mmu.h> 14 15 #include <asm/kvm_pgtable.h> 15 16 #include <asm/ptdump.h> 16 17 17 18 #define MARKERS_LEN 2 18 19 #define KVM_PGTABLE_MAX_LEVELS (KVM_PGTABLE_LAST_LEVEL + 1) 20 + #define S2FNAMESZ sizeof("0x0123456789abcdef-0x0123456789abcdef-s2-disabled") 19 21 20 22 struct kvm_ptdump_guest_state { 21 - struct kvm *kvm; 23 + struct kvm_s2_mmu *mmu; 22 24 struct ptdump_pg_state parser_state; 23 25 struct addr_marker ipa_marker[MARKERS_LEN]; 24 26 struct ptdump_pg_level level[KVM_PGTABLE_MAX_LEVELS]; 25 - struct ptdump_range range[MARKERS_LEN]; 26 27 }; 27 28 28 29 static const struct ptdump_prot_bits stage2_pte_bits[] = { ··· 113 112 return 0; 114 113 } 115 114 116 - static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm *kvm) 115 + static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm_s2_mmu *mmu) 117 116 { 118 117 struct kvm_ptdump_guest_state *st; 119 - struct kvm_s2_mmu *mmu = &kvm->arch.mmu; 120 118 struct kvm_pgtable *pgtable = mmu->pgt; 121 119 int ret; 122 120 ··· 131 131 132 132 st->ipa_marker[0].name = "Guest IPA"; 133 133 st->ipa_marker[1].start_address = BIT(pgtable->ia_bits); 134 - st->range[0].end = BIT(pgtable->ia_bits); 135 134 136 - st->kvm = kvm; 137 - st->parser_state = (struct ptdump_pg_state) { 138 - .marker = &st->ipa_marker[0], 139 - .level = -1, 140 - .pg_level = &st->level[0], 141 - .ptdump.range = &st->range[0], 142 - .start_address = 0, 143 - }; 144 - 135 + st->mmu = mmu; 145 136 return st; 146 137 } 147 138 ··· 140 149 { 141 150 int ret; 142 151 struct kvm_ptdump_guest_state *st = m->private; 143 - struct kvm *kvm = st->kvm; 144 - struct kvm_s2_mmu *mmu = &kvm->arch.mmu; 145 - struct ptdump_pg_state *parser_state = &st->parser_state; 152 + struct kvm_s2_mmu *mmu = st->mmu; 153 + struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu); 146 154 struct kvm_pgtable_walker walker = (struct kvm_pgtable_walker) { 147 155 .cb = kvm_ptdump_visitor, 148 - .arg = parser_state, 156 + .arg = &st->parser_state, 149 157 .flags = KVM_PGTABLE_WALK_LEAF, 150 158 }; 151 159 152 - parser_state->seq = m; 160 + st->parser_state = (struct ptdump_pg_state) { 161 + .marker = &st->ipa_marker[0], 162 + .level = -1, 163 + .pg_level = &st->level[0], 164 + .seq = m, 165 + }; 153 166 154 167 write_lock(&kvm->mmu_lock); 155 168 ret = kvm_pgtable_walk(mmu->pgt, 0, BIT(mmu->pgt->ia_bits), &walker); ··· 164 169 165 170 static int kvm_ptdump_guest_open(struct inode *m, struct file *file) 166 171 { 167 - struct kvm *kvm = m->i_private; 172 + struct kvm_s2_mmu *mmu = m->i_private; 173 + struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu); 168 174 struct kvm_ptdump_guest_state *st; 169 175 int ret; 170 176 171 177 if (!kvm_get_kvm_safe(kvm)) 172 178 return -ENOENT; 173 179 174 - st = kvm_ptdump_parser_create(kvm); 180 + st = kvm_ptdump_parser_create(mmu); 175 181 if (IS_ERR(st)) { 176 182 ret = PTR_ERR(st); 177 183 goto err_with_kvm_ref; ··· 190 194 191 195 static int kvm_ptdump_guest_close(struct inode *m, struct file *file) 192 196 { 193 - struct kvm *kvm = m->i_private; 197 + struct kvm *kvm = kvm_s2_mmu_to_kvm(m->i_private); 194 198 void *st = ((struct seq_file *)file->private_data)->private; 195 199 196 200 kfree(st); ··· 225 229 static int kvm_pgtable_debugfs_open(struct inode *m, struct file *file, 226 230 int (*show)(struct seq_file *, void *)) 227 231 { 228 - struct kvm *kvm = m->i_private; 232 + struct kvm_s2_mmu *mmu = m->i_private; 233 + struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu); 229 234 struct kvm_pgtable *pgtable; 230 235 int ret; 231 236 232 237 if (!kvm_get_kvm_safe(kvm)) 233 238 return -ENOENT; 234 239 235 - pgtable = kvm->arch.mmu.pgt; 240 + pgtable = mmu->pgt; 236 241 237 242 ret = single_open(file, show, pgtable); 238 243 if (ret < 0) ··· 253 256 254 257 static int kvm_pgtable_debugfs_close(struct inode *m, struct file *file) 255 258 { 256 - struct kvm *kvm = m->i_private; 259 + struct kvm *kvm = kvm_s2_mmu_to_kvm(m->i_private); 257 260 258 261 kvm_put_kvm(kvm); 259 262 return single_release(m, file); ··· 273 276 .release = kvm_pgtable_debugfs_close, 274 277 }; 275 278 279 + void kvm_nested_s2_ptdump_create_debugfs(struct kvm_s2_mmu *mmu) 280 + { 281 + struct dentry *dent; 282 + char file_name[S2FNAMESZ]; 283 + 284 + snprintf(file_name, sizeof(file_name), "0x%016llx-0x%016llx-s2-%sabled", 285 + mmu->tlb_vttbr, 286 + mmu->tlb_vtcr, 287 + mmu->nested_stage2_enabled ? "en" : "dis"); 288 + 289 + dent = debugfs_create_file(file_name, 0400, 290 + mmu->arch->debugfs_nv_dentry, mmu, 291 + &kvm_ptdump_guest_fops); 292 + 293 + mmu->shadow_pt_debugfs_dentry = dent; 294 + } 295 + 296 + void kvm_nested_s2_ptdump_remove_debugfs(struct kvm_s2_mmu *mmu) 297 + { 298 + debugfs_remove(mmu->shadow_pt_debugfs_dentry); 299 + } 300 + 276 301 void kvm_s2_ptdump_create_debugfs(struct kvm *kvm) 277 302 { 278 303 debugfs_create_file("stage2_page_tables", 0400, kvm->debugfs_dentry, 279 - kvm, &kvm_ptdump_guest_fops); 280 - debugfs_create_file("ipa_range", 0400, kvm->debugfs_dentry, kvm, 281 - &kvm_pgtable_range_fops); 304 + &kvm->arch.mmu, &kvm_ptdump_guest_fops); 305 + debugfs_create_file("ipa_range", 0400, kvm->debugfs_dentry, 306 + &kvm->arch.mmu, &kvm_pgtable_range_fops); 282 307 debugfs_create_file("stage2_levels", 0400, kvm->debugfs_dentry, 283 - kvm, &kvm_pgtable_levels_fops); 308 + &kvm->arch.mmu, &kvm_pgtable_levels_fops); 309 + if (cpus_have_final_cap(ARM64_HAS_NESTED_VIRT)) 310 + kvm->arch.debugfs_nv_dentry = debugfs_create_dir("nested", kvm->debugfs_dentry); 284 311 }