]> git.proxmox.com Git - mirror_qemu.git/commitdiff
virtual memory access for gdbstub
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 24 Jan 2004 15:23:36 +0000 (15:23 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 24 Jan 2004 15:23:36 +0000 (15:23 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@581 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-all.h
exec.c
gdbstub.c

index 499e1483d9e10f5f780b3bf53ce279bbdf76d6d4..1cf35ea235007837df706ddf3f5299ef404cad5f 100644 (file)
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -473,6 +473,11 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc);
 int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
 void cpu_single_step(CPUState *env, int enabled);
 
+/* Return the physical page corresponding to a virtual one. Use it
+   only for debugging because no protection checks are done. Return -1
+   if no page found. */
+target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
+
 #define CPU_LOG_ALL 1
 void cpu_set_log(int log_flags);
 void cpu_set_log_filename(const char *filename);
@@ -515,6 +520,11 @@ int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write);
 
+void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, 
+                            int len, int is_write);
+int cpu_memory_rw_debug(CPUState *env, 
+                        uint8_t *buf, target_ulong addr, int len, int is_write);
+
 /* gdb stub API */
 extern int gdbstub_fd;
 CPUState *cpu_gdbstub_get_env(void *opaque);
diff --git a/exec.c b/exec.c
index 3ae2f31a9cd287b02489b727159fc45aa329547a..9104efbb1dca536c24911a0b9cf172e221cc72d4 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1561,6 +1561,144 @@ int cpu_register_io_memory(int io_index,
     return io_index << IO_MEM_SHIFT;
 }
 
+/* physical memory access (slow version, mainly for debug) */
+#if defined(CONFIG_USER_ONLY)
+void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, 
+                            int len, int is_write)
+{
+    int l, flags;
+    target_ulong page;
+
+    while (len > 0) {
+        page = addr & TARGET_PAGE_MASK;
+        l = (page + TARGET_PAGE_SIZE) - addr;
+        if (l > len)
+            l = len;
+        flags = page_get_flags(page);
+        if (!(flags & PAGE_VALID))
+            return;
+        if (is_write) {
+            if (!(flags & PAGE_WRITE))
+                return;
+            memcpy((uint8_t *)addr, buf, len);
+        } else {
+            if (!(flags & PAGE_READ))
+                return;
+            memcpy(buf, (uint8_t *)addr, len);
+        }
+        len -= l;
+        buf += l;
+        addr += l;
+    }
+}
+#else
+void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, 
+                            int len, int is_write)
+{
+    int l, io_index;
+    uint8_t *ptr;
+    uint32_t val;
+    target_ulong page, pd;
+    PageDesc *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);
+        if (!p) {
+            pd = IO_MEM_UNASSIGNED;
+        } else {
+            pd = p->phys_offset;
+        }
+        
+        if (is_write) {
+            if ((pd & ~TARGET_PAGE_MASK) != 0) {
+                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+                if (l >= 4 && ((addr & 3) == 0)) {
+                    /* 32 bit read access */
+                    val = ldl_raw(buf);
+                    io_mem_write[io_index][2](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);
+                    l = 2;
+                } else {
+                    /* 8 bit access */
+                    val = ldub_raw(buf);
+                    io_mem_write[io_index][0](addr, val);
+                    l = 1;
+                }
+            } else {
+                /* RAM case */
+                ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
+                    (addr & ~TARGET_PAGE_MASK);
+                memcpy(ptr, buf, l);
+            }
+        } else {
+            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);
+                if (l >= 4 && ((addr & 3) == 0)) {
+                    /* 32 bit read access */
+                    val = io_mem_read[io_index][2](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);
+                    stw_raw(buf, val);
+                    l = 2;
+                } else {
+                    /* 8 bit access */
+                    val = io_mem_read[io_index][0](addr);
+                    stb_raw(buf, val);
+                    l = 1;
+                }
+            } else {
+                /* RAM case */
+                ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
+                    (addr & ~TARGET_PAGE_MASK);
+                memcpy(buf, ptr, l);
+            }
+        }
+        len -= l;
+        buf += l;
+        addr += l;
+    }
+}
+#endif
+
+/* virtual memory access for debug */
+int cpu_memory_rw_debug(CPUState *env, 
+                        uint8_t *buf, target_ulong addr, int len, int is_write)
+{
+    int l;
+    target_ulong page, phys_addr;
+
+    while (len > 0) {
+        page = addr & TARGET_PAGE_MASK;
+        phys_addr = cpu_get_phys_page_debug(env, page);
+        /* if no physical page mapped, return an error */
+        if (phys_addr == -1)
+            return -1;
+        l = (page + TARGET_PAGE_SIZE) - addr;
+        if (l > len)
+            l = len;
+        cpu_physical_memory_rw(env, buf, 
+                               phys_addr + (addr & ~TARGET_PAGE_MASK), l, 
+                               is_write);
+        len -= l;
+        buf += l;
+        addr += l;
+    }
+    return 0;
+}
+
 #if !defined(CONFIG_USER_ONLY) 
 
 #define MMUSUFFIX _cmmu
