[PATCH v2 24/37] target/arm: Use flush_if_asid_change in vmsa_ttbr_write

Richard Henderson posted 37 patches 1 month ago
Maintainers: Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>, Peter Maydell <peter.maydell@linaro.org>, Alexander Graf <agraf@csgraf.de>, Mads Ynddal <mads@ynddal.dk>, Paolo Bonzini <pbonzini@redhat.com>
[PATCH v2 24/37] target/arm: Use flush_if_asid_change in vmsa_ttbr_write
Posted by Richard Henderson 1 month ago
Only flush the subset of tlbs that are affected by the ttbr
register to which we are writing.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index c6d290ce7c..2b55e219c2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2943,11 +2943,20 @@ static void flush_if_asid_change(CPUARMState *env, const ARMCPRegInfo *ri,
 static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                             uint64_t value)
 {
-    /* If the ASID changes (with a 64-bit write), we must flush the TLB.  */
-    if (cpreg_field_type(ri) == MO_64 &&
-        extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
-        ARMCPU *cpu = env_archcpu(env);
-        tlb_flush(CPU(cpu));
+    /*
+     * If the ASID changes (with a 64-bit write), we must flush the TLB.
+     * The non-secure ttbr registers affect the EL1 regime;
+     * the secure ttbr registers affect the AA32 EL3 regime.
+     */
+    if (cpreg_field_type(ri) == MO_64) {
+        flush_if_asid_change(env, ri, value,
+                             ri->secure & ARM_CP_SECSTATE_S
+                             ? (ARMMMUIdxBit_E30_0 |
+                                ARMMMUIdxBit_E30_3_PAN |
+                                ARMMMUIdxBit_E3)
+                             : (ARMMMUIdxBit_E10_1 |
+                                ARMMMUIdxBit_E10_1_PAN |
+                                ARMMMUIdxBit_E10_0));
     }
     raw_write(env, ri, value);
 }
-- 
2.43.0
Re: [PATCH v2 24/37] target/arm: Use flush_if_asid_change in vmsa_ttbr_write
Posted by Peter Maydell 3 weeks, 4 days ago
On Tue, 14 Oct 2025 at 21:17, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Only flush the subset of tlbs that are affected by the ttbr
> register to which we are writing.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/helper.c | 19 ++++++++++++++-----
>  1 file changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index c6d290ce7c..2b55e219c2 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -2943,11 +2943,20 @@ static void flush_if_asid_change(CPUARMState *env, const ARMCPRegInfo *ri,
>  static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>                              uint64_t value)
>  {
> -    /* If the ASID changes (with a 64-bit write), we must flush the TLB.  */
> -    if (cpreg_field_type(ri) == MO_64 &&
> -        extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
> -        ARMCPU *cpu = env_archcpu(env);
> -        tlb_flush(CPU(cpu));
> +    /*
> +     * If the ASID changes (with a 64-bit write), we must flush the TLB.
> +     * The non-secure ttbr registers affect the EL1 regime;
> +     * the secure ttbr registers affect the AA32 EL3 regime.
> +     */
> +    if (cpreg_field_type(ri) == MO_64) {
> +        flush_if_asid_change(env, ri, value,
> +                             ri->secure & ARM_CP_SECSTATE_S
> +                             ? (ARMMMUIdxBit_E30_0 |
> +                                ARMMMUIdxBit_E30_3_PAN |
> +                                ARMMMUIdxBit_E3)
> +                             : (ARMMMUIdxBit_E10_1 |
> +                                ARMMMUIdxBit_E10_1_PAN |
> +                                ARMMMUIdxBit_E10_0));
>      }

What's the value of ri->secure here for the case where EL3 is
AArch64 and we're in Secure EL1 at AArch32 ?

thanks
-- PMM
Re: [PATCH v2 24/37] target/arm: Use flush_if_asid_change in vmsa_ttbr_write
Posted by Richard Henderson 2 weeks, 2 days ago
On 10/20/25 16:08, Peter Maydell wrote:
> On Tue, 14 Oct 2025 at 21:17, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> Only flush the subset of tlbs that are affected by the ttbr
>> register to which we are writing.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   target/arm/helper.c | 19 ++++++++++++++-----
>>   1 file changed, 14 insertions(+), 5 deletions(-)
>>
>> diff --git a/target/arm/helper.c b/target/arm/helper.c
>> index c6d290ce7c..2b55e219c2 100644
>> --- a/target/arm/helper.c
>> +++ b/target/arm/helper.c
>> @@ -2943,11 +2943,20 @@ static void flush_if_asid_change(CPUARMState *env, const ARMCPRegInfo *ri,
>>   static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>>                               uint64_t value)
>>   {
>> -    /* If the ASID changes (with a 64-bit write), we must flush the TLB.  */
>> -    if (cpreg_field_type(ri) == MO_64 &&
>> -        extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
>> -        ARMCPU *cpu = env_archcpu(env);
>> -        tlb_flush(CPU(cpu));
>> +    /*
>> +     * If the ASID changes (with a 64-bit write), we must flush the TLB.
>> +     * The non-secure ttbr registers affect the EL1 regime;
>> +     * the secure ttbr registers affect the AA32 EL3 regime.
>> +     */
>> +    if (cpreg_field_type(ri) == MO_64) {
>> +        flush_if_asid_change(env, ri, value,
>> +                             ri->secure & ARM_CP_SECSTATE_S
>> +                             ? (ARMMMUIdxBit_E30_0 |
>> +                                ARMMMUIdxBit_E30_3_PAN |
>> +                                ARMMMUIdxBit_E3)
>> +                             : (ARMMMUIdxBit_E10_1 |
>> +                                ARMMMUIdxBit_E10_1_PAN |
>> +                                ARMMMUIdxBit_E10_0));
>>       }
> 
> What's the value of ri->secure here for the case where EL3 is
> AArch64 and we're in Secure EL1 at AArch32 ?

Um.. the state of the cpu doesn't apply.
ri->secure is true only for TTBR[01]_S.

I'm not sure what the question is?


r~
Re: [PATCH v2 24/37] target/arm: Use flush_if_asid_change in vmsa_ttbr_write
Posted by Peter Maydell 2 weeks, 2 days ago
On Wed, 29 Oct 2025 at 13:14, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 10/20/25 16:08, Peter Maydell wrote:
> > On Tue, 14 Oct 2025 at 21:17, Richard Henderson
> > <richard.henderson@linaro.org> wrote:
> >>
> >> Only flush the subset of tlbs that are affected by the ttbr
> >> register to which we are writing.
> >>
> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> >> ---
> >>   target/arm/helper.c | 19 ++++++++++++++-----
> >>   1 file changed, 14 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/target/arm/helper.c b/target/arm/helper.c
> >> index c6d290ce7c..2b55e219c2 100644
> >> --- a/target/arm/helper.c
> >> +++ b/target/arm/helper.c
> >> @@ -2943,11 +2943,20 @@ static void flush_if_asid_change(CPUARMState *env, const ARMCPRegInfo *ri,
> >>   static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> >>                               uint64_t value)
> >>   {
> >> -    /* If the ASID changes (with a 64-bit write), we must flush the TLB.  */
> >> -    if (cpreg_field_type(ri) == MO_64 &&
> >> -        extract64(raw_read(env, ri) ^ value, 48, 16) != 0) {
> >> -        ARMCPU *cpu = env_archcpu(env);
> >> -        tlb_flush(CPU(cpu));
> >> +    /*
> >> +     * If the ASID changes (with a 64-bit write), we must flush the TLB.
> >> +     * The non-secure ttbr registers affect the EL1 regime;
> >> +     * the secure ttbr registers affect the AA32 EL3 regime.
> >> +     */
> >> +    if (cpreg_field_type(ri) == MO_64) {
> >> +        flush_if_asid_change(env, ri, value,
> >> +                             ri->secure & ARM_CP_SECSTATE_S
> >> +                             ? (ARMMMUIdxBit_E30_0 |
> >> +                                ARMMMUIdxBit_E30_3_PAN |
> >> +                                ARMMMUIdxBit_E3)
> >> +                             : (ARMMMUIdxBit_E10_1 |
> >> +                                ARMMMUIdxBit_E10_1_PAN |
> >> +                                ARMMMUIdxBit_E10_0));
> >>       }
> >
> > What's the value of ri->secure here for the case where EL3 is
> > AArch64 and we're in Secure EL1 at AArch32 ?
>
> Um.. the state of the cpu doesn't apply.
> ri->secure is true only for TTBR[01]_S.
>
> I'm not sure what the question is?

If you get into this function because of a TTBR write
executed at Secure EL1 AArch32 (where EL3 is AArch64),
what is ri->secure ? That is, do we correctly flush for the
EL1 mmuidx, or is ri->secure true and we wrongly flush EL3 ?
(For EL3 == AArch32 a TTBR write in a Secure PL should
flush for the EL3 mmuidx values.)

-- PMM