Commit 623a930ec30a75e6d6482ca8208d7bf1ca8d359b
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
Showing
8 changed files
with
51 additions
and
37 deletions
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) { | ... | ... |