All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
@ 2014-06-05 10:39 Fabian Aggeler
  2014-06-05 13:41 ` Greg Bellows
  2014-06-09 11:27 ` Peter Maydell
  0 siblings, 2 replies; 8+ messages in thread
From: Fabian Aggeler @ 2014-06-05 10:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, greg.bellows

Corrected handling of writes to TTBCR for ARMv8 (previously UNK/SBZP
bits are not RES0) and ARMv7 (new bits PD0/PD1 for CPUs with Security
Extensions).

Bits PD0/PD1 are now respected in get_phys_addr_v6/v5() and
get_level1_table_address.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
---
v1 -> v2:
* dropped changes in get_phys_addr_lpae()
* simplified get_level1_table_address as suggested
* fixed checkpath issues

v1: http://lists.gnu.org/archive/html/qemu-devel/2014-05/msg06590.html

 target-arm/cpu.h    | 16 ++++++++++++++
 target-arm/helper.c | 60 ++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8d04385..b0e8b0c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -430,6 +430,22 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 /* Execution state bits.  MRS read as zero, MSR writes ignored.  */
 #define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J)
 
+#define TTBCR_N      (7U << 0) /* TTBCR.EAE==0 */
+#define TTBCR_T0SZ   (7U << 0) /* TTBCR.EAE==1 */
+#define TTBCR_PD0    (1U << 4)
+#define TTBCR_PD1    (1U << 5)
+#define TTBCR_EPD0   (1U << 7)
+#define TTBCR_IRGN0  (3U << 8)
+#define TTBCR_ORGN0  (3U << 10)
+#define TTBCR_SH0    (3U << 12)
+#define TTBCR_T1SZ   (3U << 16)
+#define TTBCR_A1     (1U << 22)
+#define TTBCR_EPD1   (1U << 23)
+#define TTBCR_IRGN1  (3U << 24)
+#define TTBCR_ORGN1  (3U << 26)
+#define TTBCR_SH1    (1U << 28)
+#define TTBCR_EAE    (1U << 31)
+
 /* Bit definitions for ARMv8 SPSR (PSTATE) format.
  * Only these are valid when in AArch64 mode; in
  * AArch32 mode SPSRs are basically CPSR-format.
diff --git a/target-arm/helper.c b/target-arm/helper.c
index ec031f5..0b2ebc3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -312,7 +312,7 @@ static inline bool extended_addresses_enabled(CPUARMState *env)
 {
     return arm_el_is_aa64(env, 1)
         || ((arm_feature(env, ARM_FEATURE_LPAE)
-             && (env->cp15.c2_control & (1U << 31))));
+             && (env->cp15.c2_control & TTBCR_EAE)));
 }
 
 static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
@@ -1413,11 +1413,22 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     int maskshift = extract32(value, 0, 3);
 
-    if (arm_feature(env, ARM_FEATURE_LPAE) && (value & (1 << 31))) {
-        value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
-    } else {
-        value &= 7;
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+        if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
+            /* Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
+             * using Long-desciptor translation table format */
+            value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
+        } else if (arm_feature(env, ARM_FEATURE_EL3)) {
+            /* In an implementation that includes the Security Extensions
+             * TTBCR has additional fields PD0 [4] and PD1 [5] for
+             * Short-descriptor translation table format.
+             */
+            value &= TTBCR_PD1 | TTBCR_PD0 | TTBCR_N;
+        } else {
+            value &= TTBCR_N;
+        }
     }
+
     /* Note that we always calculate c2_mask and c2_base_mask, but
      * they are only used for short-descriptor tables (ie if EAE is 0);
      * for long-descriptor tables the TTBCR fields are used differently
@@ -3540,17 +3551,24 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
   }
 }
 
-static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
+static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
+                                         uint32_t address)
 {
-    uint32_t table;
-
-    if (address & env->cp15.c2_mask)
-        table = env->cp15.ttbr1_el1 & 0xffffc000;
-    else
-        table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
-
-    table |= (address >> 18) & 0x3ffc;
-    return table;
+    if (address & env->cp15.c2_mask) {
+        if ((env->cp15.c2_control & TTBCR_PD1)) {
+            /* Translation table walk disabled for TTBR1 */
+            return false;
+        }
+        *table = env->cp15.ttbr1_el1 & 0xffffc000;
+    } else {
+        if ((env->cp15.c2_control & TTBCR_PD0)) {
+            /* Translation table walk disabled for TTBR0 */
+            return false;
+        }
+        *table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
+    }
+    *table |= (address >> 18) & 0x3ffc;
+    return true;
 }
 
 static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
