Skip to content

Commit efe7254

Browse files
Yicong Yangctmarinas
authored andcommitted
arm64: Add support for FEAT_HAFT
Armv8.9/v9.4 introduces the feature Hardware managed Access Flag for Table descriptors (FEAT_HAFT). The feature is indicated by ID_AA64MMFR1_EL1.HAFDBS == 0b0011 and can be enabled by TCR2_EL1.HAFT so it has a dependency on FEAT_TCR2. Adds the Kconfig for FEAT_HAFT and support detecting and enabling the feature. The feature is enabled in __cpu_setup() before MMU on just like HA. A CPU capability is added to notify the user of the feature. Add definition of P{G,4,U,M}D_TABLE_AF bit and set the AF bit when creating the page table, which will save the hardware from having to update them at runtime. This will be ignored if FEAT_HAFT is not enabled. The AF bit of table descriptors cannot be managed by the software per spec, unlike the HA. So this should be used only if it's supported system wide by system_supports_haft(). Signed-off-by: Yicong Yang <yangyicong@hisilicon.com> Link: https://lore.kernel.org/r/20241102104235.62560-4-yangyicong@huawei.com Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> [catalin.marinas@arm.com: added the ID check back to __cpu_setup in case of future CPU errata] Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 926b66e commit efe7254

File tree

9 files changed

+64
-13
lines changed

9 files changed

+64
-13
lines changed

arch/arm64/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,21 @@ config ARCH_PKEY_BITS
21762176
int
21772177
default 3
21782178

2179+
config ARM64_HAFT
2180+
bool "Support for Hardware managed Access Flag for Table Descriptors"
2181+
depends on ARM64_HW_AFDBM
2182+
default y
2183+
help
2184+
The ARMv8.9/ARMv9.5 introduces the feature Hardware managed Access
2185+
Flag for Table descriptors. When enabled an architectural executed
2186+
memory access will update the Access Flag in each Table descriptor
2187+
which is accessed during the translation table walk and for which
2188+
the Access Flag is 0. The Access Flag of the Table descriptor use
2189+
the same bit of PTE_AF.
2190+
2191+
The feature will only be enabled if all the CPUs in the system
2192+
support this feature. If unsure, say Y.
2193+
21792194
endmenu # "ARMv8.9 architectural features"
21802195

21812196
config ARM64_SVE

arch/arm64/include/asm/cpufeature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,12 @@ static inline bool system_supports_poe(void)
838838
alternative_has_cap_unlikely(ARM64_HAS_S1POE);
839839
}
840840

841+
static inline bool system_supports_haft(void)
842+
{
843+
return IS_ENABLED(CONFIG_ARM64_HAFT) &&
844+
cpus_have_final_cap(ARM64_HAFT);
845+
}
846+
841847
int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
842848
bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
843849

arch/arm64/include/asm/pgalloc.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static inline void __pud_populate(pud_t *pudp, phys_addr_t pmdp, pudval_t prot)
2828

2929
static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmdp)
3030
{
31-
pudval_t pudval = PUD_TYPE_TABLE;
31+
pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_AF;
3232

3333
pudval |= (mm == &init_mm) ? PUD_TABLE_UXN : PUD_TABLE_PXN;
3434
__pud_populate(pudp, __pa(pmdp), pudval);
@@ -50,7 +50,7 @@ static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot)
5050

5151
static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp)
5252
{
53-
p4dval_t p4dval = P4D_TYPE_TABLE;
53+
p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_AF;
5454

5555
p4dval |= (mm == &init_mm) ? P4D_TABLE_UXN : P4D_TABLE_PXN;
5656
__p4d_populate(p4dp, __pa(pudp), p4dval);
@@ -79,7 +79,7 @@ static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t p4dp, pgdval_t prot)
7979

