Commit 55754d9ef27178cf0e13aea85062fc4c32e25f83
1 parent
afc7df11
MMU fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1308 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
38 additions
and
16 deletions
target-sparc/helper.c
| @@ -414,9 +414,9 @@ target_ulong mmu_probe(target_ulong address, int mmulev) | @@ -414,9 +414,9 @@ target_ulong mmu_probe(target_ulong address, int mmulev) | ||
| 414 | return 0; | 414 | return 0; |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | +#ifdef DEBUG_MMU | ||
| 417 | void dump_mmu(void) | 418 | void dump_mmu(void) |
| 418 | { | 419 | { |
| 419 | -#ifdef DEBUG_MMU | ||
| 420 | target_ulong va, va1, va2; | 420 | target_ulong va, va1, va2; |
| 421 | unsigned int n, m, o; | 421 | unsigned int n, m, o; |
| 422 | target_phys_addr_t pde_ptr, pa; | 422 | target_phys_addr_t pde_ptr, pa; |
| @@ -448,5 +448,5 @@ void dump_mmu(void) | @@ -448,5 +448,5 @@ void dump_mmu(void) | ||
| 448 | } | 448 | } |
| 449 | } | 449 | } |
| 450 | printf("MMU dump ends\n"); | 450 | printf("MMU dump ends\n"); |
| 451 | -#endif | ||
| 452 | } | 451 | } |
| 452 | +#endif |
target-sparc/op_helper.c
| @@ -105,8 +105,11 @@ void helper_ld_asi(int asi, int size, int sign) | @@ -105,8 +105,11 @@ void helper_ld_asi(int asi, int size, int sign) | ||
| 105 | int reg = (T0 >> 8) & 0xf; | 105 | int reg = (T0 >> 8) & 0xf; |
| 106 | 106 | ||
| 107 | ret = env->mmuregs[reg]; | 107 | ret = env->mmuregs[reg]; |
| 108 | - if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/ | ||
| 109 | - env->mmuregs[4] = 0; | 108 | + if (reg == 3) /* Fault status cleared on read */ |
| 109 | + env->mmuregs[reg] = 0; | ||
| 110 | +#ifdef DEBUG_MMU | ||
| 111 | + printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret); | ||
| 112 | +#endif | ||
| 110 | } | 113 | } |
| 111 | break; | 114 | break; |
| 112 | case 0x20 ... 0x2f: /* MMU passthrough */ | 115 | case 0x20 ... 0x2f: /* MMU passthrough */ |
| @@ -131,20 +134,25 @@ void helper_st_asi(int asi, int size, int sign) | @@ -131,20 +134,25 @@ void helper_st_asi(int asi, int size, int sign) | ||
| 131 | int mmulev; | 134 | int mmulev; |
| 132 | 135 | ||
| 133 | mmulev = (T0 >> 8) & 15; | 136 | mmulev = (T0 >> 8) & 15; |
| 137 | +#ifdef DEBUG_MMU | ||
| 138 | + printf("mmu flush level %d\n", mmulev); | ||
| 139 | +#endif | ||
| 134 | switch (mmulev) { | 140 | switch (mmulev) { |
| 135 | case 0: // flush page | 141 | case 0: // flush page |
| 136 | - tlb_flush_page(cpu_single_env, T0 & 0xfffff000); | 142 | + tlb_flush_page(env, T0 & 0xfffff000); |
| 137 | break; | 143 | break; |
| 138 | case 1: // flush segment (256k) | 144 | case 1: // flush segment (256k) |
| 139 | case 2: // flush region (16M) | 145 | case 2: // flush region (16M) |
| 140 | case 3: // flush context (4G) | 146 | case 3: // flush context (4G) |
| 141 | case 4: // flush entire | 147 | case 4: // flush entire |
| 142 | - tlb_flush(cpu_single_env, 1); | 148 | + tlb_flush(env, 1); |
| 143 | break; | 149 | break; |
| 144 | default: | 150 | default: |
| 145 | break; | 151 | break; |
| 146 | } | 152 | } |
| 153 | +#ifdef DEBUG_MMU | ||
| 147 | dump_mmu(); | 154 | dump_mmu(); |
| 155 | +#endif | ||
| 148 | return; | 156 | return; |
| 149 | } | 157 | } |
| 150 | case 4: /* write MMU regs */ | 158 | case 4: /* write MMU regs */ |
| @@ -152,20 +160,34 @@ void helper_st_asi(int asi, int size, int sign) | @@ -152,20 +160,34 @@ void helper_st_asi(int asi, int size, int sign) | ||
| 152 | int reg = (T0 >> 8) & 0xf, oldreg; | 160 | int reg = (T0 >> 8) & 0xf, oldreg; |
| 153 | 161 | ||
| 154 | oldreg = env->mmuregs[reg]; | 162 | oldreg = env->mmuregs[reg]; |
| 155 | - if (reg == 0) { | 163 | + switch(reg) { |
| 164 | + case 0: | ||
| 156 | env->mmuregs[reg] &= ~(MMU_E | MMU_NF); | 165 | env->mmuregs[reg] &= ~(MMU_E | MMU_NF); |
| 157 | env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); | 166 | env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); |
| 158 | - } else | 167 | + if ((oldreg & MMU_E) != (env->mmuregs[reg] & MMU_E)) |
| 168 | + tlb_flush(env, 1); | ||
| 169 | + break; | ||
| 170 | + case 2: | ||
| 159 | env->mmuregs[reg] = T1; | 171 | env->mmuregs[reg] = T1; |
| 160 | - if (oldreg != env->mmuregs[reg]) { | ||
| 161 | -#if 0 | ||
| 162 | - // XXX: Only if MMU mapping change, we may need to flush? | ||
| 163 | - tlb_flush(cpu_single_env, 1); | ||
| 164 | - cpu_loop_exit(); | ||
| 165 | - FORCE_RET(); | ||
| 166 | -#endif | ||
| 167 | - } | 172 | + if (oldreg != env->mmuregs[reg]) { |
| 173 | + /* we flush when the MMU context changes because | ||
| 174 | + QEMU has no MMU context support */ | ||
| 175 | + tlb_flush(env, 1); | ||
| 176 | + } | ||
| 177 | + break; | ||
| 178 | + case 3: | ||
| 179 | + case 4: | ||
| 180 | + break; | ||
| 181 | + default: | ||
| 182 | + env->mmuregs[reg] = T1; | ||
| 183 | + break; | ||
| 184 | + } | ||
| 185 | +#ifdef DEBUG_MMU | ||
| 186 | + if (oldreg != env->mmuregs[reg]) { | ||
| 187 | + printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); | ||
| 188 | + } | ||
| 168 | dump_mmu(); | 189 | dump_mmu(); |
| 190 | +#endif | ||
| 169 | return; | 191 | return; |
| 170 | } | 192 | } |
| 171 | case 0x17: /* Block copy, sta access */ | 193 | case 0x17: /* Block copy, sta access */ |