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 | 261 | MIPS_HFLAG_FPU | MIPS_HFLAG_UM); |
262 | 262 | if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
263 | 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 | 270 | #ifdef TARGET_MIPS64 |
268 | 271 | if (!(env->hflags & MIPS_HFLAG_UM) || |
269 | 272 | (env->CP0_Status & (1 << CP0St_PX)) || |
270 | 273 | (env->CP0_Status & (1 << CP0St_UX))) |
271 | 274 | env->hflags |= MIPS_HFLAG_64; |
272 | 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 | 279 | env->hflags |= MIPS_HFLAG_CP0; |
275 | 280 | if (env->CP0_Status & (1 << CP0St_CU1)) |
276 | 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 | 106 | { |
107 | 107 | /* User mode can only access useg/xuseg */ |
108 | 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 | 111 | #ifdef TARGET_MIPS64 |
110 | 112 | int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; |
111 | 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 | 122 | } |
121 | 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 | 125 | if (address <= (int32_t)0x7FFFFFFFUL) { |
132 | 126 | /* useg */ |
133 | 127 | if (env->CP0_Status & (1 << CP0St_ERL)) { |
... | ... | @@ -150,16 +144,16 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
150 | 144 | } |
151 | 145 | } else if (address < 0x7FFFFFFFFFFFFFFFULL) { |
152 | 146 | /* xsseg */ |
153 | - if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { | |
147 | + if ((supervisor_mode || kernel_mode) && | |
148 | + SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { | |
154 | 149 | ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); |
155 | 150 | } else { |
156 | 151 | ret = TLBRET_BADADDR; |
157 | 152 | } |
158 | 153 | } else if (address < 0xBFFFFFFFFFFFFFFFULL) { |
159 | 154 | /* xkphys */ |
160 | - /* XXX: check supervisor mode */ | |
161 | - if (KX && (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) | |
162 | - { | |
155 | + if (kernel_mode && KX && | |
156 | + (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) { | |
163 | 157 | *physical = address & 0X0000000FFFFFFFFFULL; |
164 | 158 | *prot = PAGE_READ | PAGE_WRITE; |
165 | 159 | } else { |
... | ... | @@ -167,8 +161,8 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
167 | 161 | } |
168 | 162 | } else if (address < 0xFFFFFFFF7FFFFFFFULL) { |
169 | 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 | 166 | ret = env->tlb->map_address(env, physical, prot, address, rw, access_type); |
173 | 167 | } else { |
174 | 168 | ret = TLBRET_BADADDR; |
... | ... | @@ -176,22 +170,35 @@ static int get_physical_address (CPUState *env, target_ulong *physical, |
176 | 170 | #endif |
177 | 171 | } else if (address < (int32_t)0xA0000000UL) { |
178 | 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 | 179 | } else if (address < (int32_t)0xC0000000UL) { |
183 | 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 | 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 | 194 | } else { |
191 | 195 | /* kseg3 */ |
192 | - /* XXX: check supervisor mode */ | |
193 | 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 | 203 | #if 0 |
197 | 204 | if (logfile) { |
... | ... | @@ -369,7 +376,7 @@ void do_interrupt (CPUState *env) |
369 | 376 | } |
370 | 377 | enter_debug_mode: |
371 | 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 | 380 | /* EJTAG probe trap enable is not implemented... */ |
374 | 381 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
375 | 382 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
... | ... | @@ -395,7 +402,7 @@ void do_interrupt (CPUState *env) |
395 | 402 | } |
396 | 403 | env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); |
397 | 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 | 406 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
400 | 407 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
401 | 408 | env->PC[env->current_tc] = (int32_t)0xBFC00000; |
... | ... | @@ -497,7 +504,7 @@ void do_interrupt (CPUState *env) |
497 | 504 | } |
498 | 505 | env->CP0_Status |= (1 << CP0St_EXL); |
499 | 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 | 509 | env->hflags &= ~MIPS_HFLAG_BMASK; |
503 | 510 | if (env->CP0_Status & (1 << CP0St_BEV)) { | ... | ... |
target-mips/translate_init.c
... | ... | @@ -141,7 +141,7 @@ static mips_def_t mips_defs[] = |
141 | 141 | .SYNCI_Step = 32, |
142 | 142 | .CCRes = 2, |
143 | 143 | /* No DSP implemented. */ |
144 | - .CP0_Status_rw_bitmask = 0x1278FF17, | |
144 | + .CP0_Status_rw_bitmask = 0x1278FF1F, | |
145 | 145 | .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, |
146 | 146 | }, |
147 | 147 | { |
... | ... | @@ -156,7 +156,7 @@ static mips_def_t mips_defs[] = |
156 | 156 | .SYNCI_Step = 32, |
157 | 157 | .CCRes = 2, |
158 | 158 | /* No DSP implemented. */ |
159 | - .CP0_Status_rw_bitmask = 0x3678FF17, | |
159 | + .CP0_Status_rw_bitmask = 0x3678FF1F, | |
160 | 160 | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | |
161 | 161 | (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), |
162 | 162 | .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, |
... | ... | @@ -173,7 +173,7 @@ static mips_def_t mips_defs[] = |
173 | 173 | .SYNCI_Step = 32, |
174 | 174 | .CCRes = 2, |
175 | 175 | /* No DSP implemented. */ |
176 | - .CP0_Status_rw_bitmask = 0x3678FF17, | |
176 | + .CP0_Status_rw_bitmask = 0x3678FF1F, | |
177 | 177 | /* No DSP implemented. */ |
178 | 178 | .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) | |
179 | 179 | (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | | ... | ... |