win32 load_kernel() fix
[qemu] / exec.c
diff --git a/exec.c b/exec.c
index 617dea1..c33661b 100644 (file)
--- a/exec.c
+++ b/exec.c
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "config.h"
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/mman.h>
+#endif
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -25,9 +30,6 @@
 #include <errno.h>
 #include <unistd.h>
 #include <inttypes.h>
-#if !defined(CONFIG_SOFTMMU)
-#include <sys/mman.h>
-#endif
 
 #include "cpu.h"
 #include "exec-all.h"
@@ -100,10 +102,10 @@ typedef struct VirtPageDesc {
 
 static void io_mem_init(void);
 
-unsigned long real_host_page_size;
-unsigned long host_page_bits;
-unsigned long host_page_size;
-unsigned long host_page_mask;
+unsigned long qemu_real_host_page_size;
+unsigned long qemu_host_page_bits;
+unsigned long qemu_host_page_size;
+unsigned long qemu_host_page_mask;
 
 /* XXX: for system emulation, it could just be an array */
 static PageDesc *l1_map[L1_SIZE];
@@ -127,21 +129,44 @@ int loglevel;
 
 static void page_init(void)
 {
-    /* NOTE: we can always suppose that host_page_size >=
+    /* NOTE: we can always suppose that qemu_host_page_size >=
        TARGET_PAGE_SIZE */
 #ifdef _WIN32
-    real_host_page_size = 4096;
+    {
+        SYSTEM_INFO system_info;
+        DWORD old_protect;
+        
+        GetSystemInfo(&system_info);
+        qemu_real_host_page_size = system_info.dwPageSize;
+        
+        VirtualProtect(code_gen_buffer, sizeof(code_gen_buffer),
+                       PAGE_EXECUTE_READWRITE, &old_protect);
+    }
 #else
-    real_host_page_size = getpagesize();
+    qemu_real_host_page_size = getpagesize();
+    {
+        unsigned long start, end;
+
+        start = (unsigned long)code_gen_buffer;
+        start &= ~(qemu_real_host_page_size - 1);
+        
+        end = (unsigned long)code_gen_buffer + sizeof(code_gen_buffer);
+        end += qemu_real_host_page_size - 1;
+        end &= ~(qemu_real_host_page_size - 1);
+        
+        mprotect((void *)start, end - start, 
+                 PROT_READ | PROT_WRITE | PROT_EXEC);
+    }
 #endif
-    if (host_page_size == 0)
-        host_page_size = real_host_page_size;
-    if (host_page_size < TARGET_PAGE_SIZE)
-        host_page_size = TARGET_PAGE_SIZE;
-    host_page_bits = 0;
-    while ((1 << host_page_bits) < host_page_size)
-        host_page_bits++;
-    host_page_mask = ~(host_page_size - 1);
+
+    if (qemu_host_page_size == 0)
+        qemu_host_page_size = qemu_real_host_page_size;
+    if (qemu_host_page_size < TARGET_PAGE_SIZE)
+        qemu_host_page_size = TARGET_PAGE_SIZE;
+    qemu_host_page_bits = 0;
+    while ((1 << qemu_host_page_bits) < qemu_host_page_size)
+        qemu_host_page_bits++;
+    qemu_host_page_mask = ~(qemu_host_page_size - 1);
 #if !defined(CONFIG_USER_ONLY)
     virt_valid_tag = 1;
 #endif
@@ -609,11 +634,9 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
                                    int is_cpu_write_access)
 {
     int n, current_tb_modified, current_tb_not_found, current_flags;
-#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
     CPUState *env = cpu_single_env;
-#endif
     PageDesc *p;
-    TranslationBlock *tb, *tb_next, *current_tb;
+    TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
     target_ulong tb_start, tb_end;
     target_ulong current_pc, current_cs_base;
 
@@ -681,7 +704,12 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
 #endif
             }
 #endif /* TARGET_HAS_PRECISE_SMC */
+            saved_tb = env->current_tb;
+            env->current_tb = NULL;
             tb_phys_invalidate(tb, -1);
+            env->current_tb = saved_tb;
+            if (env->interrupt_request && env->current_tb)
+                cpu_interrupt(env, env->interrupt_request);
         }
         tb = tb_next;
     }
@@ -699,6 +727,7 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
         /* we generate a block containing just the instruction
            modifying the memory. It will ensure that it cannot modify
            itself */
+        env->current_tb = NULL;
         tb_gen_code(env, current_pc, current_cs_base, current_flags, 
                     CF_SINGLE_INSN);
         cpu_resume_from_signal(env, NULL);
@@ -795,6 +824,7 @@ static void tb_invalidate_phys_page(target_ulong addr,
         /* we generate a block containing just the instruction
            modifying the memory. It will ensure that it cannot modify
            itself */
+        env->current_tb = NULL;
         tb_gen_code(env, current_pc, current_cs_base, current_flags, 
                     CF_SINGLE_INSN);
         cpu_resume_from_signal(env, puc);
@@ -817,7 +847,7 @@ static inline void tb_alloc_page(TranslationBlock *tb,
     p->first_tb = (TranslationBlock *)((long)tb | n);
     invalidate_page_bitmap(p);
 
-#ifdef TARGET_HAS_SMC
+#if defined(TARGET_HAS_SMC) || 1
 
 #if defined(CONFIG_USER_ONLY)
     if (p->flags & PAGE_WRITE) {
@@ -826,12 +856,12 @@ static inline void tb_alloc_page(TranslationBlock *tb,
 
         /* force the host page as non writable (writes will have a
            page fault + mprotect overhead) */
-        host_start = page_addr & host_page_mask;
-        host_end = host_start + host_page_size;
+        host_start = page_addr & qemu_host_page_mask;
+        host_end = host_start + qemu_host_page_size;
         prot = 0;
         for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)
             prot |= page_get_flags(addr);
-        mprotect((void *)host_start, host_page_size, 
+        mprotect((void *)host_start, qemu_host_page_size, 
                  (prot & PAGE_BITS) & ~PAGE_WRITE);
 #ifdef DEBUG_TB_INVALIDATE
         printf("protecting code page: 0x%08lx\n", 
@@ -1732,12 +1762,12 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc)
     PageDesc *p, *p1;
     unsigned long host_start, host_end, addr;
 
-    host_start = address & host_page_mask;
+    host_start = address & qemu_host_page_mask;
     page_index = host_start >> TARGET_PAGE_BITS;
     p1 = page_find(page_index);
     if (!p1)
         return 0;
-    host_end = host_start + host_page_size;
+    host_end = host_start + qemu_host_page_size;
     p = p1;
     prot = 0;
     for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
@@ -1749,7 +1779,7 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc)
     if (prot & PAGE_WRITE_ORG) {
         pindex = (address - host_start) >> TARGET_PAGE_BITS;
         if (!(p1[pindex].flags & PAGE_WRITE)) {
-            mprotect((void *)host_start, host_page_size, 
+            mprotect((void *)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