index 469a15962fdcfb32f8ab44a3dcce4091fa02ab6f..4fa4af79a36d042e3342825bf4c957848952f4ca 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -248,53 +248,6 @@ static int put_packet(char *buf)
     return 0;
 }
 
-/* better than nothing for SOFTMMU : we use physical addresses */
-#if !defined(CONFIG_USER_ONLY)
-static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write)
-{
-    uint8_t *ptr;
-
-    if (addr >= phys_ram_size ||
-        ((int64_t)addr + len > phys_ram_size))
-        return -1;
-    ptr = phys_ram_base + addr;
-    if (is_write)
-        memcpy(ptr, buf, len);
-    else
-        memcpy(buf, ptr, len);
-    return 0;
-}
-#else
-static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write)
-{
-    int l, flags;
-    uint32_t page;
-
-    while (len > 0) {
-        page = addr & TARGET_PAGE_MASK;
-        l = (page + TARGET_PAGE_SIZE) - addr;
-        if (l > len)
-            l = len;
-        flags = page_get_flags(page);
-        if (!(flags & PAGE_VALID))
-            return -1;
-        if (is_write) {
-            if (!(flags & PAGE_WRITE))
-                return -1;
-            memcpy((uint8_t *)addr, buf, l);
-        } else {
-            if (!(flags & PAGE_READ))
-                return -1;
-            memcpy(buf, (uint8_t *)addr, l);
-        }
-        len -= l;
-        buf += l;
-        addr += l;
-    }
-    return 0;
-}
-#endif
-
 #if defined(TARGET_I386)
 
 static void to_le32(uint8_t *p, int v)
@@ -514,16 +467,18 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
             put_packet("OK");
             break;
         case 'm':
+            env = cpu_gdbstub_get_env(opaque);
             addr = strtoul(p, (char **)&p, 16);
             if (*p == ',')
                 p++;
             len = strtoul(p, NULL, 16);
-            if (memory_rw(mem_buf, addr, len, 0) != 0)
+            if (cpu_memory_rw_debug(env, mem_buf, addr, len, 0) != 0)
                 memset(mem_buf, 0, len);
             memtohex(buf, mem_buf, len);
             put_packet(buf);
             break;
         case 'M':
+            env = cpu_gdbstub_get_env(opaque);
             addr = strtoul(p, (char **)&p, 16);
             if (*p == ',')
                 p++;
@@ -531,7 +486,7 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
             if (*p == ',')
                 p++;
             hextomem(mem_buf, p, len);
-            if (memory_rw(mem_buf, addr, len, 1) != 0)
+            if (cpu_memory_rw_debug(env, mem_buf, addr, len, 1) != 0)
                 put_packet("ENN");
             else
                 put_packet("OK");