Skip to content

Commit d8d7839

Browse files
rananta468oupton
authored andcommitted
KVM: arm64: selftests: Introduce and use hardware-definition macros
The kvm selftest library for arm64 currently configures the hardware fields, such as shift and mask in the page-table entries and registers, directly with numbers. While it add comments at places, it's better to rewrite them with appropriate macros to improve the readability and reduce the risk of errors. Hence, introduce macros to define the hardware fields and use them in the arm64 processor library. Most of the definitions are primary copied from the Linux's header, arch/arm64/include/asm/pgtable-hwdef.h. No functional change intended. Suggested-by: Oliver Upton <oupton@google.com> Signed-off-by: Raghavendra Rao Ananta <rananta@google.com> Link: https://lore.kernel.org/r/20250405001042.1470552-2-rananta@google.com Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 26fbdf3 commit d8d7839

File tree

3 files changed

+92
-33
lines changed

3 files changed

+92
-33
lines changed

tools/testing/selftests/kvm/arm64/page_fault_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ static bool guest_set_ha(void)
199199
if (hadbs == 0)
200200
return false;
201201

202-
tcr = read_sysreg(tcr_el1) | TCR_EL1_HA;
202+
tcr = read_sysreg(tcr_el1) | TCR_HA;
203203
write_sysreg(tcr, tcr_el1);
204204
isb();
205205

tools/testing/selftests/kvm/include/arm64/processor.h

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,66 @@
6262
MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \
6363
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT))
6464

65+
/* TCR_EL1 specific flags */
66+
#define TCR_T0SZ_OFFSET 0
67+
#define TCR_T0SZ(x) ((UL(64) - (x)) << TCR_T0SZ_OFFSET)
68+
69+
#define TCR_IRGN0_SHIFT 8
70+
#define TCR_IRGN0_MASK (UL(3) << TCR_IRGN0_SHIFT)
71+
#define TCR_IRGN0_NC (UL(0) << TCR_IRGN0_SHIFT)
72+
#define TCR_IRGN0_WBWA (UL(1) << TCR_IRGN0_SHIFT)
73+
#define TCR_IRGN0_WT (UL(2) << TCR_IRGN0_SHIFT)
74+
#define TCR_IRGN0_WBnWA (UL(3) << TCR_IRGN0_SHIFT)
75+
76+
#define TCR_ORGN0_SHIFT 10
77+
#define TCR_ORGN0_MASK (UL(3) << TCR_ORGN0_SHIFT)
78+
#define TCR_ORGN0_NC (UL(0) << TCR_ORGN0_SHIFT)
79+
#define TCR_ORGN0_WBWA (UL(1) << TCR_ORGN0_SHIFT)
80+
#define TCR_ORGN0_WT (UL(2) << TCR_ORGN0_SHIFT)
81+
#define TCR_ORGN0_WBnWA (UL(3) << TCR_ORGN0_SHIFT)
82+
83+
#define TCR_SH0_SHIFT 12
84+
#define TCR_SH0_MASK (UL(3) << TCR_SH0_SHIFT)
85+
#define TCR_SH0_INNER (UL(3) << TCR_SH0_SHIFT)
86+
87+
#define TCR_TG0_SHIFT 14
88+
#define TCR_TG0_MASK (UL(3) << TCR_TG0_SHIFT)
89+
#define TCR_TG0_4K (UL(0) << TCR_TG0_SHIFT)
90+
#define TCR_TG0_64K (UL(1) << TCR_TG0_SHIFT)
91+
#define TCR_TG0_16K (UL(2) << TCR_TG0_SHIFT)
92+
93+
#define TCR_IPS_SHIFT 32
94+
#define TCR_IPS_MASK (UL(7) << TCR_IPS_SHIFT)
95+
#define TCR_IPS_52_BITS (UL(6) << TCR_IPS_SHIFT)
96+
#define TCR_IPS_48_BITS (UL(5) << TCR_IPS_SHIFT)
97+
#define TCR_IPS_40_BITS (UL(2) << TCR_IPS_SHIFT)
98+
#define TCR_IPS_36_BITS (UL(1) << TCR_IPS_SHIFT)
99+
100+
#define TCR_HA (UL(1) << 39)
101+
#define TCR_DS (UL(1) << 59)
102+
103+
/*
104+
* AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
105+
*/
106+
#define PTE_ATTRINDX(t) ((t) << 2)
107+
#define PTE_ATTRINDX_MASK GENMASK(4, 2)
108+
#define PTE_ATTRINDX_SHIFT 2
109+
110+
#define PTE_VALID BIT(0)
111+
#define PGD_TYPE_TABLE BIT(1)
112+
#define PUD_TYPE_TABLE BIT(1)
113+
#define PMD_TYPE_TABLE BIT(1)
114+
#define PTE_TYPE_PAGE BIT(1)
115+
116+
#define PTE_AF BIT(10)
117+
118+
#define PTE_ADDR_MASK(page_shift) GENMASK(47, (page_shift))
119+
#define PTE_ADDR_51_48 GENMASK(15, 12)
120+
#define PTE_ADDR_51_48_SHIFT 12
121+
#define PTE_ADDR_MASK_LPA2(page_shift) GENMASK(49, (page_shift))
122+
#define PTE_ADDR_51_50_LPA2 GENMASK(9, 8)
123+
#define PTE_ADDR_51_50_LPA2_SHIFT 8
124+
65125
void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init);
66126
struct kvm_vcpu *aarch64_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id,
67127
struct kvm_vcpu_init *init, void *guest_code);
@@ -102,12 +162,6 @@ enum {
102162
(v) == VECTOR_SYNC_LOWER_64 || \
103163
(v) == VECTOR_SYNC_LOWER_32)
104164

