[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/9] Add trustzone support.
From: |
Mark Langsdorf |
Subject: |
[Qemu-devel] [PATCH 2/9] Add trustzone support. |
Date: |
Tue, 20 Dec 2011 13:10:38 -0600 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:8.0) Gecko/20111124 Thunderbird/8.0 |
From: address@hidden
Conflicts:
target-arm/cpu.h
target-arm/helper.c
Signed-off-by: Mark Langsdorf <address@hidden>
---
target-arm/cpu.h | 4 +
target-arm/helper.c | 556
+++++++++++++++++++++++++++++---------------------
target-arm/machine.c | 6 +
3 files changed, 335 insertions(+), 231 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c4d742f..129edbb 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -116,6 +116,9 @@ typedef struct CPUARMState {
uint32_t c1_sys; /* System control register. */
uint32_t c1_coproc; /* Coprocessor access register. */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
+ uint32_t c1_secfg; /* Secure configuration register. */
+ uint32_t c1_sedbg; /* Secure debug enable register. */
+ uint32_t c1_nseac; /* Non-secure access control register. */
uint32_t c2_base0; /* MMU translation table base 0. */
uint32_t c2_base1; /* MMU translation table base 1. */
uint32_t c2_control; /* MMU translation table base control. */
@@ -377,6 +380,7 @@ enum arm_features {
ARM_FEATURE_VAPA, /* cp15 VA to PA lookups */
ARM_FEATURE_ARM_DIV, /* divide supported in ARM encoding */
ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */
+ ARM_FEATURE_TRUSTZONE /* TrustZone Security Extensions. */
};
static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 65f4fbf..816c4c4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -124,6 +124,7 @@ static void cpu_reset_model_id(CPUARMState *env,
uint32_t id)
set_feature(env, ARM_FEATURE_VFP3);
set_feature(env, ARM_FEATURE_NEON);
set_feature(env, ARM_FEATURE_THUMB2EE);
+ set_feature(env, ARM_FEATURE_TRUSTZONE);
env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0;
env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100;
@@ -147,6 +148,7 @@ static void cpu_reset_model_id(CPUARMState *env,
uint32_t id)
* and valid configurations; we don't model A9UP).
*/
set_feature(env, ARM_FEATURE_V7MP);
+ set_feature(env, ARM_FEATURE_TRUSTZONE);
env->vfp.xregs[ARM_VFP_FPSID] = 0x41034000; /* Guess */
env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
env->vfp.xregs[ARM_VFP_MVFR1] = 0x01111111;
@@ -1000,7 +1002,7 @@ static uint32_t get_level1_table_address(CPUState
*env, uint32_t address)
}
static int get_phys_addr_v5(CPUState *env, uint32_t address, int
access_type,
- int is_user, uint32_t *phys_ptr, int *prot,
+ int is_user, uint32_t *phys_ptr, int *prot,
target_ulong *page_size)
{
int code;
@@ -1039,13 +1041,13 @@ static int get_phys_addr_v5(CPUState *env,
uint32_t address, int access_type,
*page_size = 1024 * 1024;
} else {
/* Lookup l2 entry. */
- if (type == 1) {
- /* Coarse pagetable. */
- table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
- } else {
- /* Fine pagetable. */
- table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
- }
+ if (type == 1) {
+ /* Coarse pagetable. */
+ table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
+ } else {
+ /* Fine pagetable. */
+ table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
+ }
desc = ldl_phys(table);
switch (desc & 3) {
case 0: /* Page translation fault. */
@@ -1062,17 +1064,17 @@ static int get_phys_addr_v5(CPUState *env,
uint32_t address, int access_type,
*page_size = 0x1000;
break;
case 3: /* 1k page. */
- if (type == 1) {
- if (arm_feature(env, ARM_FEATURE_XSCALE)) {
- phys_addr = (desc & 0xfffff000) | (address & 0xfff);
- } else {
- /* Page translation fault. */
- code = 7;
- goto do_fault;
- }
- } else {
- phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
- }
+ if (type == 1) {
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+ phys_addr = (desc & 0xfffff000) | (address & 0xfff);
+ } else {
+ /* Page translation fault. */
+ code = 7;
+ goto do_fault;
+ }
+ } else {
+ phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
+ }
ap = (desc >> 4) & 3;
*page_size = 0x400;
break;
@@ -1095,7 +1097,7 @@ do_fault:
}
static int get_phys_addr_v6(CPUState *env, uint32_t address, int
access_type,
- int is_user, uint32_t *phys_ptr, int *prot,
+ int is_user, uint32_t *phys_ptr, int *prot,
target_ulong *page_size)
{
int code;
@@ -1113,7 +1115,7 @@ static int get_phys_addr_v6(CPUState *env,
uint32_t address, int access_type,
table = get_level1_table_address(env, address);
desc = ldl_phys(table);
type = (desc & 3);
- if (type == 0) {
+ if (type == 0 || type == 3) {
/* Section translation fault. */
code = 5;
domain = 0;
@@ -1199,7 +1201,7 @@ do_fault:
}
static int get_phys_addr_mpu(CPUState *env, uint32_t address, int
access_type,
- int is_user, uint32_t *phys_ptr, int *prot)
+ int is_user, uint32_t *phys_ptr, int *prot)
{
int n;
uint32_t mask;
@@ -1207,52 +1209,58 @@ static int get_phys_addr_mpu(CPUState *env,
uint32_t address, int access_type,
*phys_ptr = address;
for (n = 7; n >= 0; n--) {
- base = env->cp15.c6_region[n];
- if ((base & 1) == 0)
- continue;
- mask = 1 << ((base >> 1) & 0x1f);
- /* Keep this shift separate from the above to avoid an
- (undefined) << 32. */
- mask = (mask << 1) - 1;
- if (((base ^ address) & ~mask) == 0)
- break;
- }
- if (n < 0)
- return 2;
+ base = env->cp15.c6_region[n];
+ if ((base & 1) == 0) {
+ continue;
+ }
+ mask = 1 << ((base >> 1) & 0x1f);
+ /* Keep this shift separate from the above to avoid an
+ (undefined) << 32. */
+ mask = (mask << 1) - 1;
+ if (((base ^ address) & ~mask) == 0) {
+ break;
+ }
+ }
+ if (n < 0) {
+ return 2;
+ }
if (access_type == 2) {
- mask = env->cp15.c5_insn;
+ mask = env->cp15.c5_insn;
} else {
- mask = env->cp15.c5_data;
+ mask = env->cp15.c5_data;
}
mask = (mask >> (n * 4)) & 0xf;
switch (mask) {
case 0:
- return 1;
+ return 1;
case 1:
- if (is_user)
- return 1;
- *prot = PAGE_READ | PAGE_WRITE;
- break;
+ if (is_user) {
+ return 1;
+ }
+ *prot = PAGE_READ | PAGE_WRITE;
+ break;
case 2:
- *prot = PAGE_READ;
- if (!is_user)
- *prot |= PAGE_WRITE;
- break;
+ *prot = PAGE_READ;
+ if (!is_user) {
+ *prot |= PAGE_WRITE;
+ }
+ break;
case 3:
- *prot = PAGE_READ | PAGE_WRITE;
- break;
+ *prot = PAGE_READ | PAGE_WRITE;
+ break;
case 5:
- if (is_user)
- return 1;
- *prot = PAGE_READ;
- break;
+ if (is_user) {
+ return 1;
+ }
+ *prot = PAGE_READ;
+ break;
case 6:
- *prot = PAGE_READ;
- break;
+ *prot = PAGE_READ;
+ break;
default:
- /* Bad permission. */
- return 1;
+ /* Bad permission. */
+ return 1;
}
*prot |= PAGE_EXEC;
return 0;
@@ -1264,8 +1272,9 @@ static inline int get_phys_addr(CPUState *env,
uint32_t address,
target_ulong *page_size)
{
/* Fast Context Switch Extension. */
- if (address < 0x02000000)
+ if (address < 0x02000000) {
address += env->cp15.c13_fcse;
+ }
if ((env->cp15.c1_sys & 1) == 0) {
/* MMU/MPU disabled. */
@@ -1275,8 +1284,8 @@ static inline int get_phys_addr(CPUState *env,
uint32_t address,
return 0;
} else if (arm_feature(env, ARM_FEATURE_MPU)) {
*page_size = TARGET_PAGE_SIZE;
- return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
- prot);
+ return get_phys_addr_mpu(env, address, access_type, is_user,
phys_ptr,
+ prot);
} else if (env->cp15.c1_sys & (1 << 23)) {
return get_phys_addr_v6(env, address, access_type, is_user,
phys_ptr,
prot, page_size);
@@ -1328,9 +1337,9 @@ target_phys_addr_t
cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot, &page_size);
- if (ret != 0)
+ if (ret != 0) {
return -1;
-
+ }
return phys_addr;
}
@@ -1341,9 +1350,10 @@ void HELPER(set_cp)(CPUState *env, uint32_t insn,
uint32_t val)
int src = (insn >> 16) & 0xf;
int operand = insn & 0xf;
- if (env->cp[cp_num].cp_write)
+ if (env->cp[cp_num].cp_write) {
env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
cp_info, src, operand, val);
+ }
}
uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
@@ -1353,9 +1363,10 @@ uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
int dest = (insn >> 16) & 0xf;
int operand = insn & 0xf;
- if (env->cp[cp_num].cp_read)
+ if (env->cp[cp_num].cp_read) {
return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
cp_info, dest, operand);
+ }
return 0;
}
@@ -1401,10 +1412,12 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
switch ((insn >> 16) & 0xf) {
case 0:
/* ID codes. */
- if (arm_feature(env, ARM_FEATURE_XSCALE))
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
break;
- if (arm_feature(env, ARM_FEATURE_OMAPCP))
+ }
+ if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
break;
+ }
if (arm_feature(env, ARM_FEATURE_V7)
&& op1 == 2 && crm == 0 && op2 == 0) {
env->cp15.c0_cssel = val & 0xf;
@@ -1412,17 +1425,21 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
}
goto bad_reg;
case 1: /* System configuration. */
- if (arm_feature(env, ARM_FEATURE_OMAPCP))
+ switch (crm) {
+ case 0:
+ if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
op2 = 0;
+ }
switch (op2) {
case 0:
- if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
+ if (!arm_feature(env, ARM_FEATURE_XSCALE)) {
env->cp15.c1_sys = val;
+ }
/* ??? Lots of these bits are not implemented. */
/* This may enable/disable the MMU, so do a TLB flush. */
tlb_flush(env, 1);
break;
- case 1: /* Auxiliary control register. */
+ case 1: /* Auxiliary cotrol register. */
if (arm_feature(env, ARM_FEATURE_XSCALE)) {
env->cp15.c1_xscaleauxcr = val;
break;
@@ -1430,8 +1447,9 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
/* Not implemented. */
break;
case 2:
- if (arm_feature(env, ARM_FEATURE_XSCALE))
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
goto bad_reg;
+ }
if (env->cp15.c1_coproc != val) {
env->cp15.c1_coproc = val;
/* ??? Is this safe when called from within a TB? */
@@ -1442,6 +1460,38 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
goto bad_reg;
}
break;
+ case 1:
+ if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)
+ || (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
+ goto bad_reg;
+ }
+ switch (op2) {
+ case 0: /* Secure configuration register. */
+ if (env->cp15.c1_secfg & 1) {
+ goto bad_reg;
+ }
+ env->cp15.c1_secfg = val;
+ break;
+ case 1: /* Secure debug enable register. */
+ if (env->cp15.c1_secfg & 1) {
+ goto bad_reg;
+ }
+ env->cp15.c1_sedbg = val;
+ break;
+ case 2: /* Nonsecure access control register. */
+ if (env->cp15.c1_secfg & 1) {
+ goto bad_reg;
+ }
+ env->cp15.c1_nseac = val;
+ break;
+ default:
+ goto bad_reg;
+ }
+ break;
+ default:
+ goto bad_reg;
+ }
+ break;
case 2: /* MMU Page table control / MPU cache control. */
if (arm_feature(env, ARM_FEATURE_MPU)) {
switch (op2) {
@@ -1455,22 +1505,22 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
goto bad_reg;
}
} else {
- switch (op2) {
- case 0:
- env->cp15.c2_base0 = val;
- break;
- case 1:
- env->cp15.c2_base1 = val;
- break;
- case 2:
+ switch (op2) {
+ case 0:
+ env->cp15.c2_base0 = val;
+ break;
+ case 1:
+ env->cp15.c2_base1 = val;
+ break;
+ case 2:
val &= 7;
env->cp15.c2_control = val;
- env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
+ env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> val);
- break;
- default:
- goto bad_reg;
- }
+ break;
+ default:
+ goto bad_reg;
+ }
}
break;
case 3: /* MMU Domain access control / MPU write buffer control. */
@@ -1509,8 +1559,9 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
break;
case 6: /* MMU Fault address / MPU base/size. */
if (arm_feature(env, ARM_FEATURE_MPU)) {
- if (crm >= 8)
+ if (crm >= 8) {
goto bad_reg;
+ }
env->cp15.c6_region[crm] = val;
} else {
if (arm_feature(env, ARM_FEATURE_OMAPCP))
@@ -1544,7 +1595,7 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
env->cp15.c7_par = val & 0xfffff1ff;
}
break;
- case 8: {
+ case 8:
uint32_t phys_addr;
target_ulong page_size;
int prot;
@@ -1572,7 +1623,6 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
}
break;
}
- }
}
break;
case 8: /* MMU TLB control. */
@@ -1595,32 +1645,34 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
}
break;
case 9:
- if (arm_feature(env, ARM_FEATURE_OMAPCP))
+ if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
break;
- if (arm_feature(env, ARM_FEATURE_STRONGARM))
+ }
+ if (arm_feature(env, ARM_FEATURE_STRONGARM)) {
break; /* Ignore ReadBuffer access */
+ }
switch (crm) {
case 0: /* Cache lockdown. */
- switch (op1) {
- case 0: /* L1 cache. */
- switch (op2) {
- case 0:
- env->cp15.c9_data = val;
- break;
- case 1:
- env->cp15.c9_insn = val;
- break;
- default:
- goto bad_reg;
- }
- break;
- case 1: /* L2 cache. */
- /* Ignore writes to L2 lockdown/auxiliary registers. */
- break;
- default:
- goto bad_reg;
- }
- break;
+ switch (op1) {
+ case 0: /* L1 cache. */
+ switch (op2) {
+ case 0:
+ env->cp15.c9_data = val;
+ break;
+ case 1:
+ env->cp15.c9_insn = val;
+ break;
+ default:
+ goto bad_reg;
+ }
+ break;
+ case 1: /* L2 cache. */
+ /* Ignore writes to L2 lockdown/auxiliary registers. */
+ break;
+ default:
+ goto bad_reg;
+ }
+ break;
case 1: /* TCM memory region registers. */
/* Not implemented. */
goto bad_reg;
@@ -1714,15 +1766,17 @@ void HELPER(set_cp15)(CPUState *env, uint32_t
insn, uint32_t val)
/* Unlike real hardware the qemu TLB uses virtual addresses,
not modified virtual addresses, so this causes a TLB flush.
*/
- if (env->cp15.c13_fcse != val)
- tlb_flush(env, 1);
+ if (env->cp15.c13_fcse != val) {
+ tlb_flush(env, 1);
+ }
env->cp15.c13_fcse = val;
break;
case 1:
/* This changes the ASID, so do a TLB flush. */
if (env->cp15.c13_context != val
- && !arm_feature(env, ARM_FEATURE_MPU))
- tlb_flush(env, 0);
+ && !arm_feature(env, ARM_FEATURE_MPU)) {
+ tlb_flush(env, 0);
+ }
env->cp15.c13_context = val;
break;
default:
@@ -1796,7 +1850,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t
insn)
case 0: /* Device ID. */
return env->cp15.c0_cpuid;
case 1: /* Cache Type. */
- return env->cp15.c0_cachetype;
+ return env->cp15.c0_cachetype;
case 2: /* TCM status. */
return 0;
case 3: /* TLB type register. */
@@ -1839,15 +1893,19 @@ uint32_t HELPER(get_cp15)(CPUState *env,
uint32_t insn)
default:
goto bad_reg;
}
+ break;
case 1:
/* These registers aren't documented on arm11 cores. However
Linux looks at them anyway. */
- if (!arm_feature(env, ARM_FEATURE_V6))
+ if (!arm_feature(env, ARM_FEATURE_V6)) {
goto bad_reg;
- if (crm != 0)
+ }
+ if (crm != 0) {
goto bad_reg;
- if (!arm_feature(env, ARM_FEATURE_V7))
+ }
+ if (!arm_feature(env, ARM_FEATURE_V7)) {
return 0;
+ }
switch (op2) {
case 0:
@@ -1859,46 +1917,81 @@ uint32_t HELPER(get_cp15)(CPUState *env,
uint32_t insn)
}
goto bad_reg;
case 2:
- if (op2 != 0 || crm != 0)
+ if (op2 != 0 || crm != 0) {
goto bad_reg;
+ }
return env->cp15.c0_cssel;
default:
goto bad_reg;
}
+ break;
case 1: /* System configuration. */
- if (arm_feature(env, ARM_FEATURE_OMAPCP))
- op2 = 0;
- switch (op2) {
- case 0: /* Control register. */
- return env->cp15.c1_sys;
- case 1: /* Auxiliary control register. */
- if (arm_feature(env, ARM_FEATURE_XSCALE))
- return env->cp15.c1_xscaleauxcr;
- if (!arm_feature(env, ARM_FEATURE_AUXCR))
- goto bad_reg;
- switch (ARM_CPUID(env)) {
- case ARM_CPUID_ARM1026:
- return 1;
- case ARM_CPUID_ARM1136:
- case ARM_CPUID_ARM1136_R2:
- case ARM_CPUID_ARM1176:
- return 7;
- case ARM_CPUID_ARM11MPCORE:
- return 1;
- case ARM_CPUID_CORTEXA8:
- return 2;
- case ARM_CPUID_CORTEXA9:
- return 0;
+ switch (crm) {
+ case 0:
+ if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
+ op2 = 0;
+ }
+ switch (op2) {
+ case 0: /* Control register. */
+ return env->cp15.c1_sys;
+ case 1: /* Auxiliary control register. */
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+ return env->cp15.c1_xscaleauxcr;
+ }
+ if (!arm_feature(env, ARM_FEATURE_AUXCR)) {
+ goto bad_reg;
+ }
+ switch (ARM_CPUID(env)) {
+ case ARM_CPUID_ARM1026:
+ return 1;
+ case ARM_CPUID_ARM1136:
+ case ARM_CPUID_ARM1136_R2:
+ return 7;
+ case ARM_CPUID_ARM11MPCORE:
+ return 1;
+ case ARM_CPUID_CORTEXA8:
+ return 2;
+ case ARM_CPUID_CORTEXA9:
+ return 0;
+ default:
+ goto bad_reg;
+ }
+ break;
+ case 2: /* Coprocessor access register. */
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+ goto bad_reg;
+ }
+ return env->cp15.c1_coproc;
default:
goto bad_reg;
}
- case 2: /* Coprocessor access register. */
- if (arm_feature(env, ARM_FEATURE_XSCALE))
+ break;
+ case 1:
+ if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)
+ || (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
+ goto bad_reg;
+ }
+ switch (op2) {
+ case 0: /* Secure configuration register. */
+ if (env->cp15.c1_secfg & 1) {
+ goto bad_reg;
+ }
+ return env->cp15.c1_secfg;
+ case 1: /* Secure debug enable register. */
+ if (env->cp15.c1_secfg & 1) {
+ goto bad_reg;
+ }
+ return env->cp15.c1_sedbg;
+ case 2: /* Nonsecure access control register. */
+ return env->cp15.c1_nseac;
+ default:
goto bad_reg;
- return env->cp15.c1_coproc;
+ }
+ break;
default:
goto bad_reg;
}
+ break;
case 2: /* MMU Page table control / MPU cache control. */
if (arm_feature(env, ARM_FEATURE_MPU)) {
switch (op2) {
@@ -1912,17 +2005,17 @@ uint32_t HELPER(get_cp15)(CPUState *env,
uint32_t insn)
goto bad_reg;
}
} else {
- switch (op2) {
- case 0:
- return env->cp15.c2_base0;
- case 1:
- return env->cp15.c2_base1;
- case 2:
+ switch (op2) {
+ case 0:
+ return env->cp15.c2_base0;
+ case 1:
+ return env->cp15.c2_base1;
+ case 2:
return env->cp15.c2_control;
- default:
- goto bad_reg;
- }
- }
+ default:
+ goto bad_reg;
+ }
+ }
case 3: /* MMU Domain access control / MPU write buffer control. */
return env->cp15.c3;
case 4: /* Reserved. */
@@ -1932,95 +2025,76 @@ uint32_t HELPER(get_cp15)(CPUState *env,
uint32_t insn)
op2 = 0;
switch (op2) {
case 0:
- if (arm_feature(env, ARM_FEATURE_MPU))
+ if (arm_feature(env, ARM_FEATURE_MPU)) {
return simple_mpu_ap_bits(env->cp15.c5_data);
+ }
return env->cp15.c5_data;
case 1:
- if (arm_feature(env, ARM_FEATURE_MPU))
+ if (arm_feature(env, ARM_FEATURE_MPU)) {
return simple_mpu_ap_bits(env->cp15.c5_data);
+ }
return env->cp15.c5_insn;
case 2:
- if (!arm_feature(env, ARM_FEATURE_MPU))
+ if (!arm_feature(env, ARM_FEATURE_MPU)) {
goto bad_reg;
+ }
return env->cp15.c5_data;
case 3:
- if (!arm_feature(env, ARM_FEATURE_MPU))
+ if (!arm_feature(env, ARM_FEATURE_MPU)) {
goto bad_reg;
+ }
return env->cp15.c5_insn;
default:
goto bad_reg;
}
case 6: /* MMU Fault address. */
if (arm_feature(env, ARM_FEATURE_MPU)) {
- if (crm >= 8)
+ if (crm >= 8) {
goto bad_reg;
+ }
return env->cp15.c6_region[crm];
} else {
if (arm_feature(env, ARM_FEATURE_OMAPCP))
op2 = 0;
- switch (op2) {
- case 0:
- return env->cp15.c6_data;
- case 1:
- if (arm_feature(env, ARM_FEATURE_V6)) {
- /* Watchpoint Fault Adrress. */
- return 0; /* Not implemented. */
- } else {
- /* Instruction Fault Adrress. */
- /* Arm9 doesn't have an IFAR, but implementing it anyway
- shouldn't do any harm. */
- return env->cp15.c6_insn;
- }
- case 2:
- if (arm_feature(env, ARM_FEATURE_V6)) {
- /* Instruction Fault Adrress. */
- return env->cp15.c6_insn;
- } else {
- goto bad_reg;
- }
- default:
- goto bad_reg;
- }
+ switch (op2) {
+ case 0:
+ return env->cp15.c6_data;
+ case 1:
+ if (arm_feature(env, ARM_FEATURE_V6)) {
+ /* Watchpoint Fault Adrress. */
+ return 0; /* Not implemented. */
+ }
+ /* Instruction Fault Adrress. */
+ /* Arm9 doesn't have an IFAR, but implementing it anyway
+ shouldn't do any harm. */
+ return env->cp15.c6_insn;
+ case 2:
+ if (arm_feature(env, ARM_FEATURE_V6)) {
+ /* Instruction Fault Adrress. */
+ return env->cp15.c6_insn;
+ }
+ goto bad_reg;
+ default:
+ goto bad_reg;
+ }
}
case 7: /* Cache control. */
if (crm == 4 && op1 == 0 && op2 == 0) {
return env->cp15.c7_par;
}
- /* FIXME: Should only clear Z flag if destination is r15. */
- env->ZF = 0;
+ /* FIXME this is still totally in the wrong place! */
+ /* clear ZF only if destination is r15 */
+ if (((insn >> 12) & 0xf) == 0xf) {
+ env->ZF = 0;
+ }
return 0;
case 8: /* MMU TLB control. */
goto bad_reg;
- case 9:
- switch (crm) {
- case 0: /* Cache lockdown */
- switch (op1) {
- case 0: /* L1 cache. */
- if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
- return 0;
- }
- switch (op2) {
- case 0:
- return env->cp15.c9_data;
- case 1:
- return env->cp15.c9_insn;
- default:
- goto bad_reg;
- }
- case 1: /* L2 cache */
- if (crm != 0) {
- goto bad_reg;
- }
- /* L2 Lockdown and Auxiliary control. */
+ case 9: /* Cache lockdown. */
+ switch (op1) {
+ case 0: /* L1 cache. */
+ if (arm_feature(env, ARM_FEATURE_OMAPCP))
return 0;
- default:
- goto bad_reg;
- }
- break;
- case 12: /* Performance monitor control */
- if (!arm_feature(env, ARM_FEATURE_V7)) {
- goto bad_reg;
- }
switch (op2) {
case 0: /* performance monitor control register */
return env->cp15.c9_pmcr;
@@ -2071,6 +2145,18 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t
insn)
return 0;
case 11: /* TCM DMA control. */
case 12: /* Reserved. */
+ if (!op1) {
+ switch (crm) {
+ case 0: /* secure or nonsecure vector base address */
+ if (arm_feature(env, ARM_FEATURE_TRUSTZONE)) {
+ /* FIXME: implement true vector base addressing */
+ return 0; /* reset value according to ARM Cortex-A8
TRM */
+ }
+ break;
+ default:
+ break;
+ }
+ }
goto bad_reg;
case 13: /* Process ID. */
switch (op2) {
@@ -2212,10 +2298,11 @@ void HELPER(v7m_msr)(CPUState *env, uint32_t
reg, uint32_t val)
env->v7m.other_sp = val;
break;
case 16: /* PRIMASK */
- if (val & 1)
+ if (val & 1) {
env->uncached_cpsr |= CPSR_I;
- else
+ } else {
env->uncached_cpsr &= ~CPSR_I;
+ }
break;
case 17: /* BASEPRI */
env->v7m.basepri = val & 0xff;
@@ -2226,10 +2313,11 @@ void HELPER(v7m_msr)(CPUState *env, uint32_t
reg, uint32_t val)
env->v7m.basepri = val;
break;
case 19: /* FAULTMASK */
- if (val & 1)
+ if (val & 1) {
env->uncached_cpsr |= CPSR_F;
- else
+ } else {
env->uncached_cpsr &= ~CPSR_F;
+ }
break;
case 20: /* CONTROL */
env->v7m.control = val & 3;
@@ -2271,10 +2359,11 @@ static inline uint16_t add16_sat(uint16_t a,
uint16_t b)
res = a + b;
if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
- if (a & 0x8000)
+ if (a & 0x8000) {
res = 0x8000;
- else
+ } else {
res = 0x7fff;
+ }
}
return res;
}
@@ -2286,10 +2375,11 @@ static inline uint8_t add8_sat(uint8_t a, uint8_t b)
res = a + b;
if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
- if (a & 0x80)
+ if (a & 0x80) {
res = 0x80;
- else
+ } else {
res = 0x7f;
+ }
}
return res;
}
@@ -2301,10 +2391,11 @@ static inline uint16_t sub16_sat(uint16_t a,
uint16_t b)
res = a - b;
if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
- if (a & 0x8000)
+ if (a & 0x8000) {
res = 0x8000;
- else
+ } else {
res = 0x7fff;
+ }
}
return res;
}
@@ -2316,10 +2407,11 @@ static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
res = a - b;
if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
- if (a & 0x80)
+ if (a & 0x80) {
res = 0x80;
- else
+ } else {
res = 0x7f;
+ }
}
return res;
}
@@ -2344,10 +2436,11 @@ static inline uint16_t add16_usat(uint16_t a,
uint16_t b)
static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
{
- if (a > b)
+ if (a > b) {
return a - b;
- else
+ } else {
return 0;
+ }
}
static inline uint8_t add8_usat(uint8_t a, uint8_t b)
@@ -2361,10 +2454,11 @@ static inline uint8_t add8_usat(uint8_t a,
uint8_t b)
static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
{
- if (a > b)
+ if (a > b) {
return a - b;
- else
+ } else {
return 0;
+ }
}
#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
@@ -2468,10 +2562,11 @@ static inline uint8_t sub8_usat(uint8_t a,
uint8_t b)
static inline uint8_t do_usad(uint8_t a, uint8_t b)
{
- if (a > b)
+ if (a > b) {
return a - b;
- else
+ } else {
return b - a;
+ }
}
/* Unsigned sum of absolute byte differences. */
@@ -2925,9 +3020,8 @@ float32 HELPER(recpe_f32)(float32 a, CPUState *env)
f64 = recip_estimate(f64, env);
- val32 = sign
- | ((result_exp & 0xff) << 23)
- | ((float64_val(f64) >> 29) & 0x7fffff);
+ val32 = sign | ((result_exp & 0xff) << 23) |
+ ((float64_val(f64) >> 29) & 0x7fffff);
return make_float32(val32);
}
diff --git a/target-arm/machine.c b/target-arm/machine.c
index aaee9b9..975b522 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -26,6 +26,9 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, env->cp15.c1_sys);
qemu_put_be32(f, env->cp15.c1_coproc);
qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+ qemu_put_be32(f, env->cp15.c1_secfg);
+ qemu_put_be32(f, env->cp15.c1_sedbg);
+ qemu_put_be32(f, env->cp15.c1_nseac);
qemu_put_be32(f, env->cp15.c2_base0);
qemu_put_be32(f, env->cp15.c2_base1);
qemu_put_be32(f, env->cp15.c2_control);
@@ -140,6 +143,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
env->cp15.c1_sys = qemu_get_be32(f);
env->cp15.c1_coproc = qemu_get_be32(f);
env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+ env->cp15.c1_secfg = qemu_get_be32(f);
+ env->cp15.c1_sedbg = qemu_get_be32(f);
+ env->cp15.c1_nseac = qemu_get_be32(f);
env->cp15.c2_base0 = qemu_get_be32(f);
env->cp15.c2_base1 = qemu_get_be32(f);
env->cp15.c2_control = qemu_get_be32(f);
--
1.7.5.4
- [Qemu-devel] [PATCH 2/9] Add trustzone support.,
Mark Langsdorf <=