Commit e22a25c9361c44995c9241c24df0e1e2c47a56c8

Authored by aliguori
1 parent eda578e5

Guest debugging support for KVM (Jan Kiszka)

This is a backport of the guest debugging support for the KVM
accelerator that is now part of the KVM tree. It implements the reworked
KVM kernel API for guest debugging (KVM_CAP_SET_GUEST_DEBUG) which is
not yet part of any mainline kernel but will probably be 2.6.30 stuff.
So far supported is x86, but PPC is expected to catch up soon.

Core features are:
 - unlimited soft-breakpoints via code patching
 - hardware-assisted x86 breakpoints and watchpoints

Changes in this version:
 - use generic hook cpu_synchronize_state to transfer registers between
   user space and kvm
 - push kvm_sw_breakpoints into KVMState

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6825 c046a42c-6fe2-441c-8c8c-71466251a162
@@ -1457,9 +1457,13 @@ void cpu_single_step(CPUState *env, int enabled) @@ -1457,9 +1457,13 @@ void cpu_single_step(CPUState *env, int enabled)
1457 #if defined(TARGET_HAS_ICE) 1457 #if defined(TARGET_HAS_ICE)
1458 if (env->singlestep_enabled != enabled) { 1458 if (env->singlestep_enabled != enabled) {
1459 env->singlestep_enabled = enabled; 1459 env->singlestep_enabled = enabled;
1460 - /* must flush all the translated code to avoid inconsistancies */  
1461 - /* XXX: only flush what is necessary */  
1462 - tb_flush(env); 1460 + if (kvm_enabled())
  1461 + kvm_update_guest_debug(env, 0);
  1462 + else {
  1463 + /* must flush all the translated code to avoid inconsistancies */
  1464 + /* XXX: only flush what is necessary */
  1465 + tb_flush(env);
  1466 + }
1463 } 1467 }
1464 #endif 1468 #endif
1465 } 1469 }
gdbstub.c
@@ -39,6 +39,7 @@ @@ -39,6 +39,7 @@
39 #define MAX_PACKET_LENGTH 4096 39 #define MAX_PACKET_LENGTH 4096
40 40
41 #include "qemu_socket.h" 41 #include "qemu_socket.h"
  42 +#include "kvm.h"
