Commit 10f0e412f81c40a2b853b0f44708bb92a99cd587

Authored by bellard
1 parent 4b7aba51

combine PDE and PTE protections as in intel specs - added cpu_get_phys_page_debug()


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@584 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 62 additions and 18 deletions
target-i386/helper2.c
... ... @@ -260,7 +260,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr,
260 260 int is_write, int is_user, int is_softmmu)
261 261 {
262 262 uint8_t *pde_ptr, *pte_ptr;
263   - uint32_t pde, pte, virt_addr;
  263 + uint32_t pde, pte, virt_addr, ptep;
264 264 int error_code, is_dirty, prot, page_size, ret;
265 265 unsigned long paddr, vaddr, page_offset;
266 266  
... ... @@ -291,18 +291,18 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr,
291 291 error_code = 0;
292 292 goto do_fault;
293 293 }
294   - if (is_user) {
295   - if (!(pde & PG_USER_MASK))
296   - goto do_fault_protect;
297   - if (is_write && !(pde & PG_RW_MASK))
298   - goto do_fault_protect;
299   - } else {
300   - if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
301   - is_write && !(pde & PG_RW_MASK))
302   - goto do_fault_protect;
303   - }
304 294 /* if PSE bit is set, then we use a 4MB page */
305 295 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
  296 + if (is_user) {
  297 + if (!(pde & PG_USER_MASK))
  298 + goto do_fault_protect;
  299 + if (is_write && !(pde & PG_RW_MASK))
  300 + goto do_fault_protect;
  301 + } else {
  302 + if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
  303 + is_write && !(pde & PG_RW_MASK))
  304 + goto do_fault_protect;
  305 + }
306 306 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
307 307 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
308 308 pde |= PG_ACCESSED_MASK;
... ... @@ -312,6 +312,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr,
312 312 }
313 313  
314 314 pte = pde & ~0x003ff000; /* align to 4MB */
  315 + ptep = pte;
315 316 page_size = 4096 * 1024;
316 317 virt_addr = addr & ~0x003fffff;
317 318 } else {
... ... @@ -328,14 +329,16 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr,
328 329 error_code = 0;
329 330 goto do_fault;
330 331 }
  332 + /* combine pde and pte user and rw protections */
  333 + ptep = pte & pde;
331 334 if (is_user) {
332   - if (!(pte & PG_USER_MASK))
  335 + if (!(ptep & PG_USER_MASK))
333 336 goto do_fault_protect;
334   - if (is_write && !(pte & PG_RW_MASK))
  337 + if (is_write && !(ptep & PG_RW_MASK))
335 338 goto do_fault_protect;
336 339 } else {
337   - if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) &&
338   - is_write && !(pte & PG_RW_MASK))
  340 + if ((env->cr[0] & CR0_WP_MASK) && (ptep & PG_USER_MASK) &&
  341 + is_write && !(ptep & PG_RW_MASK))
339 342 goto do_fault_protect;
340 343 }
341 344 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
... ... @@ -355,11 +358,11 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr,
355 358 /* only set write access if already dirty... otherwise wait
356 359 for dirty access */
357 360 if (is_user) {
358   - if (pte & PG_RW_MASK)
  361 + if (ptep & PG_RW_MASK)
359 362 prot |= PROT_WRITE;
360 363 } else {
361   - if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) ||
362   - (pte & PG_RW_MASK))
  364 + if (!(env->cr[0] & CR0_WP_MASK) || !(ptep & PG_USER_MASK) ||
  365 + (ptep & PG_RW_MASK))
363 366 prot |= PROT_WRITE;
364 367 }
365 368 }
... ... @@ -384,3 +387,44 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr,
384 387 env->error_code |= PG_ERROR_U_MASK;
385 388 return 1;
386 389 }
  390 +
  391 +#if defined(CONFIG_USER_ONLY)
  392 +target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
  393 +{
  394 + return addr;
  395 +}
  396 +#else
  397 +target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
  398 +{
  399 + uint8_t *pde_ptr, *pte_ptr;
  400 + uint32_t pde, pte, paddr, page_offset, page_size;
  401 +
  402 + if (!(env->cr[0] & CR0_PG_MASK)) {
  403 + pte = addr;
  404 + page_size = 4096;
  405 + } else {
  406 + /* page directory entry */
  407 + pde_ptr = phys_ram_base +
  408 + (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask);
  409 + pde = ldl_raw(pde_ptr);
  410 + if (!(pde & PG_PRESENT_MASK))
  411 + return -1;
  412 + if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
  413 + pte = pde & ~0x003ff000; /* align to 4MB */
  414 + page_size = 4096 * 1024;
  415 + } else {
  416 + /* page directory entry */
  417 + pte_ptr = phys_ram_base +
  418 + (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask);
  419 + pte = ldl_raw(pte_ptr);
  420 + if (!(pte & PG_PRESENT_MASK))
  421 + return -1;
  422 + page_size = 4096;
  423 + }
  424 + }
  425 + pte = pte & a20_mask;
  426 + page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
  427 + paddr = (pte & TARGET_PAGE_MASK) + page_offset;
  428 + return paddr;
  429 +}
  430 +#endif
... ...