105-
/* Access flag */
106-
#define PTE_AF (1ULL << 10)
107-
108-
/* Access flag update enable/disable */
109-
#define TCR_EL1_HA (1ULL << 39)
110-
111165
void aarch64_get_supported_page_sizes(uint32_t ipa, uint32_t *ipa4k,
112166
uint32_t *ipa16k, uint32_t *ipa64k);
113167

tools/testing/selftests/kvm/lib/arm64/processor.c

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,13 @@ static uint64_t addr_pte(struct kvm_vm *vm, uint64_t pa, uint64_t attrs)
7272
uint64_t pte;
7373

7474
if (use_lpa2_pte_format(vm)) {
75-
pte = pa & GENMASK(49, vm->page_shift);
76-
pte |= FIELD_GET(GENMASK(51, 50), pa) << 8;
77-
attrs &= ~GENMASK(9, 8);
75+
pte = pa & PTE_ADDR_MASK_LPA2(vm->page_shift);
76+
pte |= FIELD_GET(GENMASK(51, 50), pa) << PTE_ADDR_51_50_LPA2_SHIFT;
77+
attrs &= ~PTE_ADDR_51_50_LPA2;
7878
} else {
79-
pte = pa & GENMASK(47, vm->page_shift);
79+
pte = pa & PTE_ADDR_MASK(vm->page_shift);
8080
if (vm->page_shift == 16)
81-
pte |= FIELD_GET(GENMASK(51, 48), pa) << 12;
81+
pte |= FIELD_GET(GENMASK(51, 48), pa) << PTE_ADDR_51_48_SHIFT;
8282
}
8383
pte |= attrs;
8484

@@ -90,12 +90,12 @@ static uint64_t pte_addr(struct kvm_vm *vm, uint64_t pte)
9090
uint64_t pa;
9191

9292
if (use_lpa2_pte_format(vm)) {
93-
pa = pte & GENMASK(49, vm->page_shift);
94-
pa |= FIELD_GET(GENMASK(9, 8), pte) << 50;
93+
pa = pte & PTE_ADDR_MASK_LPA2(vm->page_shift);
94+
pa |= FIELD_GET(PTE_ADDR_51_50_LPA2, pte) << 50;
9595
} else {
96-
pa = pte & GENMASK(47, vm->page_shift);
96+
pa = pte & PTE_ADDR_MASK(vm->page_shift);
9797
if (vm->page_shift == 16)
98-
pa |= FIELD_GET(GENMASK(15, 12), pte) << 48;
98+
pa |= FIELD_GET(PTE_ADDR_51_48, pte) << 48;
9999
}
100100

