Commit 623a930ec30a75e6d6482ca8208d7bf1ca8d359b

Authored by ths
1 parent 8e129e07

Implement missing MIPS supervisor mode bits.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3472 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-defs.h
... ... @@ -122,7 +122,7 @@ typedef struct CPUTLBEntry {
122 122 written */ \
123 123 target_ulong mem_write_vaddr; /* target virtual addr at which the \
124 124 memory was written */ \
125   - /* 0 = kernel, 1 = user */ \
  125 + /* The meaning of the MMU modes is defined in the target code. */ \
126 126 CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
127 127 struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
128 128 \
... ...
linux-user/elfload.c
... ... @@ -374,7 +374,7 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
374 374  
375 375 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
376 376 {
377   - regs->cp0_status = CP0St_UM;
  377 + regs->cp0_status = 2 << CP0St_KSU;
378 378 regs->cp0_epc = infop->entry;
379 379 regs->regs[29] = infop->start_stack;
380 380 }
... ...
target-mips/cpu.h
... ... @@ -107,7 +107,7 @@ struct CPUMIPSFPUContext {
107 107 #define FP_UNIMPLEMENTED 32
108 108 };
109 109  
110   -#define NB_MMU_MODES 2
  110 +#define NB_MMU_MODES 3
111 111  
112 112 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
113 113 struct CPUMIPSMVPContext {
... ... @@ -285,8 +285,7 @@ struct CPUMIPSState {
285 285 #define CP0St_KX 7
286 286 #define CP0St_SX 6
287 287 #define CP0St_UX 5
288   -#define CP0St_UM 4
289   -#define CP0St_R0 3
  288 +#define CP0St_KSU 3
290 289 #define CP0St_ERL 2
291 290 #define CP0St_EXL 1
292 291 #define CP0St_IE 0
... ... @@ -418,9 +417,14 @@ struct CPUMIPSState {
418 417 /* TMASK defines different execution modes */
419 418 #define MIPS_HFLAG_TMASK 0x00FF
420 419 #define MIPS_HFLAG_MODE 0x0007 /* execution modes */
421   -#define MIPS_HFLAG_UM 0x0001 /* user mode */
422   -#define MIPS_HFLAG_DM 0x0002 /* Debug mode */
423   -#define MIPS_HFLAG_SM 0x0004 /* Supervisor mode */
  420 + /* The KSU flags must be the lowest bits in hflags. The flag order
  421 + must be the same as defined for CP0 Status. This allows to use
  422 + the bits as the value of mmu_idx. */
  423 +#define MIPS_HFLAG_KSU 0x0003 /* kernel/supervisor/user mode mask */
  424 +#define MIPS_HFLAG_UM 0x0002 /* user mode flag */
  425 +#define MIPS_HFLAG_SM 0x0001 /* supervisor mode flag */
  426 +#define MIPS_HFLAG_KM 0x0000 /* kernel mode flag */
  427 +#define MIPS_HFLAG_DM 0x0004 /* Debug mode */
424 428 #define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */
425 429 #define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
426 430 #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,
489 493 #define cpu_signal_handler cpu_mips_signal_handler
490 494 #define cpu_list mips_cpu_list
491 495  
492   -/* MMU modes definitions */
  496 +/* MMU modes definitions. We carefully match the indices with our
  497 + hflags layout. */
493 498 #define MMU_MODE0_SUFFIX _kernel
494   -#define MMU_MODE1_SUFFIX _user
495   -#define MMU_USER_IDX 1
  499 +#define MMU_MODE1_SUFFIX _super
  500 +#define MMU_MODE2_SUFFIX _user
  501 +#define MMU_USER_IDX 2
496 502 static inline int cpu_mmu_index (CPUState *env)
497 503 {
498   - return (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 1 : 0;
  504 + return env->hflags & MIPS_HFLAG_KSU;
499 505 }
500 506  
501 507 #include "cpu-all.h"
... ...
target-mips/exec.h
... ... @@ -230,24 +230,20 @@ static always_inline int cpu_halted(CPUState *env)
230 230 static always_inline void compute_hflags(CPUState *env)
231 231 {
232 232 env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 |
233   - MIPS_HFLAG_FPU | MIPS_HFLAG_UM);
  233 + MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
234 234 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
235 235 !(env->CP0_Status & (1 << CP0St_ERL)) &&
236 236 !(env->hflags & MIPS_HFLAG_DM)) {
237   - if (env->CP0_Status & (1 << CP0St_UM))
238   - env->hflags |= MIPS_HFLAG_UM;
239   - if (env->CP0_Status & (1 << CP0St_R0))
240   - env->hflags |= MIPS_HFLAG_SM;
  237 + env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
241 238 }
242 239 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
243   - if (!(env->hflags & MIPS_HFLAG_UM) ||
  240 + if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
244 241 (env->CP0_Status & (1 << CP0St_PX)) ||
245 242 (env->CP0_Status & (1 << CP0St_UX)))
246 243 env->hflags |= MIPS_HFLAG_64;
247 244 #endif
248 245 if ((env->CP0_Status & (1 << CP0St_CU0)) ||
249   - (!(env->hflags & MIPS_HFLAG_UM) &&
250   - !(env->hflags & MIPS_HFLAG_SM)))
  246 + !(env->hflags & MIPS_HFLAG_KSU))
251 247 env->hflags |= MIPS_HFLAG_CP0;
252 248 if (env->CP0_Status & (1 << CP0St_CU1))
253 249 env->hflags |= MIPS_HFLAG_FPU;
... ...
target-mips/helper.c
... ... @@ -373,7 +373,7 @@ void do_interrupt (CPUState *env)
373 373 }
374 374 enter_debug_mode:
375 375 env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
376   - env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
  376 + env->hflags &= ~(MIPS_HFLAG_KSU);
377 377 /* EJTAG probe trap enable is not implemented... */
378 378 if (!(env->CP0_Status & (1 << CP0St_EXL)))
379 379 env->CP0_Cause &= ~(1 << CP0Ca_BD);
... ... @@ -399,7 +399,7 @@ void do_interrupt (CPUState *env)
399 399 }
400 400 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
401 401 env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
402   - env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
  402 + env->hflags &= ~(MIPS_HFLAG_KSU);
403 403 if (!(env->CP0_Status & (1 << CP0St_EXL)))
404 404 env->CP0_Cause &= ~(1 << CP0Ca_BD);
405 405 env->PC[env->current_tc] = (int32_t)0xBFC00000;
... ... @@ -501,7 +501,7 @@ void do_interrupt (CPUState *env)
501 501 }
502 502 env->CP0_Status |= (1 << CP0St_EXL);
503 503 env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
504   - env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
  504 + env->hflags &= ~(MIPS_HFLAG_KSU);
