Skip to content

Commit a035001

Browse files
author
Marc Zyngier
committed
arm64: Convert VTCR_EL2 to sysreg infratructure
Our definition of VTCR_EL2 is both partial (tons of fields are missing) and totally inconsistent (some constants are shifted, some are not). They are also expressed in terms of TCR, which is rather inconvenient. Replace the ad-hoc definitions with the the generated version. This results in a bunch of additional changes to make the code with the unshifted nature of generated enumerations. The register data was extracted from the BSD licenced AARCHMRS (AARCHMRS_OPENSOURCE_A_profile_FAT-2025-09_ASL0). Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com> Reviewed-by: Fuad Tabba <tabba@google.com> Tested-by: Fuad Tabba <tabba@google.com> Link: https://patch.msgid.link/20251210173024.561160-4-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent f164017 commit a035001

5 files changed

Lines changed: 76 additions & 50 deletions

File tree

arch/arm64/include/asm/kvm_arm.h

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -124,47 +124,14 @@
124124
#define TCR_EL2_MASK (TCR_EL2_TG0_MASK | TCR_EL2_SH0_MASK | \
125125
TCR_EL2_ORGN0_MASK | TCR_EL2_IRGN0_MASK)
126126

127-
/* VTCR_EL2 Registers bits */
128-
#define VTCR_EL2_DS TCR_EL2_DS
129-
#define VTCR_EL2_RES1 (1U << 31)
130-
#define VTCR_EL2_HD (1 << 22)
131-
#define VTCR_EL2_HA (1 << 21)
132-
#define VTCR_EL2_PS_SHIFT TCR_EL2_PS_SHIFT
133-
#define VTCR_EL2_PS_MASK TCR_EL2_PS_MASK
134-
#define VTCR_EL2_TG0_MASK TCR_TG0_MASK
135-
#define VTCR_EL2_TG0_4K TCR_TG0_4K
136-
#define VTCR_EL2_TG0_16K TCR_TG0_16K
137-
#define VTCR_EL2_TG0_64K TCR_TG0_64K
138-
#define VTCR_EL2_SH0_MASK TCR_SH0_MASK
139-
#define VTCR_EL2_SH0_INNER TCR_SH0_INNER
140-
#define VTCR_EL2_ORGN0_MASK TCR_ORGN0_MASK
141-
#define VTCR_EL2_ORGN0_WBWA TCR_ORGN0_WBWA
142-
#define VTCR_EL2_IRGN0_MASK TCR_IRGN0_MASK
143-
#define VTCR_EL2_IRGN0_WBWA TCR_IRGN0_WBWA
144-
#define VTCR_EL2_SL0_SHIFT 6
145-
#define VTCR_EL2_SL0_MASK (3 << VTCR_EL2_SL0_SHIFT)
146-
#define VTCR_EL2_T0SZ_MASK 0x3f
147-
#define VTCR_EL2_VS_SHIFT 19
148-
#define VTCR_EL2_VS_8BIT (0 << VTCR_EL2_VS_SHIFT)
149-
#define VTCR_EL2_VS_16BIT (1 << VTCR_EL2_VS_SHIFT)
150-
151-
#define VTCR_EL2_T0SZ(x) TCR_T0SZ(x)
152-
153127
/*
154-
* We configure the Stage-2 page tables to always restrict the IPA space to be
155-
* 40 bits wide (T0SZ = 24). Systems with a PARange smaller than 40 bits are
156-
* not known to exist and will break with this configuration.
157-
*
158128
* The VTCR_EL2 is configured per VM and is initialised in kvm_init_stage2_mmu.
159129
*
160130
* Note that when using 4K pages, we concatenate two first level page tables
161131
* together. With 16K pages, we concatenate 16 first level page tables.
162132
*
163133
*/
164134

165-
#define VTCR_EL2_COMMON_BITS (VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \
166-
VTCR_EL2_IRGN0_WBWA | VTCR_EL2_RES1)
167-
168135
/*
169136
* VTCR_EL2:SL0 indicates the entry level for Stage2 translation.
170137
* Interestingly, it depends on the page size.
@@ -196,30 +163,35 @@
196163
*/
197164
#ifdef CONFIG_ARM64_64K_PAGES
198165

199-
#define VTCR_EL2_TGRAN VTCR_EL2_TG0_64K
166+
#define VTCR_EL2_TGRAN 64K
200167
#define VTCR_EL2_TGRAN_SL0_BASE 3UL
201168

