Commit 671880e651e611ec32dbb978e61c0bd4bc3e180e
1 parent
54454097
Supervisor mode implementation, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3267 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
46 additions
and
34 deletions
target-mips/exec.h
| @@ -261,16 +261,21 @@ static inline void compute_hflags(CPUState *env) | @@ -261,16 +261,21 @@ static inline void compute_hflags(CPUState *env) | ||
| 261 | MIPS_HFLAG_FPU | MIPS_HFLAG_UM); | 261 | MIPS_HFLAG_FPU | MIPS_HFLAG_UM); |
| 262 | if (!(env->CP0_Status & (1 << CP0St_EXL)) && | 262 | if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
| 263 | !(env->CP0_Status & (1 << CP0St_ERL)) && | 263 | !(env->CP0_Status & (1 << CP0St_ERL)) && |
| 264 | - !(env->hflags & MIPS_HFLAG_DM) && | ||
| 265 | - (env->CP0_Status & (1 << CP0St_UM))) | ||
| 266 | - env->hflags |= MIPS_HFLAG_UM; | 264 | + !(env->hflags & MIPS_HFLAG_DM)) { |
| 265 | + if (env->CP0_Status & (1 << CP0St_UM)) | ||
| 266 | + env->hflags |= MIPS_HFLAG_UM; | ||
| 267 | + if (env->CP0_Status & (1 << CP0St_R0)) | ||
| 268 | + env->hflags |= MIPS_HFLAG_SM; | ||
| 269 | + } | ||
| 267 | #ifdef TARGET_MIPS64 | 270 | #ifdef TARGET_MIPS64 |
| 268 | if (!(env->hflags & MIPS_HFLAG_UM) || | 271 | if (!(env->hflags & MIPS_HFLAG_UM) || |
| 269 | (env->CP0_Status & (1 << CP0St_PX)) || | 272 | (env->CP0_Status & (1 << CP0St_PX)) || |
| 270 | (env->CP0_Status & (1 << CP0St_UX))) | 273 | (env->CP0_Status & (1 << CP0St_UX))) |
| 271 | env->hflags |= MIPS_HFLAG_64; | 274 | env->hflags |= MIPS_HFLAG_64; |
| 272 | #endif | 275 | #endif |
| 273 | - if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM)) | 276 | + if ((env->CP0_Status & (1 << CP0St_CU0)) || |
| 277 | + (!(env->hflags & MIPS_HFLAG_UM) && | ||
| 278 | + !(env->hflags & MIPS_HFLAG_SM))) | ||
| 274 | env->hflags |= MIPS_HFLAG_CP0; | 279 | env->hflags |= MIPS_HFLAG_CP0; |
| 275 | if (env->CP0_Status & (1 << CP0St_CU1)) | 280 | if (env->CP0_Status & (1 << CP0St_CU1)) |
| 276 | env->hflags |= MIPS_HFLAG_FPU; | 281 | env->hflags |= MIPS_HFLAG_FPU; |
target-mips/helper.c
| @@ -106,6 +106,8 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -106,6 +106,8 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 106 | { | 106 | { |
| 107 | /* User mode can only access useg/xuseg */ | 107 | /* User mode can only access useg/xuseg */ |
| 108 | int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; | 108 | int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM; |
| 109 | + int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM; | ||
| 110 | + int kernel_mode = !user_mode && !supervisor_mode; | ||
| 109 | #ifdef TARGET_MIPS64 | 111 | #ifdef TARGET_MIPS64 |
| 110 | int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; | 112 | int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; |
| 111 | int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; | 113 | int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; |
| @@ -120,14 +122,6 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -120,14 +122,6 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 120 | } | 122 | } |
| 121 | #endif | 123 | #endif |
| 122 | 124 | ||
| 123 | -#ifdef TARGET_MIPS64 | ||
| 124 | - if (user_mode && address > 0x3FFFFFFFFFFFFFFFULL) | ||
| 125 | - return TLBRET_BADADDR; | ||
| 126 | -#else | ||
| 127 | - if (user_mode && address > 0x7FFFFFFFUL) | ||
| 128 | - return TLBRET_BADADDR; | ||
| 129 | -#endif | ||
| 130 | - | ||
| 131 | if (address <= (int32_t)0x7FFFFFFFUL) { | 125 | if (address <= (int32_t)0x7FFFFFFFUL) { |
| 132 | /* useg */ | 126 | /* useg */ |
| 133 | if (env->CP0_Status & (1 << CP0St_ERL)) { | 127 | if (env->CP0_Status & (1 << CP0St_ERL)) { |
| @@ -150,16 +144,16 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -150,16 +144,16 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 150 | } | 144 | } |
| 151 | } else if (address < 0x7FFFFFFFFFFFFFFFULL) { | 145 | } else if (address < 0x7FFFFFFFFFFFFFFFULL) { |
| 152 | /* xsseg */ | 146 | /* xsseg */ |
| 153 | - if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { | 147 | + if ((supervisor_mode || kernel_mode) && |
| 148 | + SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { | ||
| 154 | ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | 149 | ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); |
| 155 | } else { | 150 | } else { |
| 156 | ret = TLBRET_BADADDR; | 151 | ret = TLBRET_BADADDR; |
| 157 | } | 152 | } |
| 158 | } else if (address < 0xBFFFFFFFFFFFFFFFULL) { | 153 | } else if (address < 0xBFFFFFFFFFFFFFFFULL) { |
| 159 | /* xkphys */ | 154 | /* xkphys */ |
| 160 | - /* XXX: check supervisor mode */ | ||
| 161 | - if (KX && (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) | ||
| 162 | - { | 155 | + if (kernel_mode && KX && |
| 156 | + (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) { | ||
| 163 | *physical = address & 0X0000000FFFFFFFFFULL; | 157 | *physical = address & 0X0000000FFFFFFFFFULL; |
| 164 | *prot = PAGE_READ | PAGE_WRITE; | 158 | *prot = PAGE_READ | PAGE_WRITE; |
| 165 | } else { | 159 | } else { |
| @@ -167,8 +161,8 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -167,8 +161,8 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 167 | } | 161 | } |
| 168 | } else if (address < 0xFFFFFFFF7FFFFFFFULL) { | 162 | } else if (address < 0xFFFFFFFF7FFFFFFFULL) { |
| 169 | /* xkseg */ | 163 | /* xkseg */ |
| 170 | - /* XXX: check supervisor mode */ | ||
| 171 | - if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { | 164 | + if (kernel_mode && KX && |
| 165 | + address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { | ||
| 172 | ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | 166 | ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); |
| 173 | } else { | 167 | } else { |
| 174 | ret = TLBRET_BADADDR; | 168 | ret = TLBRET_BADADDR; |
| @@ -176,22 +170,35 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | @@ -176,22 +170,35 @@ static int get_physical_address (CPUState *env, target_ulong *physical, | ||
| 176 | #endif | 170 | #endif |
| 177 | } else if (address < (int32_t)0xA0000000UL) { | 171 | } else if (address < (int32_t)0xA0000000UL) { |
| 178 | /* kseg0 */ | 172 | /* kseg0 */ |
| 179 | - /* XXX: check supervisor mode */ | ||
| 180 | - *physical = address - (int32_t)0x80000000UL; | ||
| 181 | - *prot = PAGE_READ | PAGE_WRITE; | 173 | + if (kernel_mode) { |
| 174 | + *physical = address - (int32_t)0x80000000UL; | ||
| 175 | + *prot = PAGE_READ | PAGE_WRITE; | ||
| 176 | + } else { | ||
| 177 | + ret = TLBRET_BADADDR; | ||
| 178 | + } | ||
| 182 | } else if (address < (int32_t)0xC0000000UL) { | 179 | } else if (address < (int32_t)0xC0000000UL) { |
| 183 | /* kseg1 */ | 180 | /* kseg1 */ |
| 184 | - /* XXX: check supervisor mode */ | ||
| 185 | - *physical = address - (int32_t)0xA0000000UL; | ||
| 186 | - *prot = PAGE_READ | PAGE_WRITE; | 181 | + if (kernel_mode) { |
| 182 | + *physical = address - (int32_t)0xA0000000UL; | ||
| 183 | + *prot = PAGE_READ | PAGE_WRITE; | ||
| 184 | + } else { | ||
| 185 | + ret = TLBRET_BADADDR; | ||
| 186 | + } | ||
| 187 | } else if (address < (int32_t)0xE0000000UL) { | 187 | } else if (address < (int32_t)0xE0000000UL) { |
| 188 | - /* kseg2 */ | ||
| 189 | - ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | 188 | + /* sseg */ |
| 189 | + if (supervisor_mode || kernel_mode) { | ||
| 190 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | ||
| 191 | + } else { | ||
| 192 | + ret = TLBRET_BADADDR; | ||
| 193 | + } | ||
| 190 | } else { | 194 | } else { |
| 191 | /* kseg3 */ | 195 | /* kseg3 */ |
| 192 | - /* XXX: check supervisor mode */ | ||
| 193 | /* XXX: debug segment is not emulated */ | 196 | /* XXX: debug segment is not emulated */ |
| 194 | - ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | 197 | + if (kernel_mode) { |
| 198 | + ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); | ||
| 199 | + } else { | ||
| 200 | + ret = TLBRET_BADADDR; | ||
| 201 | + } | ||
| 195 | } | 202 | } |
| 196 | #if 0 | 203 | #if 0 |
| 197 | if (logfile) { | 204 | if (logfile) { |
| @@ -369,7 +376,7 @@ void do_interrupt (CPUState *env) | @@ -369,7 +376,7 @@ void do_interrupt (CPUState *env) | ||
| 369 | } | 376 | } |
| 370 | enter_debug_mode: | 377 | enter_debug_mode: |
| 371 | env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; | 378 | env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; |
| 372 | - env->hflags &= ~MIPS_HFLAG_UM; | 379 | + env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM); |
| 373 | /* EJTAG probe trap enable is not implemented... */ | 380 | /* EJTAG probe trap enable is not implemented... */ |
| 374 | if (!(env->CP0_Status & (1 << CP0St_EXL))) | 381 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
| 375 | env->CP0_Cause &= ~(1 << CP0Ca_BD); | 382 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
| @@ -395,7 +402,7 @@ void do_interrupt (CPUState *env) | @@ -395,7 +402,7 @@ void do_interrupt (CPUState *env) | ||
| 395 | } | 402 | } |
| 396 | env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); | 403 | env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); |
| 397 | env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; | 404 | env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; |
| 398 | - env->hflags &= ~MIPS_HFLAG_UM; | 405 | + env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM); |
| 399 | if (!(env->CP0_Status & (1 << CP0St_EXL))) | 406 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
| 400 | env->CP0_Cause &= ~(1 << CP0Ca_BD); | 407 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
| 401 | env->PC[env->current_tc] = (int32_t)0xBFC00000; | 408 | env->PC[env->current_tc] = (int32_t)0xBFC00000; |
| @@ -497,7 +504,7 @@ void do_interrupt (CPUState *env) | @@ -497,7 +504,7 @@ void do_interrupt (CPUState *env) | ||
| 497 | } | 504 | } |
| 498 | env->CP0_Status |= (1 << CP0St_EXL); | 505 | env->CP0_Status |= (1 << CP0St_EXL); |
| 499 | env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; | 506 | env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; |
| 500 | - env->hflags &= ~MIPS_HFLAG_UM; | 507 | + env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM); |
| 501 | } | 508 | } |
| 502 | env->hflags &= ~MIPS_HFLAG_BMASK; | 509 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| 503 | if (env->CP0_Status & (1 << CP0St_BEV)) { | 510 | if (env->CP0_Status & (1 << CP0St_BEV)) { |
target-mips/translate_init.c
| @@ -141,7 +141,7 @@ static mips_def_t mips_defs[] = | @@ -141,7 +141,7 @@ static mips_def_t mips_defs[] = | ||
| 141 | .SYNCI_Step = 32, | 141 | .SYNCI_Step = 32, |
| 142 | .CCRes = 2, | 142 | .CCRes = 2, |
| 143 | /* No DSP implemented. */ | 143 | /* No DSP implemented. */ |
| 144 | - .CP0_Status_rw_bitmask = 0x1278FF17, | 144 | + .CP0_Status_rw_bitmask = 0x1278FF1F, |
| 145 | .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, | 145 | .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, |
| 146 | }, | 146 | }, |
| 147 | { | 147 | { |
| @@ -156,7 +156,7 @@ static mips_def_t mips_defs[] = | @@ -156,7 +156,7 @@ static mips_def_t mips_defs[] = | ||
| 156 | .SYNCI_Step = 32, | 156 | .SYNCI_Step = 32, |
| 157 | .CCRes = 2, | 157 | .CCRes = 2, |
| 158 | /* No DSP implemented. */ | 158 | /* No DSP implemented. */ |
| 159 | - .CP0_Status_rw_bitmask = 0x3678FF17, | 159 | + .CP0_Status_rw_bitmask = 0x3678FF1F, |
| 160 | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | | 160 | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | |
| 161 | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), | 161 | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), |
| 162 | .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, | 162 | .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, |
| @@ -173,7 +173,7 @@ static mips_def_t mips_defs[] = | @@ -173,7 +173,7 @@ static mips_def_t mips_defs[] = | ||
| 173 | .SYNCI_Step = 32, | 173 | .SYNCI_Step = 32, |
| 174 | .CCRes = 2, | 174 | .CCRes = 2, |
| 175 | /* No DSP implemented. */ | 175 | /* No DSP implemented. */ |
| 176 | - .CP0_Status_rw_bitmask = 0x3678FF17, | 176 | + .CP0_Status_rw_bitmask = 0x3678FF1F, |
| 177 | /* No DSP implemented. */ | 177 | /* No DSP implemented. */ |
| 178 | .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) | | 178 | .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) | |
| 179 | (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | | 179 | (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | |