whpx: Added support for breakpoints and stepping

Below is the updated version of the patch adding debugging support to WHPX.
It incorporates feedback from Alex Bennée and Peter Maydell regarding not
changing the emulation logic depending on the gdb connection status.

Instead of checking for an active gdb connection to determine whether QEMU
should intercept the INT1 exceptions, it now checks whether any breakpoints
have been set, or whether gdb has explicitly requested one or more CPUs to
do single-stepping. Having none of these condition present now has the same
effect as not using gdb at all.

Message-Id: <0e7f01d82e9e$00e9c360$02bd4a20$@sysprogs.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Ivan Shcherbakov
2022-04-06 14:31:55 +02:00
committed by Paolo Bonzini
parent 9d734b85ed
commit d7482ffe97
8 changed files with 815 additions and 18 deletions
+9 -1
View File
@@ -518,7 +518,15 @@ static int gdb_continue_partial(char *newstates)
int flag = 0;
if (!runstate_needs_reset()) {
if (vm_prepare_start()) {
bool step_requested = false;
CPU_FOREACH(cpu) {
if (newstates[cpu->cpu_index] == 's') {
step_requested = true;
break;
}
}
if (vm_prepare_start(step_requested)) {
return 0;
}
+1
View File
@@ -38,6 +38,7 @@ struct AccelOpsClass {
void (*synchronize_post_init)(CPUState *cpu);
void (*synchronize_state)(CPUState *cpu);
void (*synchronize_pre_loadvm)(CPUState *cpu);
void (*synchronize_pre_resume)(bool step_pending);
void (*handle_interrupt)(CPUState *cpu, int mask);
+7 -1
View File
@@ -34,7 +34,13 @@ static inline bool shutdown_caused_by_guest(ShutdownCause cause)
}
void vm_start(void);
int vm_prepare_start(void);
/**
* vm_prepare_start: Prepare for starting/resuming the VM
*
* @step_pending: whether any of the CPUs is about to be single-stepped by gdb
*/
int vm_prepare_start(bool step_pending);
int vm_stop(RunState state);
int vm_stop_force_state(RunState state);
int vm_shutdown(void);
+10 -2
View File
@@ -672,7 +672,7 @@ int vm_stop(RunState state)
* Returns -1 if the vCPUs are not to be restarted (e.g. if they are already
* running or in case of an error condition), 0 otherwise.
*/
int vm_prepare_start(void)
int vm_prepare_start(bool step_pending)
{
RunState requested;
@@ -692,6 +692,14 @@ int vm_prepare_start(void)
return -1;
}
/*
* WHPX accelerator needs to know whether we are going to step
* any CPUs, before starting the first one.
*/
if (cpus_accel->synchronize_pre_resume) {
cpus_accel->synchronize_pre_resume(step_pending);
}
/* We are sending this now, but the CPUs will be resumed shortly later */
qapi_event_send_resume();
@@ -703,7 +711,7 @@ int vm_prepare_start(void)
void vm_start(void)
{
if (!vm_prepare_start()) {
if (!vm_prepare_start(false)) {
resume_all_vcpus();
}
}
+1
View File
@@ -100,6 +100,7 @@ static void whpx_accel_ops_class_init(ObjectClass *oc, void *data)
ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
ops->synchronize_state = whpx_cpu_synchronize_state;
ops->synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm;
ops->synchronize_pre_resume = whpx_cpu_synchronize_pre_resume;
}
static const TypeInfo whpx_accel_ops_type = {
+1
View File
@@ -21,6 +21,7 @@ void whpx_cpu_synchronize_state(CPUState *cpu);
void whpx_cpu_synchronize_post_reset(CPUState *cpu);
void whpx_cpu_synchronize_post_init(CPUState *cpu);
void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu);
void whpx_cpu_synchronize_pre_resume(bool step_pending);
/* state subset only touched by the VCPU itself during runtime */
#define WHPX_SET_RUNTIME_STATE 1
File diff suppressed because it is too large Load Diff
+30
View File
@@ -5,9 +5,39 @@
#include <WinHvPlatform.h>
#include <WinHvEmulation.h>
typedef enum WhpxBreakpointState {
WHPX_BP_CLEARED = 0,
WHPX_BP_SET_PENDING,
WHPX_BP_SET,
WHPX_BP_CLEAR_PENDING,
} WhpxBreakpointState;
struct whpx_breakpoint {
vaddr address;
WhpxBreakpointState state;
uint8_t original_instruction;
};
struct whpx_breakpoint_collection {
int allocated, used;
struct whpx_breakpoint data[0];
};
struct whpx_breakpoints {
int original_address_count;
vaddr *original_addresses;
struct whpx_breakpoint_collection *breakpoints;
};
struct whpx_state {
uint64_t mem_quota;
WHV_PARTITION_HANDLE partition;
uint64_t exception_exit_bitmap;
int32_t running_cpus;
struct whpx_breakpoints breakpoints;
bool step_pending;
bool kernel_irqchip_allowed;
bool kernel_irqchip_required;
bool apic_in_platform;