Skip to content

Commit f625469

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/s2-ptdump into kvmarm-master/next
* kvm-arm64/s2-ptdump: : . : Stage-2 page table dumper, reusing the main ptdump infrastructure, : courtesy of Sebastian Ene. From the cover letter: : : "This series extends the ptdump support to allow dumping the guest : stage-2 pagetables. When CONFIG_PTDUMP_STAGE2_DEBUGFS is enabled, ptdump : registers the new following files under debugfs: : - /sys/debug/kvm/<guest_id>/stage2_page_tables : - /sys/debug/kvm/<guest_id>/stage2_levels : - /sys/debug/kvm/<guest_id>/ipa_range : : This allows userspace tools (eg. cat) to dump the stage-2 pagetables by : reading the 'stage2_page_tables' file. : [...]" : . KVM: arm64: Register ptdump with debugfs on guest creation arm64: ptdump: Don't override the level when operating on the stage-2 tables arm64: ptdump: Use the ptdump description from a local context arm64: ptdump: Expose the attribute parsing functionality KVM: arm64: Move pagetable definitions to common header Signed-off-by: Marc Zyngier <[email protected]>
2 parents 2e0f239 + 7c4f735 commit f625469

File tree

9 files changed

+397
-93
lines changed

9 files changed

+397
-93
lines changed

arch/arm64/include/asm/kvm_mmu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,5 +352,11 @@ static inline bool kvm_is_nested_s2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu)
352352
return &kvm->arch.mmu != mmu;
353353
}
354354

355+
#ifdef CONFIG_PTDUMP_STAGE2_DEBUGFS
356+
void kvm_s2_ptdump_create_debugfs(struct kvm *kvm);
357+
#else
358+
static inline void kvm_s2_ptdump_create_debugfs(struct kvm *kvm) {}
359+
#endif /* CONFIG_PTDUMP_STAGE2_DEBUGFS */
360+
355361
#endif /* __ASSEMBLY__ */
356362
#endif /* __ARM64_KVM_MMU_H__ */

arch/arm64/include/asm/kvm_pgtable.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,48 @@ typedef u64 kvm_pte_t;
5959

6060
#define KVM_PHYS_INVALID (-1ULL)
6161

62+
#define KVM_PTE_LEAF_ATTR_LO GENMASK(11, 2)
63+
64+
#define KVM_PTE_LEAF_ATTR_LO_S1_ATTRIDX GENMASK(4, 2)
65+
#define KVM_PTE_LEAF_ATTR_LO_S1_AP GENMASK(7, 6)
66+
#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RO \
67+
({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 2 : 3; })
68+
#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RW \
69+
({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 0 : 1; })
70+
#define KVM_PTE_LEAF_ATTR_LO_S1_SH GENMASK(9, 8)
71+
#define KVM_PTE_LEAF_ATTR_LO_S1_SH_IS 3
72+
#define KVM_PTE_LEAF_ATTR_LO_S1_AF BIT(10)
73+
74+
#define KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR GENMASK(5, 2)
75+
#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R BIT(6)
76+
#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W BIT(7)
77+
#define KVM_PTE_LEAF_ATTR_LO_S2_SH GENMASK(9, 8)
78+
#define KVM_PTE_LEAF_ATTR_LO_S2_SH_IS 3
79+
#define KVM_PTE_LEAF_ATTR_LO_S2_AF BIT(10)
80+
81+
#define KVM_PTE_LEAF_ATTR_HI GENMASK(63, 50)
82+
83+
#define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55)
84+
85+
#define KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54)
86+
87+
#define KVM_PTE_LEAF_ATTR_HI_S2_XN BIT(54)
88+
89+
#define KVM_PTE_LEAF_ATTR_HI_S1_GP BIT(50)
90+
91+
#define KVM_PTE_LEAF_ATTR_S2_PERMS (KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \
92+
KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \
93+
KVM_PTE_LEAF_ATTR_HI_S2_XN)
94+
95+
#define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2)
96+
#define KVM_MAX_OWNER_ID 1
97+
98+
/*
99+
* Used to indicate a pte for which a 'break-before-make' sequence is in
100+
* progress.
101+
*/
102+
#define KVM_INVALID_PTE_LOCKED BIT(10)
103+
62104
static inline bool kvm_pte_valid(kvm_pte_t pte)
63105
{
64106
return pte & KVM_PTE_VALID;

arch/arm64/include/asm/ptdump.h

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef __ASM_PTDUMP_H
66
#define __ASM_PTDUMP_H
77

8+
#include <linux/ptdump.h>
9+
810
#ifdef CONFIG_PTDUMP_CORE
911

1012
#include <linux/mm_types.h>
@@ -21,14 +23,53 @@ struct ptdump_info {
2123
unsigned long base_addr;
2224
};
2325

26+
struct ptdump_prot_bits {
27+
u64 mask;
28+
u64 val;
29+
const char *set;
30+
const char *clear;
31+
};
32+
33+
struct ptdump_pg_level {
34+
const struct ptdump_prot_bits *bits;
35+
char name[4];
36+
int num;
37+
u64 mask;
38+
};
39+
40+
/*
41+
* The page dumper groups page table entries of the same type into a single
42+
* description. It uses pg_state to track the range information while
43+
* iterating over the pte entries. When the continuity is broken it then
44+
* dumps out a description of the range.
45+
*/
46+
struct ptdump_pg_state {
47+
struct ptdump_state ptdump;
48+
struct ptdump_pg_level *pg_level;
49+
struct seq_file *seq;
50+
const struct addr_marker *marker;
51+
const struct mm_struct *mm;
52+
unsigned long start_address;
53+
int level;
54+
u64 current_prot;
55+
bool check_wx;
56+
unsigned long wx_pages;
57+
unsigned long uxn_pages;
58+
};
59+
2460
void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
61+
void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
62+
u64 val);
2563
#ifdef CONFIG_PTDUMP_DEBUGFS
2664
#define EFI_RUNTIME_MAP_END DEFAULT_MAP_WINDOW_64
2765
void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name);
2866
#else
2967
static inline void ptdump_debugfs_register(struct ptdump_info *info,
3068
const char *name) { }
31-
#endif
69+
#endif /* CONFIG_PTDUMP_DEBUGFS */
70+
#else
71+
static inline void note_page(struct ptdump_state *pt_st, unsigned long addr,
72+
int level, u64 val) { }
3273
#endif /* CONFIG_PTDUMP_CORE */
3374

