virtual memory access for gdbstub

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@581 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2004-01-24 15:23:36 +00:00
parent 3cf1e035ba
commit 13eb76e091
3 changed files with 152 additions and 49 deletions

View File

@ -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);

138
exec.c
View File

@ -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

View File

@ -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");