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 | 473 | int cpu_breakpoint_remove(CPUState *env, uint32_t pc); |
474 | 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 | 481 | #define CPU_LOG_ALL 1 |
477 | 482 | void cpu_set_log(int log_flags); |
478 | 483 | void cpu_set_log_filename(const char *filename); |
... | ... | @@ -515,6 +520,11 @@ int cpu_register_io_memory(int io_index, |
515 | 520 | CPUReadMemoryFunc **mem_read, |
516 | 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 | 528 | /* gdb stub API */ |
519 | 529 | extern int gdbstub_fd; |
520 | 530 | CPUState *cpu_gdbstub_get_env(void *opaque); | ... | ... |
exec.c
... | ... | @@ -1561,6 +1561,144 @@ int cpu_register_io_memory(int io_index, |
1561 | 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 | 1702 | #if !defined(CONFIG_USER_ONLY) |
1565 | 1703 | |
1566 | 1704 | #define MMUSUFFIX _cmmu | ... | ... |
gdbstub.c
... | ... | @@ -248,53 +248,6 @@ static int put_packet(char *buf) |
248 | 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 | 251 | #if defined(TARGET_I386) |
299 | 252 | |
300 | 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 | 467 | put_packet("OK"); |
515 | 468 | break; |
516 | 469 | case 'm': |
470 | + env = cpu_gdbstub_get_env(opaque); | |
517 | 471 | addr = strtoul(p, (char **)&p, 16); |
518 | 472 | if (*p == ',') |
519 | 473 | p++; |
520 | 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 | 476 | memset(mem_buf, 0, len); |
523 | 477 | memtohex(buf, mem_buf, len); |
524 | 478 | put_packet(buf); |
525 | 479 | break; |
526 | 480 | case 'M': |
481 | + env = cpu_gdbstub_get_env(opaque); | |
527 | 482 | addr = strtoul(p, (char **)&p, 16); |
528 | 483 | if (*p == ',') |
529 | 484 | p++; |
... | ... | @@ -531,7 +486,7 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) |
531 | 486 | if (*p == ',') |
532 | 487 | p++; |
533 | 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 | 490 | put_packet("ENN"); |
536 | 491 | else |
537 | 492 | put_packet("OK"); | ... | ... |