From: Mark Langsdorf <mark.langsdorf@calxeda.com>
To: qemu-devel@nongnu.org, paul@codesourcery.com, peter.maydell@linaro.org
Subject: [Qemu-devel] [PATCH 2/9] Add trustzone support.
Date: Tue, 20 Dec 2011 13:10:38 -0600 [thread overview]
Message-ID: <4EF0DDAE.50706@calxeda.com> (raw)
From: juha.riihimaki@nokia.com
Conflicts:
target-arm/cpu.h
target-arm/helper.c
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
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
next reply other threads:[~2011-12-20 19:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-20 19:10 Mark Langsdorf [this message]
2011-12-20 19:38 ` [Qemu-devel] [PATCH 2/9] Add trustzone support Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4EF0DDAE.50706@calxeda.com \
--to=mark.langsdorf@calxeda.com \
--cc=paul@codesourcery.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.