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:
parent
3cf1e035ba
commit
13eb76e091
10
cpu-all.h
10
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);
|
||||
|
138
exec.c
138
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
|
||||
|
53
gdbstub.c
53
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");
|
||||
|
Loading…
Reference in New Issue
Block a user