42 43
43 44
44 enum { 45 enum {
@@ -1418,13 +1419,6 @@ void gdb_register_coprocessor(CPUState * env, @@ -1418,13 +1419,6 @@ void gdb_register_coprocessor(CPUState * env,
1418 } 1419 }
1419 } 1420 }
1420 1421
1421 -/* GDB breakpoint/watchpoint types */  
1422 -#define GDB_BREAKPOINT_SW 0  
1423 -#define GDB_BREAKPOINT_HW 1  
1424 -#define GDB_WATCHPOINT_WRITE 2  
1425 -#define GDB_WATCHPOINT_READ 3  
1426 -#define GDB_WATCHPOINT_ACCESS 4  
1427 -  
1428 #ifndef CONFIG_USER_ONLY 1422 #ifndef CONFIG_USER_ONLY
1429 static const int xlat_gdb_type[] = { 1423 static const int xlat_gdb_type[] = {
1430 [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE, 1424 [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE,
@@ -1438,6 +1432,9 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) @@ -1438,6 +1432,9 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
1438 CPUState *env; 1432 CPUState *env;
1439 int err = 0; 1433 int err = 0;
1440 1434
  1435 + if (kvm_enabled())
  1436 + return kvm_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);
  1437 +
1441 switch (type) { 1438 switch (type) {
1442 case GDB_BREAKPOINT_SW: 1439 case GDB_BREAKPOINT_SW:
1443 case GDB_BREAKPOINT_HW: 1440 case GDB_BREAKPOINT_HW:
@@ -1469,6 +1466,9 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) @@ -1469,6 +1466,9 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
1469 CPUState *env; 1466 CPUState *env;
1470 int err = 0; 1467 int err = 0;
1471 1468
  1469 + if (kvm_enabled())
  1470 + return kvm_remove_breakpoint(gdbserver_state->c_cpu, addr, len, type);
  1471 +
1472 switch (type) { 1472 switch (type) {
1473 case GDB_BREAKPOINT_SW: 1473 case GDB_BREAKPOINT_SW:
1474 case GDB_BREAKPOINT_HW: 1474 case GDB_BREAKPOINT_HW:
@@ -1498,6 +1498,11 @@ static void gdb_breakpoint_remove_all(void) @@ -1498,6 +1498,11 @@ static void gdb_breakpoint_remove_all(void)
1498 { 1498 {
1499 CPUState *env; 1499 CPUState *env;
1500 1500
  1501 + if (kvm_enabled()) {
  1502 + kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
  1503 + return;
  1504 + }
  1505 +
1501 for (env = first_cpu; env != NULL; env = env->next_cpu) { 1506 for (env = first_cpu; env != NULL; env = env->next_cpu) {
1502 cpu_breakpoint_remove_all(env, BP_GDB); 1507 cpu_breakpoint_remove_all(env, BP_GDB);
1503 #ifndef CONFIG_USER_ONLY 1508 #ifndef CONFIG_USER_ONLY
@@ -1538,6 +1543,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) @@ -1538,6 +1543,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1538 addr = strtoull(p, (char **)&p, 16); 1543 addr = strtoull(p, (char **)&p, 16);
1539 #if defined(TARGET_I386) 1544 #if defined(TARGET_I386)
1540 s->c_cpu->eip = addr; 1545 s->c_cpu->eip = addr;
  1546 + cpu_synchronize_state(s->c_cpu, 1);
1541 #elif defined (TARGET_PPC) 1547 #elif defined (TARGET_PPC)
1542 s->c_cpu->nip = addr; 1548 s->c_cpu->nip = addr;
1543 #elif defined (TARGET_SPARC) 1549 #elif defined (TARGET_SPARC)
@@ -1579,6 +1585,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) @@ -1579,6 +1585,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1579 addr = strtoull(p, (char **)&p, 16); 1585 addr = strtoull(p, (char **)&p, 16);
1580 #if defined(TARGET_I386) 1586 #if defined(TARGET_I386)
1581 s->c_cpu->eip = addr; 1587 s->c_cpu->eip = addr;
  1588 + cpu_synchronize_state(s->c_cpu, 1);
1582 #elif defined (TARGET_PPC) 1589 #elif defined (TARGET_PPC)
1583 s->c_cpu->nip = addr; 1590 s->c_cpu->nip = addr;
1584 #elif defined (TARGET_SPARC) 1591 #elif defined (TARGET_SPARC)
@@ -1624,6 +1631,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) @@ -1624,6 +1631,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1624 } 1631 }
1625 break; 1632 break;
1626 case 'g': 1633 case 'g':
  1634 + cpu_synchronize_state(s->g_cpu, 0);
1627 len = 0; 1635 len = 0;
1628 for (addr = 0; addr < num_g_regs; addr++) { 1636 for (addr = 0; addr < num_g_regs; addr++) {
1629 reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr); 1637 reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
@@ -1641,6 +1649,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) @@ -1641,6 +1649,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1641 len -= reg_size; 1649 len -= reg_size;
1642 registers += reg_size; 1650 registers += reg_size;
1643 } 1651 }
  1652 + cpu_synchronize_state(s->g_cpu, 1);
1644 put_packet(s, "OK"); 1653 put_packet(s, "OK");
1645 break; 1654 break;
1646 case 'm': 1655 case 'm':
@@ -1799,6 +1808,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) @@ -1799,6 +1808,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1799 thread = strtoull(p+16, (char **)&p, 16); 1808 thread = strtoull(p+16, (char **)&p, 16);
1800 for (env = first_cpu; env != NULL; env = env->next_cpu) 1809 for (env = first_cpu; env != NULL; env = env->next_cpu)
1801 if (env->cpu_index + 1 == thread) { 1810 if (env->cpu_index + 1 == thread) {
  1811 + cpu_synchronize_state(env, 0);
1802 len = snprintf((char *)mem_buf, sizeof(mem_buf), 1812 len = snprintf((char *)mem_buf, sizeof(mem_buf),
1803 "CPU#%d [%s]", env->cpu_index, 1813 "CPU#%d [%s]", env->cpu_index,
1804 env->halted ? "halted " : "running"); 1814 env->halted ? "halted " : "running");
gdbstub.h
@@ -3,6 +3,13 @@ @@ -3,6 +3,13 @@
3 3
4 #define DEFAULT_GDBSTUB_PORT "1234" 4 #define DEFAULT_GDBSTUB_PORT "1234"
5 5
  6 +/* GDB breakpoint/watchpoint types */
  7 +#define GDB_BREAKPOINT_SW 0
  8 +#define GDB_BREAKPOINT_HW 1
  9 +#define GDB_WATCHPOINT_WRITE 2
  10 +#define GDB_WATCHPOINT_READ 3
  11 +#define GDB_WATCHPOINT_ACCESS 4
  12 +
6 typedef void (*gdb_syscall_complete_cb)(CPUState *env, 13 typedef void (*gdb_syscall_complete_cb)(CPUState *env,
7 target_ulong ret, target_ulong err); 14 target_ulong ret, target_ulong err);
8 15
kvm-all.c
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 22
23 #include "qemu-common.h" 23 #include "qemu-common.h"
24 #include "sysemu.h" 24 #include "sysemu.h"
  25 +#include "gdbstub.h"
25 #include "kvm.h" 26 #include "kvm.h"
26 27
27 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */ 28 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
@@ -56,6 +57,9 @@ struct KVMState @@ -56,6 +57,9 @@ struct KVMState
56 int fd; 57 int fd;
57 int vmfd; 58 int vmfd;
58 int coalesced_mmio; 59 int coalesced_mmio;
  60 +#ifdef KVM_CAP_SET_GUEST_DEBUG
  61 + struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
  62 +#endif
59 }; 63 };
60 64
61 static KVMState *kvm_state; 65 static KVMState *kvm_state;
@@ -291,6 +295,9 @@ int kvm_init(int smp_cpus) @@ -291,6 +295,9 @@ int kvm_init(int smp_cpus)
291 295
292 s = qemu_mallocz(sizeof(KVMState)); 296 s = qemu_mallocz(sizeof(KVMState));
293 297
  298 +#ifdef KVM_CAP_SET_GUEST_DEBUG
  299 + TAILQ_INIT(&s->kvm_sw_breakpoints);
  300 +#endif
294 for (i = 0; i < ARRAY_SIZE(s->slots); i++) 301 for (i = 0; i < ARRAY_SIZE(s->slots); i++)
295 s->slots[i].slot = i; 302 s->slots[i].slot = i;
296 303
@@ -504,6 +511,16 @@ int kvm_cpu_exec(CPUState *env) @@ -504,6 +511,16 @@ int kvm_cpu_exec(CPUState *env)
504 break; 511 break;
505 case KVM_EXIT_DEBUG: 512 case KVM_EXIT_DEBUG:
506 dprintf("kvm_exit_debug\n"); 513 dprintf("kvm_exit_debug\n");
  514 +#ifdef KVM_CAP_SET_GUEST_DEBUG
  515 + if (kvm_arch_debug(&run->debug.arch)) {
  516 + gdb_set_stop_cpu(env);
  517 + vm_stop(EXCP_DEBUG);
  518 + env->exception_index = EXCP_DEBUG;
  519 + return 0;
  520 + }
  521 + /* re-enter, this exception was guest-internal */
  522 + ret = 1;
  523 +#endif /* KVM_CAP_SET_GUEST_DEBUG */
507 break; 524 break;
508 default: 525 default:
509 dprintf("kvm_arch_handle_exit\n"); 526 dprintf("kvm_arch_handle_exit\n");
@@ -656,3 +673,159 @@ int kvm_has_sync_mmu(void) @@ -656,3 +673,159 @@ int kvm_has_sync_mmu(void)
656 673
657 return 0; 674 return 0;
658 } 675 }
  676 +
  677 +#ifdef KVM_CAP_SET_GUEST_DEBUG
  678 +struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
  679 + target_ulong pc)
  680 +{
  681 + struct kvm_sw_breakpoint *bp;
  682 +
  683 + TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
  684 + if (bp->pc == pc)
  685 + return bp;
  686 + }
  687 + return NULL;
  688 +}
  689 +
  690 +int kvm_sw_breakpoints_active(CPUState *env)
  691 +{
  692 + return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
  693 +}
  694 +
  695 +int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
  696 +{
  697 + struct kvm_guest_debug dbg;
  698 +
  699 + dbg.control = 0;
  700 + if (env->singlestep_enabled)
  701 + dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
  702 +
  703 + kvm_arch_update_guest_debug(env, &dbg);
  704 + dbg.control |= reinject_trap;
  705 +
  706 + return kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg);
  707 +}
  708 +
  709 +int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
  710 + target_ulong len, int type)
  711 +{
  712 + struct kvm_sw_breakpoint *bp;
  713 + CPUState *env;
  714 + int err;
  715 +
  716 + if (type == GDB_BREAKPOINT_SW) {
  717 + bp = kvm_find_sw_breakpoint(current_env, addr);
  718 + if (bp) {
  719 + bp->use_count++;
  720 + return 0;
  721 + }
  722 +
  723 + bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
  724 + if (!bp)
  725 + return -ENOMEM;
  726 +
  727 + bp->pc = addr;
  728 + bp->use_count = 1;
  729 + err = kvm_arch_insert_sw_breakpoint(current_env, bp);
  730 + if (err) {
  731 + free(bp);
  732 + return err;
  733 + }
  734 +
  735 + TAILQ_INSERT_HEAD(&current_env->kvm_state->kvm_sw_breakpoints,
  736 + bp, entry);
  737 + } else {
  738 + err = kvm_arch_insert_hw_breakpoint(addr, len, type);
  739 + if (err)
  740 + return err;
  741 + }
  742 +
  743 + for (env = first_cpu; env != NULL; env = env->next_cpu) {
  744 + err = kvm_update_guest_debug(env, 0);
  745 + if (err)
  746 + return err;
  747 + }
  748 + return 0;
  749 +}
  750 +
  751 +int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
  752 + target_ulong len, int type)
  753 +{
  754 + struct kvm_sw_breakpoint *bp;
  755 + CPUState *env;
  756 + int err;
  757 +
  758 + if (type == GDB_BREAKPOINT_SW) {
  759 + bp = kvm_find_sw_breakpoint(current_env, addr);
  760 + if (!bp)
  761 + return -ENOENT;
  762 +
  763 + if (bp->use_count > 1) {
  764 + bp->use_count--;
  765 + return 0;
  766 + }
  767 +
  768 + err = kvm_arch_remove_sw_breakpoint(current_env, bp);
  769 + if (err)
  770 + return err;
  771 +
  772 + TAILQ_REMOVE(&current_env->kvm_state->kvm_sw_breakpoints, bp, entry);
  773 + qemu_free(bp);
  774 + } else {
  775 + err = kvm_arch_remove_hw_breakpoint(addr, len, type);
  776 + if (err)
  777 + return err;
  778 + }
  779 +
  780 + for (env = first_cpu; env != NULL; env = env->next_cpu) {
  781 + err = kvm_update_guest_debug(env, 0);
  782 + if (err)
  783 + return err;
  784 + }
  785 + return 0;
  786 +}
  787 +
  788 +void kvm_remove_all_breakpoints(CPUState *current_env)
  789 +{
  790 + struct kvm_sw_breakpoint *bp, *next;
  791 + KVMState *s = current_env->kvm_state;
  792 + CPUState *env;
  793 +
  794 + TAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
  795 + if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
  796 + /* Try harder to find a CPU that currently sees the breakpoint. */
  797 + for (env = first_cpu; env != NULL; env = env->next_cpu) {
  798 + if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
  799 + break;
  800 + }
  801 + }
  802 + }
  803 + kvm_arch_remove_all_hw_breakpoints();
  804 +
  805 + for (env = first_cpu; env != NULL; env = env->next_cpu)
  806 + kvm_update_guest_debug(env, 0);
  807 +}
  808 +
  809 +#else /* !KVM_CAP_SET_GUEST_DEBUG */
  810 +
  811 +int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
  812 +{
  813 + return -EINVAL;
  814 +}
  815 +
  816 +int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
  817 + target_ulong len, int type)
  818 +{
  819 + return -EINVAL;
  820 +}
  821 +
  822 +int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
  823 + target_ulong len, int type)
  824 +{
  825 + return -EINVAL;
  826 +}
  827 +
  828 +void kvm_remove_all_breakpoints(CPUState *current_env)
  829 +{
  830 +}
  831 +#endif /* !KVM_CAP_SET_GUEST_DEBUG */
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 #define QEMU_KVM_H 15 #define QEMU_KVM_H
16 16
17 #include "config.h" 17 #include "config.h"
  18 +#include "sys-queue.h"