8080
static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, p4d_t *p4dp)
8181
{
82-
pgdval_t pgdval = PGD_TYPE_TABLE;
82+
pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_AF;
8383

8484
pgdval |= (mm == &init_mm) ? PGD_TABLE_UXN : PGD_TABLE_PXN;
8585
__pgd_populate(pgdp, __pa(p4dp), pgdval);
@@ -127,14 +127,16 @@ static inline void
127127
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
128128
{
129129
VM_BUG_ON(mm && mm != &init_mm);
130-
__pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE | PMD_TABLE_UXN);
130+
__pmd_populate(pmdp, __pa(ptep),
131+
PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_UXN);
131132
}
132133

133134
static inline void
134135
pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
135136
{
136137
VM_BUG_ON(mm == &init_mm);
137-
__pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE | PMD_TABLE_PXN);
138+
__pmd_populate(pmdp, page_to_phys(ptep),
139+
PMD_TYPE_TABLE | PMD_TABLE_AF | PMD_TABLE_PXN);
138140
}
139141

140142
#endif

arch/arm64/include/asm/pgtable-hwdef.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
#define PGD_TYPE_TABLE (_AT(pgdval_t, 3) << 0)
100100
#define PGD_TABLE_BIT (_AT(pgdval_t, 1) << 1)
101101
#define PGD_TYPE_MASK (_AT(pgdval_t, 3) << 0)
102+
#define PGD_TABLE_AF (_AT(pgdval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
102103
#define PGD_TABLE_PXN (_AT(pgdval_t, 1) << 59)
103104
#define PGD_TABLE_UXN (_AT(pgdval_t, 1) << 60)
104105

@@ -110,6 +111,7 @@
110111
#define P4D_TYPE_MASK (_AT(p4dval_t, 3) << 0)
111112
#define P4D_TYPE_SECT (_AT(p4dval_t, 1) << 0)
112113
#define P4D_SECT_RDONLY (_AT(p4dval_t, 1) << 7) /* AP[2] */
114+
#define P4D_TABLE_AF (_AT(p4dval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
113115
#define P4D_TABLE_PXN (_AT(p4dval_t, 1) << 59)
114116
#define P4D_TABLE_UXN (_AT(p4dval_t, 1) << 60)
115117

@@ -121,6 +123,7 @@
121123
#define PUD_TYPE_MASK (_AT(pudval_t, 3) << 0)
122124
#define PUD_TYPE_SECT (_AT(pudval_t, 1) << 0)
123125
#define PUD_SECT_RDONLY (_AT(pudval_t, 1) << 7) /* AP[2] */
126+
#define PUD_TABLE_AF (_AT(pudval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
124127
#define PUD_TABLE_PXN (_AT(pudval_t, 1) << 59)
125128
#define PUD_TABLE_UXN (_AT(pudval_t, 1) << 60)
126129

@@ -131,6 +134,7 @@
131134
#define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0)
132135
#define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0)
133136
#define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1)
137+
#define PMD_TABLE_AF (_AT(pmdval_t, 1) << 10) /* Ignored if no FEAT_HAFT */
134138

135139
/*
136140
* Section

arch/arm64/kernel/cpufeature.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,21 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
25902590
.cpus = &dbm_cpus,
25912591
ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, DBM)
25922592
},
2593+
#endif
2594+
#ifdef CONFIG_ARM64_HAFT
2595+
{
2596+
.desc = "Hardware managed Access Flag for Table Descriptors",
2597+
/*
2598+
* Contrary to the page/block access flag, the table access flag
2599+
* cannot be emulated in software (no access fault will occur).
2600+
* Therefore this should be used only if it's supported system
2601+
* wide.
2602+
*/
2603+
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
2604+
.capability = ARM64_HAFT,
2605+
.matches = has_cpuid_feature,
2606+
ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, HAFT)
2607+
},
25932608
#endif
25942609
{
25952610
.desc = "CRC32 instructions",

arch/arm64/mm/fixmap.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ static void __init early_fixmap_init_pte(pmd_t *pmdp, unsigned long addr)
4747

4848
if (pmd_none(pmd)) {
4949
ptep = bm_pte[BM_PTE_TABLE_IDX(addr)];
50-
__pmd_populate(pmdp, __pa_symbol(ptep), PMD_TYPE_TABLE);
50+
__pmd_populate(pmdp, __pa_symbol(ptep),
51+
PMD_TYPE_TABLE | PMD_TABLE_AF);
5152
}
5253
}
5354