@@ -3569,7 +3587,11 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
 
     /* Pagetable walk.  */
     /* Lookup l1 descriptor.  */
-    table = get_level1_table_address(env, address);
+    if (!get_level1_table_address(env, &table, address)) {
+        /* Section translation fault if page walk is disabled by PD0 or PD1 */
+        code = 5;
+        goto do_fault;
+    }
     desc = ldl_phys(cs->as, table);
     type = (desc & 3);
     domain = (desc >> 5) & 0x0f;
@@ -3667,7 +3689,11 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 
     /* Pagetable walk.  */
     /* Lookup l1 descriptor.  */
-    table = get_level1_table_address(env, address);
+    if (!get_level1_table_address(env, &table, address)) {
+        /* Section translation fault if page walk is disabled by PD0 or PD1 */
+        code = 5;
+        goto do_fault;
+    }
     desc = ldl_phys(cs->as, table);
     type = (desc & 3);
     if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
  2014-06-05 10:39 [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR Fabian Aggeler
@ 2014-06-05 13:41 ` Greg Bellows
  2014-06-09 11:27 ` Peter Maydell
  1 sibling, 0 replies; 8+ messages in thread
From: Greg Bellows @ 2014-06-05 13:41 UTC (permalink / raw)
  To: Fabian Aggeler; +Cc: Peter Maydell, QEMU Developers

[-- Attachment #1: Type: text/plain, Size: 6111 bytes --]

Reviewed by: Greg Bellows <greg.bellows@linaro.org>


On 5 June 2014 05:39, Fabian Aggeler <aggelerf@ethz.ch> wrote:

> Corrected handling of writes to TTBCR for ARMv8 (previously UNK/SBZP
> bits are not RES0) and ARMv7 (new bits PD0/PD1 for CPUs with Security
> Extensions).
>
> Bits PD0/PD1 are now respected in get_phys_addr_v6/v5() and
> get_level1_table_address.
>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> ---
> v1 -> v2:
> * dropped changes in get_phys_addr_lpae()
> * simplified get_level1_table_address as suggested
> * fixed checkpath issues
>
> v1: http://lists.gnu.org/archive/html/qemu-devel/2014-05/msg06590.html
>
>  target-arm/cpu.h    | 16 ++++++++++++++
>  target-arm/helper.c | 60
> ++++++++++++++++++++++++++++++++++++++---------------
>  2 files changed, 59 insertions(+), 17 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 8d04385..b0e8b0c 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -430,6 +430,22 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr
> address, int rw,
>  /* Execution state bits.  MRS read as zero, MSR writes ignored.  */
>  #define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J)
>
> +#define TTBCR_N      (7U << 0) /* TTBCR.EAE==0 */
> +#define TTBCR_T0SZ   (7U << 0) /* TTBCR.EAE==1 */
> +#define TTBCR_PD0    (1U << 4)
> +#define TTBCR_PD1    (1U << 5)
> +#define TTBCR_EPD0   (1U << 7)
> +#define TTBCR_IRGN0  (3U << 8)
> +#define TTBCR_ORGN0  (3U << 10)
> +#define TTBCR_SH0    (3U << 12)
> +#define TTBCR_T1SZ   (3U << 16)
> +#define TTBCR_A1     (1U << 22)
> +#define TTBCR_EPD1   (1U << 23)
> +#define TTBCR_IRGN1  (3U << 24)
> +#define TTBCR_ORGN1  (3U << 26)
> +#define TTBCR_SH1    (1U << 28)
> +#define TTBCR_EAE    (1U << 31)
> +
>  /* Bit definitions for ARMv8 SPSR (PSTATE) format.
>   * Only these are valid when in AArch64 mode; in
>   * AArch32 mode SPSRs are basically CPSR-format.
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index ec031f5..0b2ebc3 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -312,7 +312,7 @@ static inline bool
> extended_addresses_enabled(CPUARMState *env)
>  {
>      return arm_el_is_aa64(env, 1)
>          || ((arm_feature(env, ARM_FEATURE_LPAE)
> -             && (env->cp15.c2_control & (1U << 31))));
> +             && (env->cp15.c2_control & TTBCR_EAE)));
>  }
>
>  static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t
> value)
> @@ -1413,11 +1413,22 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env,
> const ARMCPRegInfo *ri,
>  {
>      int maskshift = extract32(value, 0, 3);
>
> -    if (arm_feature(env, ARM_FEATURE_LPAE) && (value & (1 << 31))) {
> -        value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
> -    } else {
> -        value &= 7;
> +    if (!arm_feature(env, ARM_FEATURE_V8)) {
> +        if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
> +            /* Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
> +             * using Long-desciptor translation table format */
> +            value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
> +        } else if (arm_feature(env, ARM_FEATURE_EL3)) {
> +            /* In an implementation that includes the Security Extensions
> +             * TTBCR has additional fields PD0 [4] and PD1 [5] for
> +             * Short-descriptor translation table format.
> +             */
> +            value &= TTBCR_PD1 | TTBCR_PD0 | TTBCR_N;
> +        } else {
> +            value &= TTBCR_N;
> +        }
>      }
> +
>      /* Note that we always calculate c2_mask and c2_base_mask, but
>       * they are only used for short-descriptor tables (ie if EAE is 0);
>       * for long-descriptor tables the TTBCR fields are used differently
> @@ -3540,17 +3551,24 @@ static inline int check_ap(CPUARMState *env, int
> ap, int domain_prot,
>    }
>  }
>
> -static uint32_t get_level1_table_address(CPUARMState *env, uint32_t
> address)
> +static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
> +                                         uint32_t address)
>  {
> -    uint32_t table;
> -
> -    if (address & env->cp15.c2_mask)
> -        table = env->cp15.ttbr1_el1 & 0xffffc000;
> -    else
> -        table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
> -
> -    table |= (address >> 18) & 0x3ffc;
> -    return table;
> +    if (address & env->cp15.c2_mask) {
> +        if ((env->cp15.c2_control & TTBCR_PD1)) {
> +            /* Translation table walk disabled for TTBR1 */
> +            return false;
> +        }
> +        *table = env->cp15.ttbr1_el1 & 0xffffc000;
> +    } else {
> +        if ((env->cp15.c2_control & TTBCR_PD0)) {
> +            /* Translation table walk disabled for TTBR0 */
> +            return false;
> +        }
> +        *table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
> +    }
> +    *table |= (address >> 18) & 0x3ffc;
> +    return true;
>  }
>
>  static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int
> access_type,
> @@ -3569,7 +3587,11 @@ static int get_phys_addr_v5(CPUARMState *env,
> uint32_t address, int access_type,
>
>      /* Pagetable walk.  */
>      /* Lookup l1 descriptor.  */
> -    table = get_level1_table_address(env, address);
> +    if (!get_level1_table_address(env, &table, address)) {
> +        /* Section translation fault if page walk is disabled by PD0 or
> PD1 */
> +        code = 5;
> +        goto do_fault;
> +    }
>      desc = ldl_phys(cs->as, table);
>      type = (desc & 3);
>      domain = (desc >> 5) & 0x0f;
> @@ -3667,7 +3689,11 @@ static int get_phys_addr_v6(CPUARMState *env,
> uint32_t address, int access_type,
>
>      /* Pagetable walk.  */
>      /* Lookup l1 descriptor.  */
> -    table = get_level1_table_address(env, address);
> +    if (!get_level1_table_address(env, &table, address)) {
> +        /* Section translation fault if page walk is disabled by PD0 or
> PD1 */
> +        code = 5;
> +        goto do_fault;
> +    }
>      desc = ldl_phys(cs->as, table);
>      type = (desc & 3);
>      if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
> --
> 1.8.3.2
>
>

[-- Attachment #2: Type: text/html, Size: 7857 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
  2014-06-05 10:39 [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR Fabian Aggeler
  2014-06-05 13:41 ` Greg Bellows
@ 2014-06-09 11:27 ` Peter Maydell
  2014-06-09 15:18   ` Peter Maydell
  1 sibling, 1 reply; 8+ messages in thread
From: Peter Maydell @ 2014-06-09 11:27 UTC (permalink / raw)
  To: Fabian Aggeler; +Cc: QEMU Developers, Greg Bellows

On 5 June 2014 11:39, Fabian Aggeler <aggelerf@ethz.ch> wrote:
> Corrected handling of writes to TTBCR for ARMv8 (previously UNK/SBZP
> bits are not RES0) and ARMv7 (new bits PD0/PD1 for CPUs with Security
> Extensions).
>
> Bits PD0/PD1 are now respected in get_phys_addr_v6/v5() and
> get_level1_table_address.
>
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>

Applied to target-arm.next.

> -static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
> +static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
> +                                         uint32_t address)

(I tidied up this line so the 'uint32_t' lines up with the
'CPUARMState' on the previous line.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
  2014-06-09 11:27 ` Peter Maydell
@ 2014-06-09 15:18   ` Peter Maydell
  2014-06-10 14:06     ` Aggeler  Fabian
  0 siblings, 1 reply; 8+ messages in thread
From: Peter Maydell @ 2014-06-09 15:18 UTC (permalink / raw)
  To: Fabian Aggeler; +Cc: QEMU Developers, Greg Bellows

On 9 June 2014 12:27, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 5 June 2014 11:39, Fabian Aggeler <aggelerf@ethz.ch> wrote:
>> Corrected handling of writes to TTBCR for ARMv8 (previously UNK/SBZP
>> bits are not RES0) and ARMv7 (new bits PD0/PD1 for CPUs with Security
>> Extensions).
>>
>> Bits PD0/PD1 are now respected in get_phys_addr_v6/v5() and
>> get_level1_table_address.
>>
>> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
>
> Applied to target-arm.next.

Unapplied -- the 'goto do_fault' codepaths in get_phys_addr_v5()
end up using 'domain' in constructing the returned fault status
code without ever initialising it.

Since this is a first level Translation fault, the DFSR Domain
field is UNKNOWN, so it should be sufficient to set it to 0.
You might as well just set it to 0 when it's defined at the top
of the function, as get_phys_addr_v6() does.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
  2014-06-09 15:18   ` Peter Maydell
@ 2014-06-10 14:06     ` Aggeler  Fabian
  0 siblings, 0 replies; 8+ messages in thread
From: Aggeler  Fabian @ 2014-06-10 14:06 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Greg Bellows


On 09 Jun 2014, at 17:18, Peter Maydell <peter.maydell@linaro.org> wrote:

> On 9 June 2014 12:27, Peter Maydell <peter.maydell@linaro.org> wrote:
>> On 5 June 2014 11:39, Fabian Aggeler <aggelerf@ethz.ch> wrote:
>>> Corrected handling of writes to TTBCR for ARMv8 (previously UNK/SBZP
>>> bits are not RES0) and ARMv7 (new bits PD0/PD1 for CPUs with Security
>>> Extensions).
>>> 
>>> Bits PD0/PD1 are now respected in get_phys_addr_v6/v5() and
>>> get_level1_table_address.
>>> 
>>> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
>> 
>> Applied to target-arm.next.
> 
> Unapplied -- the 'goto do_fault' codepaths in get_phys_addr_v5()
> end up using 'domain' in constructing the returned fault status
> code without ever initialising it.
> 
> Since this is a first level Translation fault, the DFSR Domain
> field is UNKNOWN, so it should be sufficient to set it to 0.
> You might as well just set it to 0 when it's defined at the top
> of the function, as get_phys_addr_v6() does.
> 
> thanks
> -- PMM

Thanks, I will send a v3 with domain initialised.

Fabian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
  2014-06-10 17:00 ` Aggeler  Fabian
@ 2014-06-10 17:27   ` Peter Maydell
  0 siblings, 0 replies; 8+ messages in thread
From: Peter Maydell @ 2014-06-10 17:27 UTC (permalink / raw)
  To: Aggeler Fabian; +Cc: qemu-devel, greg.bellows

On 10 June 2014 18:00, Aggeler  Fabian <aggelerf@student.ethz.ch> wrote:
> Obviously not v2 but v3 (subject). Sorry for that, please ignore it as I am going to resend.

You don't need to resend just for that. Applied to target-arm.next.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
  2014-06-10 14:12 Fabian Aggeler
@ 2014-06-10 17:00 ` Aggeler  Fabian
  2014-06-10 17:27   ` Peter Maydell
  0 siblings, 1 reply; 8+ messages in thread
From: Aggeler  Fabian @ 2014-06-10 17:00 UTC (permalink / raw)
  To: Aggeler Fabian; +Cc: peter.maydell, qemu-devel, greg.bellows

Obviously not v2 but v3 (subject). Sorry for that, please ignore it as I am going to resend.

Regards,
Fabian

On 10 Jun 2014, at 16:12, Fabian Aggeler <aggelerf@ethz.ch> wrote:

> Corrected handling of writes to TTBCR for ARMv8 (previously UNK/SBZP
> bits are not RES0) and ARMv7 (new bits PD0/PD1 for CPUs with Security
> Extensions).
> 
> Bits PD0/PD1 are now respected in get_phys_addr_v6/v5() and
> get_level1_table_address.
> 
> Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
> ---
> v2 -> v3:
> * rebased
> * initializing domain in get_phys_addr_v5() as done in get_phys_addr_v6()
> 
> v2: http://lists.gnu.org/archive/html/qemu-devel/2014-06/msg01197.html
> 
> target-arm/cpu.h    | 16 ++++++++++++++
> target-arm/helper.c | 62 +++++++++++++++++++++++++++++++++++++----------------
> 2 files changed, 60 insertions(+), 18 deletions(-)
> 
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 79e7f82..369d472 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -430,6 +430,22 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
> /* Execution state bits.  MRS read as zero, MSR writes ignored.  */
> #define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J)
> 
> +#define TTBCR_N      (7U << 0) /* TTBCR.EAE==0 */
> +#define TTBCR_T0SZ   (7U << 0) /* TTBCR.EAE==1 */
> +#define TTBCR_PD0    (1U << 4)
> +#define TTBCR_PD1    (1U << 5)
> +#define TTBCR_EPD0   (1U << 7)
> +#define TTBCR_IRGN0  (3U << 8)
> +#define TTBCR_ORGN0  (3U << 10)
> +#define TTBCR_SH0    (3U << 12)
> +#define TTBCR_T1SZ   (3U << 16)
> +#define TTBCR_A1     (1U << 22)
> +#define TTBCR_EPD1   (1U << 23)
> +#define TTBCR_IRGN1  (3U << 24)
> +#define TTBCR_ORGN1  (3U << 26)
> +#define TTBCR_SH1    (1U << 28)
> +#define TTBCR_EAE    (1U << 31)
> +
> /* Bit definitions for ARMv8 SPSR (PSTATE) format.
>  * Only these are valid when in AArch64 mode; in
>  * AArch32 mode SPSRs are basically CPSR-format.
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 050c409..12285cd 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -312,7 +312,7 @@ static inline bool extended_addresses_enabled(CPUARMState *env)
> {
>     return arm_el_is_aa64(env, 1)
>         || ((arm_feature(env, ARM_FEATURE_LPAE)
> -             && (env->cp15.c2_control & (1U << 31))));
> +             && (env->cp15.c2_control & TTBCR_EAE)));
> }
> 
> static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
> @@ -1413,11 +1413,22 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
> {
>     int maskshift = extract32(value, 0, 3);
> 
> -    if (arm_feature(env, ARM_FEATURE_LPAE) && (value & (1 << 31))) {
> -        value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
> -    } else {
> -        value &= 7;
> +    if (!arm_feature(env, ARM_FEATURE_V8)) {
> +        if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
> +            /* Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
> +             * using Long-desciptor translation table format */
> +            value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
> +        } else if (arm_feature(env, ARM_FEATURE_EL3)) {
> +            /* In an implementation that includes the Security Extensions
> +             * TTBCR has additional fields PD0 [4] and PD1 [5] for
> +             * Short-descriptor translation table format.
> +             */
> +            value &= TTBCR_PD1 | TTBCR_PD0 | TTBCR_N;
> +        } else {
> +            value &= TTBCR_N;
> +        }
>     }
> +
>     /* Note that we always calculate c2_mask and c2_base_mask, but
>      * they are only used for short-descriptor tables (ie if EAE is 0);
>      * for long-descriptor tables the TTBCR fields are used differently
> @@ -3540,17 +3551,24 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
>   }
> }
> 
> -static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
> +static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
> +                                         uint32_t address)
> {
> -    uint32_t table;
> -
> -    if (address & env->cp15.c2_mask)
> -        table = env->cp15.ttbr1_el1 & 0xffffc000;
> -    else
> -        table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
> -
> -    table |= (address >> 18) & 0x3ffc;
> -    return table;
> +    if (address & env->cp15.c2_mask) {
> +        if ((env->cp15.c2_control & TTBCR_PD1)) {
> +            /* Translation table walk disabled for TTBR1 */
> +            return false;
> +        }
> +        *table = env->cp15.ttbr1_el1 & 0xffffc000;
> +    } else {
> +        if ((env->cp15.c2_control & TTBCR_PD0)) {
> +            /* Translation table walk disabled for TTBR0 */
> +            return false;
> +        }
> +        *table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
> +    }
> +    *table |= (address >> 18) & 0x3ffc;
> +    return true;
> }
> 
> static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
> @@ -3563,13 +3581,17 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
>     uint32_t desc;
>     int type;
>     int ap;
> -    int domain;
> +    int domain = 0;
>     int domain_prot;
>     hwaddr phys_addr;
> 
>     /* Pagetable walk.  */
>     /* Lookup l1 descriptor.  */
> -    table = get_level1_table_address(env, address);
> +    if (!get_level1_table_address(env, &table, address)) {
> +        /* Section translation fault if page walk is disabled by PD0 or PD1 */
> +        code = 5;
> +        goto do_fault;
> +    }
>     desc = ldl_phys(cs->as, table);
>     type = (desc & 3);
>     domain = (desc >> 5) & 0x0f;
> @@ -3667,7 +3689,11 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
> 
>     /* Pagetable walk.  */
>     /* Lookup l1 descriptor.  */
> -    table = get_level1_table_address(env, address);
> +    if (!get_level1_table_address(env, &table, address)) {
> +        /* Section translation fault if page walk is disabled by PD0 or PD1 */
> +        code = 5;
> +        goto do_fault;
> +    }
>     desc = ldl_phys(cs->as, table);
>     type = (desc & 3);
>     if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
> -- 
> 1.8.3.2
> 
> 
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR
@ 2014-06-10 14:12 Fabian Aggeler
  2014-06-10 17:00 ` Aggeler  Fabian
  0 siblings, 1 reply; 8+ messages in thread
From: Fabian Aggeler @ 2014-06-10 14:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, greg.bellows

Corrected handling of writes to TTBCR for ARMv8 (previously UNK/SBZP
bits are not RES0) and ARMv7 (new bits PD0/PD1 for CPUs with Security
Extensions).

Bits PD0/PD1 are now respected in get_phys_addr_v6/v5() and
get_level1_table_address.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
---
v2 -> v3:
* rebased
* initializing domain in get_phys_addr_v5() as done in get_phys_addr_v6()

v2: http://lists.gnu.org/archive/html/qemu-devel/2014-06/msg01197.html

 target-arm/cpu.h    | 16 ++++++++++++++
 target-arm/helper.c | 62 +++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 79e7f82..369d472 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -430,6 +430,22 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 /* Execution state bits.  MRS read as zero, MSR writes ignored.  */
 #define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J)
 
+#define TTBCR_N      (7U << 0) /* TTBCR.EAE==0 */
+#define TTBCR_T0SZ   (7U << 0) /* TTBCR.EAE==1 */
+#define TTBCR_PD0    (1U << 4)
+#define TTBCR_PD1    (1U << 5)
+#define TTBCR_EPD0   (1U << 7)
+#define TTBCR_IRGN0  (3U << 8)
+#define TTBCR_ORGN0  (3U << 10)
+#define TTBCR_SH0    (3U << 12)
+#define TTBCR_T1SZ   (3U << 16)
+#define TTBCR_A1     (1U << 22)
+#define TTBCR_EPD1   (1U << 23)
+#define TTBCR_IRGN1  (3U << 24)
+#define TTBCR_ORGN1  (3U << 26)
+#define TTBCR_SH1    (1U << 28)
+#define TTBCR_EAE    (1U << 31)
+
 /* Bit definitions for ARMv8 SPSR (PSTATE) format.
  * Only these are valid when in AArch64 mode; in
  * AArch32 mode SPSRs are basically CPSR-format.
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 050c409..12285cd 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -312,7 +312,7 @@ static inline bool extended_addresses_enabled(CPUARMState *env)
 {
     return arm_el_is_aa64(env, 1)
         || ((arm_feature(env, ARM_FEATURE_LPAE)
-             && (env->cp15.c2_control & (1U << 31))));
+             && (env->cp15.c2_control & TTBCR_EAE)));
 }
 
 static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
@@ -1413,11 +1413,22 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     int maskshift = extract32(value, 0, 3);
 
-    if (arm_feature(env, ARM_FEATURE_LPAE) && (value & (1 << 31))) {
-        value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
-    } else {
-        value &= 7;
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+        if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
+            /* Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
+             * using Long-desciptor translation table format */
+            value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
+        } else if (arm_feature(env, ARM_FEATURE_EL3)) {
+            /* In an implementation that includes the Security Extensions
+             * TTBCR has additional fields PD0 [4] and PD1 [5] for
+             * Short-descriptor translation table format.
+             */
+            value &= TTBCR_PD1 | TTBCR_PD0 | TTBCR_N;
+        } else {
+            value &= TTBCR_N;
+        }
     }
+
     /* Note that we always calculate c2_mask and c2_base_mask, but
      * they are only used for short-descriptor tables (ie if EAE is 0);
      * for long-descriptor tables the TTBCR fields are used differently
@@ -3540,17 +3551,24 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
   }
 }
 
-static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
+static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
+                                         uint32_t address)
 {
-    uint32_t table;
-
-    if (address & env->cp15.c2_mask)
-        table = env->cp15.ttbr1_el1 & 0xffffc000;
-    else
-        table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
-
-    table |= (address >> 18) & 0x3ffc;
-    return table;
+    if (address & env->cp15.c2_mask) {
+        if ((env->cp15.c2_control & TTBCR_PD1)) {
+            /* Translation table walk disabled for TTBR1 */
+            return false;
+        }
+        *table = env->cp15.ttbr1_el1 & 0xffffc000;
+    } else {
+        if ((env->cp15.c2_control & TTBCR_PD0)) {
+            /* Translation table walk disabled for TTBR0 */
+            return false;
+        }
+        *table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
+    }
+    *table |= (address >> 18) & 0x3ffc;
+    return true;
 }
 
 static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
@@ -3563,13 +3581,17 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
     uint32_t desc;
     int type;
     int ap;
-    int domain;
+    int domain = 0;
     int domain_prot;
     hwaddr phys_addr;
 
     /* Pagetable walk.  */
     /* Lookup l1 descriptor.  */
-    table = get_level1_table_address(env, address);
+    if (!get_level1_table_address(env, &table, address)) {
+        /* Section translation fault if page walk is disabled by PD0 or PD1 */
+        code = 5;
+        goto do_fault;
+    }
     desc = ldl_phys(cs->as, table);
     type = (desc & 3);
     domain = (desc >> 5) & 0x0f;
@@ -3667,7 +3689,11 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 
     /* Pagetable walk.  */
     /* Lookup l1 descriptor.  */
-    table = get_level1_table_address(env, address);
+    if (!get_level1_table_address(env, &table, address)) {
+        /* Section translation fault if page walk is disabled by PD0 or PD1 */
+        code = 5;
+        goto do_fault;
+    }
     desc = ldl_phys(cs->as, table);
     type = (desc & 3);
     if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2014-06-10 17:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-05 10:39 [Qemu-devel] [PATCH v2] target-arm: implement PD0/PD1 bits for TTBCR Fabian Aggeler
2014-06-05 13:41 ` Greg Bellows
2014-06-09 11:27 ` Peter Maydell
2014-06-09 15:18   ` Peter Maydell
2014-06-10 14:06     ` Aggeler  Fabian
2014-06-10 14:12 Fabian Aggeler
2014-06-10 17:00 ` Aggeler  Fabian
2014-06-10 17:27   ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.