18 19
19 #ifdef CONFIG_KVM 20 #ifdef CONFIG_KVM
20 extern int kvm_allowed; 21 extern int kvm_allowed;
@@ -49,6 +50,13 @@ int kvm_has_sync_mmu(void); @@ -49,6 +50,13 @@ int kvm_has_sync_mmu(void);
49 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); 50 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
50 int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); 51 int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
51 52
  53 +int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
  54 + target_ulong len, int type);
  55 +int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
  56 + target_ulong len, int type);
  57 +void kvm_remove_all_breakpoints(CPUState *current_env);
  58 +int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
  59 +
52 /* internal API */ 60 /* internal API */
53 61
54 struct KVMState; 62 struct KVMState;
@@ -76,4 +84,47 @@ int kvm_arch_init(KVMState *s, int smp_cpus); @@ -76,4 +84,47 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
76 84
77 int kvm_arch_init_vcpu(CPUState *env); 85 int kvm_arch_init_vcpu(CPUState *env);
78 86
  87 +struct kvm_guest_debug;
  88 +struct kvm_debug_exit_arch;
  89 +
  90 +struct kvm_sw_breakpoint {
  91 + target_ulong pc;
  92 + target_ulong saved_insn;
  93 + int use_count;
  94 + TAILQ_ENTRY(kvm_sw_breakpoint) entry;
  95 +};
  96 +
  97 +TAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
  98 +
  99 +int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info);
  100 +
  101 +struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
  102 + target_ulong pc);
  103 +
  104 +int kvm_sw_breakpoints_active(CPUState *env);
  105 +
  106 +int kvm_arch_insert_sw_breakpoint(CPUState *current_env,
  107 + struct kvm_sw_breakpoint *bp);
  108 +int kvm_arch_remove_sw_breakpoint(CPUState *current_env,
  109 + struct kvm_sw_breakpoint *bp);
  110 +int kvm_arch_insert_hw_breakpoint(target_ulong addr,
  111 + target_ulong len, int type);
  112 +int kvm_arch_remove_hw_breakpoint(target_ulong addr,
  113 + target_ulong len, int type);
  114 +void kvm_arch_remove_all_hw_breakpoints(void);
  115 +
  116 +void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
  117 +
  118 +/* generic hooks - to be moved/refactored once there are more users */
  119 +
  120 +static inline void cpu_synchronize_state(CPUState *env, int modified)
  121 +{
  122 + if (kvm_enabled()) {
  123 + if (modified)
  124 + kvm_arch_put_registers(env);
  125 + else
  126 + kvm_arch_get_registers(env);
  127 + }
  128 +}
  129 +
79 #endif 130 #endif
target-i386/kvm.c
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 #include "sysemu.h" 22 #include "sysemu.h"
23 #include "kvm.h" 23 #include "kvm.h"
24 #include "cpu.h" 24 #include "cpu.h"
  25 +#include "gdbstub.h"
25 26
26 //#define DEBUG_KVM 27 //#define DEBUG_KVM
27 28
@@ -683,3 +684,193 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) @@ -683,3 +684,193 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
683 684
684 return ret; 685 return ret;
685 } 686 }
  687 +
  688 +#ifdef KVM_CAP_SET_GUEST_DEBUG
  689 +static int kvm_patch_opcode_byte(CPUState *env, target_ulong addr, uint8_t val)
  690 +{
  691 + target_phys_addr_t phys_page_addr;
  692 + unsigned long pd;
  693 + uint8_t *ptr;
  694 +
  695 + phys_page_addr = cpu_get_phys_page_debug(env, addr & TARGET_PAGE_MASK);
  696 + if (phys_page_addr == -1)
  697 + return -EINVAL;
  698 +
  699 + pd = cpu_get_physical_page_desc(phys_page_addr);
  700 + if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
  701 + (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM && !(pd & IO_MEM_ROMD))
  702 + return -EINVAL;
  703 +
  704 + ptr = phys_ram_base + (pd & TARGET_PAGE_MASK)
  705 + + (addr & ~TARGET_PAGE_MASK);
  706 + *ptr = val;
  707 + return 0;
  708 +}
  709 +
  710 +int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
  711 +{
  712 + if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
  713 + kvm_patch_opcode_byte(env, bp->pc, 0xcc))
  714 + return -EINVAL;
  715 + return 0;
  716 +}
  717 +
  718 +int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
  719 +{
  720 + uint8_t int3;
  721 +
  722 + if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
  723 + kvm_patch_opcode_byte(env, bp->pc, bp->saved_insn))
  724 + return -EINVAL;
  725 + return 0;
  726 +}
  727 +
  728 +static struct {
  729 + target_ulong addr;
  730 + int len;
  731 + int type;
  732 +} hw_breakpoint[4];
  733 +
  734 +static int nb_hw_breakpoint;
  735 +
  736 +static int find_hw_breakpoint(target_ulong addr, int len, int type)
  737 +{
  738 + int n;
  739 +
  740 + for (n = 0; n < nb_hw_breakpoint; n++)
  741 + if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
  742 + (hw_breakpoint[n].len == len || len == -1))
  743 + return n;
  744 + return -1;
  745 +}
  746 +
  747 +int kvm_arch_insert_hw_breakpoint(target_ulong addr,
  748 + target_ulong len, int type)
  749 +{
  750 + switch (type) {
  751 + case GDB_BREAKPOINT_HW:
  752 + len = 1;
  753 + break;
  754 + case GDB_WATCHPOINT_WRITE:
  755 + case GDB_WATCHPOINT_ACCESS:
  756 + switch (len) {
  757 + case 1:
  758 + break;
  759 + case 2:
  760 + case 4:
  761 + case 8:
  762 + if (addr & (len - 1))
  763 + return -EINVAL;
  764 + break;
  765 + default:
  766 + return -EINVAL;
  767 + }
  768 + break;
  769 + default:
  770 + return -ENOSYS;
  771 + }
  772 +
  773 + if (nb_hw_breakpoint == 4)
  774 + return -ENOBUFS;
  775 +
  776 + if (find_hw_breakpoint(addr, len, type) >= 0)
  777 + return -EEXIST;
  778 +
  779 + hw_breakpoint[nb_hw_breakpoint].addr = addr;
  780 + hw_breakpoint[nb_hw_breakpoint].len = len;
  781 + hw_breakpoint[nb_hw_breakpoint].type = type;
  782 + nb_hw_breakpoint++;
  783 +
  784 + return 0;
  785 +}
  786 +
  787 +int kvm_arch_remove_hw_breakpoint(target_ulong addr,
  788 + target_ulong len, int type)
  789 +{
  790 + int n;
  791 +
  792 + n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
  793 + if (n < 0)
  794 + return -ENOENT;
  795 +
  796 + nb_hw_breakpoint--;
  797 + hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
  798 +
  799 + return 0;
  800 +}
  801 +
  802 +void kvm_arch_remove_all_hw_breakpoints(void)
  803 +{
  804 + nb_hw_breakpoint = 0;
  805 +}
  806 +
  807 +static CPUWatchpoint hw_watchpoint;
  808 +
  809 +int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
  810 +{
  811 + int handle = 0;
  812 + int n;
  813 +
  814 + if (arch_info->exception == 1) {
  815 + if (arch_info->dr6 & (1 << 14)) {
  816 + if (cpu_single_env->singlestep_enabled)
  817 + handle = 1;
  818 + } else {
  819 + for (n = 0; n < 4; n++)
  820 + if (arch_info->dr6 & (1 << n))
  821 + switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
  822 + case 0x0:
  823 + handle = 1;
  824 + break;
  825 + case 0x1:
  826 + handle = 1;
  827 + cpu_single_env->watchpoint_hit = &hw_watchpoint;
  828 + hw_watchpoint.vaddr = hw_breakpoint[n].addr;
  829 + hw_watchpoint.flags = BP_MEM_WRITE;
  830 + break;
  831 + case 0x3:
  832 + handle = 1;
  833 + cpu_single_env->watchpoint_hit = &hw_watchpoint;
  834 + hw_watchpoint.vaddr = hw_breakpoint[n].addr;
  835 + hw_watchpoint.flags = BP_MEM_ACCESS;
  836 + break;
  837 + }
  838 + }
  839 + } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
  840 + handle = 1;
  841 +
  842 + if (!handle)
  843 + kvm_update_guest_debug(cpu_single_env,
  844 + (arch_info->exception == 1) ?
  845 + KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
  846 +
  847 + return handle;
  848 +}
  849 +
  850 +void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
  851 +{
  852 + const uint8_t type_code[] = {
  853 + [GDB_BREAKPOINT_HW] = 0x0,
  854 + [GDB_WATCHPOINT_WRITE] = 0x1,
  855 + [GDB_WATCHPOINT_ACCESS] = 0x3
  856 + };
  857 + const uint8_t len_code[] = {
  858 + [1] = 0x0, [2] = 0x1, [4] = 0x3, [8] = 0x2
  859 + };
  860 + int n;
  861 +
  862 + if (kvm_sw_breakpoints_active(env))
  863 + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
  864 +
  865 + if (nb_hw_breakpoint > 0) {
  866 + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
  867 + dbg->arch.debugreg[7] = 0x0600;
  868 + for (n = 0; n < nb_hw_breakpoint; n++) {
  869 + dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
  870 + dbg->arch.debugreg[7] |= (2 << (n * 2)) |
  871 + (type_code[hw_breakpoint[n].type] << (16 + n*4)) |
  872 + (len_code[hw_breakpoint[n].len] << (18 + n*4));
  873 + }
  874 + }
  875 +}
  876 +#endif /* KVM_CAP_SET_GUEST_DEBUG */