diff mbox

[5/6] ARM: enable ARM_FEATURE_MPU for Cortex-M3/M4

Message ID 704fcca8-e18a-4c36-9c84-f0979ebefa7c@EXCHANGE-3K.hds.local
State New
Headers show

Commit Message

Alex Zuepke July 7, 2015, 6:25 p.m. UTC
Signed-off-by: Alex Zuepke <alexander.zuepke@hs-rm.de>
---
 hw/arm/armv7m.c     |   17 ++++++++++++++++-
 target-arm/cpu.c    |    2 ++
 target-arm/helper.c |   30 ++++++++++++++++++++++++++++--
 3 files changed, 46 insertions(+), 3 deletions(-)
diff mbox

Patch

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index c6eab6d..db6bc3c 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -179,15 +179,30 @@  qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
     int i;
     int big_endian;
     MemoryRegion *hack = g_new(MemoryRegion, 1);
+    ObjectClass *cpu_oc;
+    Error *err = NULL;
 
     if (cpu_model == NULL) {
 	cpu_model = "cortex-m3";
     }
-    cpu = cpu_arm_init(cpu_model);
+    cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
+    cpu = ARM_CPU(object_new(object_class_get_name(cpu_oc)));
     if (cpu == NULL) {
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
+    /* On Cortex-M3/M4, the MPU has 8 windows */
+    object_property_set_int(OBJECT(cpu), 8, "pmsav7-dregion", &err);
+    if (err) {
+        error_report_err(err);
+        exit(1);
+    }
+    object_property_set_bool(OBJECT(cpu), true, "realized", &err);
+    if (err) {
+        error_report_err(err);
+        exit(1);
+    }
+
     env = &cpu->env;
 
     armv7m_bitband_init();
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 80669a6..d8cfbb1 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -832,6 +832,7 @@  static void cortex_m3_initfn(Object *obj)
     ARMCPU *cpu = ARM_CPU(obj);
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_M);
+    set_feature(&cpu->env, ARM_FEATURE_MPU);
     cpu->midr = 0x410fc231;
 }
 
@@ -841,6 +842,7 @@  static void cortex_m4_initfn(Object *obj)
 
     set_feature(&cpu->env, ARM_FEATURE_V7);
     set_feature(&cpu->env, ARM_FEATURE_M);
+    set_feature(&cpu->env, ARM_FEATURE_MPU);
     set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
     cpu->midr = 0x410fc240; /* r0p0 */
 }
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 555bc5f..637dbf6 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5854,6 +5854,26 @@  static inline void get_phys_addr_pmsav7_default(CPUARMState *env,
 
 }
 
+static inline void get_phys_addr_v7m_default(CPUARMState *env,
+                                             ARMMMUIdx mmu_idx,
+                                             int32_t address, int *prot)
+{
+    *prot = PAGE_READ | PAGE_WRITE;
+    switch (address) {
+    case 0xFFFFF000 ... 0xFFFFFFFF:
+        /* the special exception return address memory region is EXEC only */
+        *prot = PAGE_EXEC;
+        break;
+
+    case 0x00000000 ... 0x1FFFFFFF:
+    case 0x20000000 ... 0x3FFFFFFF:
+    case 0x60000000 ... 0x7FFFFFFF:
+    case 0x80000000 ... 0x9FFFFFFF:
+        *prot |= PAGE_EXEC;
+        break;
+    }
+}
+
 static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
                                  int access_type, ARMMMUIdx mmu_idx,
                                  hwaddr *phys_ptr, int *prot, uint32_t *fsr)
@@ -5866,7 +5886,10 @@  static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
     *prot = 0;
 
     if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */
-        get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
+        if (arm_feature(env, ARM_FEATURE_M))
+            get_phys_addr_v7m_default(env, mmu_idx, address, prot);
+        else
+            get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
     } else { /* MPU enabled */
         for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
             /* region search */
@@ -5944,7 +5967,10 @@  static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
                 *fsr = 0;
                 return true;
             }
-            get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
+            if (arm_feature(env, ARM_FEATURE_M))
+                get_phys_addr_v7m_default(env, mmu_idx, address, prot);
+            else
+                get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
         } else { /* a MPU hit! */
             uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3);