202169
#elif defined(CONFIG_ARM64_16K_PAGES)
203170

204-
#define VTCR_EL2_TGRAN VTCR_EL2_TG0_16K
171+
#define VTCR_EL2_TGRAN 16K
205172
#define VTCR_EL2_TGRAN_SL0_BASE 3UL
206173

207174
#else /* 4K */
208175

209-
#define VTCR_EL2_TGRAN VTCR_EL2_TG0_4K
176+
#define VTCR_EL2_TGRAN 4K
210177
#define VTCR_EL2_TGRAN_SL0_BASE 2UL
211178

212179
#endif
213180

214181
#define VTCR_EL2_LVLS_TO_SL0(levels) \
215-
((VTCR_EL2_TGRAN_SL0_BASE - (4 - (levels))) << VTCR_EL2_SL0_SHIFT)
182+
FIELD_PREP(VTCR_EL2_SL0, (VTCR_EL2_TGRAN_SL0_BASE - (4 - (levels))))
216183
#define VTCR_EL2_SL0_TO_LVLS(sl0) \
217184
((sl0) + 4 - VTCR_EL2_TGRAN_SL0_BASE)
218185
#define VTCR_EL2_LVLS(vtcr) \
219-
VTCR_EL2_SL0_TO_LVLS(((vtcr) & VTCR_EL2_SL0_MASK) >> VTCR_EL2_SL0_SHIFT)
186+
VTCR_EL2_SL0_TO_LVLS(FIELD_GET(VTCR_EL2_SL0, (vtcr)))
187+
188+
#define VTCR_EL2_FLAGS (SYS_FIELD_PREP_ENUM(VTCR_EL2, SH0, INNER) | \
189+
SYS_FIELD_PREP_ENUM(VTCR_EL2, ORGN0, WBWA) | \
190+
SYS_FIELD_PREP_ENUM(VTCR_EL2, IRGN0, WBWA) | \
191+
SYS_FIELD_PREP_ENUM(VTCR_EL2, TG0, VTCR_EL2_TGRAN) | \
192+
VTCR_EL2_RES1)
220193

221-
#define VTCR_EL2_FLAGS (VTCR_EL2_COMMON_BITS | VTCR_EL2_TGRAN)
222-
#define VTCR_EL2_IPA(vtcr) (64 - ((vtcr) & VTCR_EL2_T0SZ_MASK))
194+
#define VTCR_EL2_IPA(vtcr) (64 - FIELD_GET(VTCR_EL2_T0SZ, (vtcr)))
223195

224196
/*
225197
* ARM VMSAv8-64 defines an algorithm for finding the translation table

arch/arm64/include/asm/sysreg.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,6 @@
517517
#define SYS_TTBR1_EL2 sys_reg(3, 4, 2, 0, 1)
518518
#define SYS_TCR_EL2 sys_reg(3, 4, 2, 0, 2)
519519
#define SYS_VTTBR_EL2 sys_reg(3, 4, 2, 1, 0)
520-
#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2)
521520

522521
#define SYS_HAFGRTR_EL2 sys_reg(3, 4, 3, 1, 6)
523522
#define SYS_SPSR_EL2 sys_reg(3, 4, 4, 0, 0)

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,8 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
583583
u64 vtcr = VTCR_EL2_FLAGS;
584584
s8 lvls;
585585

586-
vtcr |= kvm_get_parange(mmfr0) << VTCR_EL2_PS_SHIFT;
587-
vtcr |= VTCR_EL2_T0SZ(phys_shift);
586+
vtcr |= FIELD_PREP(VTCR_EL2_PS, kvm_get_parange(mmfr0));
587+
vtcr |= FIELD_PREP(VTCR_EL2_T0SZ, (UL(64) - phys_shift));
588588
/*
589589
* Use a minimum 2 level page table to prevent splitting
590590
* host PMD huge pages at stage2.
@@ -624,9 +624,7 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
624624
vtcr |= VTCR_EL2_DS;
625625

626626
/* Set the vmid bits */
627-
vtcr |= (get_vmid_bits(mmfr1) == 16) ?
628-
VTCR_EL2_VS_16BIT :
629-
VTCR_EL2_VS_8BIT;
627+
vtcr |= (get_vmid_bits(mmfr1) == 16) ? VTCR_EL2_VS : 0;
630628

631629
return vtcr;
632630
}

