diff mbox

target-arm: Add missed AArch32 TLBI sytem registers

Message ID 1466694717-556963-1-git-send-email-afarallax@yandex.ru
State New
Headers show

Commit Message

Sergey Sorokin June 23, 2016, 3:11 p.m. UTC
Some PL2 related TLBI system registers are missed in AArch32
implementation. The patch fixes it.

Signed-off-by: Sergey Sorokin <afarallax@yandex.ru>
---
 target-arm/helper.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)

Comments

Sergey Sorokin July 8, 2016, 3:47 p.m. UTC | #1
23.06.2016, 18:12, "Sergey Sorokin" <afarallax@yandex.ru>:

     Some PL2 related TLBI system registers are missed in AArch32
     implementation. The patch fixes it.
     Signed-off-by: Sergey Sorokin <[1]afarallax@yandex.ru>
     ---
     Â target-arm/helper.c | 148
     ++++++++++++++++++++++++++++++++++++++++++++++++++++
     Â 1 file changed, 148 insertions(+)
     diff --git a/target-arm/helper.c b/target-arm/helper.c
     index 35ff772..73c844f 100644
     --- a/target-arm/helper.c
     +++ b/target-arm/helper.c
     @@ -572,6 +572,111 @@ static void tlbimvaa_is_write(CPUARMState
     *env, const ARMCPRegInfo *ri,
     Â Â Â Â Â }
     Â }
     +static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo
     *ri,
     + uint64_t value)
     +{
     + CPUState *cs = ENV_GET_CPU(env);
     +
     + if (arm_feature(env, ARM_FEATURE_EL2)) {
     + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0,
     + ARMMMUIdx_S2NS, -1);
     + } else {
     + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, -1);
     + }
     +}
     +
     +static void tlbiall_nsnh_is_write(CPUARMState *env, const
     ARMCPRegInfo *ri,
     + uint64_t value)
     +{
     + bool has_el2 = arm_feature(env, ARM_FEATURE_EL2);
     + CPUState *other_cs;
     +
     + CPU_FOREACH(other_cs) {
     + if (has_el2) {
     + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
     + ARMMMUIdx_S12NSE0, ARMMMUIdx_S2NS, -1);
     + } else {
     + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
     + ARMMMUIdx_S12NSE0, -1);
     + }
     + }
     +}
     +
     +static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo
     *ri,
     + uint64_t value)
     +{
     + /* Invalidate by IPA. This has to invalidate any structures that
     + * contain only stage 2 translation information, but does not need
     + * to apply to structures that contain combined stage 1 and stage 2
     + * translation information.
     + * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero.
     + */
     + CPUState *cs = ENV_GET_CPU(env);
     + uint64_t pageaddr;
     +
     + if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 &
     SCR_NS)) {
     + return;
     + }
     +
     + pageaddr = sextract64(value << 12, 0, 40);
     +
     + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S2NS, -1);
     +}
     +
     +static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo
     *ri,
     + uint64_t value)
     +{
     + CPUState *other_cs;
     + uint64_t pageaddr;
     +
     + if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 &
     SCR_NS)) {
     + return;
     + }
     +
     + pageaddr = sextract64(value << 12, 0, 40);
     +
     + CPU_FOREACH(other_cs) {
     + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S2NS, -1);
     + }
     +}
     +
     +static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo
     *ri,
     + uint64_t value)
     +{
     + CPUState *cs = ENV_GET_CPU(env);
     +
     + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E2, -1);
     +}
     +
     +static void tlbiall_hyp_is_write(CPUARMState *env, const
     ARMCPRegInfo *ri,
     + uint64_t value)
     +{
     + CPUState *other_cs;
     +
     + CPU_FOREACH(other_cs) {
     + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E2, -1);
     + }
     +}
     +
     +static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo
     *ri,
     + uint64_t value)
     +{
     + CPUState *cs = ENV_GET_CPU(env);
     +
     + tlb_flush_page_by_mmuidx(cs, value & TARGET_PAGE_MASK,
     ARMMMUIdx_S1E2, -1);
     +}
     +
     +static void tlbimva_hyp_is_write(CPUARMState *env, const
     ARMCPRegInfo *ri,
     + uint64_t value)
     +{
     + CPUState *other_cs;
     + uint64_t pageaddr = value & TARGET_PAGE_MASK;
     +
     + CPU_FOREACH(other_cs) {
     + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
     + }
     +}
     +
     Â static const ARMCPRegInfo cp_reginfo[] = {
     Â Â Â Â Â /* Define the secure and non-secure FCSE identifier CP
     registers
     Â Â Â Â Â Â * separately because there is no secure bank in V8 (no
     _EL3). This allows
     @@ -1238,6 +1343,14 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
     Â Â Â Â Â Â Â .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn =
     tlbiasid_write },
     Â Â Â Â Â { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm
     = 7, .opc2 = 3,
     Â Â Â Â Â Â Â .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn =
     tlbimvaa_write },
     + { .name = "TLBIALLNSNH",
     + .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiall_nsnh_write },
     + { .name = "TLBIALLNSNHIS",
     + .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiall_nsnh_is_write },
     Â Â Â Â Â REGINFO_SENTINEL
     Â };
     @@ -3273,6 +3386,22 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
     Â Â Â Â Â Â Â .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn =
     tlbimva_write },
     Â Â Â Â Â { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm
     = 7, .opc2 = 7,
     Â Â Â Â Â Â Â .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn =
     tlbimvaa_write },
     + { .name = "TLBIIPAS2",
     + .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiipas2_write },
     + { .name = "TLBIIPAS2IS",
     + .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiipas2_is_write },
     + { .name = "TLBIIPAS2L",
     + .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiipas2_write },
     + { .name = "TLBIIPAS2LIS",
     + .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiipas2_is_write },
     Â Â Â Â Â /* 32 bit cache operations */
     Â Â Â Â Â { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm
     = 1, .opc2 = 0,
     Â Â Â Â Â Â Â .type = ARM_CP_NOP, .access = PL1_W },
     @@ -3605,6 +3734,25 @@ static const ARMCPRegInfo el2_cp_reginfo[] =
     {
     Â Â Â Â Â { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
     Â Â Â Â Â Â Â .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
     Â Â Â Â Â Â Â .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2])
     },
     + { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7,
     .opc2 = 0,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiall_hyp_write },
     + { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3,
     .opc2 = 0,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbiall_hyp_is_write },
     + { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7,
     .opc2 = 1,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbimva_hyp_write },
     + { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3,
     .opc2 = 1,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbimva_hyp_is_write },
     + { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7,
     .opc2 = 5,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbimva_hyp_write },
     + { .name = "TLBIMVALHIS",
     + .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
     + .type = ARM_CP_NO_RAW, .access = PL2_W,
     + .writefn = tlbimva_hyp_is_write },
     Â Â Â Â Â { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
     Â Â Â Â Â Â Â .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
     Â Â Â Â Â Â Â .type = ARM_CP_NO_RAW, .access = PL2_W,
     --
     1.9.3

   ping

   http://patchwork.ozlabs.org/patch/639688/

References

   Visible links
   1. mailto:afarallax@yandex.ru

   Hidden links:
   2. http://patchwork.ozlabs.org/patch/639688/
Sergey Sorokin July 11, 2016, 12:12 p.m. UTC | #2
ping

http://patchwork.ozlabs.org/patch/639688/
Peter Maydell July 11, 2016, 5:39 p.m. UTC | #3
On 23 June 2016 at 16:11, Sergey Sorokin <afarallax@yandex.ru> wrote:
> Some PL2 related TLBI system registers are missed in AArch32
> implementation. The patch fixes it.
>
> Signed-off-by: Sergey Sorokin <afarallax@yandex.ru>
> ---
>  target-arm/helper.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 148 insertions(+)

Apologies for the delayed review, I think I missed this patch and
failed to put it in my to-review queue.

A couple of minor points below but most of this is good.

> +static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                              uint64_t value)
> +{
> +    CPUState *cs = ENV_GET_CPU(env);
> +
> +    tlb_flush_page_by_mmuidx(cs, value & TARGET_PAGE_MASK, ARMMMUIdx_S1E2, -1);

TARGET_PAGE_MASK isn't what you think it is (TARGET_PAGE_BITS is only 10).
You need to do something that's definitely a 12 bit mask (use extract32,
or MAKE_64BIT_MASK, or a literal, I don't care much).

> +}
> +
> +static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                                 uint64_t value)
> +{
> +    CPUState *other_cs;
> +    uint64_t pageaddr = value & TARGET_PAGE_MASK;

Ditto.

> +
> +    CPU_FOREACH(other_cs) {
> +        tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
> +    }
> +}
> +
>  static const ARMCPRegInfo cp_reginfo[] = {
>      /* Define the secure and non-secure FCSE identifier CP registers
>       * separately because there is no secure bank in V8 (no _EL3).  This allows
> @@ -1238,6 +1343,14 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
>        .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
>      { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
>        .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
> +    { .name = "TLBIALLNSNH",
> +      .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiall_nsnh_write },
> +    { .name = "TLBIALLNSNHIS",
> +      .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiall_nsnh_is_write },

These don't exist on v7 unless the virtualization extensions are present
(though they do exist on v8 without EL3).

>      REGINFO_SENTINEL
>  };
>
> @@ -3273,6 +3386,22 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
>        .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
>      { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
>        .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
> +    { .name = "TLBIIPAS2",
> +      .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiipas2_write },
> +    { .name = "TLBIIPAS2IS",
> +      .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiipas2_is_write },
> +    { .name = "TLBIIPAS2L",
> +      .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiipas2_write },
> +    { .name = "TLBIIPAS2LIS",
> +      .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiipas2_is_write },
>      /* 32 bit cache operations */
>      { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
>        .type = ARM_CP_NOP, .access = PL1_W },
> @@ -3605,6 +3734,25 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
>      { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
>        .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
>        .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
> +    { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiall_hyp_write },
> +    { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbiall_hyp_is_write },
> +    { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbimva_hyp_write },
> +    { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbimva_hyp_is_write },
> +    { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbimva_hyp_write },

This doesn't exist on v7.

> +    { .name = "TLBIMVALHIS",
> +      .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
> +      .type = ARM_CP_NO_RAW, .access = PL2_W,
> +      .writefn = tlbimva_hyp_is_write },

Nor does this.

>      { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
>        .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
>        .type = ARM_CP_NO_RAW, .access = PL2_W,
> --
> 1.9.3

thanks
-- PMM
Sergey Sorokin July 11, 2016, 6:23 p.m. UTC | #4
11.07.2016, 20:39, "Peter Maydell" <peter.maydell@linaro.org>:
>>  +
>>  + CPU_FOREACH(other_cs) {
>>  + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
>>  + }
>>  +}
>>  +
>>   static const ARMCPRegInfo cp_reginfo[] = {
>>       /* Define the secure and non-secure FCSE identifier CP registers
>>        * separately because there is no secure bank in V8 (no _EL3). This allows
>>  @@ -1238,6 +1343,14 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
>>         .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
>>       { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
>>         .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
>>  + { .name = "TLBIALLNSNH",
>>  + .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
>>  + .type = ARM_CP_NO_RAW, .access = PL2_W,
>>  + .writefn = tlbiall_nsnh_write },
>>  + { .name = "TLBIALLNSNHIS",
>>  + .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
>>  + .type = ARM_CP_NO_RAW, .access = PL2_W,
>>  + .writefn = tlbiall_nsnh_is_write },
>
> These don't exist on v7 unless the virtualization extensions are present
> (though they do exist on v8 without EL3).

So I should check arm_feature(env, ARM_FEATURE_EL2) to add these registers,
e.g. by moving them to el2_cp_reginfo, right?
Peter Maydell July 11, 2016, 6:35 p.m. UTC | #5
On 11 July 2016 at 19:23, Sergey Sorokin <afarallax@yandex.ru> wrote:
> 11.07.2016, 20:39, "Peter Maydell" <peter.maydell@linaro.org>:
>>>  +
>>>  + CPU_FOREACH(other_cs) {
>>>  + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
>>>  + }
>>>  +}
>>>  +
>>>   static const ARMCPRegInfo cp_reginfo[] = {
>>>       /* Define the secure and non-secure FCSE identifier CP registers
>>>        * separately because there is no secure bank in V8 (no _EL3). This allows
>>>  @@ -1238,6 +1343,14 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
>>>         .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
>>>       { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
>>>         .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
>>>  + { .name = "TLBIALLNSNH",
>>>  + .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
>>>  + .type = ARM_CP_NO_RAW, .access = PL2_W,
>>>  + .writefn = tlbiall_nsnh_write },
>>>  + { .name = "TLBIALLNSNHIS",
>>>  + .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
>>>  + .type = ARM_CP_NO_RAW, .access = PL2_W,
>>>  + .writefn = tlbiall_nsnh_is_write },
>>
>> These don't exist on v7 unless the virtualization extensions are present
>> (though they do exist on v8 without EL3).
>
> So I should check arm_feature(env, ARM_FEATURE_EL2) to add these registers,
> e.g. by moving them to el2_cp_reginfo, right?

That would make them incorrectly not exist for v8-without-EL3, I think.
If there isn't a suitable reginfo array for this case, you might need
to either list them in two arrays or add a new array.

thanks
-- PMM
Sergey Sorokin July 11, 2016, 6:47 p.m. UTC | #6
11.07.2016, 21:36, "Peter Maydell" <peter.maydell@linaro.org>:
> On 11 July 2016 at 19:23, Sergey Sorokin <afarallax@yandex.ru> wrote:
>>  11.07.2016, 20:39, "Peter Maydell" <peter.maydell@linaro.org>:
>>>>   +
>>>>   + CPU_FOREACH(other_cs) {
>>>>   + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
>>>>   + }
>>>>   +}
>>>>   +
>>>>    static const ARMCPRegInfo cp_reginfo[] = {
>>>>        /* Define the secure and non-secure FCSE identifier CP registers
>>>>         * separately because there is no secure bank in V8 (no _EL3). This allows
>>>>   @@ -1238,6 +1343,14 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
>>>>          .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
>>>>        { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
>>>>          .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
>>>>   + { .name = "TLBIALLNSNH",
>>>>   + .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
>>>>   + .type = ARM_CP_NO_RAW, .access = PL2_W,
>>>>   + .writefn = tlbiall_nsnh_write },
>>>>   + { .name = "TLBIALLNSNHIS",
>>>>   + .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
>>>>   + .type = ARM_CP_NO_RAW, .access = PL2_W,
>>>>   + .writefn = tlbiall_nsnh_is_write },
>>>
>>>  These don't exist on v7 unless the virtualization extensions are present
>>>  (though they do exist on v8 without EL3).
>>
>>  So I should check arm_feature(env, ARM_FEATURE_EL2) to add these registers,
>>  e.g. by moving them to el2_cp_reginfo, right?
>
> That would make them incorrectly not exist for v8-without-EL3, I think.
> If there isn't a suitable reginfo array for this case, you might need
> to either list them in two arrays or add a new array.
>
> thanks
> -- PMM

Table G4-25 Effect of the TLB maintenance instructions says:
b. Available only in an implementation that includes EL2.

So seems they should be in el2_cp_reginfo which is exist regardless EL3 enabled.
And also I need to fix tlbiall_nsnh_[is_]write functions accordingly.
Peter Maydell July 11, 2016, 7:25 p.m. UTC | #7
On 11 July 2016 at 19:47, Sergey Sorokin <afarallax@yandex.ru> wrote:
[re TLBIALLNSNH and TLBIALLNSNHIS]

> Table G4-25 Effect of the TLB maintenance instructions says:
> b. Available only in an implementation that includes EL2.
>
> So seems they should be in el2_cp_reginfo which is exist regardless EL3 enabled.
> And also I need to fix tlbiall_nsnh_[is_]write functions accordingly.

Ah, yes. I was looking at the register description, which doesn't
mention that it's an EL2-only operation. el2_cp_reginfo is the right
place, then.

thanks
-- PMM
diff mbox

Patch

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 35ff772..73c844f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -572,6 +572,111 @@  static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
     }
 }
 
+static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    CPUState *cs = ENV_GET_CPU(env);
+
+    if (arm_feature(env, ARM_FEATURE_EL2)) {
+        tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0,
+                            ARMMMUIdx_S2NS, -1);
+    } else {
+        tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, -1);
+    }
+}
+
+static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                  uint64_t value)
+{
+    bool has_el2 = arm_feature(env, ARM_FEATURE_EL2);
+    CPUState *other_cs;
+
+    CPU_FOREACH(other_cs) {
+        if (has_el2) {
+            tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
+                                ARMMMUIdx_S12NSE0, ARMMMUIdx_S2NS, -1);
+        } else {
+            tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1,
+                                ARMMMUIdx_S12NSE0, -1);
+        }
+    }
+}
+
+static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                            uint64_t value)
+{
+    /* Invalidate by IPA. This has to invalidate any structures that
+     * contain only stage 2 translation information, but does not need
+     * to apply to structures that contain combined stage 1 and stage 2
+     * translation information.
+     * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero.
+     */
+    CPUState *cs = ENV_GET_CPU(env);
+    uint64_t pageaddr;
+
+    if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
+        return;
+    }
+
+    pageaddr = sextract64(value << 12, 0, 40);
+
+    tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S2NS, -1);
+}
+
+static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    CPUState *other_cs;
+    uint64_t pageaddr;
+
+    if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) {
+        return;
+    }
+
+    pageaddr = sextract64(value << 12, 0, 40);
+
+    CPU_FOREACH(other_cs) {
+        tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S2NS, -1);
+    }
+}
+
+static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t value)
+{
+    CPUState *cs = ENV_GET_CPU(env);
+
+    tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E2, -1);
+}
+
+static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                 uint64_t value)
+{
+    CPUState *other_cs;
+
+    CPU_FOREACH(other_cs) {
+        tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E2, -1);
+    }
+}
+
+static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t value)
+{
+    CPUState *cs = ENV_GET_CPU(env);
+
+    tlb_flush_page_by_mmuidx(cs, value & TARGET_PAGE_MASK, ARMMMUIdx_S1E2, -1);
+}
+
+static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                 uint64_t value)
+{
+    CPUState *other_cs;
+    uint64_t pageaddr = value & TARGET_PAGE_MASK;
+
+    CPU_FOREACH(other_cs) {
+        tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1);
+    }
+}
+
 static const ARMCPRegInfo cp_reginfo[] = {
     /* Define the secure and non-secure FCSE identifier CP registers
      * separately because there is no secure bank in V8 (no _EL3).  This allows
@@ -1238,6 +1343,14 @@  static const ARMCPRegInfo v7_cp_reginfo[] = {
       .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
     { .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
       .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
+    { .name = "TLBIALLNSNH",
+      .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiall_nsnh_write },
+    { .name = "TLBIALLNSNHIS",
+      .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiall_nsnh_is_write },
     REGINFO_SENTINEL
 };
 
@@ -3273,6 +3386,22 @@  static const ARMCPRegInfo v8_cp_reginfo[] = {
       .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
     { .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
       .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
+    { .name = "TLBIIPAS2",
+      .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiipas2_write },
+    { .name = "TLBIIPAS2IS",
+      .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiipas2_is_write },
+    { .name = "TLBIIPAS2L",
+      .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiipas2_write },
+    { .name = "TLBIIPAS2LIS",
+      .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiipas2_is_write },
     /* 32 bit cache operations */
     { .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
       .type = ARM_CP_NOP, .access = PL1_W },
@@ -3605,6 +3734,25 @@  static const ARMCPRegInfo el2_cp_reginfo[] = {
     { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2,
       .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
       .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) },
+    { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiall_hyp_write },
+    { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbiall_hyp_is_write },
+    { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbimva_hyp_write },
+    { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbimva_hyp_is_write },
+    { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbimva_hyp_write },
+    { .name = "TLBIMVALHIS",
+      .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5,
+      .type = ARM_CP_NO_RAW, .access = PL2_W,
+      .writefn = tlbimva_hyp_is_write },
     { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64,
       .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0,
       .type = ARM_CP_NO_RAW, .access = PL2_W,