qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]