CUDA + ADB support
[qemu] / exec.c
diff --git a/exec.c b/exec.c
index 5357dcd..617dea1 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -64,9 +64,7 @@ uint8_t *phys_ram_base;
 uint8_t *phys_ram_dirty;
 
 typedef struct PageDesc {
-    /* offset in host memory of the page + io_index in the low 12 bits */
-    unsigned long phys_offset;
-    /* list of TBs intersecting this physical page */
+    /* list of TBs intersecting this ram page */
     TranslationBlock *first_tb;
     /* in order to optimize self modifying code, we count the number
        of lookups we do to a given page to use a bitmap */
@@ -77,6 +75,11 @@ typedef struct PageDesc {
 #endif
 } PageDesc;
 
+typedef struct PhysPageDesc {
+    /* offset in host memory of the page + io_index in the low 12 bits */
+    unsigned long phys_offset;
+} PhysPageDesc;
+
 typedef struct VirtPageDesc {
     /* physical address of code page. It is valid only if 'valid_tag'
        matches 'virt_valid_tag' */ 
@@ -102,7 +105,9 @@ unsigned long host_page_bits;
 unsigned long host_page_size;
 unsigned long host_page_mask;
 
+/* XXX: for system emulation, it could just be an array */
 static PageDesc *l1_map[L1_SIZE];
+static PhysPageDesc *l1_phys_map[L1_SIZE];
 
 #if !defined(CONFIG_USER_ONLY)
 static VirtPageDesc *l1_virt_map[L1_SIZE];
@@ -112,6 +117,7 @@ static unsigned int virt_valid_tag;
 /* io memory support */
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 static int io_mem_nb;
 
 /* log support */
@@ -166,6 +172,31 @@ static inline PageDesc *page_find(unsigned int index)
     return p + (index & (L2_SIZE - 1));
 }
 
+static inline PhysPageDesc *phys_page_find_alloc(unsigned int index)
+{
+    PhysPageDesc **lp, *p;
+
+    lp = &l1_phys_map[index >> L2_BITS];
+    p = *lp;
+    if (!p) {
+        /* allocate if not found */
+        p = qemu_malloc(sizeof(PhysPageDesc) * L2_SIZE);
+        memset(p, 0, sizeof(PhysPageDesc) * L2_SIZE);
+        *lp = p;
+    }
+    return p + (index & (L2_SIZE - 1));
+}
+
+static inline PhysPageDesc *phys_page_find(unsigned int index)
+{
+    PhysPageDesc *p;
+
+    p = l1_phys_map[index >> L2_BITS];
+    if (!p)
+        return 0;
+    return p + (index & (L2_SIZE - 1));
+}
+
 #if !defined(CONFIG_USER_ONLY)
 static void tlb_protect_code(CPUState *env, target_ulong addr);
 static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr);
@@ -681,10 +712,13 @@ static inline void tb_invalidate_phys_page_fast(target_ulong start, int len)
     PageDesc *p;
     int offset, b;
 #if 0
-    if (cpu_single_env->cr[0] & CR0_PE_MASK) {
-        printf("modifying code at 0x%x size=%d EIP=%x\n", 
-               (vaddr & TARGET_PAGE_MASK) | (start & ~TARGET_PAGE_MASK), len, 
-               cpu_single_env->eip);
+    if (1) {
+        if (loglevel) {
+            fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n", 
+                   cpu_single_env->mem_write_vaddr, len, 
+                   cpu_single_env->eip, 
+                   cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
+        }
     }
 #endif
     p = page_find(start >> TARGET_PAGE_BITS);
@@ -1132,6 +1166,8 @@ CPULogItem cpu_log_items[] = {
       "show interrupts/exceptions in short format" },
     { CPU_LOG_EXEC, "exec",
       "show trace before each executed TB (lots of logs)" },
+    { CPU_LOG_TB_CPU, "cpu",
+      "show CPU state before bloc translation" },
 #ifdef TARGET_I386
     { CPU_LOG_PCALL, "pcall",
       "show protected mode far calls/returns/exceptions" },
@@ -1221,7 +1257,7 @@ void tlb_flush(CPUState *env, int flush_global)
 #endif
 }
 