505 505 }
506 506 env->hflags &= ~MIPS_HFLAG_BMASK;
507 507 if (env->CP0_Status & (1 << CP0St_BEV)) {
... ...
target-mips/op.c
... ... @@ -286,6 +286,10 @@ void op_store_LO (void)
286 286 #include "op_mem.c"
287 287 #undef MEMSUFFIX
288 288  
  289 +#define MEMSUFFIX _super
  290 +#include "op_mem.c"
  291 +#undef MEMSUFFIX
  292 +
289 293 #define MEMSUFFIX _kernel
290 294 #include "op_mem.c"
291 295 #undef MEMSUFFIX
... ... @@ -298,7 +302,7 @@ void op_addr_add (void)
298 302 with Status_UX = 0 should be casted to 32-bit and sign extended.
299 303 See the MIPS64 PRA manual, section 4.10. */
300 304 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
301   - if ((env->hflags & MIPS_HFLAG_UM) &&
  305 + if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
302 306 !(env->CP0_Status & (1 << CP0St_UX)))
303 307 T0 = (int64_t)(int32_t)(T0 + T1);
304 308 else
... ... @@ -1269,7 +1273,7 @@ void op_mftc0_status(void)
1269 1273 T0 = env->CP0_Status & ~0xf1000018;
1270 1274 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1271 1275 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
1272   - T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0);
  1276 + T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