arch/arm64/kvm/nested.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ static void vtcr_to_walk_info(u64 vtcr, struct s2_walk_info *wi)
377377
{
378378
wi->t0sz = vtcr & TCR_EL2_T0SZ_MASK;
379379

380-
switch (vtcr & VTCR_EL2_TG0_MASK) {
380+
switch (FIELD_GET(VTCR_EL2_TG0_MASK, vtcr)) {
381381
case VTCR_EL2_TG0_4K:
382382
wi->pgshift = 12; break;
383383
case VTCR_EL2_TG0_16K:
@@ -513,7 +513,7 @@ static u8 get_guest_mapping_ttl(struct kvm_s2_mmu *mmu, u64 addr)
513513

514514
lockdep_assert_held_write(&kvm_s2_mmu_to_kvm(mmu)->mmu_lock);
515515

516-
switch (vtcr & VTCR_EL2_TG0_MASK) {
516+
switch (FIELD_GET(VTCR_EL2_TG0_MASK, vtcr)) {
517517
case VTCR_EL2_TG0_4K:
518518
ttl = (TLBI_TTL_TG_4K << 2);
519519
break;
@@ -530,7 +530,7 @@ static u8 get_guest_mapping_ttl(struct kvm_s2_mmu *mmu, u64 addr)
530530

531531
again:
532532
/* Iteratively compute the block sizes for a particular granule size */
533-
switch (vtcr & VTCR_EL2_TG0_MASK) {
533+
switch (FIELD_GET(VTCR_EL2_TG0_MASK, vtcr)) {
534534
case VTCR_EL2_TG0_4K:
535535
if (sz < SZ_4K) sz = SZ_4K;
536536
else if (sz < SZ_2M) sz = SZ_2M;
@@ -593,7 +593,7 @@ unsigned long compute_tlb_inval_range(struct kvm_s2_mmu *mmu, u64 val)
593593

594594
if (!max_size) {
595595
/* Compute the maximum extent of the invalidation */
596-
switch (mmu->tlb_vtcr & VTCR_EL2_TG0_MASK) {
596+
switch (FIELD_GET(VTCR_EL2_TG0_MASK, mmu->tlb_vtcr)) {
597597
case VTCR_EL2_TG0_4K:
598598
max_size = SZ_1G;
599599
break;

arch/arm64/tools/sysreg

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4400,6 +4400,63 @@ Field 56:12 BADDR
44004400
Res0 11:0
44014401
EndSysreg
44024402

4403+
Sysreg VTCR_EL2 3 4 2 1 2
4404+
Res0 63:46
4405+
Field 45 HDBSS
4406+
Field 44 HAFT
4407+
Res0 43:42
4408+
Field 41 TL0
4409+
Field 40 GCSH
4410+
Res0 39
4411+
Field 38 D128
4412+
Field 37 S2POE
4413+
Field 36 S2PIE
4414+
Field 35 TL1
4415+
Field 34 AssuredOnly
4416+
Field 33 SL2
4417+
Field 32 DS
4418+
Res1 31
4419+
Field 30 NSA
4420+
Field 29 NSW
4421+
Field 28 HWU62
4422+
Field 27 HWU61
4423+
Field 26 HWU60
4424+
Field 25 HWU59
4425+
Res0 24:23
4426+
Field 22 HD
4427+
Field 21 HA
4428+
Res0 20
4429+
Enum 19 VS
4430+
0b0 8BIT
4431+
0b1 16BIT
4432+
EndEnum
4433+
Field 18:16 PS
4434+
Enum 15:14 TG0
4435+
0b00 4K
4436+
0b01 64K
4437+
0b10 16K
4438+
EndEnum
4439+
Enum 13:12 SH0
4440+
0b00 NONE
4441+
0b01 OUTER
4442+
0b11 INNER
4443+
EndEnum
4444+
Enum 11:10 ORGN0
4445+
0b00 NC
4446+
0b01 WBWA
4447+
0b10 WT
4448+
0b11 WBnWA
4449+
EndEnum
4450+
Enum 9:8 IRGN0
4451+
0b00 NC
4452+
0b01 WBWA
4453+
0b10 WT
4454+
0b11 WBnWA
4455+
EndEnum
4456+
Field 7:6 SL0
4457+
Field 5:0 T0SZ
4458+
EndSysreg
4459+
44034460
Sysreg GCSCR_EL2 3 4 2 5 0
44044461
Fields GCSCR_ELx
44054462
EndSysreg

0 commit comments

Comments
 (0)