-static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr)
+static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
 {
     if (addr == (tlb_entry->address & 
                  (TARGET_PAGE_MASK | TLB_INVALID_MASK)))
@@ -1426,7 +1462,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
                  target_phys_addr_t paddr, int prot, 
                  int is_user, int is_softmmu)
 {
-    PageDesc *p;
+    PhysPageDesc *p;
     unsigned long pd;
     TranslationBlock *first_tb;
     unsigned int index;
@@ -1434,13 +1470,18 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
     unsigned long addend;
     int ret;
 
-    p = page_find(paddr >> TARGET_PAGE_BITS);
+    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
+    first_tb = NULL;
     if (!p) {
         pd = IO_MEM_UNASSIGNED;
-        first_tb = NULL;
     } else {
+        PageDesc *p1;
         pd = p->phys_offset;
-        first_tb = p->first_tb;
+        if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+            /* NOTE: we also allocate the page at this stage */
+            p1 = page_find_alloc(pd >> TARGET_PAGE_BITS);
+            first_tb = p1->first_tb;
+        }
     }
 #if defined(DEBUG_TLB)
     printf("tlb_set_page: vaddr=0x%08x paddr=0x%08x prot=%x u=%d c=%d smmu=%d pd=0x%08x\n",
@@ -1750,23 +1791,24 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr,
                                   unsigned long phys_offset)
 {
     unsigned long addr, end_addr;
-    PageDesc *p;
+    PhysPageDesc *p;
 
+    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
     end_addr = start_addr + size;
-    for(addr = start_addr; addr < end_addr; addr += TARGET_PAGE_SIZE) {
-        p = page_find_alloc(addr >> TARGET_PAGE_BITS);
+    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
+        p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS);
         p->phys_offset = phys_offset;
         if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM)
             phys_offset += TARGET_PAGE_SIZE;
     }
 }
 
-static uint32_t unassigned_mem_readb(target_phys_addr_t addr)
+static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
 {
     return 0;
 }
 
-static void unassigned_mem_writeb(target_phys_addr_t addr, uint32_t val)
+static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
 }
 
@@ -1785,11 +1827,11 @@ static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
 /* self modifying code support in soft mmu mode : writing to a page
    containing code comes to these functions */
 
-static void code_mem_writeb(target_phys_addr_t addr, uint32_t val)
+static void code_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     unsigned long phys_addr;
 
-    phys_addr = addr - (long)phys_ram_base;
+    phys_addr = addr - (unsigned long)phys_ram_base;
 #if !defined(CONFIG_USER_ONLY)
     tb_invalidate_phys_page_fast(phys_addr, 1);
 #endif
@@ -1797,11 +1839,11 @@ static void code_mem_writeb(target_phys_addr_t addr, uint32_t val)
     phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
 }
 
-static void code_mem_writew(target_phys_addr_t addr, uint32_t val)
+static void code_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     unsigned long phys_addr;
 
-    phys_addr = addr - (long)phys_ram_base;
+    phys_addr = addr - (unsigned long)phys_ram_base;
 #if !defined(CONFIG_USER_ONLY)
     tb_invalidate_phys_page_fast(phys_addr, 2);
 #endif
@@ -1809,11 +1851,11 @@ static void code_mem_writew(target_phys_addr_t addr, uint32_t val)
     phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
 }
 
-static void code_mem_writel(target_phys_addr_t addr, uint32_t val)
+static void code_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     unsigned long phys_addr;
 
-    phys_addr = addr - (long)phys_ram_base;
+    phys_addr = addr - (unsigned long)phys_ram_base;
 #if !defined(CONFIG_USER_ONLY)
     tb_invalidate_phys_page_fast(phys_addr, 4);
 #endif