1273 1277 RETURN();
1274 1278 }
1275 1279  
... ... @@ -1833,7 +1837,7 @@ void op_mttc0_status(void)
1833 1837 env->CP0_Status = T0 & ~0xf1000018;
1834 1838 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1835 1839 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1836   - tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_R0)) << (CP0TCSt_TKSU - CP0St_R0));
  1840 + tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1837 1841 env->CP0_TCStatus[other_tc] = tcstatus;
1838 1842 RETURN();
1839 1843 }
... ...
target-mips/op_helper.c
... ... @@ -315,8 +315,12 @@ void do_mtc0_status_debug(uint32_t old, uint32_t val)
315 315 old, old & env->CP0_Cause & CP0Ca_IP_mask,
316 316 val, val & env->CP0_Cause & CP0Ca_IP_mask,
317 317 env->CP0_Cause);
318   - (env->hflags & MIPS_HFLAG_UM) ? fputs(", UM\n", logfile)
319   - : fputs("\n", logfile);
  318 + switch (env->hflags & MIPS_HFLAG_KSU) {
  319 + case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
  320 + case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
  321 + case MIPS_HFLAG_KM: fputs("\n", logfile); break;
  322 + default: cpu_abort(env, "Invalid MMU mode!\n"); break;
  323 + }
320 324 }
321 325  
322 326 void do_mtc0_status_irqraise_debug(void)
... ... @@ -518,10 +522,12 @@ void debug_post_eret (void)
518 522 fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
519 523 if (env->hflags & MIPS_HFLAG_DM)
520 524 fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
521   - if (env->hflags & MIPS_HFLAG_UM)
522   - fputs(", UM\n", logfile);
523   - else
524   - fputs("\n", logfile);
  525 + switch (env->hflags & MIPS_HFLAG_KSU) {
  526 + case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
  527 + case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
  528 + case MIPS_HFLAG_KM: fputs("\n", logfile); break;
  529 + default: cpu_abort(env, "Invalid MMU mode!\n"); break;
  530 + }
525 531 }
526 532  
527 533 void do_pmon (int function)
... ...
target-mips/translate.c
... ... @@ -790,13 +790,15 @@ static always_inline void check_mips_64(DisasContext *ctx)
790 790 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
791 791 #define OP_LD_TABLE(width) \
792 792 static GenOpFunc *gen_op_l##width[] = { \
793   - &gen_op_l##width##_user, \
794 793 &gen_op_l##width##_kernel, \
  794 + &gen_op_l##width##_super, \
  795 + &gen_op_l##width##_user, \
795 796 }
796 797 #define OP_ST_TABLE(width) \
797 798 static GenOpFunc *gen_op_s##width[] = { \
798   - &gen_op_s##width##_user, \
799 799 &gen_op_s##width##_kernel, \
  800 + &gen_op_s##width##_super, \
  801 + &gen_op_s##width##_user, \
800 802 }
801 803 #endif
802 804  
... ... @@ -6494,9 +6496,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
6494 6496 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
6495 6497 restore_cpu_state(env, &ctx);
6496 6498 #if defined(CONFIG_USER_ONLY)
6497   - ctx.mem_idx = 0;
  6499 + ctx.mem_idx = MIPS_HFLAG_UM;
6498 6500 #else
6499   - ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
  6501 + ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
6500 6502 #endif
6501 6503 #ifdef DEBUG_DISAS
6502 6504 if (loglevel & CPU_LOG_TB_CPU) {
... ... @@ -6507,7 +6509,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
6507 6509 #endif
6508 6510 #ifdef MIPS_DEBUG_DISAS
6509 6511 if (loglevel & CPU_LOG_TB_IN_ASM)
6510   - fprintf(logfile, "\ntb %p super %d cond %04x\n",
  6512 + fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
6511 6513 tb, ctx.mem_idx, ctx.hflags);
6512 6514 #endif
6513 6515 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
... ...