Implement missing MIPS supervisor mode bits.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3472 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2007-10-28 19:45:05 +00:00
parent 8e129e0748
commit 623a930ec3
8 changed files with 51 additions and 37 deletions

View File

@ -122,7 +122,7 @@ typedef struct CPUTLBEntry {
written */ \
target_ulong mem_write_vaddr; /* target virtual addr at which the \
memory was written */ \
/* 0 = kernel, 1 = user */ \
/* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
\

View File

@ -374,7 +374,7 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
regs->cp0_status = CP0St_UM;
regs->cp0_status = 2 << CP0St_KSU;
regs->cp0_epc = infop->entry;
regs->regs[29] = infop->start_stack;
}

View File

@ -107,7 +107,7 @@ struct CPUMIPSFPUContext {
#define FP_UNIMPLEMENTED 32
};
#define NB_MMU_MODES 2
#define NB_MMU_MODES 3
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
struct CPUMIPSMVPContext {
@ -285,8 +285,7 @@ struct CPUMIPSState {
#define CP0St_KX 7
#define CP0St_SX 6
#define CP0St_UX 5
#define CP0St_UM 4
#define CP0St_R0 3
#define CP0St_KSU 3
#define CP0St_ERL 2
#define CP0St_EXL 1
#define CP0St_IE 0
@ -418,9 +417,14 @@ struct CPUMIPSState {
/* TMASK defines different execution modes */
#define MIPS_HFLAG_TMASK 0x00FF
#define MIPS_HFLAG_MODE 0x0007 /* execution modes */
#define MIPS_HFLAG_UM 0x0001 /* user mode */
#define MIPS_HFLAG_DM 0x0002 /* Debug mode */
#define MIPS_HFLAG_SM 0x0004 /* Supervisor mode */
/* The KSU flags must be the lowest bits in hflags. The flag order
must be the same as defined for CP0 Status. This allows to use
the bits as the value of mmu_idx. */
#define MIPS_HFLAG_KSU 0x0003 /* kernel/supervisor/user mode mask */
#define MIPS_HFLAG_UM 0x0002 /* user mode flag */
#define MIPS_HFLAG_SM 0x0001 /* supervisor mode flag */
#define MIPS_HFLAG_KM 0x0000 /* kernel mode flag */
#define MIPS_HFLAG_DM 0x0004 /* Debug mode */
#define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */
#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
@ -489,13 +493,15 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
#define cpu_signal_handler cpu_mips_signal_handler
#define cpu_list mips_cpu_list
/* MMU modes definitions */
/* MMU modes definitions. We carefully match the indices with our
hflags layout. */
#define MMU_MODE0_SUFFIX _kernel
#define MMU_MODE1_SUFFIX _user
#define MMU_USER_IDX 1
#define MMU_MODE1_SUFFIX _super
#define MMU_MODE2_SUFFIX _user
#define MMU_USER_IDX 2
static inline int cpu_mmu_index (CPUState *env)
{
return (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 1 : 0;
return env->hflags & MIPS_HFLAG_KSU;
}
#include "cpu-all.h"

View File

@ -230,24 +230,20 @@ static always_inline int cpu_halted(CPUState *env)
static always_inline void compute_hflags(CPUState *env)
{
env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 |
MIPS_HFLAG_FPU | MIPS_HFLAG_UM);
MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM)) {
if (env->CP0_Status & (1 << CP0St_UM))
env->hflags |= MIPS_HFLAG_UM;
if (env->CP0_Status & (1 << CP0St_R0))
env->hflags |= MIPS_HFLAG_SM;
env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
}
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
if (!(env->hflags & MIPS_HFLAG_UM) ||
if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
(env->CP0_Status & (1 << CP0St_PX)) ||
(env->CP0_Status & (1 << CP0St_UX)))
env->hflags |= MIPS_HFLAG_64;
#endif
if ((env->CP0_Status & (1 << CP0St_CU0)) ||
(!(env->hflags & MIPS_HFLAG_UM) &&
!(env->hflags & MIPS_HFLAG_SM)))
!(env->hflags & MIPS_HFLAG_KSU))
env->hflags |= MIPS_HFLAG_CP0;
if (env->CP0_Status & (1 << CP0St_CU1))
env->hflags |= MIPS_HFLAG_FPU;

View File

