#include "cpu.h"
#include "exec-all.h"
+#if defined(CONFIG_USER_ONLY)
+#include <qemu.h>
+#endif
//#define DEBUG_TB_INVALIDATE
//#define DEBUG_FLUSH
static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
{
void **lp, **p;
+ PhysPageDesc *pd;
p = (void **)l1_phys_map;
#if TARGET_PHYS_ADDR_SPACE_BITS > 32
}
#endif
lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
- p = *lp;
- if (!p) {
+ pd = *lp;
+ if (!pd) {
+ int i;
/* allocate if not found */
if (!alloc)
return NULL;
- p = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
- memset(p, 0, sizeof(PhysPageDesc) * L2_SIZE);
- *lp = p;
+ pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
+ *lp = pd;
+ for (i = 0; i < L2_SIZE; i++)
+ pd[i].phys_offset = IO_MEM_UNASSIGNED;
}
- return ((PhysPageDesc *)p) + (index & (L2_SIZE - 1));
+ return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
}
static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
/* add the tb in the target page and protect it if necessary */
static inline void tb_alloc_page(TranslationBlock *tb,
- unsigned int n, unsigned int page_addr)
+ unsigned int n, target_ulong page_addr)
{
PageDesc *p;
TranslationBlock *last_first_tb;
#if defined(CONFIG_USER_ONLY)
if (p->flags & PAGE_WRITE) {
- unsigned long host_start, host_end, addr;
+ target_ulong addr;
+ PageDesc *p2;
int prot;
/* force the host page as non writable (writes will have a
page fault + mprotect overhead) */
- host_start = page_addr & qemu_host_page_mask;
- host_end = host_start + qemu_host_page_size;
+ page_addr &= qemu_host_page_mask;
prot = 0;
- for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)
- prot |= page_get_flags(addr);
- mprotect((void *)host_start, qemu_host_page_size,
+ for(addr = page_addr; addr < page_addr + qemu_host_page_size;
+ addr += TARGET_PAGE_SIZE) {
+
+ p2 = page_find (addr >> TARGET_PAGE_BITS);
+ if (!p2)
+ continue;
+ prot |= p2->flags;
+ p2->flags &= ~PAGE_WRITE;
+ page_get_flags(addr);
+ }
+ mprotect(g2h(page_addr), qemu_host_page_size,
(prot & PAGE_BITS) & ~PAGE_WRITE);
#ifdef DEBUG_TB_INVALIDATE
printf("protecting code page: 0x%08lx\n",
- host_start);
+ page_addr);
#endif
- p->flags &= ~PAGE_WRITE;
}
#else
/* if some code is already present, then the pages are already
#if defined(TARGET_HAS_ICE)
static void breakpoint_invalidate(CPUState *env, target_ulong pc)
{
- target_ulong phys_addr;
+ target_ulong addr, pd;
+ ram_addr_t ram_addr;
+ PhysPageDesc *p;
- phys_addr = cpu_get_phys_page_debug(env, pc);
- tb_invalidate_phys_page_range(phys_addr, phys_addr + 1, 0);
+ addr = cpu_get_phys_page_debug(env, pc);
+ p = phys_page_find(addr >> TARGET_PAGE_BITS);
+ if (!p) {
+ pd = IO_MEM_UNASSIGNED;
+ } else {
+ pd = p->phys_offset;
+ }
+ ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
+ tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
}
#endif
/* called from signal handler: invalidate the code and unprotect the
page. Return TRUE if the fault was succesfully handled. */
-int page_unprotect(unsigned long addr, unsigned long pc, void *puc)
+int page_unprotect(target_ulong addr, unsigned long pc, void *puc)
{
#if !defined(CONFIG_SOFTMMU)
VirtPageDesc *vp;
}
}
-int page_get_flags(unsigned long address)
+int page_get_flags(target_ulong address)
{
PageDesc *p;
/* modify the flags of a page and invalidate the code if
necessary. The flag PAGE_WRITE_ORG is positionned automatically
depending on PAGE_WRITE */
-void page_set_flags(unsigned long start, unsigned long end, int flags)
+void page_set_flags(target_ulong start, target_ulong end, int flags)
{
PageDesc *p;
- unsigned long addr;
+ target_ulong addr;
start = start & TARGET_PAGE_MASK;
end = TARGET_PAGE_ALIGN(end);
/* called from signal handler: invalidate the code and unprotect the
page. Return TRUE if the fault was succesfully handled. */
-int page_unprotect(unsigned long address, unsigned long pc, void *puc)
+int page_unprotect(target_ulong address, unsigned long pc, void *puc)
{
unsigned int page_index, prot, pindex;
PageDesc *p, *p1;
- unsigned long host_start, host_end, addr;
+ target_ulong host_start, host_end, addr;
host_start = address & qemu_host_page_mask;
page_index = host_start >> TARGET_PAGE_BITS;
if (prot & PAGE_WRITE_ORG) {
pindex = (address - host_start) >> TARGET_PAGE_BITS;
if (!(p1[pindex].flags & PAGE_WRITE)) {
- mprotect((void *)host_start, qemu_host_page_size,
+ mprotect((void *)g2h(host_start), qemu_host_page_size,
(prot & PAGE_BITS) | PAGE_WRITE);
p1[pindex].flags |= PAGE_WRITE;
/* and since the content will be modified, we must invalidate
}
/* call this function when system calls directly modify a memory area */
-void page_unprotect_range(uint8_t *data, unsigned long data_size)
+/* ??? This should be redundant now we have lock_user. */
+void page_unprotect_range(target_ulong data, target_ulong data_size)
{
- unsigned long start, end, addr;
+ target_ulong start, end, addr;
- start = (unsigned long)data;
+ start = data;
end = start + data_size;
start &= TARGET_PAGE_MASK;
end = TARGET_PAGE_ALIGN(end);
{
int l, flags;
target_ulong page;
+ void * p;
while (len > 0) {
page = addr & TARGET_PAGE_MASK;
if (is_write) {
if (!(flags & PAGE_WRITE))
return;
- memcpy((uint8_t *)addr, buf, len);
+ p = lock_user(addr, len, 0);
+ memcpy(p, buf, len);
+ unlock_user(p, addr, len);
} else {
if (!(flags & PAGE_READ))
return;
- memcpy(buf, (uint8_t *)addr, len);
+ p = lock_user(addr, len, 1);
+ memcpy(buf, p, len);
+ unlock_user(p, addr, 0);
}
len -= l;
buf += l;