Commit 461c0471af05cf29ac416afdbc9480e4732e4252
1 parent
9c3ad574
a20 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@440 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
33 additions
and
5 deletions
target-i386/cpu.h
| ... | ... | @@ -389,6 +389,9 @@ void cpu_x86_init_mmu(CPUX86State *env); |
| 389 | 389 | extern int phys_ram_size; |
| 390 | 390 | extern int phys_ram_fd; |
| 391 | 391 | extern uint8_t *phys_ram_base; |
| 392 | +extern int a20_enabled; | |
| 393 | + | |
| 394 | +void cpu_x86_set_a20(CPUX86State *env, int a20_state); | |
| 392 | 395 | |
| 393 | 396 | /* used to debug */ |
| 394 | 397 | #define X86_DUMP_FPU 0x0001 /* dump FPU state too */ | ... | ... |
target-i386/helper2.c
| ... | ... | @@ -158,10 +158,29 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) |
| 158 | 158 | /* called when cr3 or PG bit are modified */ |
| 159 | 159 | static int last_pg_state = -1; |
| 160 | 160 | static int last_pe_state = 0; |
| 161 | +static uint32_t a20_mask; | |
| 162 | +int a20_enabled; | |
| 163 | + | |
| 161 | 164 | int phys_ram_size; |
| 162 | 165 | int phys_ram_fd; |
| 163 | 166 | uint8_t *phys_ram_base; |
| 164 | 167 | |
| 168 | +void cpu_x86_set_a20(CPUX86State *env, int a20_state) | |
| 169 | +{ | |
| 170 | + a20_state = (a20_state != 0); | |
| 171 | + if (a20_state != a20_enabled) { | |
| 172 | + /* when a20 is changed, all the MMU mappings are invalid, so | |
| 173 | + we must flush everything */ | |
| 174 | + page_unmap(); | |
| 175 | + tlb_flush(env); | |
| 176 | + a20_enabled = a20_state; | |
| 177 | + if (a20_enabled) | |
| 178 | + a20_mask = 0xffffffff; | |
| 179 | + else | |
| 180 | + a20_mask = 0xffefffff; | |
| 181 | + } | |
| 182 | +} | |
| 183 | + | |
| 165 | 184 | void cpu_x86_update_cr0(CPUX86State *env) |
| 166 | 185 | { |
| 167 | 186 | int pg_state, pe_state; |
| ... | ... | @@ -195,6 +214,9 @@ void cpu_x86_update_cr3(CPUX86State *env) |
| 195 | 214 | |
| 196 | 215 | void cpu_x86_init_mmu(CPUX86State *env) |
| 197 | 216 | { |
| 217 | + a20_enabled = 1; | |
| 218 | + a20_mask = 0xffffffff; | |
| 219 | + | |
| 198 | 220 | last_pg_state = -1; |
| 199 | 221 | cpu_x86_update_cr0(env); |
| 200 | 222 | } |
| ... | ... | @@ -244,14 +266,15 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
| 244 | 266 | |
| 245 | 267 | if (!(env->cr[0] & CR0_PG_MASK)) { |
| 246 | 268 | pte = addr; |
| 247 | - virt_addr = addr & ~0xfff; | |
| 269 | + virt_addr = addr & TARGET_PAGE_MASK; | |
| 248 | 270 | prot = PROT_READ | PROT_WRITE; |
| 249 | 271 | page_size = 4096; |
| 250 | 272 | goto do_mapping; |
| 251 | 273 | } |
| 252 | 274 | |
| 253 | 275 | /* page directory entry */ |
| 254 | - pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)); | |
| 276 | + pde_ptr = phys_ram_base + | |
| 277 | + (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask); | |
| 255 | 278 | pde = ldl_raw(pde_ptr); |
| 256 | 279 | if (!(pde & PG_PRESENT_MASK)) { |
| 257 | 280 | error_code = 0; |
| ... | ... | @@ -287,7 +310,8 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
| 287 | 310 | } |
| 288 | 311 | |
| 289 | 312 | /* page directory entry */ |
| 290 | - pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc)); | |
| 313 | + pte_ptr = phys_ram_base + | |
| 314 | + (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask); | |
| 291 | 315 | pte = ldl_raw(pte_ptr); |
| 292 | 316 | if (!(pte & PG_PRESENT_MASK)) { |
| 293 | 317 | error_code = 0; |
| ... | ... | @@ -325,6 +349,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
| 325 | 349 | } |
| 326 | 350 | |
| 327 | 351 | do_mapping: |
| 352 | + pte = pte & a20_mask; | |
| 328 | 353 | #if !defined(CONFIG_SOFTMMU) |
| 329 | 354 | if (is_softmmu) |
| 330 | 355 | #endif |
| ... | ... | @@ -334,8 +359,8 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
| 334 | 359 | |
| 335 | 360 | /* software MMU case. Even if 4MB pages, we map only one 4KB |
| 336 | 361 | page in the cache to avoid filling it too fast */ |
| 337 | - page_offset = (addr & ~0xfff) & (page_size - 1); | |
| 338 | - paddr = (pte & ~0xfff) + page_offset; | |
| 362 | + page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1); | |
| 363 | + paddr = (pte & TARGET_PAGE_MASK) + page_offset; | |
| 339 | 364 | vaddr = virt_addr + page_offset; |
| 340 | 365 | index = (addr >> 12) & (CPU_TLB_SIZE - 1); |
| 341 | 366 | pd = physpage_find(paddr); | ... | ... |