@ -373,7 +373,7 @@ void do_interrupt (CPUState *env)
}
enter_debug_mode:
env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
env->hflags &= ~(MIPS_HFLAG_KSU);
/* EJTAG probe trap enable is not implemented... */
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
@ -399,7 +399,7 @@ void do_interrupt (CPUState *env)
}
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
env->hflags &= ~(MIPS_HFLAG_KSU);
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->PC[env->current_tc] = (int32_t)0xBFC00000;
@ -501,7 +501,7 @@ void do_interrupt (CPUState *env)
}
env->CP0_Status |= (1 << CP0St_EXL);
env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
env->hflags &= ~(MIPS_HFLAG_KSU);
}
env->hflags &= ~MIPS_HFLAG_BMASK;
if (env->CP0_Status & (1 << CP0St_BEV)) {

View File

@ -286,6 +286,10 @@ void op_store_LO (void)
#include "op_mem.c"
#undef MEMSUFFIX
#define MEMSUFFIX _super
#include "op_mem.c"
#undef MEMSUFFIX
#define MEMSUFFIX _kernel
#include "op_mem.c"
#undef MEMSUFFIX
@ -298,7 +302,7 @@ void op_addr_add (void)
with Status_UX = 0 should be casted to 32-bit and sign extended.
See the MIPS64 PRA manual, section 4.10. */
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
if ((env->hflags & MIPS_HFLAG_UM) &&
if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
!(env->CP0_Status & (1 << CP0St_UX)))
T0 = (int64_t)(int32_t)(T0 + T1);
else
@ -1269,7 +1273,7 @@ void op_mftc0_status(void)
T0 = env->CP0_Status & ~0xf1000018;
T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0);
T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
RETURN();
}
@ -1833,7 +1837,7 @@ void op_mttc0_status(void)
env->CP0_Status = T0 & ~0xf1000018;
tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_R0)) << (CP0TCSt_TKSU - CP0St_R0));
tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
env->CP0_TCStatus[other_tc] = tcstatus;
RETURN();
}

View File

@ -315,8 +315,12 @@ void do_mtc0_status_debug(uint32_t old, uint32_t val)
old, old & env->CP0_Cause & CP0Ca_IP_mask,
val, val & env->CP0_Cause & CP0Ca_IP_mask,
env->CP0_Cause);
(env->hflags & MIPS_HFLAG_UM) ? fputs(", UM\n", logfile)
: fputs("\n", logfile);
switch (env->hflags & MIPS_HFLAG_KSU) {
case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
case MIPS_HFLAG_KM: fputs("\n", logfile); break;
default: cpu_abort(env, "Invalid MMU mode!\n"); break;
}
}
void do_mtc0_status_irqraise_debug(void)
@ -518,10 +522,12 @@ void debug_post_eret (void)
fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
if (env->hflags & MIPS_HFLAG_DM)
fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
if (env->hflags & MIPS_HFLAG_UM)
fputs(", UM\n", logfile);
else
fputs("\n", logfile);
switch (env->hflags & MIPS_HFLAG_KSU) {
case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
case MIPS_HFLAG_KM: fputs("\n", logfile); break;
default: cpu_abort(env, "Invalid MMU mode!\n"); break;
}
}
void do_pmon (int function)

View File

@ -790,13 +790,15 @@ static always_inline void check_mips_64(DisasContext *ctx)
#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
#define OP_LD_TABLE(width) \
static GenOpFunc *gen_op_l##width[] = { \
&gen_op_l##width##_user, \
&gen_op_l##width##_kernel, \
&gen_op_l##width##_super, \
&gen_op_l##width##_user, \
}
#define OP_ST_TABLE(width) \
static GenOpFunc *gen_op_s##width[] = { \
&gen_op_s##width##_user, \
&gen_op_s##width##_kernel, \
&gen_op_s##width##_super, \
&gen_op_s##width##_user, \
}
#endif
@ -6494,9 +6496,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
restore_cpu_state(env, &ctx);
#if defined(CONFIG_USER_ONLY)
ctx.mem_idx = 0;
ctx.mem_idx = MIPS_HFLAG_UM;
#else
ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
#endif
#ifdef DEBUG_DISAS
if (loglevel & CPU_LOG_TB_CPU) {
@ -6507,7 +6509,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
#endif
#ifdef MIPS_DEBUG_DISAS
if (loglevel & CPU_LOG_TB_IN_ASM)
fprintf(logfile, "\ntb %p super %d cond %04x\n",
fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
tb, ctx.mem_idx, ctx.hflags);
#endif
while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {