From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Emanuele Giuseppe Esposito <eesposit@redhat.com>,
Jon Doron <arilou@gmail.com>
Subject: [PULL 46/53] hyperv: Add support to process syndbg commands
Date: Tue, 19 Apr 2022 07:51:02 +0200 [thread overview]
Message-ID: <20220419055109.142788-47-pbonzini@redhat.com> (raw)
In-Reply-To: <20220419055109.142788-1-pbonzini@redhat.com>
From: Jon Doron <arilou@gmail.com>
SynDbg commands can come from two different flows:
1. Hypercalls, in this mode the data being sent is fully
encapsulated network packets.
2. SynDbg specific MSRs, in this mode only the data that needs to be
transfered is passed.
Signed-off-by: Jon Doron <arilou@gmail.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Message-Id: <20220216102500.692781-4-arilou@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
docs/hyperv.txt | 15 +++
hw/hyperv/hyperv.c | 243 ++++++++++++++++++++++++++++++++++
include/hw/hyperv/hyperv.h | 58 ++++++++
target/i386/cpu.c | 2 +
target/i386/cpu.h | 7 +
target/i386/kvm/hyperv-stub.c | 6 +
target/i386/kvm/hyperv.c | 52 +++++++-
target/i386/kvm/kvm.c | 76 ++++++++++-
8 files changed, 451 insertions(+), 8 deletions(-)
diff --git a/docs/hyperv.txt b/docs/hyperv.txt
index 0417c183a3..33588a0396 100644
--- a/docs/hyperv.txt
+++ b/docs/hyperv.txt
@@ -225,6 +225,21 @@ default (WS2016).
Note: hv-version-id-* are not enlightenments and thus don't enable Hyper-V
identification when specified without any other enlightenments.
+3.21. hv-syndbg
+===============
+Enables Hyper-V synthetic debugger interface, this is a special interface used
+by Windows Kernel debugger to send the packets through, rather than sending
+them via serial/network .
+When enabled, this enlightenment provides additional communication facilities
+to the guest: SynDbg messages.
+This new communication is used by Windows Kernel debugger rather than sending
+packets via serial/network, adding significant performance boost over the other
+comm channels.
+This enlightenment requires a VMBus device (-device vmbus-bridge,irq=15)
+and the follow enlightenments to work:
+hv-relaxed,hv_time,hv-vapic,hv-vpindex,hv-synic,hv-runtime,hv-stimer
+
+
4. Supplementary features
=========================
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 8b832566c1..4a1b59cb9d 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -704,3 +704,246 @@ uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast)
}
return HV_STATUS_INVALID_CONNECTION_ID;
}
+
+static HvSynDbgHandler hv_syndbg_handler;
+static void *hv_syndbg_context;
+
+void hyperv_set_syndbg_handler(HvSynDbgHandler handler, void *context)
+{
+ assert(!hv_syndbg_handler);
+ hv_syndbg_handler = handler;
+ hv_syndbg_context = context;
+}
+
+uint16_t hyperv_hcall_reset_dbg_session(uint64_t outgpa)
+{
+ uint16_t ret;
+ HvSynDbgMsg msg;
+ struct hyperv_reset_debug_session_output *reset_dbg_session = NULL;
+ hwaddr len;
+
+ if (!hv_syndbg_handler) {
+ ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+ goto cleanup;
+ }
+
+ len = sizeof(*reset_dbg_session);
+ reset_dbg_session = cpu_physical_memory_map(outgpa, &len, 1);
+ if (!reset_dbg_session || len < sizeof(*reset_dbg_session)) {
+ ret = HV_STATUS_INSUFFICIENT_MEMORY;
+ goto cleanup;
+ }
+
+ msg.type = HV_SYNDBG_MSG_CONNECTION_INFO;
+ ret = hv_syndbg_handler(hv_syndbg_context, &msg);
+ if (ret) {
+ goto cleanup;
+ }
+
+ reset_dbg_session->host_ip = msg.u.connection_info.host_ip;
+ reset_dbg_session->host_port = msg.u.connection_info.host_port;
+ /* The following fields are only used as validation for KDVM */
+ memset(&reset_dbg_session->host_mac, 0,
+ sizeof(reset_dbg_session->host_mac));
+ reset_dbg_session->target_ip = msg.u.connection_info.host_ip;
+ reset_dbg_session->target_port = msg.u.connection_info.host_port;
+ memset(&reset_dbg_session->target_mac, 0,
+ sizeof(reset_dbg_session->target_mac));
+cleanup:
+ if (reset_dbg_session) {
+ cpu_physical_memory_unmap(reset_dbg_session,
+ sizeof(*reset_dbg_session), 1, len);
+ }
+
+ return ret;
+}
+
+uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa,
+ bool fast)
+{
+ uint16_t ret;
+ struct hyperv_retrieve_debug_data_input *debug_data_in = NULL;
+ struct hyperv_retrieve_debug_data_output *debug_data_out = NULL;
+ hwaddr in_len, out_len;
+ HvSynDbgMsg msg;
+
+ if (fast || !hv_syndbg_handler) {
+ ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+ goto cleanup;
+ }
+
+ in_len = sizeof(*debug_data_in);
+ debug_data_in = cpu_physical_memory_map(ingpa, &in_len, 0);
+ if (!debug_data_in || in_len < sizeof(*debug_data_in)) {
+ ret = HV_STATUS_INSUFFICIENT_MEMORY;
+ goto cleanup;
+ }
+
+ out_len = sizeof(*debug_data_out);
+ debug_data_out = cpu_physical_memory_map(outgpa, &out_len, 1);
+ if (!debug_data_out || out_len < sizeof(*debug_data_out)) {
+ ret = HV_STATUS_INSUFFICIENT_MEMORY;
+ goto cleanup;
+ }
+
+ msg.type = HV_SYNDBG_MSG_RECV;
+ msg.u.recv.buf_gpa = outgpa + sizeof(*debug_data_out);
+ msg.u.recv.count = TARGET_PAGE_SIZE - sizeof(*debug_data_out);
+ msg.u.recv.options = debug_data_in->options;
+ msg.u.recv.timeout = debug_data_in->timeout;
+ msg.u.recv.is_raw = true;
+ ret = hv_syndbg_handler(hv_syndbg_context, &msg);
+ if (ret == HV_STATUS_NO_DATA) {
+ debug_data_out->retrieved_count = 0;
+ debug_data_out->remaining_count = debug_data_in->count;
+ goto cleanup;
+ } else if (ret != HV_STATUS_SUCCESS) {
+ goto cleanup;
+ }
+
+ debug_data_out->retrieved_count = msg.u.recv.retrieved_count;
+ debug_data_out->remaining_count =
+ debug_data_in->count - msg.u.recv.retrieved_count;
+cleanup:
+ if (debug_data_out) {
+ cpu_physical_memory_unmap(debug_data_out, sizeof(*debug_data_out), 1,
+ out_len);
+ }
+
+ if (debug_data_in) {
+ cpu_physical_memory_unmap(debug_data_in, sizeof(*debug_data_in), 0,
+ in_len);
+ }
+
+ return ret;
+}
+
+uint16_t hyperv_hcall_post_dbg_data(uint64_t ingpa, uint64_t outgpa, bool fast)
+{
+ uint16_t ret;
+ struct hyperv_post_debug_data_input *post_data_in = NULL;
+ struct hyperv_post_debug_data_output *post_data_out = NULL;
+ hwaddr in_len, out_len;
+ HvSynDbgMsg msg;
+
+ if (fast || !hv_syndbg_handler) {
+ ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+ goto cleanup;
+ }
+
+ in_len = sizeof(*post_data_in);
+ post_data_in = cpu_physical_memory_map(ingpa, &in_len, 0);
+ if (!post_data_in || in_len < sizeof(*post_data_in)) {
+ ret = HV_STATUS_INSUFFICIENT_MEMORY;
+ goto cleanup;
+ }
+
+ if (post_data_in->count > TARGET_PAGE_SIZE - sizeof(*post_data_in)) {
+ ret = HV_STATUS_INVALID_PARAMETER;
+ goto cleanup;
+ }
+
+ out_len = sizeof(*post_data_out);
+ post_data_out = cpu_physical_memory_map(outgpa, &out_len, 1);
+ if (!post_data_out || out_len < sizeof(*post_data_out)) {
+ ret = HV_STATUS_INSUFFICIENT_MEMORY;
+ goto cleanup;
+ }
+
+ msg.type = HV_SYNDBG_MSG_SEND;
+ msg.u.send.buf_gpa = ingpa + sizeof(*post_data_in);
+ msg.u.send.count = post_data_in->count;
+ msg.u.send.is_raw = true;
+ ret = hv_syndbg_handler(hv_syndbg_context, &msg);
+ if (ret != HV_STATUS_SUCCESS) {
+ goto cleanup;
+ }
+
+ post_data_out->pending_count = msg.u.send.pending_count;
+ ret = post_data_out->pending_count ? HV_STATUS_INSUFFICIENT_BUFFERS :
+ HV_STATUS_SUCCESS;
+cleanup:
+ if (post_data_out) {
+ cpu_physical_memory_unmap(post_data_out,
+ sizeof(*post_data_out), 1, out_len);
+ }
+
+ if (post_data_in) {
+ cpu_physical_memory_unmap(post_data_in,
+ sizeof(*post_data_in), 0, in_len);
+ }
+
+ return ret;
+}
+
+uint32_t hyperv_syndbg_send(uint64_t ingpa, uint32_t count)
+{
+ HvSynDbgMsg msg;
+
+ if (!hv_syndbg_handler) {
+ return HV_SYNDBG_STATUS_INVALID;
+ }
+
+ msg.type = HV_SYNDBG_MSG_SEND;
+ msg.u.send.buf_gpa = ingpa;
+ msg.u.send.count = count;
+ msg.u.send.is_raw = false;
+ if (hv_syndbg_handler(hv_syndbg_context, &msg)) {
+ return HV_SYNDBG_STATUS_INVALID;
+ }
+
+ return HV_SYNDBG_STATUS_SEND_SUCCESS;
+}
+
+uint32_t hyperv_syndbg_recv(uint64_t ingpa, uint32_t count)
+{
+ uint16_t ret;
+ HvSynDbgMsg msg;
+
+ if (!hv_syndbg_handler) {
+ return HV_SYNDBG_STATUS_INVALID;
+ }
+
+ msg.type = HV_SYNDBG_MSG_RECV;
+ msg.u.recv.buf_gpa = ingpa;
+ msg.u.recv.count = count;
+ msg.u.recv.options = 0;
+ msg.u.recv.timeout = 0;
+ msg.u.recv.is_raw = false;
+ ret = hv_syndbg_handler(hv_syndbg_context, &msg);
+ if (ret != HV_STATUS_SUCCESS) {
+ return 0;
+ }
+
+ return HV_SYNDBG_STATUS_SET_SIZE(HV_SYNDBG_STATUS_RECV_SUCCESS,
+ msg.u.recv.retrieved_count);
+}
+
+void hyperv_syndbg_set_pending_page(uint64_t ingpa)
+{
+ HvSynDbgMsg msg;
+
+ if (!hv_syndbg_handler) {
+ return;
+ }
+
+ msg.type = HV_SYNDBG_MSG_SET_PENDING_PAGE;
+ msg.u.pending_page.buf_gpa = ingpa;
+ hv_syndbg_handler(hv_syndbg_context, &msg);
+}
+
+uint64_t hyperv_syndbg_query_options(void)
+{
+ HvSynDbgMsg msg;
+
+ if (!hv_syndbg_handler) {
+ return 0;
+ }
+
+ msg.type = HV_SYNDBG_MSG_QUERY_OPTIONS;
+ if (hv_syndbg_handler(hv_syndbg_context, &msg) != HV_STATUS_SUCCESS) {
+ return 0;
+ }
+
+ return msg.u.query_options.options;
+}
diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h
index a63ee0003c..015c3524b1 100644
--- a/include/hw/hyperv/hyperv.h
+++ b/include/hw/hyperv/hyperv.h
@@ -81,4 +81,62 @@ void hyperv_synic_update(CPUState *cs, bool enable,
hwaddr msg_page_addr, hwaddr event_page_addr);
bool hyperv_is_synic_enabled(void);
+/*
+ * Process HVCALL_RESET_DEBUG_SESSION hypercall.
+ */
+uint16_t hyperv_hcall_reset_dbg_session(uint64_t outgpa);
+/*
+ * Process HVCALL_RETREIVE_DEBUG_DATA hypercall.
+ */
+uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa,
+ bool fast);
+/*
+ * Process HVCALL_POST_DEBUG_DATA hypercall.
+ */
+uint16_t hyperv_hcall_post_dbg_data(uint64_t ingpa, uint64_t outgpa, bool fast);
+
+uint32_t hyperv_syndbg_send(uint64_t ingpa, uint32_t count);
+uint32_t hyperv_syndbg_recv(uint64_t ingpa, uint32_t count);
+void hyperv_syndbg_set_pending_page(uint64_t ingpa);
+uint64_t hyperv_syndbg_query_options(void);
+
+typedef enum HvSynthDbgMsgType {
+ HV_SYNDBG_MSG_CONNECTION_INFO,
+ HV_SYNDBG_MSG_SEND,
+ HV_SYNDBG_MSG_RECV,
+ HV_SYNDBG_MSG_SET_PENDING_PAGE,
+ HV_SYNDBG_MSG_QUERY_OPTIONS
+} HvDbgSynthMsgType;
+
+typedef struct HvSynDbgMsg {
+ HvDbgSynthMsgType type;
+ union {
+ struct {
+ uint32_t host_ip;
+ uint16_t host_port;
+ } connection_info;
+ struct {
+ uint64_t buf_gpa;
+ uint32_t count;
+ uint32_t pending_count;
+ bool is_raw;
+ } send;
+ struct {
+ uint64_t buf_gpa;
+ uint32_t count;
+ uint32_t options;
+ uint64_t timeout;
+ uint32_t retrieved_count;
+ bool is_raw;
+ } recv;
+ struct {
+ uint64_t buf_gpa;
+ } pending_page;
+ struct {
+ uint64_t options;
+ } query_options;
+ } u;
+} HvSynDbgMsg;
+typedef uint16_t (*HvSynDbgHandler)(void *context, HvSynDbgMsg *msg);
+void hyperv_set_syndbg_handler(HvSynDbgHandler handler, void *context);
#endif
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index cb6b5467d0..99343be926 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6927,6 +6927,8 @@ static Property x86_cpu_properties[] = {
HYPERV_FEAT_AVIC, 0),
DEFINE_PROP_ON_OFF_AUTO("hv-no-nonarch-coresharing", X86CPU,
hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF),
+ DEFINE_PROP_BIT64("hv-syndbg", X86CPU, hyperv_features,
+ HYPERV_FEAT_SYNDBG, 0),
DEFINE_PROP_BOOL("hv-passthrough", X86CPU, hyperv_passthrough, false),
DEFINE_PROP_BOOL("hv-enforce-cpuid", X86CPU, hyperv_enforce_cpuid, false),
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 8422f6c18e..6b61124887 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1085,6 +1085,7 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
#define HYPERV_FEAT_IPI 13
#define HYPERV_FEAT_STIMER_DIRECT 14
#define HYPERV_FEAT_AVIC 15
+#define HYPERV_FEAT_SYNDBG 16
#ifndef HYPERV_SPINLOCK_NEVER_NOTIFY
#define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF
@@ -1601,6 +1602,12 @@ typedef struct CPUArchState {
uint64_t msr_hv_hypercall;
uint64_t msr_hv_guest_os_id;
uint64_t msr_hv_tsc;
+ uint64_t msr_hv_syndbg_control;
+ uint64_t msr_hv_syndbg_status;
+ uint64_t msr_hv_syndbg_send_page;
+ uint64_t msr_hv_syndbg_recv_page;
+ uint64_t msr_hv_syndbg_pending_page;
+ uint64_t msr_hv_syndbg_options;
/* Per-VCPU HV MSRs */
uint64_t msr_hv_vapic;
diff --git a/target/i386/kvm/hyperv-stub.c b/target/i386/kvm/hyperv-stub.c
index 0028527e79..778ed782e6 100644
--- a/target/i386/kvm/hyperv-stub.c
+++ b/target/i386/kvm/hyperv-stub.c
@@ -27,6 +27,12 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
return 0;
case KVM_EXIT_HYPERV_HCALL:
exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE;
+ return 0;
+ case KVM_EXIT_HYPERV_SYNDBG:
+ if (!hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNDBG)) {
+ return -1;
+ }
+
return 0;
default:
return -1;
diff --git a/target/i386/kvm/hyperv.c b/target/i386/kvm/hyperv.c
index 26efc1e0e6..9026ef3a81 100644
--- a/target/i386/kvm/hyperv.c
+++ b/target/i386/kvm/hyperv.c
@@ -81,20 +81,66 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
case KVM_EXIT_HYPERV_HCALL: {
uint16_t code = exit->u.hcall.input & 0xffff;
bool fast = exit->u.hcall.input & HV_HYPERCALL_FAST;
- uint64_t param = exit->u.hcall.params[0];
+ uint64_t in_param = exit->u.hcall.params[0];
+ uint64_t out_param = exit->u.hcall.params[1];
switch (code) {
case HV_POST_MESSAGE:
- exit->u.hcall.result = hyperv_hcall_post_message(param, fast);
+ exit->u.hcall.result = hyperv_hcall_post_message(in_param, fast);
break;
case HV_SIGNAL_EVENT:
- exit->u.hcall.result = hyperv_hcall_signal_event(param, fast);
+ exit->u.hcall.result = hyperv_hcall_signal_event(in_param, fast);
+ break;
+ case HV_POST_DEBUG_DATA:
+ exit->u.hcall.result =
+ hyperv_hcall_post_dbg_data(in_param, out_param, fast);
+ break;
+ case HV_RETRIEVE_DEBUG_DATA:
+ exit->u.hcall.result =
+ hyperv_hcall_retreive_dbg_data(in_param, out_param, fast);
+ break;
+ case HV_RESET_DEBUG_SESSION:
+ exit->u.hcall.result =
+ hyperv_hcall_reset_dbg_session(out_param);
break;
default:
exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE;
}
return 0;
}
+
+ case KVM_EXIT_HYPERV_SYNDBG:
+ if (!hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNDBG)) {
+ return -1;
+ }
+
+ switch (exit->u.syndbg.msr) {
+ case HV_X64_MSR_SYNDBG_CONTROL: {
+ uint64_t control = exit->u.syndbg.control;
+ env->msr_hv_syndbg_control = control;
+ env->msr_hv_syndbg_send_page = exit->u.syndbg.send_page;
+ env->msr_hv_syndbg_recv_page = exit->u.syndbg.recv_page;
+ exit->u.syndbg.status = HV_STATUS_SUCCESS;
+ if (control & HV_SYNDBG_CONTROL_SEND) {
+ exit->u.syndbg.status =
+ hyperv_syndbg_send(env->msr_hv_syndbg_send_page,
+ HV_SYNDBG_CONTROL_SEND_SIZE(control));
+ } else if (control & HV_SYNDBG_CONTROL_RECV) {
+ exit->u.syndbg.status =
+ hyperv_syndbg_recv(env->msr_hv_syndbg_recv_page,
+ TARGET_PAGE_SIZE);
+ }
+ break;
+ }
+ case HV_X64_MSR_SYNDBG_PENDING_BUFFER:
+ env->msr_hv_syndbg_pending_page = exit->u.syndbg.pending_page;
+ hyperv_syndbg_set_pending_page(env->msr_hv_syndbg_pending_page);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
default:
return -1;
}
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 9cf8e03669..0bb3176edc 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -104,6 +104,7 @@ static bool has_msr_hv_synic;
static bool has_msr_hv_stimer;
static bool has_msr_hv_frequencies;
static bool has_msr_hv_reenlightenment;
+static bool has_msr_hv_syndbg_options;
static bool has_msr_xss;
static bool has_msr_umwait;
static bool has_msr_spec_ctrl;
@@ -964,6 +965,14 @@ static struct {
.bits = HV_DEPRECATING_AEOI_RECOMMENDED}
}
},
+ [HYPERV_FEAT_SYNDBG] = {
+ .desc = "Enable synthetic kernel debugger channel (hv-syndbg)",
+ .flags = {
+ {.func = HV_CPUID_FEATURES, .reg = R_EDX,
+ .bits = HV_FEATURE_DEBUG_MSRS_AVAILABLE}
+ },
+ .dependencies = BIT(HYPERV_FEAT_SYNIC) | BIT(HYPERV_FEAT_RELAXED)
+ },
};
static struct kvm_cpuid2 *try_get_hv_cpuid(CPUState *cs, int max,
@@ -1004,8 +1013,8 @@ static struct kvm_cpuid2 *try_get_hv_cpuid(CPUState *cs, int max,
static struct kvm_cpuid2 *get_supported_hv_cpuid(CPUState *cs)
{
struct kvm_cpuid2 *cpuid;
- /* 0x40000000..0x40000005, 0x4000000A, 0x40000080..0x40000080 leaves */
- int max = 10;
+ /* 0x40000000..0x40000005, 0x4000000A, 0x40000080..0x40000082 leaves */
+ int max = 11;
int i;
bool do_sys_ioctl;
@@ -1118,6 +1127,12 @@ static struct kvm_cpuid2 *get_supported_hv_cpuid_legacy(CPUState *cs)
entry_feat->eax |= HV_SYNTIMERS_AVAILABLE;
}
+ if (has_msr_hv_syndbg_options) {
+ entry_feat->edx |= HV_GUEST_DEBUGGING_AVAILABLE;
+ entry_feat->edx |= HV_FEATURE_DEBUG_MSRS_AVAILABLE;
+ entry_feat->ebx |= HV_PARTITION_DEBUGGING_ALLOWED;
+ }
+
if (kvm_check_extension(cs->kvm_state,
KVM_CAP_HYPERV_TLBFLUSH) > 0) {
entry_recomm->eax |= HV_REMOTE_TLB_FLUSH_RECOMMENDED;
@@ -1369,12 +1384,22 @@ static int hyperv_fill_cpuids(CPUState *cs,
{
X86CPU *cpu = X86_CPU(cs);
struct kvm_cpuid_entry2 *c;
- uint32_t cpuid_i = 0;
+ uint32_t signature[3];
+ uint32_t cpuid_i = 0, max_cpuid_leaf = 0;
+
+ max_cpuid_leaf = HV_CPUID_IMPLEMENT_LIMITS;
+ if (hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS)) {
+ max_cpuid_leaf = MAX(max_cpuid_leaf, HV_CPUID_NESTED_FEATURES);
+ }
+
+ if (hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNDBG)) {
+ max_cpuid_leaf =
+ MAX(max_cpuid_leaf, HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES);
+ }
c = &cpuid_ent[cpuid_i++];
c->function = HV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
- c->eax = hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ?
- HV_CPUID_NESTED_FEATURES : HV_CPUID_IMPLEMENT_LIMITS;
+ c->eax = max_cpuid_leaf;
c->ebx = cpu->hyperv_vendor_id[0];
c->ecx = cpu->hyperv_vendor_id[1];
c->edx = cpu->hyperv_vendor_id[2];
@@ -1453,6 +1478,33 @@ static int hyperv_fill_cpuids(CPUState *cs,
c->eax = cpu->hyperv_nested[0];
}
+ if (hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNDBG)) {
+ c = &cpuid_ent[cpuid_i++];
+ c->function = HV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS;
+ c->eax = hyperv_feat_enabled(cpu, HYPERV_FEAT_EVMCS) ?
+ HV_CPUID_NESTED_FEATURES : HV_CPUID_IMPLEMENT_LIMITS;
+ memcpy(signature, "Microsoft VS", 12);
+ c->eax = 0;
+ c->ebx = signature[0];
+ c->ecx = signature[1];
+ c->edx = signature[2];
+
+ c = &cpuid_ent[cpuid_i++];
+ c->function = HV_CPUID_SYNDBG_INTERFACE;
+ memcpy(signature, "VS#1\0\0\0\0\0\0\0\0", 12);
+ c->eax = signature[0];
+ c->ebx = 0;
+ c->ecx = 0;
+ c->edx = 0;
+
+ c = &cpuid_ent[cpuid_i++];
+ c->function = HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES;
+ c->eax = HV_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING;
+ c->ebx = 0;
+ c->ecx = 0;
+ c->edx = 0;
+ }
+
return cpuid_i;
}
@@ -2261,6 +2313,9 @@ static int kvm_get_supported_msrs(KVMState *s)
case HV_X64_MSR_REENLIGHTENMENT_CONTROL:
has_msr_hv_reenlightenment = true;
break;
+ case HV_X64_MSR_SYNDBG_OPTIONS:
+ has_msr_hv_syndbg_options = true;
+ break;
case MSR_IA32_SPEC_CTRL:
has_msr_spec_ctrl = true;
break;
@@ -3178,6 +3233,11 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_STATUS,
env->msr_hv_tsc_emulation_status);
}
+ if (hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNDBG) &&
+ has_msr_hv_syndbg_options) {
+ kvm_msr_entry_add(cpu, HV_X64_MSR_SYNDBG_OPTIONS,
+ hyperv_syndbg_query_options());
+ }
}
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VAPIC)) {
kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE,
@@ -3619,6 +3679,9 @@ static int kvm_get_msrs(X86CPU *cpu)
kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_CONTROL, 0);
kvm_msr_entry_add(cpu, HV_X64_MSR_TSC_EMULATION_STATUS, 0);
}
+ if (has_msr_hv_syndbg_options) {
+ kvm_msr_entry_add(cpu, HV_X64_MSR_SYNDBG_OPTIONS, 0);
+ }
if (has_msr_hv_crash) {
int j;
@@ -3910,6 +3973,9 @@ static int kvm_get_msrs(X86CPU *cpu)
case HV_X64_MSR_TSC_EMULATION_STATUS:
env->msr_hv_tsc_emulation_status = msrs[i].data;
break;
+ case HV_X64_MSR_SYNDBG_OPTIONS:
+ env->msr_hv_syndbg_options = msrs[i].data;
+ break;
case MSR_MTRRdefType:
env->mtrr_deftype = msrs[i].data;
break;
--
2.35.1
next prev parent reply other threads:[~2022-04-19 7:25 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-19 5:50 [PULL for-7.1 00/53] Misc pull request for QEMU 7.1 Paolo Bonzini
2022-04-19 5:50 ` [PULL 01/53] qapi, target/i386/sev: Add cpu0-id to query-sev-capabilities Paolo Bonzini
2022-04-19 7:16 ` Dov Murik
2022-04-20 19:06 ` Dov Murik
2022-04-19 5:50 ` [PULL 02/53] qtest: replace gettimeofday with GTimer Paolo Bonzini
2022-04-19 5:50 ` [PULL 03/53] qga: replace qemu_gettimeofday() with g_get_real_time() Paolo Bonzini
2022-04-19 5:50 ` [PULL 04/53] Replace " Paolo Bonzini
2022-04-19 5:50 ` [PULL 05/53] oslib: drop qemu_gettimeofday() Paolo Bonzini
2022-04-19 5:50 ` [PULL 06/53] meson: use chardev_ss dependencies Paolo Bonzini
2022-04-19 5:50 ` [PULL 07/53] meson: add util dependency for oslib-posix on freebsd Paolo Bonzini
2022-04-19 5:50 ` [PULL 08/53] meson: remove unneeded py3 Paolo Bonzini
2022-04-19 5:50 ` [PULL 09/53] meson: remove test-qdev-global-props dependency on testqapi Paolo Bonzini
2022-04-19 5:50 ` [PULL 10/53] char: move qemu_openpty_raw from util/ to char/ Paolo Bonzini
2022-04-19 5:50 ` [PULL 11/53] Replace config-time define HOST_WORDS_BIGENDIAN Paolo Bonzini
2022-04-19 5:50 ` [PULL 12/53] Replace TARGET_WORDS_BIGENDIAN Paolo Bonzini
2022-04-19 5:50 ` [PULL 13/53] osdep: poison {HOST,TARGET}_WORDS_BIGENDIAN Paolo Bonzini
2022-04-19 5:50 ` [PULL 14/53] include/qapi: add g_autoptr support for qobject types Paolo Bonzini
2022-04-19 5:50 ` [PULL 15/53] tests: replace free_all() usage with g_auto Paolo Bonzini
2022-04-19 5:50 ` [PULL 16/53] Replace qemu_real_host_page variables with inlined functions Paolo Bonzini
2022-04-19 5:50 ` [PULL 17/53] qga: replace deprecated g_get_current_time() Paolo Bonzini
2022-04-19 5:50 ` [PULL 18/53] error-report: replace deprecated g_get_current_time() with glib >= 2.62 Paolo Bonzini
2022-04-19 5:50 ` [PULL 19/53] util: rename qemu-error.c to match its header name Paolo Bonzini
2022-04-19 5:50 ` [PULL 20/53] error-report: use error_printf() for program prefix Paolo Bonzini
2022-04-19 5:50 ` [PULL 21/53] include: move TFR to osdep.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 22/53] include: move qemu_write_full() declaration " Paolo Bonzini
2022-04-19 5:50 ` [PULL 23/53] include: move qemu_pipe() " Paolo Bonzini
2022-04-19 5:50 ` [PULL 24/53] include: move coroutine IO functions to coroutine.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 25/53] include: move dump_in_progress() to runstate.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 26/53] include: move C/util-related declarations to cutils.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 27/53] include: move cpu_exec* declarations to cpu-common.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 28/53] include: move target page bits declaration to page-vary.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 29/53] include: move progress API to qemu-progress.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 30/53] include: move qemu_get_vm_name() to sysemu.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 31/53] include: move os_*() to os-foo.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 32/53] include: move page_size_init() to include/hw/core/cpu.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 33/53] Move CPU softfloat unions to cpu-float.h Paolo Bonzini
2022-04-19 5:50 ` [PULL 34/53] Move fcntl_setfl() to oslib-posix Paolo Bonzini
2022-04-19 5:50 ` [PULL 35/53] qga: remove explicit environ argument from exec/spawn Paolo Bonzini
2022-04-19 5:50 ` [PULL 36/53] Remove qemu-common.h include from most units Paolo Bonzini
2022-04-19 5:50 ` [PULL 37/53] build-sys: drop ntddscsi.h check Paolo Bonzini
2022-04-19 5:50 ` [PULL 38/53] build-sys: simplify AF_VSOCK check Paolo Bonzini
2022-04-19 5:50 ` [PULL 39/53] whpx: Added support for breakpoints and stepping Paolo Bonzini
2022-04-19 5:50 ` [PULL 40/53] thread-posix: remove the posix semaphore support Paolo Bonzini
2022-04-19 5:50 ` [PULL 41/53] thread-posix: use monotonic clock for QemuCond and QemuSemaphore Paolo Bonzini
2022-04-19 5:50 ` [PULL 42/53] thread-posix: implement Semaphore with QemuCond and QemuMutex Paolo Bonzini
2022-04-19 5:50 ` [PULL 43/53] thread-posix: optimize qemu_sem_timedwait with zero timeout Paolo Bonzini
2022-04-19 5:51 ` [PULL 44/53] hyperv: SControl is optional to enable SynIc Paolo Bonzini
2022-04-19 5:51 ` [PULL 45/53] hyperv: Add definitions for syndbg Paolo Bonzini
2022-04-19 5:51 ` Paolo Bonzini [this message]
2022-04-19 5:51 ` [PULL 47/53] hw: hyperv: Initial commit for Synthetic Debugging device Paolo Bonzini
2022-04-19 5:51 ` [PULL 48/53] s390x: follow qdev tree to detect SCSI device on a CCW bus Paolo Bonzini
2022-04-19 5:51 ` [PULL 49/53] virtio-ccw: move vhost_ccw_scsi to a separate file Paolo Bonzini
2022-04-19 5:51 ` [PULL 50/53] virtio-ccw: move device type declarations to .c files Paolo Bonzini
2022-04-19 5:51 ` [PULL 51/53] virtio-ccw: do not include headers for all virtio devices Paolo Bonzini
2022-04-19 5:51 ` [PULL 52/53] target/i386: do not access beyond the low 128 bits of SSE registers Paolo Bonzini
2022-04-19 5:51 ` [PULL 53/53] target/i386: Remove unused XMMReg, YMMReg types and CPUState fields Paolo Bonzini
2022-04-19 9:32 ` [PULL for-7.1 00/53] Misc pull request for QEMU 7.1 Peter Maydell
2022-04-20 3:57 ` Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220419055109.142788-47-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=arilou@gmail.com \
--cc=eesposit@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).