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,6 +389,9 @@ void cpu_x86_init_mmu(CPUX86State *env); | ||
| 389 | extern int phys_ram_size; | 389 | extern int phys_ram_size; |
| 390 | extern int phys_ram_fd; | 390 | extern int phys_ram_fd; |
| 391 | extern uint8_t *phys_ram_base; | 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 | /* used to debug */ | 396 | /* used to debug */ |
| 394 | #define X86_DUMP_FPU 0x0001 /* dump FPU state too */ | 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,10 +158,29 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) | ||
| 158 | /* called when cr3 or PG bit are modified */ | 158 | /* called when cr3 or PG bit are modified */ |
| 159 | static int last_pg_state = -1; | 159 | static int last_pg_state = -1; |
| 160 | static int last_pe_state = 0; | 160 | static int last_pe_state = 0; |
| 161 | +static uint32_t a20_mask; | ||
| 162 | +int a20_enabled; | ||
| 163 | + | ||
| 161 | int phys_ram_size; | 164 | int phys_ram_size; |
| 162 | int phys_ram_fd; | 165 | int phys_ram_fd; |
| 163 | uint8_t *phys_ram_base; | 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 | void cpu_x86_update_cr0(CPUX86State *env) | 184 | void cpu_x86_update_cr0(CPUX86State *env) |
| 166 | { | 185 | { |
| 167 | int pg_state, pe_state; | 186 | int pg_state, pe_state; |
| @@ -195,6 +214,9 @@ void cpu_x86_update_cr3(CPUX86State *env) | @@ -195,6 +214,9 @@ void cpu_x86_update_cr3(CPUX86State *env) | ||
| 195 | 214 | ||
| 196 | void cpu_x86_init_mmu(CPUX86State *env) | 215 | void cpu_x86_init_mmu(CPUX86State *env) |
| 197 | { | 216 | { |
| 217 | + a20_enabled = 1; | ||
| 218 | + a20_mask = 0xffffffff; | ||
| 219 | + | ||
| 198 | last_pg_state = -1; | 220 | last_pg_state = -1; |
| 199 | cpu_x86_update_cr0(env); | 221 | cpu_x86_update_cr0(env); |
| 200 | } | 222 | } |
| @@ -244,14 +266,15 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | @@ -244,14 +266,15 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | ||
| 244 | 266 | ||
| 245 | if (!(env->cr[0] & CR0_PG_MASK)) { | 267 | if (!(env->cr[0] & CR0_PG_MASK)) { |
| 246 | pte = addr; | 268 | pte = addr; |
| 247 | - virt_addr = addr & ~0xfff; | 269 | + virt_addr = addr & TARGET_PAGE_MASK; |
| 248 | prot = PROT_READ | PROT_WRITE; | 270 | prot = PROT_READ | PROT_WRITE; |
| 249 | page_size = 4096; | 271 | page_size = 4096; |
| 250 | goto do_mapping; | 272 | goto do_mapping; |
| 251 | } | 273 | } |
| 252 | 274 | ||
| 253 | /* page directory entry */ | 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 | pde = ldl_raw(pde_ptr); | 278 | pde = ldl_raw(pde_ptr); |
| 256 | if (!(pde & PG_PRESENT_MASK)) { | 279 | if (!(pde & PG_PRESENT_MASK)) { |
| 257 | error_code = 0; | 280 | error_code = 0; |
| @@ -287,7 +310,8 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | @@ -287,7 +310,8 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | ||
| 287 | } | 310 | } |
| 288 | 311 | ||
| 289 | /* page directory entry */ | 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 | pte = ldl_raw(pte_ptr); | 315 | pte = ldl_raw(pte_ptr); |
| 292 | if (!(pte & PG_PRESENT_MASK)) { | 316 | if (!(pte & PG_PRESENT_MASK)) { |
| 293 | error_code = 0; | 317 | error_code = 0; |
| @@ -325,6 +349,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | @@ -325,6 +349,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | ||
| 325 | } | 349 | } |
| 326 | 350 | ||
| 327 | do_mapping: | 351 | do_mapping: |
| 352 | + pte = pte & a20_mask; | ||
| 328 | #if !defined(CONFIG_SOFTMMU) | 353 | #if !defined(CONFIG_SOFTMMU) |
| 329 | if (is_softmmu) | 354 | if (is_softmmu) |
| 330 | #endif | 355 | #endif |
| @@ -334,8 +359,8 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | @@ -334,8 +359,8 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | ||
| 334 | 359 | ||
| 335 | /* software MMU case. Even if 4MB pages, we map only one 4KB | 360 | /* software MMU case. Even if 4MB pages, we map only one 4KB |
| 336 | page in the cache to avoid filling it too fast */ | 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 | vaddr = virt_addr + page_offset; | 364 | vaddr = virt_addr + page_offset; |
| 340 | index = (addr >> 12) & (CPU_TLB_SIZE - 1); | 365 | index = (addr >> 12) & (CPU_TLB_SIZE - 1); |
| 341 | pd = physpage_find(paddr); | 366 | pd = physpage_find(paddr); |