diff options
48 files changed, 362 insertions, 275 deletions
diff --git a/cpu-defs.h b/cpu-defs.h index 915877617c..86557e442b 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -112,15 +112,6 @@ typedef struct CPUTLBEntry { target_phys_addr_t addend; } CPUTLBEntry; -/* Alpha has 4 different running levels */ -#if defined(TARGET_ALPHA) -#define NB_MMU_MODES 4 -#elif defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */ -#define NB_MMU_MODES 3 -#else -#define NB_MMU_MODES 2 -#endif - #define CPU_COMMON \ struct TranslationBlock *current_tb; /* currently executing TB */ \ /* soft mmu support */ \ diff --git a/cpu-exec.c b/cpu-exec.c index d09b564af4..0f55229741 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -884,8 +884,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_x86_handle_mmu_fault(env, address, is_write, - ((env->hflags & HF_CPL_MASK) == 3), 0); + ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -934,7 +933,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, return 1; } /* see if it is an MMU fault */ - ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0); + ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -970,7 +969,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, return 1; } /* see if it is an MMU fault */ - ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0); + ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -1007,7 +1006,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0); + ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -1056,7 +1055,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, return 1; } /* see if it is an MMU fault */ - ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0); + ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -1096,7 +1095,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0); + ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -1146,7 +1145,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0); + ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -1191,7 +1190,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0); + ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) @@ -1235,7 +1234,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_cris_handle_mmu_fault(env, address, is_write, 1, 0); + ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) diff --git a/exec-all.h b/exec-all.h index a01494b03d..57086f3def 100644 --- a/exec-all.h +++ b/exec-all.h @@ -117,14 +117,14 @@ void tlb_flush_page(CPUState *env, target_ulong addr); void tlb_flush(CPUState *env, int flush_global); int tlb_set_page_exec(CPUState *env, target_ulong vaddr, target_phys_addr_t paddr, int prot, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); static inline int tlb_set_page(CPUState *env, target_ulong vaddr, target_phys_addr_t paddr, int prot, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { if (prot & PAGE_READ) prot |= PAGE_EXEC; - return tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); + return tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu); } #define CODE_GEN_MAX_SIZE 65536 @@ -562,10 +562,10 @@ extern int tb_invalidated_flag; #if !defined(CONFIG_USER_ONLY) -void tlb_fill(target_ulong addr, int is_write, int is_user, +void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr); -#define ACCESS_TYPE 3 +#define ACCESS_TYPE (NB_MMU_MODES + 1) #define MEMSUFFIX _code #define env cpu_single_env @@ -598,35 +598,15 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) is the offset relative to phys_ram_base */ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) { - int is_user, index, pd; + int mmu_idx, index, pd; index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); -#if defined(TARGET_I386) - is_user = ((env->hflags & HF_CPL_MASK) == 3); -#elif defined (TARGET_PPC) - is_user = msr_pr; -#elif defined (TARGET_MIPS) - is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM); -#elif defined (TARGET_SPARC) - is_user = (env->psrs == 0); -#elif defined (TARGET_ARM) - is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR); -#elif defined (TARGET_SH4) - is_user = ((env->sr & SR_MD) == 0); -#elif defined (TARGET_ALPHA) - is_user = ((env->ps >> 3) & 3); -#elif defined (TARGET_M68K) - is_user = ((env->sr & SR_S) == 0); -#elif defined (TARGET_CRIS) - is_user = (0); -#else -#error unimplemented CPU -#endif - if (__builtin_expect(env->tlb_table[is_user][index].addr_code != + mmu_idx = cpu_mmu_index(env); + if (__builtin_expect(env->tlb_table[mmu_idx][index].addr_code != (addr & TARGET_PAGE_MASK), 0)) { ldub_code(addr); } - pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; + pd = env->tlb_table[mmu_idx][index].addr_code & ~TARGET_PAGE_MASK; if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { #ifdef TARGET_SPARC do_unassigned_access(addr, 0, 1, 0); @@ -634,7 +614,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); #endif } - return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; + return addr + env->tlb_table[mmu_idx][index].addend - (unsigned long)phys_ram_base; } #endif @@ -1608,7 +1608,7 @@ static inline void tlb_set_dirty(CPUState *env, conflicting with the host address space). */ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, target_phys_addr_t paddr, int prot, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { PhysPageDesc *p; unsigned long pd; @@ -1626,8 +1626,8 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, pd = p->phys_offset; } #if defined(DEBUG_TLB) - printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n", - vaddr, (int)paddr, prot, is_user, is_softmmu, pd); + printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n", + vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd); #endif ret = 0; @@ -1664,7 +1664,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); addend -= vaddr; - te = &env->tlb_table[is_user][index]; + te = &env->tlb_table[mmu_idx][index]; te->addend = addend; if (prot & PAGE_READ) { te->addr_read = address; @@ -1790,7 +1790,7 @@ void tlb_flush_page(CPUState *env, target_ulong addr) int tlb_set_page_exec(CPUState *env, target_ulong vaddr, target_phys_addr_t paddr, int prot, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { return 0; } diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c index da2d9ad067..3bd2c54342 100644 --- a/hw/alpha_palcode.c +++ b/hw/alpha_palcode.c @@ -811,12 +811,14 @@ static int get_page_bits (CPUState *env) static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp, uint64_t ptebase, int page_bits, uint64_t level, - int is_user, int rw) + int mmu_idx, int rw) { uint64_t pteaddr, pte, pfn; uint8_t gh; - int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar; + int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user; + /* XXX: TOFIX */ + is_user = mmu_idx == MMU_USER_IDX; pteaddr = (ptebase << page_bits) + (8 * level); pte = ldq_raw(pteaddr); /* Decode all interresting PTE fields */ @@ -871,7 +873,7 @@ static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp, static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot, uint64_t ptebase, int page_bits, - uint64_t vaddr, int is_user, int rw) + uint64_t vaddr, int mmu_idx, int rw) { uint64_t pfn, page_mask, lvl_mask, level1, level2, level3; int lvl_bits, ret; @@ -909,7 +911,7 @@ static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot, break; } /* Level 3 PTE */ - ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, is_user, rw); + ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw); if (ret & 0x1) { /* Translation not valid */ ret = 1; @@ -943,7 +945,7 @@ static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot, static int virtual_to_physical (CPUState *env, uint64_t *physp, int *zbitsp, int *protp, - uint64_t virtual, int is_user, int rw) + uint64_t virtual, int mmu_idx, int rw) { uint64_t sva, ptebase; int seg, page_bits, ret; @@ -961,16 +963,16 @@ static int virtual_to_physical (CPUState *env, uint64_t *physp, case 0: /* seg1: 3 levels of PTE */ ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, - virtual, is_user, rw); + virtual, mmu_idx, rw); break; case 1: /* seg1: 2 levels of PTE */ ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, - virtual, is_user, rw); + virtual, mmu_idx, rw); break; case 2: /* kernel segment */ - if (is_user) { + if (mmu_idx != 0) { ret = 2; } else { *physp = virtual; @@ -979,7 +981,7 @@ static int virtual_to_physical (CPUState *env, uint64_t *physp, case 3: /* seg1: TB mapped */ ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, - virtual, is_user, rw); + virtual, mmu_idx, rw); break; default: ret = 1; @@ -991,7 +993,7 @@ static int virtual_to_physical (CPUState *env, uint64_t *physp, /* XXX: code provision */ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { uint64_t physical, page_size, end; int prot, zbits, ret; @@ -1000,7 +1002,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, ret = 2; } else { ret = virtual_to_physical(env, &physical, &zbits, &prot, - address, is_user, rw); + address, mmu_idx, rw); } switch (ret) { case 0: @@ -1009,7 +1011,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, address &= ~(page_size - 1); for (end = physical + page_size; physical < end; physical += 0x1000) { ret = tlb_set_page(env, address, physical, prot, - is_user, is_softmmu); + mmu_idx, is_softmmu); address += 0x1000; } break; diff --git a/softmmu_exec.h b/softmmu_exec.h index 3b789eeb75..b6e4849185 100644 --- a/softmmu_exec.h +++ b/softmmu_exec.h @@ -1,10 +1,16 @@ /* Common softmmu definitions and inline routines. */ -#define ldul_user ldl_user -#define ldul_kernel ldl_kernel +/* XXX: find something cleaner. + * Furthermore, this is false for 64 bits targets + */ +#define ldul_user ldl_user +#define ldul_kernel ldl_kernel +#define ldul_hypv ldl_hypv +#define ldul_executive ldl_executive +#define ldul_supervisor ldl_supervisor #define ACCESS_TYPE 0 -#define MEMSUFFIX _kernel +#define MEMSUFFIX MMU_MODE0_SUFFIX #define DATA_SIZE 1 #include "softmmu_header.h" @@ -20,7 +26,7 @@ #undef MEMSUFFIX #define ACCESS_TYPE 1 -#define MEMSUFFIX _user +#define MEMSUFFIX MMU_MODE1_SUFFIX #define DATA_SIZE 1 #include "softmmu_header.h" @@ -35,8 +41,50 @@ #undef ACCESS_TYPE #undef MEMSUFFIX -/* these access are slower, they must be as rare as possible */ +#if (NB_MMU_MODES >= 3) + #define ACCESS_TYPE 2 +#define MEMSUFFIX MMU_MODE2_SUFFIX +#define DATA_SIZE 1 +#include "softmmu_header.h" + +#define DATA_SIZE 2 +#include "softmmu_header.h" + +#define DATA_SIZE 4 +#include "softmmu_header.h" + +#define DATA_SIZE 8 +#include "softmmu_header.h" +#undef ACCESS_TYPE +#undef MEMSUFFIX + +#if (NB_MMU_MODES >= 4) + +#define ACCESS_TYPE 3 +#define MEMSUFFIX MMU_MODE3_SUFFIX +#define DATA_SIZE 1 +#include "softmmu_header.h" + +#define DATA_SIZE 2 +#include "softmmu_header.h" + +#define DATA_SIZE 4 +#include "softmmu_header.h" + +#define DATA_SIZE 8 +#include "softmmu_header.h" +#undef ACCESS_TYPE +#undef MEMSUFFIX + +#if (NB_MMU_MODES > 4) +#error "NB_MMU_MODES > 4 is not supported for now" +#endif /* (NB_MMU_MODES > 4) */ +#endif /* (NB_MMU_MODES == 4) */ +#endif /* (NB_MMU_MODES >= 3) */ + +/* these access are slower, they must be as rare as possible */ +#define ACCESS_TYPE (NB_MMU_MODES) #define MEMSUFFIX _data #define DATA_SIZE 1 #include "softmmu_header.h" diff --git a/softmmu_header.h b/softmmu_header.h index 384518bb68..80eefa80fa 100644 --- a/softmmu_header.h +++ b/softmmu_header.h @@ -39,66 +39,19 @@ #error unsupported data size #endif -#if ACCESS_TYPE == 0 +#if ACCESS_TYPE < (NB_MMU_MODES) -#define CPU_MEM_INDEX 0 +#define CPU_MMU_INDEX ACCESS_TYPE #define MMUSUFFIX _mmu -#elif ACCESS_TYPE == 1 +#elif ACCESS_TYPE == (NB_MMU_MODES) -#define CPU_MEM_INDEX 1 +#define CPU_MMU_INDEX (cpu_mmu_index(env)) #define MMUSUFFIX _mmu -#elif ACCESS_TYPE == 2 - -#ifdef TARGET_I386 -#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3) -#elif defined (TARGET_PPC) -#define CPU_MEM_INDEX (msr_pr) -#elif defined (TARGET_MIPS) -#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM) -#elif defined (TARGET_SPARC) -#define CPU_MEM_INDEX ((env->psrs) == 0) -#elif defined (TARGET_ARM) -#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) -#elif defined (TARGET_SH4) -#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0) -#elif defined (TARGET_ALPHA) -#define CPU_MEM_INDEX ((env->ps >> 3) & 3) -#elif defined (TARGET_M68K) -#define CPU_MEM_INDEX ((env->sr & SR_S) == 0) -#elif defined (TARGET_CRIS) -/* CRIS FIXME: I guess we want to validate supervisor mode acceses here. */ -#define CPU_MEM_INDEX (0) -#else -#error unsupported CPU -#endif -#define MMUSUFFIX _mmu +#elif ACCESS_TYPE == (NB_MMU_MODES + 1) -#elif ACCESS_TYPE == 3 - -#ifdef TARGET_I386 -#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3) -#elif defined (TARGET_PPC) -#define CPU_MEM_INDEX (msr_pr) -#elif defined (TARGET_MIPS) -#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM) -#elif defined (TARGET_SPARC) -#define CPU_MEM_INDEX ((env->psrs) == 0) -#elif defined (TARGET_ARM) -#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) -#elif defined (TARGET_SH4) -#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0) -#elif defined (TARGET_ALPHA) -#define CPU_MEM_INDEX ((env->ps >> 3) & 3) -#elif defined (TARGET_M68K) -#define CPU_MEM_INDEX ((env->sr & SR_S) == 0) -#elif defined (TARGET_CRIS) -/* CRIS FIXME: I guess we want to validate supervisor mode acceses here. */ -#define CPU_MEM_INDEX (0) -#else -#error unsupported CPU -#endif +#define CPU_MMU_INDEX (cpu_mmu_index(env)) #define MMUSUFFIX _cmmu #else @@ -111,18 +64,18 @@ #define RES_TYPE int #endif -#if ACCESS_TYPE == 3 +#if ACCESS_TYPE == (NB_MMU_MODES + 1) #define ADDR_READ addr_code #else #define ADDR_READ addr_read #endif DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, - int is_user); -void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user); + int mmu_idx); +void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int mmu_idx); #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \ - (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU) + (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU) #define CPU_TLB_ENTRY_BITS 4 @@ -161,8 +114,8 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), - "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)), - "i" (CPU_MEM_INDEX), + "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)), + "i" (CPU_MMU_INDEX), "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX)) : "%eax", "%ecx", "%edx", "memory", "cc"); return res; @@ -208,8 +161,8 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), - "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)), - "i" (CPU_MEM_INDEX), + "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)), + "i" (CPU_MMU_INDEX), "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX)) : "%eax", "%ecx", "%edx", "memory", "cc"); return res; @@ -260,8 +213,8 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), - "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)), - "i" (CPU_MEM_INDEX), + "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)), + "i" (CPU_MMU_INDEX), "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX)) : "%eax", "%ecx", "%edx", "memory", "cc"); } @@ -276,16 +229,16 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) RES_TYPE res; target_ulong addr; unsigned long physaddr; - int is_user; + int mmu_idx; addr = ptr; index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - is_user = CPU_MEM_INDEX; - if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ != + mmu_idx = CPU_MMU_INDEX; + if (__builtin_expect(env->tlb_table[mmu_idx][index].ADDR_READ != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { - res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user); + res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx); } else { - physaddr = addr + env->tlb_table[is_user][index].addend; + physaddr = addr + env->tlb_table[mmu_idx][index].addend; res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr); } return res; @@ -297,23 +250,23 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) int res, index; target_ulong addr; unsigned long physaddr; - int is_user; + int mmu_idx; addr = ptr; index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - is_user = CPU_MEM_INDEX; - if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ != + mmu_idx = CPU_MMU_INDEX; + if (__builtin_expect(env->tlb_table[mmu_idx][index].ADDR_READ != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { - res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user); + res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx); } else { - physaddr = addr + env->tlb_table[is_user][index].addend; + physaddr = addr + env->tlb_table[mmu_idx][index].addend; res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr); } return res; } #endif -#if ACCESS_TYPE != 3 +#if ACCESS_TYPE != (NB_MMU_MODES + 1) /* generic store macro */ @@ -322,25 +275,25 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE int index; target_ulong addr; unsigned long physaddr; - int is_user; + int mmu_idx; addr = ptr; index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - is_user = CPU_MEM_INDEX; - if (__builtin_expect(env->tlb_table[is_user][index].addr_write != + mmu_idx = CPU_MMU_INDEX; + if (__builtin_expect(env->tlb_table[mmu_idx][index].addr_write != (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { - glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user); + glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx); } else { - physaddr = addr + env->tlb_table[is_user][index].addend; + physaddr = addr + env->tlb_table[mmu_idx][index].addend; glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v); } } -#endif /* ACCESS_TYPE != 3 */ +#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */ #endif /* !asm */ -#if ACCESS_TYPE != 3 +#if ACCESS_TYPE != (NB_MMU_MODES + 1) #if DATA_SIZE == 8 static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr) @@ -386,7 +339,7 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v) } #endif /* DATA_SIZE == 4 */ -#endif /* ACCESS_TYPE != 3 */ +#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */ #undef RES_TYPE #undef DATA_TYPE @@ -394,6 +347,6 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v) #undef SUFFIX #undef USUFFIX #undef DATA_SIZE -#undef CPU_MEM_INDEX +#undef CPU_MMU_INDEX #undef MMUSUFFIX #undef ADDR_READ diff --git a/softmmu_template.h b/softmmu_template.h index ce6e4bd071..89b2f38c84 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -48,7 +48,7 @@ #endif static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, - int is_user, + int mmu_idx, void *retaddr); static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, target_ulong tlb_addr) @@ -76,7 +76,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, /* handle all cases except unaligned access which span two pages */ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, - int is_user) + int mmu_idx) { DATA_TYPE res; int index; @@ -88,9 +88,9 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, /* XXX: could done more in memory macro in a non portable way */ index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); redo: - tlb_addr = env->tlb_table[is_user][index].ADDR_READ; + tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - physaddr = addr + env->tlb_table[is_user][index].addend; + physaddr = addr + env->tlb_table[mmu_idx][index].addend; if (tlb_addr & ~TARGET_PAGE_MASK) { /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) @@ -101,16 +101,16 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, do_unaligned_access: retaddr = GETPC(); #ifdef ALIGNED_ONLY - do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr); + do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr); #endif res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr, - is_user, retaddr); + mmu_idx, retaddr); } else { /* unaligned/aligned access in the same page */ #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { retaddr = GETPC(); - do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr); + do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr); } #endif res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)physaddr); @@ -120,9 +120,9 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, retaddr = GETPC(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(addr, READ_ACCESS_TYPE, is_user, retaddr); + do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr); #endif - tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr); + tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr); goto redo; } return res; @@ -130,7 +130,7 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, /* handle all unaligned cases */ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, - int is_user, + int mmu_idx, void *retaddr) { DATA_TYPE res, res1, res2; @@ -140,9 +140,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); redo: - tlb_addr = env->tlb_table[is_user][index].ADDR_READ; + tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - physaddr = addr + env->tlb_table[is_user][index].addend; + physaddr = addr + env->tlb_table[mmu_idx][index].addend; if (tlb_addr & ~TARGET_PAGE_MASK) { /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) @@ -154,9 +154,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, addr1 = addr & ~(DATA_SIZE - 1); addr2 = addr1 + DATA_SIZE; res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1, - is_user, retaddr); + mmu_idx, retaddr); res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2, - is_user, retaddr); + mmu_idx, retaddr); shift = (addr & (DATA_SIZE - 1)) * 8; #ifdef TARGET_WORDS_BIGENDIAN res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift)); @@ -170,7 +170,7 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, } } else { /* the page is not in the TLB : fill it */ - tlb_fill(addr, READ_ACCESS_TYPE, is_user, retaddr); + tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr); goto redo; } return res; @@ -180,7 +180,7 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val, - int is_user, + int mmu_idx, void *retaddr); static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, @@ -211,7 +211,7 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val, - int is_user) + int mmu_idx) { target_phys_addr_t physaddr; target_ulong tlb_addr; @@ -220,9 +220,9 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); redo: - tlb_addr = env->tlb_table[is_user][index].addr_write; + tlb_addr = env->tlb_table[mmu_idx][index].addr_write; if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - physaddr = addr + env->tlb_table[is_user][index].addend; + physaddr = addr + env->tlb_table[mmu_idx][index].addend; if (tlb_addr & ~TARGET_PAGE_MASK) { /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) @@ -233,16 +233,16 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, do_unaligned_access: retaddr = GETPC(); #ifdef ALIGNED_ONLY - do_unaligned_access(addr, 1, is_user, retaddr); + do_unaligned_access(addr, 1, mmu_idx, retaddr); #endif glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val, - is_user, retaddr); + mmu_idx, retaddr); } else { /* aligned/unaligned access in the same page */ #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { retaddr = GETPC(); - do_unaligned_access(addr, 1, is_user, retaddr); + do_unaligned_access(addr, 1, mmu_idx, retaddr); } #endif glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)physaddr, val); @@ -252,9 +252,9 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, retaddr = GETPC(); #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(addr, 1, is_user, retaddr); + do_unaligned_access(addr, 1, mmu_idx, retaddr); #endif - tlb_fill(addr, 1, is_user, retaddr); + tlb_fill(addr, 1, mmu_idx, retaddr); goto redo; } } @@ -262,7 +262,7 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, /* handles all unaligned cases */ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE val, - int is_user, + int mmu_idx, void *retaddr) { target_phys_addr_t physaddr; @@ -271,9 +271,9 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); redo: - tlb_addr = env->tlb_table[is_user][index].addr_write; + tlb_addr = env->tlb_table[mmu_idx][index].addr_write; if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - physaddr = addr + env->tlb_table[is_user][index].addend; + physaddr = addr + env->tlb_table[mmu_idx][index].addend; if (tlb_addr & ~TARGET_PAGE_MASK) { /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) @@ -285,10 +285,10 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, for(i = 0;i < DATA_SIZE; i++) { #ifdef TARGET_WORDS_BIGENDIAN glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)), - is_user, retaddr); + mmu_idx, retaddr); #else glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8), - is_user, retaddr); + mmu_idx, retaddr); #endif } } else { @@ -297,7 +297,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, } } else { /* the page is not in the TLB : fill it */ - tlb_fill(addr, 1, is_user, retaddr); + tlb_fill(addr, 1, mmu_idx, retaddr); goto redo; } } diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 3f517e67b6..579ce613d3 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -256,6 +256,8 @@ struct pal_handler_t { void (*call_pal)(CPUAlphaState *env, uint32_t palcode); }; +#define NB_MMU_MODES 4 + struct CPUAlphaState { uint64_t ir[31]; float64 fir[31]; @@ -302,6 +304,17 @@ struct CPUAlphaState { #define cpu_gen_code cpu_alpha_gen_code #define cpu_signal_handler cpu_alpha_signal_handler +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _executive +#define MMU_MODE2_SUFFIX _supervisor +#define MMU_MODE3_SUFFIX _user +#define MMU_USER_IDX 3 +static inline int cpu_mmu_index (CPUState *env) +{ + return (env->ps >> 3) & 3; +} + #include "cpu-all.h" enum { diff --git a/target-alpha/exec.h b/target-alpha/exec.h index 80f358ca36..62cd07dcf8 100644 --- a/target-alpha/exec.h +++ b/target-alpha/exec.h @@ -73,7 +73,7 @@ static inline void regs_to_env(void) } int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp); int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp); diff --git a/target-alpha/helper.c b/target-alpha/helper.c index 72cae49cf1..fd39f5f893 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -28,7 +28,7 @@ #if defined(CONFIG_USER_ONLY) int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { if (rw == 2) env->exception_index = EXCP_ITB_MISS; @@ -57,7 +57,7 @@ target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr) } int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { uint32_t opc; diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c index deac6c2596..badb85d698 100644 --- a/target-alpha/op_helper.c +++ b/target-alpha/op_helper.c @@ -1164,20 +1164,20 @@ void helper_mtpr (int iprn) void helper_ld_phys_to_virt (void) { uint64_t tlb_addr, physaddr; - int index, is_user; + int index, mmu_idx; void *retaddr; - is_user = (env->ps >> 3) & 3; + mmu_idx = cpu_mmu_index(env); index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); redo: - tlb_addr = env->tlb_table[is_user][index].addr_read; + tlb_addr = env->tlb_table[mmu_idx][index].addr_read; if ((T0 & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - physaddr = T0 + env->tlb_table[is_user][index].addend; + physaddr = T0 + env->tlb_table[mmu_idx][index].addend; } else { /* the page is not in the TLB : fill it */ retaddr = GETPC(); - tlb_fill(T0, 0, is_user, retaddr); + tlb_fill(T0, 0, mmu_idx, retaddr); goto redo; } T0 = physaddr; @@ -1186,20 +1186,20 @@ void helper_ld_phys_to_virt (void) void helper_st_phys_to_virt (void) { uint64_t tlb_addr, physaddr; - int index, is_user; + int index, mmu_idx; void *retaddr; - is_user = (env->ps >> 3) & 3; + mmu_idx = cpu_mmu_index(env); index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); redo: - tlb_addr = env->tlb_table[is_user][index].addr_write; + tlb_addr = env->tlb_table[mmu_idx][index].addr_write; if ((T0 & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - physaddr = T0 + env->tlb_table[is_user][index].addend; + physaddr = T0 + env->tlb_table[mmu_idx][index].addend; } else { /* the page is not in the TLB : fill it */ retaddr = GETPC(); - tlb_fill(T0, 1, is_user, retaddr); + tlb_fill(T0, 1, mmu_idx, retaddr); goto redo; } T0 = physaddr; @@ -1223,7 +1223,7 @@ void helper_st_phys_to_virt (void) NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -1234,7 +1234,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (!likely(ret == 0)) { if (likely(retaddr)) { /* now we have a real cpu fault */ diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7510a2480a..5ffca1145b 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -43,6 +43,8 @@ typedef void ARMWriteCPFunc(void *opaque, int cp_info, typedef uint32_t ARMReadCPFunc(void *opaque, int cp_info, int dstreg, int operand); +#define NB_MMU_MODES 2 + /* We currently assume float and double are IEEE single and double precision respectively. Doing runtime conversions is tricky because VFP registers may contain @@ -301,6 +303,15 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, #define cpu_signal_handler cpu_arm_signal_handler #define cpu_list arm_cpu_list +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_USER_IDX 1 +static inline int cpu_mmu_index (CPUState *env) +{ + return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0; +} + #include "cpu-all.h" #endif diff --git a/target-arm/exec.h b/target-arm/exec.h index 9da19150b2..0c53b8d5f5 100644 --- a/target-arm/exec.h +++ b/target-arm/exec.h @@ -46,7 +46,7 @@ static inline void regs_to_env(void) } int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); static inline int cpu_halted(CPUState *env) { if (!env->halted) diff --git a/target-arm/helper.c b/target-arm/helper.c index 4501feaef1..4f851ce220 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -169,7 +169,7 @@ void do_interrupt (CPUState *env) } int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { if (rw == 2) { env->exception_index = EXCP_PREFETCH_ABORT; @@ -547,18 +547,19 @@ do_fault: } int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, - int access_type, int is_user, int is_softmmu) + int access_type, int mmu_idx, int is_softmmu) { uint32_t phys_addr; int prot; - int ret; + int ret, is_user; + is_user = mmu_idx == MMU_USER_IDX; ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot); if (ret == 0) { /* Map a single [sub]page. */ phys_addr &= ~(uint32_t)0x3ff; address &= ~(uint32_t)0x3ff; - return tlb_set_page (env, address, phys_addr, prot, is_user, + return tlb_set_page (env, address, phys_addr, prot, mmu_idx, is_softmmu); } diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index c861bf7e4c..c0e7c8d64a 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -196,7 +196,7 @@ void do_vfp_get_fpscr(void) NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -207,7 +207,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_arm_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (__builtin_expect(ret, 0)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-cris/cpu.h b/target-cris/cpu.h index 11652c50fb..ef0953b263 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -74,6 +74,8 @@ /* Internal flags for the implementation. */ #define F_DELAYSLOT 1 +#define NB_MMU_MODES 2 + typedef struct CPUCRISState { uint32_t debug1; uint32_t debug2; @@ -229,6 +231,16 @@ void register_cris_insns (CPUCRISState *env); #define cpu_gen_code cpu_cris_gen_code #define cpu_signal_handler cpu_cris_signal_handler +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_USER_IDX 1 +/* CRIS FIXME: I guess we want to validate supervisor mode acceses here. */ +static inline int cpu_mmu_index (CPUState *env) +{ + return 0; +} + #include "cpu-all.h" /* Register aliases. */ diff --git a/target-cris/exec.h b/target-cris/exec.h index a4f555eb28..fe63f16986 100644 --- a/target-cris/exec.h +++ b/target-cris/exec.h @@ -45,8 +45,8 @@ static inline void regs_to_env(void) } int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu); -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr); + int mmu_idx, int is_softmmu); +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr); #if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" diff --git a/target-cris/helper.c b/target-cris/helper.c index 3db3bea08d..98305605a1 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -35,7 +35,7 @@ void do_interrupt (CPUState *env) } int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { env->exception_index = 0xaa; env->debug1 = address; @@ -52,7 +52,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) #else /* !CONFIG_USER_ONLY */ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { struct cris_mmu_result_t res; int prot, miss; @@ -61,7 +61,7 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, address &= TARGET_PAGE_MASK; prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; // printf ("%s pc=%x %x w=%d smmu=%d\n", __func__, env->pc, address, rw, is_softmmu); - miss = cris_mmu_translate(&res, env, address, rw, is_user); + miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); if (miss) { /* handle the miss. */ @@ -73,7 +73,7 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, phy = res.phy; } // printf ("a=%x phy=%x\n", address, phy); - return tlb_set_page(env, address, phy, prot, is_user, is_softmmu); + return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); } diff --git a/target-cris/mmu.c b/target-cris/mmu.c index 56299b7dd1..2be4eb8f71 100644 --- a/target-cris/mmu.c +++ b/target-cris/mmu.c @@ -111,11 +111,12 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res, int cris_mmu_translate(struct cris_mmu_result_t *res, CPUState *env, uint32_t vaddr, - int rw, int is_user) + int rw, int mmu_idx) { uint32_t phy = vaddr; int seg; int miss = 0; + int is_user = mmu_idx == MMU_USER_IDX; if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) { res->phy = vaddr; diff --git a/target-cris/mmu.h b/target-cris/mmu.h index adbc1fc5df..519c0fc819 100644 --- a/target-cris/mmu.h +++ b/target-cris/mmu.h @@ -17,4 +17,4 @@ struct cris_mmu_result_t int cris_mmu_translate(struct cris_mmu_result_t *res, CPUState *env, uint32_t vaddr, - int rw, int is_user); + int rw, int mmu_idx); diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index f84ceb9da0..4f0f07cd4d 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -41,7 +41,7 @@ NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -52,7 +52,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_cris_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (__builtin_expect(ret, 0)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2cc7d64e95..23419909cf 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -432,6 +432,8 @@ typedef union { #define CPU_NB_REGS 8 #endif +#define NB_MMU_MODES 2 + typedef struct CPUX86State { #if TARGET_LONG_BITS > HOST_LONG_BITS /* temporaries if we cannot store them in host registers */ @@ -688,6 +690,15 @@ static inline int cpu_get_time_fast(void) #define cpu_gen_code cpu_x86_gen_code #define cpu_signal_handler cpu_x86_signal_handler +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_USER_IDX 1 +static inline int cpu_mmu_index (CPUState *env) +{ + return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0; +} + #include "cpu-all.h" #include "svm.h" diff --git a/target-i386/exec.h b/target-i386/exec.h index 1cb73467bb..8e2a553213 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -163,8 +163,8 @@ void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr); int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, - int is_write, int is_user, int is_softmmu); -void tlb_fill(target_ulong addr, int is_write, int is_user, + int is_write, int mmu_idx, int is_softmmu); +void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr); void __hidden cpu_lock(void); void __hidden cpu_unlock(void); diff --git a/target-i386/helper.c b/target-i386/helper.c index 91fd6a96c7..c5d4487a62 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -3885,7 +3885,7 @@ void update_fp_status(void) NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; int ret; @@ -3897,7 +3897,7 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) saved_env = env; env = cpu_single_env; - ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (ret) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-i386/helper2.c b/target-i386/helper2.c index 541d83f927..7d5275c101 100644 --- a/target-i386/helper2.c +++ b/target-i386/helper2.c @@ -571,7 +571,7 @@ void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr) #if defined(CONFIG_USER_ONLY) int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, - int is_write, int is_user, int is_softmmu) + int is_write, int mmu_idx, int is_softmmu) { /* user mode only emulation */ is_write &= 1; @@ -598,14 +598,15 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) 2 = soft MMU activation required for this block */ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, - int is_write1, int is_user, int is_softmmu) + int is_write1, int mmu_idx, int is_softmmu) { uint64_t ptep, pte; uint32_t pdpe_addr, pde_addr, pte_addr; - int error_code, is_dirty, prot, page_size, ret, is_write; + int error_code, is_dirty, prot, page_size, ret, is_write, is_user; unsigned long paddr, page_offset; target_ulong vaddr, virt_addr; + is_user = mmu_idx == MMU_USER_IDX; #if defined(DEBUG_MMU) printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", addr, is_write1, is_user, env->eip); @@ -862,7 +863,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, paddr = (pte & TARGET_PAGE_MASK) + page_offset; vaddr = virt_addr + page_offset; - ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); + ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu); return ret; do_fault_protect: error_code = PG_ERROR_P_MASK; diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index a34c137344..5004a9168b 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -53,6 +53,8 @@ #define EXCP_RTE 0x100 #define EXCP_HALT_INSN 0x101 +#define NB_MMU_MODES 2 + typedef struct CPUM68KState { uint32_t dregs[8]; uint32_t aregs[8]; @@ -223,6 +225,15 @@ void register_m68k_insns (CPUM68KState *env); #define cpu_gen_code cpu_m68k_gen_code #define cpu_signal_handler cpu_m68k_signal_handler +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_USER_IDX 1 +static inline int cpu_mmu_index (CPUState *env) +{ + return (env->sr & SR_S) == 0 ? 1 : 0; +} + #include "cpu-all.h" #endif diff --git a/target-m68k/exec.h b/target-m68k/exec.h index dc5bf5e605..b9e13ef04f 100644 --- a/target-m68k/exec.h +++ b/target-m68k/exec.h @@ -38,7 +38,7 @@ static inline void regs_to_env(void) } int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); #if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 423a0e00a9..f3c629979d 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -301,7 +301,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) #if defined(CONFIG_USER_ONLY) int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { env->exception_index = EXCP_ACCESS; env->mmu.ar = address; @@ -311,13 +311,13 @@ int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, #else int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { int prot; address &= TARGET_PAGE_MASK; prot = PAGE_READ | PAGE_WRITE; - return tlb_set_page(env, address, address, prot, is_user, is_softmmu); + return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu); } /* Notify CPU of a pending interrupt. Prioritization and vectoring should diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 70b7aec0e6..917ef52880 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -49,7 +49,7 @@ extern int semihosting_enabled; NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -60,7 +60,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (__builtin_expect(ret, 0)) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 137260f329..35bf2fbf6f 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -107,6 +107,8 @@ struct CPUMIPSFPUContext { #define FP_UNIMPLEMENTED 32 }; +#define NB_MMU_MODES 2 + typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; struct CPUMIPSMVPContext { int32_t CP0_MVPControl; @@ -484,6 +486,15 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def); #define cpu_signal_handler cpu_mips_signal_handler #define cpu_list mips_cpu_list +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_USER_IDX 1 +static inline int cpu_mmu_index (CPUState *env) +{ + return (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 1 : 0; +} + #include "cpu-all.h" /* Memory access type : diff --git a/target-mips/exec.h b/target-mips/exec.h index 45be7b37c7..c6dc25cf6e 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -105,7 +105,7 @@ void do_pmon (int function); void dump_sc (void); int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); void do_interrupt (CPUState *env); void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra); diff --git a/target-mips/helper.c b/target-mips/helper.c index a881876ff2..45874d4462 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -229,7 +229,7 @@ void cpu_mips_init_mmu (CPUState *env) #endif /* !defined(CONFIG_USER_ONLY) */ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { target_ulong physical; int prot; @@ -241,8 +241,8 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, #if 0 cpu_dump_state(env, logfile, fprintf, 0); #endif - fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d is_user %d smmu %d\n", - __func__, env->PC[env->current_tc], address, rw, is_user, is_softmmu); + fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d smmu %d\n", + __func__, env->PC[env->current_tc], address, rw, mmu_idx, is_softmmu); } rw &= 1; @@ -265,7 +265,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, if (ret == TLBRET_MATCH) { ret = tlb_set_page(env, address & TARGET_PAGE_MASK, physical & TARGET_PAGE_MASK, prot, - is_user, is_softmmu); + mmu_idx, is_softmmu); } else if (ret < 0) { do_fault: switch (ret) { diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 6d732a8a07..6d7f750d0f 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -563,7 +563,7 @@ static void do_unaligned_access (target_ulong addr, int is_write, int is_user, v do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL); } -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -574,7 +574,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (ret) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index b424abcebb..d39bd971a0 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -434,6 +434,12 @@ enum { POWERPC_FLAG_PMM = 0x00000400, }; +#if defined(TARGET_PPC64H) +#define NB_MMU_MODES 3 +#else +#define NB_MMU_MODES 2 +#endif + /*****************************************************************************/ /* The whole PowerPC CPU context */ struct CPUPPCState { @@ -575,6 +581,7 @@ struct CPUPPCState { jmp_buf jmp_env; int user_mode_only; /* user mode only simulation */ target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */ + int mmu_idx; /* precomputed MMU index to speed up mem accesses */ /* Power management */ int power_mode; @@ -699,6 +706,18 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val); #define cpu_signal_handler cpu_ppc_signal_handler #define cpu_list ppc_cpu_list +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _user +#define MMU_MODE1_SUFFIX _kernel +#if defined(TARGET_PPC64H) +#define MMU_MODE2_SUFFIX _hypv +#endif +#define MMU_USER_IDX 0 +static inline int cpu_mmu_index (CPUState *env) +{ + return env->mmu_idx; +} + #include "cpu-all.h" /*****************************************************************************/ diff --git a/target-ppc/exec.h b/target-ppc/exec.h index 3fedf493e3..5685fd7a4b 100644 --- a/target-ppc/exec.h +++ b/target-ppc/exec.h @@ -112,7 +112,7 @@ static always_inline void regs_to_env (void) } int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); static always_inline int cpu_halted (CPUState *env) { diff --git a/target-ppc/helper.c b/target-ppc/helper.c index c4eab18fc8..dd5a07a53f 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -39,7 +39,7 @@ #if defined(CONFIG_USER_ONLY) int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { int exception, error_code; @@ -1349,7 +1349,7 @@ target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr) /* Perform address translation */ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { mmu_ctx_t ctx; int access_type; @@ -1370,7 +1370,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, if (ret == 0) { ret = tlb_set_page(env, address & TARGET_PAGE_MASK, ctx.raddr & TARGET_PAGE_MASK, ctx.prot, - is_user, is_softmmu); + mmu_idx, is_softmmu); } else if (ret < 0) { #if defined (DEBUG_MMU) if (loglevel != 0) @@ -2083,7 +2083,12 @@ void do_compute_hflags (CPUPPCState *env) env->hflags |= msr_cm << MSR_CM; env->hflags |= (uint64_t)msr_sf << MSR_SF; env->hflags |= (uint64_t)msr_hv << MSR_HV; + /* Precompute MMU index */ + if (msr_pr == 0 && msr_hv == 1) + env->mmu_idx = 2; + else #endif + env->mmu_idx = 1 - msr_pr; } /*****************************************************************************/ diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 7a758f6c06..38c3a7ff8f 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -2307,7 +2307,7 @@ DO_SPE_OP1(fsctuf); NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -2318,7 +2318,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (unlikely(ret != 0)) { if (likely(retaddr)) { /* now we have a real cpu fault */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index eb795fb6f5..6f2a9721f2 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -6693,15 +6693,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, ctx.tb = tb; ctx.exception = POWERPC_EXCP_NONE; ctx.spr_cb = env->spr_cb; -#if defined(CONFIG_USER_ONLY) - supervisor = 0; -#else -#if defined(TARGET_PPC64H) - if (msr_pr == 0 && msr_hv == 1) - supervisor = 2; - else -#endif - supervisor = 1 - msr_pr; + supervisor = env->mmu_idx; +#if !defined(CONFIG_USER_ONLY) ctx.supervisor = supervisor; #endif #if defined(TARGET_PPC64) diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index add6a47b12..edfda1f90a 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -77,6 +77,8 @@ typedef struct tlb_t { #define UTLB_SIZE 64 #define ITLB_SIZE 4 +#define NB_MMU_MODES 2 + typedef struct CPUSH4State { uint32_t flags; /* general execution flags */ uint32_t gregs[24]; /* general registers */ @@ -134,6 +136,15 @@ int cpu_sh4_signal_handler(int host_signum, void *pinfo, #define cpu_gen_code cpu_sh4_gen_code #define cpu_signal_handler cpu_sh4_signal_handler +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_USER_IDX 1 +static inline int cpu_mmu_index (CPUState *env) +{ + return (env->sr & SR_MD) == 0 ? 1 : 0; +} + #include "cpu-all.h" /* Memory access type */ diff --git a/target-sh4/exec.h b/target-sh4/exec.h index a606fd1861..608179918b 100644 --- a/target-sh4/exec.h +++ b/target-sh4/exec.h @@ -63,7 +63,7 @@ static inline void env_to_regs(void) } int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); int find_itlb_entry(CPUState * env, target_ulong address, int use_asid, int update); diff --git a/target-sh4/helper.c b/target-sh4/helper.c index a5af5ba153..b8a05e124c 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -36,7 +36,7 @@ void do_interrupt (CPUState *env) } int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { env->tea = address; switch (rw) { @@ -372,15 +372,15 @@ int get_physical_address(CPUState * env, target_ulong * physical, } int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { target_ulong physical, page_offset, page_size; int prot, ret, access_type; /* XXXXX */ #if 0 - fprintf(stderr, "%s pc %08x ad %08x rw %d is_user %d smmu %d\n", - __func__, env->pc, address, rw, is_user, is_softmmu); + fprintf(stderr, "%s pc %08x ad %08x rw %d mmu_idx %d smmu %d\n", + __func__, env->pc, address, rw, mmu_idx, is_softmmu); #endif access_type = ACCESS_INT; @@ -426,7 +426,7 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, address = (address & TARGET_PAGE_MASK) + page_offset; physical = (physical & TARGET_PAGE_MASK) + page_offset; - return tlb_set_page(env, address, physical, prot, is_user, is_softmmu); + return tlb_set_page(env, address, physical, prot, mmu_idx, is_softmmu); } target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index 292e9b30df..2535b8d6aa 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -42,7 +42,7 @@ void do_raise_exception(void) #define SHIFT 3 #include "softmmu_template.h" -void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; @@ -53,7 +53,7 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) generated code */ saved_env = env; env = cpu_single_env; - ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (ret) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index fac18a7775..30e1d827da 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -166,6 +166,8 @@ typedef struct sparc_def_t sparc_def_t; +#define NB_MMU_MODES 2 + typedef struct CPUSPARCState { target_ulong gregs[8]; /* general registers */ target_ulong *regwptr; /* pointer to current register window */ @@ -317,6 +319,15 @@ void cpu_check_irqs(CPUSPARCState *env); #define cpu_signal_handler cpu_sparc_signal_handler #define cpu_list sparc_cpu_list +/* MMU modes definitions */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_USER_IDX 1 +static inline int cpu_mmu_index (CPUState *env) +{ + return env->psrs == 0 ? 1 : 0; +} + #include "cpu-all.h" #endif diff --git a/target-sparc/exec.h b/target-sparc/exec.h index 063e2ee644..81c4741be3 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -115,7 +115,7 @@ static inline void regs_to_env(void) } int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu); + int mmu_idx, int is_softmmu); static inline int cpu_halted(CPUState *env) { if (!env->halted) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index af8bc96948..ebe642f8cb 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -49,7 +49,7 @@ void cpu_unlock(void) #if defined(CONFIG_USER_ONLY) int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { if (rw & 2) env->exception_index = TT_TFAULT; @@ -100,15 +100,16 @@ static const int perm_table[2][8] = { int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, int *access_index, target_ulong address, int rw, - int is_user) + int mmu_idx) { int access_perms = 0; target_phys_addr_t pde_ptr; uint32_t pde; target_ulong virt_addr; - int error_code = 0, is_dirty; + int error_code = 0, is_dirty, is_user; unsigned long page_offset; + is_user = mmu_idx == MMU_USER_IDX; virt_addr = address & TARGET_PAGE_MASK; if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */ @@ -216,13 +217,13 @@ int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot /* Perform address translation */ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { target_phys_addr_t paddr; target_ulong vaddr; int error_code = 0, prot, ret = 0, access_index; - error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user); + error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx); if (error_code == 0) { vaddr = address & TARGET_PAGE_MASK; paddr &= TARGET_PAGE_MASK; @@ -230,7 +231,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr " TARGET_FMT_lx "\n", address, paddr, vaddr); #endif - ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); + ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu); return ret; } @@ -246,7 +247,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, // switching to normal mode. vaddr = address & TARGET_PAGE_MASK; prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); + ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu); return ret; } else { if (rw & 2) @@ -484,8 +485,10 @@ static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot, int *access_index, target_ulong address, int rw, - int is_user) + int mmu_idx) { + int is_user = mmu_idx == MMU_USER_IDX; + if (rw == 2) return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user); else @@ -494,20 +497,20 @@ int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot, /* Perform address translation */ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) + int mmu_idx, int is_softmmu) { target_ulong virt_addr, vaddr; target_phys_addr_t paddr; int error_code = 0, prot, ret = 0, access_index; - error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user); + error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx); if (error_code == 0) { virt_addr = address & TARGET_PAGE_MASK; vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1)); #ifdef DEBUG_MMU printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr); #endif - ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); + ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu); return ret; } // XXX diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index a4839a0558..6d08e1c651 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1522,7 +1522,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user, NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; int ret; @@ -1534,7 +1534,7 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) saved_env = env; env = cpu_single_env; - ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (ret) { if (retaddr) { /* now we have a real cpu fault */ diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 27c22ede59..3027bb8afc 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3689,7 +3689,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) #else extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, int *access_index, target_ulong address, int rw, - int is_user); + int mmu_idx); target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { |