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,7 +122,7 @@ typedef struct CPUTLBEntry {
122 written */ \ 122 written */ \
123 target_ulong mem_write_vaddr; /* target virtual addr at which the \ 123 target_ulong mem_write_vaddr; /* target virtual addr at which the \
124 memory was written */ \ 124 memory was written */ \
125 - /* 0 = kernel, 1 = user */ \ 125 + /* The meaning of the MMU modes is defined in the target code. */ \
126 CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ 126 CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
127 struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ 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,7 +374,7 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
374 374
375 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 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 regs->cp0_epc = infop->entry; 378 regs->cp0_epc = infop->entry;
379 regs->regs[29] = infop->start_stack; 379 regs->regs[29] = infop->start_stack;
380 } 380 }
target-mips/cpu.h
@@ -107,7 +107,7 @@ struct CPUMIPSFPUContext { @@ -107,7 +107,7 @@ struct CPUMIPSFPUContext {
107 #define FP_UNIMPLEMENTED 32 107 #define FP_UNIMPLEMENTED 32
108 }; 108 };
109 109
110 -#define NB_MMU_MODES 2 110 +#define NB_MMU_MODES 3
111 111
112 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; 112 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
113 struct CPUMIPSMVPContext { 113 struct CPUMIPSMVPContext {
@@ -285,8 +285,7 @@ struct CPUMIPSState { @@ -285,8 +285,7 @@ struct CPUMIPSState {
285 #define CP0St_KX 7 285 #define CP0St_KX 7
286 #define CP0St_SX 6 286 #define CP0St_SX 6
287 #define CP0St_UX 5 287 #define CP0St_UX 5
288 -#define CP0St_UM 4  
289 -#define CP0St_R0 3 288 +#define CP0St_KSU 3
290 #define CP0St_ERL 2 289 #define CP0St_ERL 2
291 #define CP0St_EXL 1 290 #define CP0St_EXL 1
292 #define CP0St_IE 0 291 #define CP0St_IE 0
@@ -418,9 +417,14 @@ struct CPUMIPSState { @@ -418,9 +417,14 @@ struct CPUMIPSState {
418 /* TMASK defines different execution modes */ 417 /* TMASK defines different execution modes */
419 #define MIPS_HFLAG_TMASK 0x00FF 418 #define MIPS_HFLAG_TMASK 0x00FF
420 #define MIPS_HFLAG_MODE 0x0007 /* execution modes */ 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 #define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */ 428 #define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */
425 #define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */ 429 #define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
426 #define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */ 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,13 +493,15 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
489 #define cpu_signal_handler cpu_mips_signal_handler 493 #define cpu_signal_handler cpu_mips_signal_handler
490 #define cpu_list mips_cpu_list 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 #define MMU_MODE0_SUFFIX _kernel 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 static inline int cpu_mmu_index (CPUState *env) 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 #include "cpu-all.h" 507 #include "cpu-all.h"
target-mips/exec.h
@@ -230,24 +230,20 @@ static always_inline int cpu_halted(CPUState *env) @@ -230,24 +230,20 @@ static always_inline int cpu_halted(CPUState *env)
230 static always_inline void compute_hflags(CPUState *env) 230 static always_inline void compute_hflags(CPUState *env)
231 { 231 {
232 env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | 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 if (!(env->CP0_Status & (1 << CP0St_EXL)) && 234 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
235 !(env->CP0_Status & (1 << CP0St_ERL)) && 235 !(env->CP0_Status & (1 << CP0St_ERL)) &&
236 !(env->hflags & MIPS_HFLAG_DM)) { 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 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64) 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 (env->CP0_Status & (1 << CP0St_PX)) || 241 (env->CP0_Status & (1 << CP0St_PX)) ||
245 (env->CP0_Status & (1 << CP0St_UX))) 242 (env->CP0_Status & (1 << CP0St_UX)))
246 env->hflags |= MIPS_HFLAG_64; 243 env->hflags |= MIPS_HFLAG_64;
247 #endif 244 #endif
248 if ((env->CP0_Status & (1 << CP0St_CU0)) || 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 env->hflags |= MIPS_HFLAG_CP0; 247 env->hflags |= MIPS_HFLAG_CP0;
252 if (env->CP0_Status & (1 << CP0St_CU1)) 248 if (env->CP0_Status & (1 << CP0St_CU1))
253 env->hflags |= MIPS_HFLAG_FPU; 249 env->hflags |= MIPS_HFLAG_FPU;
target-mips/helper.c
@@ -373,7 +373,7 @@ void do_interrupt (CPUState *env) @@ -373,7 +373,7 @@ void do_interrupt (CPUState *env)
373 } 373 }
374 enter_debug_mode: 374 enter_debug_mode:
375 env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 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 /* EJTAG probe trap enable is not implemented... */ 377 /* EJTAG probe trap enable is not implemented... */
378 if (!(env->CP0_Status & (1 << CP0St_EXL))) 378 if (!(env->CP0_Status & (1 << CP0St_EXL)))
379 env->CP0_Cause &= ~(1 << CP0Ca_BD); 379 env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -399,7 +399,7 @@ void do_interrupt (CPUState *env) @@ -399,7 +399,7 @@ void do_interrupt (CPUState *env)
399 } 399 }
400 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); 400 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
401 env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 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 if (!(env->CP0_Status & (1 << CP0St_EXL))) 403 if (!(env->CP0_Status & (1 << CP0St_EXL)))
404 env->CP0_Cause &= ~(1 << CP0Ca_BD); 404 env->CP0_Cause &= ~(1 << CP0Ca_BD);
405 env->PC[env->current_tc] = (int32_t)0xBFC00000; 405 env->PC[env->current_tc] = (int32_t)0xBFC00000;
@@ -501,7 +501,7 @@ void do_interrupt (CPUState *env) @@ -501,7 +501,7 @@ void do_interrupt (CPUState *env)
501 } 501 }
502 env->CP0_Status |= (1 << CP0St_EXL); 502 env->CP0_Status |= (1 << CP0St_EXL);
503 env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 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 env->hflags &= ~MIPS_HFLAG_BMASK; 506 env->hflags &= ~MIPS_HFLAG_BMASK;
507 if (env->CP0_Status & (1 << CP0St_BEV)) { 507 if (env->CP0_Status & (1 << CP0St_BEV)) {
target-mips/op.c
@@ -286,6 +286,10 @@ void op_store_LO (void) @@ -286,6 +286,10 @@ void op_store_LO (void)
286 #include "op_mem.c" 286 #include "op_mem.c"
287 #undef MEMSUFFIX 287 #undef MEMSUFFIX
288 288
  289 +#define MEMSUFFIX _super
  290 +#include "op_mem.c"
  291 +#undef MEMSUFFIX
  292 +
289 #define MEMSUFFIX _kernel 293 #define MEMSUFFIX _kernel
290 #include "op_mem.c" 294 #include "op_mem.c"
291 #undef MEMSUFFIX 295 #undef MEMSUFFIX
@@ -298,7 +302,7 @@ void op_addr_add (void) @@ -298,7 +302,7 @@ void op_addr_add (void)
298 with Status_UX = 0 should be casted to 32-bit and sign extended. 302 with Status_UX = 0 should be casted to 32-bit and sign extended.
299 See the MIPS64 PRA manual, section 4.10. */ 303 See the MIPS64 PRA manual, section 4.10. */
300 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64) 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 !(env->CP0_Status & (1 << CP0St_UX))) 306 !(env->CP0_Status & (1 << CP0St_UX)))
303 T0 = (int64_t)(int32_t)(T0 + T1); 307 T0 = (int64_t)(int32_t)(T0 + T1);
304 else 308 else
@@ -1269,7 +1273,7 @@ void op_mftc0_status(void) @@ -1269,7 +1273,7 @@ void op_mftc0_status(void)
1269 T0 = env->CP0_Status & ~0xf1000018; 1273 T0 = env->CP0_Status & ~0xf1000018;
1270 T0 |= tcstatus & (0xf << CP0TCSt_TCU0); 1274 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1271 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX); 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 RETURN(); 1277 RETURN();
1274 } 1278 }
1275 1279
@@ -1833,7 +1837,7 @@ void op_mttc0_status(void) @@ -1833,7 +1837,7 @@ void op_mttc0_status(void)
1833 env->CP0_Status = T0 & ~0xf1000018; 1837 env->CP0_Status = T0 & ~0xf1000018;
1834 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0)); 1838 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1835 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX)); 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 env->CP0_TCStatus[other_tc] = tcstatus; 1841 env->CP0_TCStatus[other_tc] = tcstatus;
1838 RETURN(); 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,8 +315,12 @@ void do_mtc0_status_debug(uint32_t old, uint32_t val)
315 old, old & env->CP0_Cause & CP0Ca_IP_mask, 315 old, old & env->CP0_Cause & CP0Ca_IP_mask,
316 val, val & env->CP0_Cause & CP0Ca_IP_mask, 316 val, val & env->CP0_Cause & CP0Ca_IP_mask,
317 env->CP0_Cause); 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 void do_mtc0_status_irqraise_debug(void) 326 void do_mtc0_status_irqraise_debug(void)
@@ -518,10 +522,12 @@ void debug_post_eret (void) @@ -518,10 +522,12 @@ void debug_post_eret (void)
518 fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); 522 fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
519 if (env->hflags & MIPS_HFLAG_DM) 523 if (env->hflags & MIPS_HFLAG_DM)
520 fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC); 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 void do_pmon (int function) 533 void do_pmon (int function)
target-mips/translate.c
@@ -790,13 +790,15 @@ static always_inline void check_mips_64(DisasContext *ctx) @@ -790,13 +790,15 @@ static always_inline void check_mips_64(DisasContext *ctx)
790 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])() 790 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
791 #define OP_LD_TABLE(width) \ 791 #define OP_LD_TABLE(width) \
792 static GenOpFunc *gen_op_l##width[] = { \ 792 static GenOpFunc *gen_op_l##width[] = { \
793 - &gen_op_l##width##_user, \  
794 &gen_op_l##width##_kernel, \ 793 &gen_op_l##width##_kernel, \
  794 + &gen_op_l##width##_super, \
  795 + &gen_op_l##width##_user, \
795 } 796 }
796 #define OP_ST_TABLE(width) \ 797 #define OP_ST_TABLE(width) \
797 static GenOpFunc *gen_op_s##width[] = { \ 798 static GenOpFunc *gen_op_s##width[] = { \
798 - &gen_op_s##width##_user, \  
799 &gen_op_s##width##_kernel, \ 799 &gen_op_s##width##_kernel, \
  800 + &gen_op_s##width##_super, \
  801 + &gen_op_s##width##_user, \
800 } 802 }
801 #endif 803 #endif
802 804
@@ -6494,9 +6496,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -6494,9 +6496,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
6494 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */ 6496 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
6495 restore_cpu_state(env, &ctx); 6497 restore_cpu_state(env, &ctx);
6496 #if defined(CONFIG_USER_ONLY) 6498 #if defined(CONFIG_USER_ONLY)
6497 - ctx.mem_idx = 0; 6499 + ctx.mem_idx = MIPS_HFLAG_UM;
6498 #else 6500 #else
6499 - ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM); 6501 + ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
6500 #endif 6502 #endif
6501 #ifdef DEBUG_DISAS 6503 #ifdef DEBUG_DISAS
6502 if (loglevel & CPU_LOG_TB_CPU) { 6504 if (loglevel & CPU_LOG_TB_CPU) {
@@ -6507,7 +6509,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -6507,7 +6509,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
6507 #endif 6509 #endif
6508 #ifdef MIPS_DEBUG_DISAS 6510 #ifdef MIPS_DEBUG_DISAS
6509 if (loglevel & CPU_LOG_TB_IN_ASM) 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 tb, ctx.mem_idx, ctx.hflags); 6513 tb, ctx.mem_idx, ctx.hflags);
6512 #endif 6514 #endif
6513 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { 6515 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {