Commit 13eb76e091a302dff848b0001a64d1b571450ccc
1 parent
3cf1e035
virtual memory access for gdbstub
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@581 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
152 additions
and
49 deletions
cpu-all.h
@@ -473,6 +473,11 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc); | @@ -473,6 +473,11 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc); | ||
473 | int cpu_breakpoint_remove(CPUState *env, uint32_t pc); | 473 | int cpu_breakpoint_remove(CPUState *env, uint32_t pc); |
474 | void cpu_single_step(CPUState *env, int enabled); | 474 | void cpu_single_step(CPUState *env, int enabled); |
475 | 475 | ||
476 | +/* Return the physical page corresponding to a virtual one. Use it | ||
477 | + only for debugging because no protection checks are done. Return -1 | ||
478 | + if no page found. */ | ||
479 | +target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr); | ||
480 | + | ||
476 | #define CPU_LOG_ALL 1 | 481 | #define CPU_LOG_ALL 1 |
477 | void cpu_set_log(int log_flags); | 482 | void cpu_set_log(int log_flags); |
478 | void cpu_set_log_filename(const char *filename); | 483 | void cpu_set_log_filename(const char *filename); |
@@ -515,6 +520,11 @@ int cpu_register_io_memory(int io_index, | @@ -515,6 +520,11 @@ int cpu_register_io_memory(int io_index, | ||
515 | CPUReadMemoryFunc **mem_read, | 520 | CPUReadMemoryFunc **mem_read, |
516 | CPUWriteMemoryFunc **mem_write); | 521 | CPUWriteMemoryFunc **mem_write); |
517 | 522 | ||
523 | +void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, | ||
524 | + int len, int is_write); | ||
525 | +int cpu_memory_rw_debug(CPUState *env, | ||
526 | + uint8_t *buf, target_ulong addr, int len, int is_write); | ||
527 | + | ||
518 | /* gdb stub API */ | 528 | /* gdb stub API */ |
519 | extern int gdbstub_fd; | 529 | extern int gdbstub_fd; |
520 | CPUState *cpu_gdbstub_get_env(void *opaque); | 530 | CPUState *cpu_gdbstub_get_env(void *opaque); |
exec.c
@@ -1561,6 +1561,144 @@ int cpu_register_io_memory(int io_index, | @@ -1561,6 +1561,144 @@ int cpu_register_io_memory(int io_index, | ||
1561 | return io_index << IO_MEM_SHIFT; | 1561 | return io_index << IO_MEM_SHIFT; |
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | +/* physical memory access (slow version, mainly for debug) */ | ||
1565 | +#if defined(CONFIG_USER_ONLY) | ||
1566 | +void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, | ||
1567 | + int len, int is_write) | ||
1568 | +{ | ||
1569 | + int l, flags; | ||
1570 | + target_ulong page; | ||
1571 | + | ||
1572 | + while (len > 0) { | ||
1573 | + page = addr & TARGET_PAGE_MASK; | ||
1574 | + l = (page + TARGET_PAGE_SIZE) - addr; | ||
1575 | + if (l > len) | ||
1576 | + l = len; | ||
1577 | + flags = page_get_flags(page); | ||
1578 | + if (!(flags & PAGE_VALID)) | ||
1579 | + return; | ||
1580 | + if (is_write) { | ||
1581 | + if (!(flags & PAGE_WRITE)) | ||
1582 | + return; | ||
1583 | + memcpy((uint8_t *)addr, buf, len); | ||
1584 | + } else { | ||
1585 | + if (!(flags & PAGE_READ)) | ||
1586 | + return; | ||
1587 | + memcpy(buf, (uint8_t *)addr, len); | ||
1588 | + } | ||
1589 | + len -= l; | ||
1590 | + buf += l; | ||
1591 | + addr += l; | ||
1592 | + } | ||
1593 | +} | ||
1594 | +#else | ||
1595 | +void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, | ||
1596 | + int len, int is_write) | ||
1597 | +{ | ||
1598 | + int l, io_index; | ||
1599 | + uint8_t *ptr; | ||
1600 | + uint32_t val; | ||
1601 | + target_ulong page, pd; | ||
1602 | + PageDesc *p; | ||
1603 | + | ||
1604 | + while (len > 0) { | ||
1605 | + page = addr & TARGET_PAGE_MASK; | ||
1606 | + l = (page + TARGET_PAGE_SIZE) - addr; | ||
1607 | + if (l > len) | ||
1608 | + l = len; | ||
1609 | + p = page_find(page >> TARGET_PAGE_BITS); | ||
1610 | + if (!p) { | ||
1611 | + pd = IO_MEM_UNASSIGNED; | ||
1612 | + } else { | ||
1613 | + pd = p->phys_offset; | ||
1614 | + } | ||
1615 | + | ||
1616 | + if (is_write) { | ||
1617 | + if ((pd & ~TARGET_PAGE_MASK) != 0) { | ||
1618 | + io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); | ||
1619 | + if (l >= 4 && ((addr & 3) == 0)) { | ||
1620 | + /* 32 bit read access */ | ||
1621 | + val = ldl_raw(buf); | ||
1622 | + io_mem_write[io_index][2](addr, val); | ||
1623 | + l = 4; | ||
1624 | + } else if (l >= 2 && ((addr & 1) == 0)) { | ||
1625 | + /* 16 bit read access */ | ||
1626 | + val = lduw_raw(buf); | ||
1627 | + io_mem_write[io_index][1](addr, val); | ||
1628 | + l = 2; | ||
1629 | + } else { | ||
1630 | + /* 8 bit access */ | ||
1631 | + val = ldub_raw(buf); | ||
1632 | + io_mem_write[io_index][0](addr, val); | ||
1633 | + l = 1; | ||
1634 | + } | ||
1635 | + } else { | ||
1636 | + /* RAM case */ | ||
1637 | + ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + | ||
1638 | + (addr & ~TARGET_PAGE_MASK); | ||
1639 | + memcpy(ptr, buf, l); | ||
1640 | + } | ||
1641 | + } else { | ||
1642 | + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && | ||
1643 | + (pd & ~TARGET_PAGE_MASK) != IO_MEM_CODE) { | ||
1644 | + /* I/O case */ | ||
1645 | + io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); | ||
1646 | + if (l >= 4 && ((addr & 3) == 0)) { | ||
1647 | + /* 32 bit read access */ | ||
1648 | + val = io_mem_read[io_index][2](addr); | ||
1649 | + stl_raw(buf, val); | ||
1650 | + l = 4; | ||
1651 | + } else if (l >= 2 && ((addr & 1) == 0)) { | ||
1652 | + /* 16 bit read access */ | ||
1653 | + val = io_mem_read[io_index][1](addr); | ||
1654 | + stw_raw(buf, val); | ||
1655 | + l = 2; | ||
1656 | + } else { | ||
1657 | + /* 8 bit access */ | ||
1658 | + val = io_mem_read[io_index][0](addr); | ||
1659 | + stb_raw(buf, val); | ||
1660 | + l = 1; | ||
1661 | + } | ||
1662 | + } else { | ||
1663 | + /* RAM case */ | ||
1664 | + ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + | ||
1665 | + (addr & ~TARGET_PAGE_MASK); | ||
1666 | + memcpy(buf, ptr, l); | ||
1667 | + } | ||
1668 | + } | ||
1669 | + len -= l; | ||
1670 | + buf += l; | ||
1671 | + addr += l; | ||
1672 | + } | ||
1673 | +} | ||
1674 | +#endif | ||
1675 | + | ||
1676 | +/* virtual memory access for debug */ | ||
1677 | +int cpu_memory_rw_debug(CPUState *env, | ||
1678 | + uint8_t *buf, target_ulong addr, int len, int is_write) | ||
1679 | +{ | ||
1680 | + int l; | ||
1681 | + target_ulong page, phys_addr; | ||
1682 | + | ||
1683 | + while (len > 0) { | ||
1684 | + page = addr & TARGET_PAGE_MASK; | ||
1685 | + phys_addr = cpu_get_phys_page_debug(env, page); | ||
1686 | + /* if no physical page mapped, return an error */ | ||
1687 | + if (phys_addr == -1) | ||
1688 | + return -1; | ||
1689 | + l = (page + TARGET_PAGE_SIZE) - addr; | ||
1690 | + if (l > len) | ||
1691 | + l = len; | ||
1692 | + cpu_physical_memory_rw(env, buf, | ||
1693 | + phys_addr + (addr & ~TARGET_PAGE_MASK), l, | ||
1694 | + is_write); | ||
1695 | + len -= l; | ||
1696 | + buf += l; | ||
1697 | + addr += l; | ||
1698 | + } | ||
1699 | + return 0; | ||
1700 | +} | ||
1701 | + | ||
1564 | #if !defined(CONFIG_USER_ONLY) | 1702 | #if !defined(CONFIG_USER_ONLY) |
1565 | 1703 | ||
1566 | #define MMUSUFFIX _cmmu | 1704 | #define MMUSUFFIX _cmmu |
gdbstub.c
@@ -248,53 +248,6 @@ static int put_packet(char *buf) | @@ -248,53 +248,6 @@ static int put_packet(char *buf) | ||
248 | return 0; | 248 | return 0; |
249 | } | 249 | } |
250 | 250 | ||
251 | -/* better than nothing for SOFTMMU : we use physical addresses */ | ||
252 | -#if !defined(CONFIG_USER_ONLY) | ||
253 | -static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write) | ||
254 | -{ | ||
255 | - uint8_t *ptr; | ||
256 | - | ||
257 | - if (addr >= phys_ram_size || | ||
258 | - ((int64_t)addr + len > phys_ram_size)) | ||
259 | - return -1; | ||
260 | - ptr = phys_ram_base + addr; | ||
261 | - if (is_write) | ||
262 | - memcpy(ptr, buf, len); | ||
263 | - else | ||
264 | - memcpy(buf, ptr, len); | ||
265 | - return 0; | ||
266 | -} | ||
267 | -#else | ||
268 | -static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write) | ||
269 | -{ | ||
270 | - int l, flags; | ||
271 | - uint32_t page; | ||
272 | - | ||
273 | - while (len > 0) { | ||
274 | - page = addr & TARGET_PAGE_MASK; | ||
275 | - l = (page + TARGET_PAGE_SIZE) - addr; | ||
276 | - if (l > len) | ||
277 | - l = len; | ||
278 | - flags = page_get_flags(page); | ||
279 | - if (!(flags & PAGE_VALID)) | ||
280 | - return -1; | ||
281 | - if (is_write) { | ||
282 | - if (!(flags & PAGE_WRITE)) | ||
283 | - return -1; | ||
284 | - memcpy((uint8_t *)addr, buf, l); | ||
285 | - } else { | ||
286 | - if (!(flags & PAGE_READ)) | ||
287 | - return -1; | ||
288 | - memcpy(buf, (uint8_t *)addr, l); | ||
289 | - } | ||
290 | - len -= l; | ||
291 | - buf += l; | ||
292 | - addr += l; | ||
293 | - } | ||
294 | - return 0; | ||
295 | -} | ||
296 | -#endif | ||
297 | - | ||
298 | #if defined(TARGET_I386) | 251 | #if defined(TARGET_I386) |
299 | 252 | ||
300 | static void to_le32(uint8_t *p, int v) | 253 | 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) | @@ -514,16 +467,18 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) | ||
514 | put_packet("OK"); | 467 | put_packet("OK"); |
515 | break; | 468 | break; |
516 | case 'm': | 469 | case 'm': |
470 | + env = cpu_gdbstub_get_env(opaque); | ||
517 | addr = strtoul(p, (char **)&p, 16); | 471 | addr = strtoul(p, (char **)&p, 16); |
518 | if (*p == ',') | 472 | if (*p == ',') |
519 | p++; | 473 | p++; |
520 | len = strtoul(p, NULL, 16); | 474 | len = strtoul(p, NULL, 16); |
521 | - if (memory_rw(mem_buf, addr, len, 0) != 0) | 475 | + if (cpu_memory_rw_debug(env, mem_buf, addr, len, 0) != 0) |
522 | memset(mem_buf, 0, len); | 476 | memset(mem_buf, 0, len); |
523 | memtohex(buf, mem_buf, len); | 477 | memtohex(buf, mem_buf, len); |
524 | put_packet(buf); | 478 | put_packet(buf); |
525 | break; | 479 | break; |
526 | case 'M': | 480 | case 'M': |
481 | + env = cpu_gdbstub_get_env(opaque); | ||
527 | addr = strtoul(p, (char **)&p, 16); | 482 | addr = strtoul(p, (char **)&p, 16); |
528 | if (*p == ',') | 483 | if (*p == ',') |
529 | p++; | 484 | p++; |
@@ -531,7 +486,7 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) | @@ -531,7 +486,7 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) | ||
531 | if (*p == ',') | 486 | if (*p == ',') |
532 | p++; | 487 | p++; |
533 | hextomem(mem_buf, p, len); | 488 | hextomem(mem_buf, p, len); |
534 | - if (memory_rw(mem_buf, addr, len, 1) != 0) | 489 | + if (cpu_memory_rw_debug(env, mem_buf, addr, len, 1) != 0) |
535 | put_packet("ENN"); | 490 | put_packet("ENN"); |
536 | else | 491 | else |
537 | put_packet("OK"); | 492 | put_packet("OK"); |