Commit 671880e651e611ec32dbb978e61c0bd4bc3e180e

Authored by ths
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
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) |
... ...