addr += l;
}
}
+
+/* never used */
+uint32_t ldl_phys(target_phys_addr_t addr)
+{
+ return 0;
+}
+
+void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
+{
+}
+
+void stl_phys(target_phys_addr_t addr, uint32_t val)
+{
+}
+
#else
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write)
addr += l;
}
}
+
+/* warning: addr must be aligned */
+uint32_t ldl_phys(target_phys_addr_t addr)
+{
+ int io_index;
+ uint8_t *ptr;
+ uint32_t val;
+ unsigned long pd;
+ PhysPageDesc *p;
+
+ p = phys_page_find(addr >> TARGET_PAGE_BITS);
+ if (!p) {
+ pd = IO_MEM_UNASSIGNED;
+ } else {
+ pd = p->phys_offset;
+ }
+
+ if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
+ (pd & ~TARGET_PAGE_MASK) != IO_MEM_CODE) {
+ /* I/O case */
+ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+ val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
+ } else {
+ /* RAM case */
+ ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
+ (addr & ~TARGET_PAGE_MASK);
+ val = ldl_p(ptr);
+ }
+ return val;
+}
+
+/* warning: addr must be aligned. The ram page is not masked as dirty
+ and the code inside is not invalidated. It is useful if the dirty
+ bits are used to track modified PTEs */
+void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
+{
+ int io_index;
+ uint8_t *ptr;
+ unsigned long pd;
+ PhysPageDesc *p;
+
+ p = phys_page_find(addr >> TARGET_PAGE_BITS);
+ if (!p) {
+ pd = IO_MEM_UNASSIGNED;
+ } else {
+ pd = p->phys_offset;
+ }
+
+ if ((pd & ~TARGET_PAGE_MASK) != 0) {
+ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+ io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+ } else {
+ ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
+ (addr & ~TARGET_PAGE_MASK);
+ stl_p(ptr, val);
+ }
+}
+
+/* warning: addr must be aligned */
+/* XXX: optimize code invalidation test */
+void stl_phys(target_phys_addr_t addr, uint32_t val)
+{
+ int io_index;
+ uint8_t *ptr;
+ unsigned long pd;
+ PhysPageDesc *p;
+
+ p = phys_page_find(addr >> TARGET_PAGE_BITS);
+ if (!p) {
+ pd = IO_MEM_UNASSIGNED;
+ } else {
+ pd = p->phys_offset;
+ }
+
+ if ((pd & ~TARGET_PAGE_MASK) != 0) {
+ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+ io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+ } else {
+ unsigned long addr1;
+ addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+ /* RAM case */
+ ptr = phys_ram_base + addr1;
+ stl_p(ptr, val);
+ /* invalidate code */
+ tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
+ /* set dirty bit */
+ phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] = 1;
+ }
+}
+
#endif
/* virtual memory access for debug */
tlb_flush_page(env, addr);
}
-static inline uint8_t *get_phys_mem_ptr(target_phys_addr_t addr)
-{
- /* XXX: incorrect */
- return phys_ram_base + addr;
-}
+#if defined(CONFIG_USER_ONLY)
-/* WARNING: addr must be aligned */
-uint32_t ldl_phys_aligned(target_phys_addr_t addr)
+int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
+ int is_write, int is_user, int is_softmmu)
{
- uint8_t *ptr;
- uint32_t val;
- ptr = get_phys_mem_ptr(addr);
- if (!ptr)
- val = 0;
- else
- val = ldl_raw(ptr);
- return val;
+ /* user mode only emulation */
+ is_write &= 1;
+ env->cr[2] = addr;
+ env->error_code = (is_write << PG_ERROR_W_BIT);
+ env->error_code |= PG_ERROR_U_MASK;
+ return 1;
}
-void stl_phys_aligned(target_phys_addr_t addr, uint32_t val)
+target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
{
- uint8_t *ptr;
- ptr = get_phys_mem_ptr(addr);
- if (!ptr)
- return;
- stl_raw(ptr, val);
+ return addr;
}
+#else
+
/* return value:
-1 = cannot handle fault
0 = nothing more to do
#endif
is_write &= 1;
- if (env->user_mode_only) {
- /* user mode only emulation */
- error_code = 0;
- goto do_fault;
- }
-
if (!(env->cr[0] & CR0_PG_MASK)) {
pte = addr;
virt_addr = addr & TARGET_PAGE_MASK;
goto do_mapping;
}
-
if (env->cr[4] & CR4_PAE_MASK) {
/* XXX: we only use 32 bit physical addresses */
#ifdef TARGET_X86_64
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
env->a20_mask;
- pml4e = ldl_phys_aligned(pml4e_addr);
+ pml4e = ldl_phys(pml4e_addr);
if (!(pml4e & PG_PRESENT_MASK)) {
error_code = 0;
goto do_fault;
}
if (!(pml4e & PG_ACCESSED_MASK)) {
pml4e |= PG_ACCESSED_MASK;
- stl_phys_aligned(pml4e_addr, pml4e);
+ stl_phys_notdirty(pml4e_addr, pml4e);
}
pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
env->a20_mask;
- pdpe = ldl_phys_aligned(pdpe_addr);
+ pdpe = ldl_phys(pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK)) {
error_code = 0;
goto do_fault;
}
if (!(pdpe & PG_ACCESSED_MASK)) {
pdpe |= PG_ACCESSED_MASK;
- stl_phys_aligned(pdpe_addr, pdpe);
+ stl_phys_notdirty(pdpe_addr, pdpe);
}
} else
#endif
{
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) &
env->a20_mask;
- pdpe = ldl_phys_aligned(pdpe_addr);
+ pdpe = ldl_phys(pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK)) {
error_code = 0;
goto do_fault;
pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
env->a20_mask;
- pde = ldl_phys_aligned(pde_addr);
+ pde = ldl_phys(pde_addr);
if (!(pde & PG_PRESENT_MASK)) {
error_code = 0;
goto do_fault;
/* 4 KB page */
if (!(pde & PG_ACCESSED_MASK)) {
pde |= PG_ACCESSED_MASK;
- stl_phys_aligned(pde_addr, pde);
+ stl_phys_notdirty(pde_addr, pde);
}
pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
env->a20_mask;
/* page directory entry */
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) &
env->a20_mask;
- pde = ldl_phys_aligned(pde_addr);
+ pde = ldl_phys(pde_addr);
if (!(pde & PG_PRESENT_MASK)) {
error_code = 0;
goto do_fault;
pde |= PG_ACCESSED_MASK;
if (is_dirty)
pde |= PG_DIRTY_MASK;
- stl_phys_aligned(pde_addr, pde);
+ stl_phys_notdirty(pde_addr, pde);
}
pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
} else {
if (!(pde & PG_ACCESSED_MASK)) {
pde |= PG_ACCESSED_MASK;
- stl_phys_aligned(pde_addr, pde);
+ stl_phys_notdirty(pde_addr, pde);
}
/* page directory entry */
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
env->a20_mask;
handle_4k_page:
- pte = ldl_phys_aligned(pte_addr);
+ pte = ldl_phys(pte_addr);
if (!(pte & PG_PRESENT_MASK)) {
error_code = 0;
goto do_fault;
pte |= PG_ACCESSED_MASK;
if (is_dirty)
pte |= PG_DIRTY_MASK;
- stl_phys_aligned(pte_addr, pte);
+ stl_phys_notdirty(pte_addr, pte);
}
page_size = 4096;
virt_addr = addr & ~0xfff;
return 1;
}
-#if defined(CONFIG_USER_ONLY)
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
-{
- return addr;
-}
-#else
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
{
uint32_t pde_addr, pte_addr;
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
env->a20_mask;
- pml4e = ldl_phys_aligned(pml4e_addr);
+ pml4e = ldl_phys(pml4e_addr);
if (!(pml4e & PG_PRESENT_MASK))
return -1;
pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
env->a20_mask;
- pdpe = ldl_phys_aligned(pdpe_addr);
+ pdpe = ldl_phys(pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK))
return -1;
} else
{
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) &
env->a20_mask;
- pdpe = ldl_phys_aligned(pdpe_addr);
+ pdpe = ldl_phys(pdpe_addr);
if (!(pdpe & PG_PRESENT_MASK))
return -1;
}
pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
env->a20_mask;
- pde = ldl_phys_aligned(pde_addr);
+ pde = ldl_phys(pde_addr);
if (!(pde & PG_PRESENT_MASK)) {
return -1;
}
pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
env->a20_mask;
page_size = 4096;
- pte = ldl_phys_aligned(pte_addr);
+ pte = ldl_phys(pte_addr);
}
} else {
if (!(env->cr[0] & CR0_PG_MASK)) {
} else {
/* page directory entry */
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask;
- pde = ldl_phys_aligned(pde_addr);
+ pde = ldl_phys(pde_addr);
if (!(pde & PG_PRESENT_MASK))
return -1;
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
} else {
/* page directory entry */
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
- pte = ldl_phys_aligned(pte_addr);
+ pte = ldl_phys(pte_addr);
if (!(pte & PG_PRESENT_MASK))
return -1;
page_size = 4096;
paddr = (pte & TARGET_PAGE_MASK) + page_offset;
return paddr;
}
-#endif
+#endif /* !CONFIG_USER_ONLY */
#if defined(USE_CODE_COPY)
struct fpstate {