@@ -59,7 +60,8 @@ static void __init early_fixmap_init_pmd(pud_t *pudp, unsigned long addr,
5960
pmd_t *pmdp;
6061

6162
if (pud_none(pud))
62-
__pud_populate(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE);
63+
__pud_populate(pudp, __pa_symbol(bm_pmd),
64+
PUD_TYPE_TABLE | PUD_TABLE_AF);
6365

6466
pmdp = pmd_offset_kimg(pudp, addr);
6567
do {
@@ -86,7 +88,8 @@ static void __init early_fixmap_init_pud(p4d_t *p4dp, unsigned long addr,
8688
}
8789

8890
if (p4d_none(p4d))
89-
__p4d_populate(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE);
91+
__p4d_populate(p4dp, __pa_symbol(bm_pud),
92+
P4D_TYPE_TABLE | P4D_TABLE_AF);
9093

9194
pudp = pud_offset_kimg(p4dp, addr);
9295
early_fixmap_init_pmd(pudp, addr, end);

arch/arm64/mm/mmu.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
201201

202202
BUG_ON(pmd_sect(pmd));
203203
if (pmd_none(pmd)) {
204-
pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN;
204+
pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF;
205205
phys_addr_t pte_phys;
206206

207207
if (flags & NO_EXEC_MAPPINGS)
@@ -288,7 +288,7 @@ static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
288288
*/
289289
BUG_ON(pud_sect(pud));
290290
if (pud_none(pud)) {
291-
pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN;
291+
pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN | PUD_TABLE_AF;
292292
phys_addr_t pmd_phys;
293293

294294
if (flags & NO_EXEC_MAPPINGS)
@@ -333,7 +333,7 @@ static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
333333
pud_t *pudp;
334334

335335
if (p4d_none(p4d)) {
336-
p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN;
336+
p4dval_t p4dval = P4D_TYPE_TABLE | P4D_TABLE_UXN | P4D_TABLE_AF;
337337
phys_addr_t pud_phys;
338338

339339
if (flags & NO_EXEC_MAPPINGS)
@@ -391,7 +391,7 @@ static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
391391
p4d_t *p4dp;
392392

393393
if (pgd_none(pgd)) {
394-
pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN;
394+
pgdval_t pgdval = PGD_TYPE_TABLE | PGD_TABLE_UXN | PGD_TABLE_AF;
395395
phys_addr_t p4d_phys;
396396

397397
if (flags & NO_EXEC_MAPPINGS)

arch/arm64/mm/proc.S

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,14 @@ alternative_else_nop_endif
495495
* via capabilities.
496496
*/
497497
mrs x9, ID_AA64MMFR1_EL1
498-
and x9, x9, ID_AA64MMFR1_EL1_HAFDBS_MASK
498+
ubfx x9, x9, ID_AA64MMFR1_EL1_HAFDBS_SHIFT, #4
499499
cbz x9, 1f
500500
orr tcr, tcr, #TCR_HA // hardware Access flag update
501+
#ifdef CONFIG_ARM64_HAFT
502+
cmp x9, ID_AA64MMFR1_EL1_HAFDBS_HAFT
503+
b.lt 1f
504+
orr tcr2, tcr2, TCR2_EL1x_HAFT
505+
#endif /* CONFIG_ARM64_HAFT */
501506
1:
502507
#endif /* CONFIG_ARM64_HW_AFDBM */
503508
msr mair_el1, mair

arch/arm64/tools/cpucaps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ HAS_TLB_RANGE
5656
HAS_VA52
5757
HAS_VIRT_HOST_EXTN
5858
HAS_WFXT
59+
HAFT
5960
HW_DBM
6061
KVM_HVHE
6162
KVM_PROTECTED_MODE

0 commit comments

Comments
 (0)