3475
#endif /* __ASM_PTDUMP_H */

arch/arm64/kvm/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,21 @@ config PROTECTED_NVHE_STACKTRACE
6666

6767
If unsure, or not using protected nVHE (pKVM), say N.
6868

69+
config PTDUMP_STAGE2_DEBUGFS
70+
bool "Present the stage-2 pagetables to debugfs"
71+
depends on KVM
72+
depends on DEBUG_KERNEL
73+
depends on DEBUG_FS
74+
depends on GENERIC_PTDUMP
75+
select PTDUMP_CORE
76+
default n
77+
help
78+
Say Y here if you want to show the stage-2 kernel pagetables
79+
layout in a debugfs file. This information is only useful for kernel developers
80+
who are working in architecture specific areas of the kernel.
81+
It is probably not a good idea to enable this feature in a production
82+
kernel.
83+
84+
If in doubt, say N.
85+
6986
endif # VIRTUALIZATION

arch/arm64/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
2727

2828
kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o
2929
kvm-$(CONFIG_ARM64_PTR_AUTH) += pauth.o
30+
kvm-$(CONFIG_PTDUMP_STAGE2_DEBUGFS) += ptdump.o
3031

3132
always-y := hyp_constants.h hyp-constants.s
3233

arch/arm64/kvm/arm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
230230
void kvm_arch_create_vm_debugfs(struct kvm *kvm)
231231
{
232232
kvm_sys_regs_create_debugfs(kvm);
233+
kvm_s2_ptdump_create_debugfs(kvm);
233234
}
234235

235236
static void kvm_destroy_mpidr_data(struct kvm *kvm)

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,6 @@
1717
#define KVM_PTE_TYPE_PAGE 1
1818
#define KVM_PTE_TYPE_TABLE 1
1919

20-
#define KVM_PTE_LEAF_ATTR_LO GENMASK(11, 2)
21-
22-
#define KVM_PTE_LEAF_ATTR_LO_S1_ATTRIDX GENMASK(4, 2)
23-
#define KVM_PTE_LEAF_ATTR_LO_S1_AP GENMASK(7, 6)
24-
#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RO \
25-
({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 2 : 3; })
26-
#define KVM_PTE_LEAF_ATTR_LO_S1_AP_RW \
27-
({ cpus_have_final_cap(ARM64_KVM_HVHE) ? 0 : 1; })
28-
#define KVM_PTE_LEAF_ATTR_LO_S1_SH GENMASK(9, 8)
29-
#define KVM_PTE_LEAF_ATTR_LO_S1_SH_IS 3
30-
#define KVM_PTE_LEAF_ATTR_LO_S1_AF BIT(10)
31-
32-
#define KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR GENMASK(5, 2)
33-
#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R BIT(6)
34-
#define KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W BIT(7)
35-
#define KVM_PTE_LEAF_ATTR_LO_S2_SH GENMASK(9, 8)
36-
#define KVM_PTE_LEAF_ATTR_LO_S2_SH_IS 3
37-
#define KVM_PTE_LEAF_ATTR_LO_S2_AF BIT(10)
38-
39-
#define KVM_PTE_LEAF_ATTR_HI GENMASK(63, 50)
40-
41-
#define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55)
42-
43-
#define KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54)
44-
45-
#define KVM_PTE_LEAF_ATTR_HI_S2_XN BIT(54)
46-
47-
#define KVM_PTE_LEAF_ATTR_HI_S1_GP BIT(50)
48-
49-
#define KVM_PTE_LEAF_ATTR_S2_PERMS (KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R | \
50-
KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \
51-
KVM_PTE_LEAF_ATTR_HI_S2_XN)
52-
53-
#define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2)
54-
#define KVM_MAX_OWNER_ID 1
55-
56-
/*
57-
* Used to indicate a pte for which a 'break-before-make' sequence is in
58-
* progress.
59-
*/
60-
#define KVM_INVALID_PTE_LOCKED BIT(10)
61-
6220
struct kvm_pgtable_walk_data {
6321
struct kvm_pgtable_walker *walker;
6422

0 commit comments

Comments
 (0)