[PATCH] arm64/mm: Re-organise setting up FEAT_S1PIE registers PIRE0_EL1 and PIR_EL1
Anshuman Khandual
anshuman.khandual at arm.com
Sun Apr 13 22:43:53 PDT 2025
On 4/10/25 17:58, Ard Biesheuvel wrote:
> Hi Anshuman,
>
> On Thu, 10 Apr 2025 at 09:40, Anshuman Khandual
> <anshuman.khandual at arm.com> wrote:
>>
>> mov_q cannot really move PIE_E[0|1] macros into a general purpose register
>> as expected if those macro constants contain some 128 bit layout elements,
>> required for D128 page tables.
>
> Could you elaborate?
Without this change in place, the following build error comes up.
arch/arm64/mm/proc.S: Assembler messages:
arch/arm64/mm/proc.S:539: Error: too many positional arguments
arch/arm64/mm/proc.S:541: Error: too many positional arguments
make[4]: *** [scripts/Makefile.build:335: arch/arm64/mm/proc.o] Error 1
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [scripts/Makefile.build:461: arch/arm64/mm] Error 2
make[3]: *** Waiting for unfinished jobs...
SYM_FUNC_START(__cpu_setup)
..........................
..........................
#define PTE_MAYBE_NG 0
#define PTE_MAYBE_SHARED 0
mov_q x0, PIE_E0 (arch/arm64/mm/proc.S:539)
msr REG_PIRE0_EL1, x0
mov_q x0, PIE_E1 (arch/arm64/mm/proc.S:541)
msr REG_PIR_EL1, x0
#undef PTE_MAYBE_NG
#undef PTE_MAYBE_SHARED
..........................
..........................
Please note the following PIE_E0 definition in D128 context.
#define PTE_PI_MASK GENMASK_U128(118, 115)
#define PTE_PI_SHIFT 115
#define pte_pi_index(pte) (((pte) & PTE_PI_MASK) >> PTE_PI_SHIFT)
#define PIE_E0 ( \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS), PIE_GCS) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS_RO), PIE_R) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_EXECONLY), PIE_X_O) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX_O) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RWX_O) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_READONLY), PIE_R_O) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_SHARED), PIE_RW_O))
Where _PAGE_XXX definitions here might contain page flags beyond just 64
bits as well.
>
>> Fix this problem via first loading up these
>> macro constants into a given memory location and then subsequently setting
>> up registers PIRE0_EL1 and PIR_EL1 by retrieving the memory stored values.
>>
>
> If this is necessary, we could also remove the PTE_MAYBE_xx override hack no?
Could you please elaborate ? Not sure if PTE_MAYBE_xx is the problem here.
>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: Ard Biesheuvel <ardb at kernel.org>
>> Cc: Ryan Roberts <ryan.roberts at arm.com>
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-kernel at vger.kernel.org
>> Signed-off-by: Anshuman Khandual <anshuman.khandual at arm.com>
>> ---
>> This patch applies on v6.15-rc1
>>
>> arch/arm64/kernel/head.S | 3 +++
>> arch/arm64/kernel/pi/map_range.c | 6 ++++++
>> arch/arm64/kernel/pi/pi.h | 1 +
>> arch/arm64/mm/mmu.c | 1 +
>> arch/arm64/mm/proc.S | 5 +++--
>> 5 files changed, 14 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
>> index 2ce73525de2c..4950d9cc638a 100644
>> --- a/arch/arm64/kernel/head.S
>> +++ b/arch/arm64/kernel/head.S
>> @@ -126,6 +126,9 @@ SYM_CODE_START(primary_entry)
>> * On return, the CPU will be ready for the MMU to be turned on and
>> * the TCR will have been set.
>> */
>> + adr_l x0, pir_data
>> + bl __pi_load_pir_data
>> +
>> bl __cpu_setup // initialise processor
>> b __primary_switch
>> SYM_CODE_END(primary_entry)
>> diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c
>> index 81345f68f9fc..cd9d24e73046 100644
>> --- a/arch/arm64/kernel/pi/map_range.c
>> +++ b/arch/arm64/kernel/pi/map_range.c
>> @@ -103,3 +103,9 @@ asmlinkage u64 __init create_init_idmap(pgd_t *pg_dir, pteval_t clrmask)
>>
>> return ptep;
>> }
>> +
>> +asmlinkage void __init load_pir_data(u64 pir_data[])
>> +{
>> + pir_data[0] = PIE_E0;
>> + pir_data[1] = PIE_E1;
>> +}
>> diff --git a/arch/arm64/kernel/pi/pi.h b/arch/arm64/kernel/pi/pi.h
>> index c91e5e965cd3..ae61df4fdb77 100644
>> --- a/arch/arm64/kernel/pi/pi.h
>> +++ b/arch/arm64/kernel/pi/pi.h
>> @@ -34,3 +34,4 @@ void map_range(u64 *pgd, u64 start, u64 end, u64 pa, pgprot_t prot,
>> asmlinkage void early_map_kernel(u64 boot_status, void *fdt);
>>
>> asmlinkage u64 create_init_idmap(pgd_t *pgd, pteval_t clrmask);
>> +asmlinkage void load_pir_data(u64 pir_data[]);
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index ea6695d53fb9..762e81ff4e85 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -58,6 +58,7 @@ static bool rodata_is_rw __ro_after_init = true;
>> * with MMU turned off.
>> */
>> long __section(".mmuoff.data.write") __early_cpu_boot_status;
>> +unsigned long __section(".mmuoff.data.write") pir_data[2];
>>
>> /*
>> * Empty_zero_page is a special page that is used for zero-initialized data
>> diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
>> index fb30c8804f87..7dd28cf101c2 100644
>> --- a/arch/arm64/mm/proc.S
>> +++ b/arch/arm64/mm/proc.S
>> @@ -524,9 +524,10 @@ alternative_else_nop_endif
>> #define PTE_MAYBE_NG 0
>> #define PTE_MAYBE_SHARED 0
>>
>> - mov_q x0, PIE_E0
>> + adr_l x1, pir_data
>> + ldr x0, [x1, #0]
>> msr REG_PIRE0_EL1, x0
>> - mov_q x0, PIE_E1
>> + ldr x0, [x1, #8]
>> msr REG_PIR_EL1, x0
>>
>> #undef PTE_MAYBE_NG
>> --
>> 2.25.1
>>
More information about the linux-arm-kernel
mailing list