101101
return pa;
@@ -128,7 +128,8 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm)
128128
static void _virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
129129
uint64_t flags)
130130
{
131-
uint8_t attr_idx = flags & 7;
131+
uint8_t attr_idx = flags & (PTE_ATTRINDX_MASK >> PTE_ATTRINDX_SHIFT);
132+
uint64_t pg_attr;
132133
uint64_t *ptep;
133134

134135
TEST_ASSERT((vaddr % vm->page_size) == 0,
@@ -147,18 +148,21 @@ static void _virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
147148

148149
ptep = addr_gpa2hva(vm, vm->pgd) + pgd_index(vm, vaddr) * 8;
149150
if (!*ptep)
150-
*ptep = addr_pte(vm, vm_alloc_page_table(vm), 3);
151+
*ptep = addr_pte(vm, vm_alloc_page_table(vm),
152+
PGD_TYPE_TABLE | PTE_VALID);
151153

152154
switch (vm->pgtable_levels) {
153155
case 4:
154156
ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pud_index(vm, vaddr) * 8;
155157
if (!*ptep)
156-
*ptep = addr_pte(vm, vm_alloc_page_table(vm), 3);
158+
*ptep = addr_pte(vm, vm_alloc_page_table(vm),
159+
PUD_TYPE_TABLE | PTE_VALID);
157160
/* fall through */
158161
case 3:
159162
ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pmd_index(vm, vaddr) * 8;
160163
if (!*ptep)
161-
*ptep = addr_pte(vm, vm_alloc_page_table(vm), 3);
164+
*ptep = addr_pte(vm, vm_alloc_page_table(vm),
165+
PMD_TYPE_TABLE | PTE_VALID);
162166
/* fall through */
163167
case 2:
164168
ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) + pte_index(vm, vaddr) * 8;
@@ -167,7 +171,8 @@ static void _virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
167171
TEST_FAIL("Page table levels must be 2, 3, or 4");
168172
}
169173

170-
*ptep = addr_pte(vm, paddr, (attr_idx << 2) | (1 << 10) | 3); /* AF */
174+
pg_attr = PTE_AF | PTE_ATTRINDX(attr_idx) | PTE_TYPE_PAGE | PTE_VALID;
175+
*ptep = addr_pte(vm, paddr, pg_attr);
171176
}
172177

173178
void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
@@ -293,20 +298,20 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
293298
case VM_MODE_P48V48_64K:
294299
case VM_MODE_P40V48_64K:
295300
case VM_MODE_P36V48_64K:
296-
tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
301+
tcr_el1 |= TCR_TG0_64K;
297302
break;
298303
case VM_MODE_P52V48_16K:
299304
case VM_MODE_P48V48_16K:
300305
case VM_MODE_P40V48_16K:
301306
case VM_MODE_P36V48_16K:
302307
case VM_MODE_P36V47_16K:
303-
tcr_el1 |= 2ul << 14; /* TG0 = 16KB */
308+
tcr_el1 |= TCR_TG0_16K;
304309
break;
305310
case VM_MODE_P52V48_4K:
306311
case VM_MODE_P48V48_4K:
307312
case VM_MODE_P40V48_4K:
308313
case VM_MODE_P36V48_4K:
309-
tcr_el1 |= 0ul << 14; /* TG0 = 4KB */
314+
tcr_el1 |= TCR_TG0_4K;
310315
break;
311316
default:
312317
TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
@@ -319,35 +324,35 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
319324
case VM_MODE_P52V48_4K:
320325
case VM_MODE_P52V48_16K:
321326
case VM_MODE_P52V48_64K:
322-
tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
327+
tcr_el1 |= TCR_IPS_52_BITS;
323328
ttbr0_el1 |= FIELD_GET(GENMASK(51, 48), vm->pgd) << 2;
324329
break;
325330
case VM_MODE_P48V48_4K:
326331
case VM_MODE_P48V48_16K:
327332
case VM_MODE_P48V48_64K:
328-
tcr_el1 |= 5ul << 32; /* IPS = 48 bits */
333+
tcr_el1 |= TCR_IPS_48_BITS;
329334
break;
330335
case VM_MODE_P40V48_4K:
331336
case VM_MODE_P40V48_16K:
332337
case VM_MODE_P40V48_64K:
333-
tcr_el1 |= 2ul << 32; /* IPS = 40 bits */
338+
tcr_el1 |= TCR_IPS_40_BITS;
334339
break;
335340
case VM_MODE_P36V48_4K:
336341
case VM_MODE_P36V48_16K:
337342
case VM_MODE_P36V48_64K:
338343
case VM_MODE_P36V47_16K:
339-
tcr_el1 |= 1ul << 32; /* IPS = 36 bits */
344+
tcr_el1 |= TCR_IPS_36_BITS;
340345
break;
341346
default:
342347
TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
343348
}
344349

345-
sctlr_el1 |= (1 << 0) | (1 << 2) | (1 << 12) /* M | C | I */;
346-
/* TCR_EL1 |= IRGN0:WBWA | ORGN0:WBWA | SH0:Inner-Shareable */;
347-
tcr_el1 |= (1 << 8) | (1 << 10) | (3 << 12);
348-
tcr_el1 |= (64 - vm->va_bits) /* T0SZ */;
350+
sctlr_el1 |= SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_I;
351+
352+
tcr_el1 |= TCR_IRGN0_WBWA | TCR_ORGN0_WBWA | TCR_SH0_INNER;
353+
tcr_el1 |= TCR_T0SZ(vm->va_bits);
349354
if (use_lpa2_pte_format(vm))
350-
tcr_el1 |= (1ul << 59) /* DS */;
355+
tcr_el1 |= TCR_DS;
351356

352357
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_SCTLR_EL1), sctlr_el1);
353358
vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TCR_EL1), tcr_el1);

0 commit comments

Comments
 (0)