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 1457 #if defined(TARGET_HAS_ICE)
1458 1458 if (env->singlestep_enabled != enabled) {
1459 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 1468 #endif
1465 1469 }
... ...
gdbstub.c
... ... @@ -39,6 +39,7 @@
39 39 #define MAX_PACKET_LENGTH 4096
40 40  
41 41 #include "qemu_socket.h"
  42 +#include "kvm.h"
42 43  
43 44  
44 45 enum {
... ... @@ -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 1422 #ifndef CONFIG_USER_ONLY
1429 1423 static const int xlat_gdb_type[] = {
1430 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 1432 CPUState *env;
1439 1433 int err = 0;
1440 1434  
  1435 + if (kvm_enabled())
  1436 + return kvm_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);
  1437 +
1441 1438 switch (type) {
1442 1439 case GDB_BREAKPOINT_SW:
1443 1440 case GDB_BREAKPOINT_HW:
... ... @@ -1469,6 +1466,9 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
1469 1466 CPUState *env;
1470 1467 int err = 0;
1471 1468  
  1469 + if (kvm_enabled())
  1470 + return kvm_remove_breakpoint(gdbserver_state->c_cpu, addr, len, type);
  1471 +
1472 1472 switch (type) {
1473 1473 case GDB_BREAKPOINT_SW:
1474 1474 case GDB_BREAKPOINT_HW:
... ... @@ -1498,6 +1498,11 @@ static void gdb_breakpoint_remove_all(void)
1498 1498 {
1499 1499 CPUState *env;
1500 1500  
  1501 + if (kvm_enabled()) {
  1502 + kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
  1503 + return;
  1504 + }
  1505 +
1501 1506 for (env = first_cpu; env != NULL; env = env->next_cpu) {
1502 1507 cpu_breakpoint_remove_all(env, BP_GDB);
1503 1508 #ifndef CONFIG_USER_ONLY
... ... @@ -1538,6 +1543,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1538 1543 addr = strtoull(p, (char **)&p, 16);
1539 1544 #if defined(TARGET_I386)
1540 1545 s->c_cpu->eip = addr;
  1546 + cpu_synchronize_state(s->c_cpu, 1);
1541 1547 #elif defined (TARGET_PPC)
1542 1548 s->c_cpu->nip = addr;
1543 1549 #elif defined (TARGET_SPARC)
... ... @@ -1579,6 +1585,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1579 1585 addr = strtoull(p, (char **)&p, 16);
1580 1586 #if defined(TARGET_I386)
1581 1587 s->c_cpu->eip = addr;
  1588 + cpu_synchronize_state(s->c_cpu, 1);
1582 1589 #elif defined (TARGET_PPC)
1583 1590 s->c_cpu->nip = addr;
1584 1591 #elif defined (TARGET_SPARC)
... ... @@ -1624,6 +1631,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1624 1631 }
1625 1632 break;
1626 1633 case 'g':
  1634 + cpu_synchronize_state(s->g_cpu, 0);
1627 1635 len = 0;
1628 1636 for (addr = 0; addr < num_g_regs; addr++) {
1629 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 1649 len -= reg_size;
1642 1650 registers += reg_size;
1643 1651 }
  1652 + cpu_synchronize_state(s->g_cpu, 1);
1644 1653 put_packet(s, "OK");
1645 1654 break;
1646 1655 case 'm':
... ... @@ -1799,6 +1808,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
1799 1808 thread = strtoull(p+16, (char **)&p, 16);
1800 1809 for (env = first_cpu; env != NULL; env = env->next_cpu)
1801 1810 if (env->cpu_index + 1 == thread) {
  1811 + cpu_synchronize_state(env, 0);
1802 1812 len = snprintf((char *)mem_buf, sizeof(mem_buf),
1803 1813 "CPU#%d [%s]", env->cpu_index,
1804 1814 env->halted ? "halted " : "running");
... ...
gdbstub.h
... ... @@ -3,6 +3,13 @@
3 3  
4 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 13 typedef void (*gdb_syscall_complete_cb)(CPUState *env,
7 14 target_ulong ret, target_ulong err);
8 15  
... ...
kvm-all.c
... ... @@ -22,6 +22,7 @@
22 22  
23 23 #include "qemu-common.h"
24 24 #include "sysemu.h"
  25 +#include "gdbstub.h"
25 26 #include "kvm.h"
26 27  
27 28 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
... ... @@ -56,6 +57,9 @@ struct KVMState
56 57 int fd;
57 58 int vmfd;
58 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 65 static KVMState *kvm_state;
... ... @@ -291,6 +295,9 @@ int kvm_init(int smp_cpus)
291 295  
292 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 301 for (i = 0; i < ARRAY_SIZE(s->slots); i++)
295 302 s->slots[i].slot = i;
296 303  
... ... @@ -504,6 +511,16 @@ int kvm_cpu_exec(CPUState *env)
504 511 break;
505 512 case KVM_EXIT_DEBUG:
506 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 524 break;
508 525 default:
509 526 dprintf("kvm_arch_handle_exit\n");
... ... @@ -656,3 +673,159 @@ int kvm_has_sync_mmu(void)
656 673  
657 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 15 #define QEMU_KVM_H
16 16  
17 17 #include "config.h"
  18 +#include "sys-queue.h"
18 19  
19 20 #ifdef CONFIG_KVM
20 21 extern int kvm_allowed;
... ... @@ -49,6 +50,13 @@ int kvm_has_sync_mmu(void);
49 50 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
50 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 60 /* internal API */
53 61  
54 62 struct KVMState;
... ... @@ -76,4 +84,47 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
76 84  
77 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 130 #endif
... ...
target-i386/kvm.c
... ... @@ -22,6 +22,7 @@
22 22 #include "sysemu.h"
23 23 #include "kvm.h"
24 24 #include "cpu.h"
  25 +#include "gdbstub.h"
25 26  
26 27 //#define DEBUG_KVM
27 28  
... ... @@ -683,3 +684,193 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
683 684  
684 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 */
... ...