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