Fix elf loader range checking
[qemu] / target-sparc / helper.c
index f222e3a..2f41418 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
  */
 #include <stdarg.h>
 #include <stdlib.h>
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <inttypes.h>
 #include <signal.h>
-#include <assert.h>
 
 #include "cpu.h"
 #include "exec-all.h"
@@ -402,12 +401,12 @@ static int get_physical_address_data(CPUState *env,
             mask = 0xffffffffffc00000ULL;
             break;
         }
-        // ctx match, vaddr match?
+        // ctx match, vaddr match, valid?
         if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
-            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
-            // valid, access ok?
-            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
-                ((env->dtlb_tte[i] & 0x4) && is_user) ||
+            (address & mask) == (env->dtlb_tag[i] & mask) &&
+            (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
+            // access ok?
+            if (((env->dtlb_tte[i] & 0x4) && is_user) ||
                 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
                 if (env->dmmuregs[3]) /* Fault status register */
                     env->dmmuregs[3] = 2; /* overflow (not read before
@@ -420,8 +419,8 @@ static int get_physical_address_data(CPUState *env,
 #endif
                 return 1;
             }
-            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
-                (address & ~mask & 0x1fffffff000ULL);
+            *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) &
+                        0x1ffffffe000ULL;
             *prot = PAGE_READ;
             if (env->dtlb_tte[i] & 0x2)
                 *prot |= PAGE_WRITE;
@@ -465,12 +464,12 @@ static int get_physical_address_code(CPUState *env,
             mask = 0xffffffffffc00000ULL;
                 break;
         }
-        // ctx match, vaddr match?
+        // ctx match, vaddr match, valid?
         if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
-            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
-            // valid, access ok?
-            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
-                ((env->itlb_tte[i] & 0x4) && is_user)) {
+            (address & mask) == (env->itlb_tag[i] & mask) &&
+            (env->itlb_tte[i] & 0x8000000000000000ULL)) {
+            // access ok?
+            if ((env->itlb_tte[i] & 0x4) && is_user) {
                 if (env->immuregs[3]) /* Fault status register */
                     env->immuregs[3] = 2; /* overflow (not read before
                                              another fault) */
@@ -481,8 +480,8 @@ static int get_physical_address_code(CPUState *env,
 #endif
                 return 1;
             }
-            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
-                (address & ~mask & 0x1fffffff000ULL);
+            *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) &
+                        0x1ffffffe000ULL;
             *prot = PAGE_EXEC;
             return 0;
         }
@@ -490,6 +489,7 @@ static int get_physical_address_code(CPUState *env,
 #ifdef DEBUG_MMU
     printf("TMISS at 0x%" PRIx64 "\n", address);
 #endif
+    /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
     env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
     env->exception_index = TT_TMISS;
     return 1;
@@ -639,12 +639,16 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 
 void cpu_reset(CPUSPARCState *env)
 {
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
     tlb_flush(env, 1);
     env->cwp = 0;
     env->wim = 1;
     env->regwptr = env->regbase + (env->cwp * 16);
 #if defined(CONFIG_USER_ONLY)
-    env->user_mode_only = 1;
 #ifdef TARGET_SPARC64
     env->cleanwin = env->nwindows - 2;
     env->cansave = env->nwindows - 2;
@@ -655,10 +659,12 @@ void cpu_reset(CPUSPARCState *env)
     env->psret = 0;
     env->psrs = 1;
     env->psrps = 1;
+    CC_OP = CC_OP_FLAGS;
 #ifdef TARGET_SPARC64
     env->pstate = PS_PRIV;
     env->hpstate = HS_PRIV;
     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
+    env->lsu = 0;
 #else
     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
     env->mmuregs[0] |= env->def->mmu_bm;
@@ -688,6 +694,7 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
 #if !defined(TARGET_SPARC64)
     env->mmuregs[0] |= def->mmu_version;
     cpu_sparc_set_id(env, 0);
+    env->mxccregs[7] |= def->mxcc_version;
 #else
     env->mmu_version = def->mmu_version;
     env->maxtl = def->maxtl;
@@ -708,8 +715,6 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model)
     CPUSPARCState *env;
 
     env = qemu_mallocz(sizeof(CPUSPARCState));
-    if (!env)
-        return NULL;
     cpu_exec_init(env);
 
     gen_intermediate_code_init(env);
@@ -719,6 +724,7 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model)
         return NULL;
     }
     cpu_reset(env);
+    qemu_init_vcpu(env);
 
     return env;
 }
@@ -972,19 +978,6 @@ static const sparc_def_t sparc_defs[] = {
         CPU_FEATURE_FSMULD,
     },
     {
-        .name = "TI SuperSparc II",
-        .iu_version = 0x40000000,
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x04000000,
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
         .name = "TI MicroSparc I",
         .iu_version = 0x41000000,
         .fpu_version = 4 << 17,
@@ -1027,9 +1020,9 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "TI SuperSparc 40", // STP1020NPGA
-        .iu_version = 0x41000000,
+        .iu_version = 0x41000000, // SuperSPARC 2.x
         .fpu_version = 0 << 17,
-        .mmu_version = 0x00000000,
+        .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1040,9 +1033,9 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "TI SuperSparc 50", // STP1020PGA
-        .iu_version = 0x40000000,
+        .iu_version = 0x40000000, // SuperSPARC 3.x
         .fpu_version = 0 << 17,
-        .mmu_version = 0x04000000,
+        .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1053,22 +1046,23 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "TI SuperSparc 51",
-        .iu_version = 0x43000000,
+        .iu_version = 0x40000000, // SuperSPARC 3.x
         .fpu_version = 0 << 17,
-        .mmu_version = 0x04000000,
+        .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
         .nwindows = 8,
         .features = CPU_DEFAULT_FEATURES,
     },
     {
         .name = "TI SuperSparc 60", // STP1020APGA
-        .iu_version = 0x40000000,
+        .iu_version = 0x40000000, // SuperSPARC 3.x
         .fpu_version = 0 << 17,
-        .mmu_version = 0x03000000,
+        .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1079,14 +1073,29 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "TI SuperSparc 61",
-        .iu_version = 0x44000000,
+        .iu_version = 0x44000000, // SuperSPARC 3.x
         .fpu_version = 0 << 17,
-        .mmu_version = 0x04000000,
+        .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc II",
+        .iu_version = 0x40000000, // SuperSPARC II 1.x
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
         .nwindows = 8,
         .features = CPU_DEFAULT_FEATURES,
     },
@@ -1240,7 +1249,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
     long long iu_version;
     uint32_t fpu_version, mmu_version, nwindows;
 
-    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
+    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
         if (strcasecmp(name, sparc_defs[i].name) == 0) {
             def = &sparc_defs[i];
         }
@@ -1336,7 +1345,7 @@ void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 {
     unsigned int i;
 
-    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
+    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
         (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
                        sparc_defs[i].name,
                        sparc_defs[i].iu_version,
@@ -1359,8 +1368,6 @@ void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
                    "fpu_version mmu_version nwindows\n");
 }
 
-#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
-
 void cpu_dump_state(CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
@@ -1404,6 +1411,9 @@ void cpu_dump_state(CPUState *env, FILE *f,
                 env->cansave, env->canrestore, env->otherwin, env->wstate,
                 env->cleanwin, env->nwindows - 1 - env->cwp);
 #else
+
+#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
+
     cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
                 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
                 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),