@@ -1833,19 +1875,19 @@ static CPUWriteMemoryFunc *code_mem_write[3] = {
     code_mem_writel,
 };
 
-static void notdirty_mem_writeb(target_phys_addr_t addr, uint32_t val)
+static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     stb_raw((uint8_t *)addr, val);
     tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
-static void notdirty_mem_writew(target_phys_addr_t addr, uint32_t val)
+static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     stw_raw((uint8_t *)addr, val);
     tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
-static void notdirty_mem_writel(target_phys_addr_t addr, uint32_t val)
+static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     stl_raw((uint8_t *)addr, val);
     tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
@@ -1859,10 +1901,10 @@ static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
 
 static void io_mem_init(void)
 {
-    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, code_mem_read, unassigned_mem_write);
-    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write);
-    cpu_register_io_memory(IO_MEM_CODE >> IO_MEM_SHIFT, code_mem_read, code_mem_write);
-    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, code_mem_read, notdirty_mem_write);
+    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, code_mem_read, unassigned_mem_write, NULL);
+    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
+    cpu_register_io_memory(IO_MEM_CODE >> IO_MEM_SHIFT, code_mem_read, code_mem_write, NULL);
+    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, code_mem_read, notdirty_mem_write, NULL);
     io_mem_nb = 5;
 
     /* alloc dirty bits array */
@@ -1877,7 +1919,8 @@ static void io_mem_init(void)
    cpu_register_physical_memory(). (-1) is returned if error. */
 int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
-                           CPUWriteMemoryFunc **mem_write)
+                           CPUWriteMemoryFunc **mem_write,
+                           void *opaque)
 {
     int i;
 
@@ -1894,6 +1937,7 @@ int cpu_register_io_memory(int io_index,
         io_mem_read[io_index][i] = mem_read[i];
         io_mem_write[io_index][i] = mem_write[i];
     }
+    io_mem_opaque[io_index] = opaque;
     return io_index << IO_MEM_SHIFT;
 }
 
@@ -1936,14 +1980,14 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
     uint32_t val;
     target_phys_addr_t page;
     unsigned long pd;
-    PageDesc *p;
+    PhysPageDesc *p;
     
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;
         l = (page + TARGET_PAGE_SIZE) - addr;
         if (l > len)
             l = len;
-        p = page_find(page >> TARGET_PAGE_BITS);
+        p = phys_page_find(page >> TARGET_PAGE_BITS);
         if (!p) {
             pd = IO_MEM_UNASSIGNED;
         } else {
@@ -1956,17 +2000,17 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 if (l >= 4 && ((addr & 3) == 0)) {
                     /* 32 bit read access */
                     val = ldl_raw(buf);
-                    io_mem_write[io_index][2](addr, val);
+                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
                     l = 4;
                 } else if (l >= 2 && ((addr & 1) == 0)) {
                     /* 16 bit read access */
                     val = lduw_raw(buf);
-                    io_mem_write[io_index][1](addr, val);
+                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
                     l = 2;
                 } else {
                     /* 8 bit access */
                     val = ldub_raw(buf);
-                    io_mem_write[io_index][0](addr, val);
+                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
                     l = 1;
                 }
             } else {
@@ -1987,17 +2031,17 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
                 if (l >= 4 && ((addr & 3) == 0)) {
                     /* 32 bit read access */
-                    val = io_mem_read[io_index][2](addr);
+                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
                     stl_raw(buf, val);
                     l = 4;
                 } else if (l >= 2 && ((addr & 1) == 0)) {
                     /* 16 bit read access */
-                    val = io_mem_read[io_index][1](addr);
+                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
                     stw_raw(buf, val);
                     l = 2;
                 } else {
                     /* 8 bit access */
-                    val = io_mem_read[io_index][0](addr);
+                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
                     stb_raw(buf, val);
                     l = 1;
                 }