Re: [PATCH v1 3/4] hyperv: Add support to process syndbg commands
On 16/02/2022, Emanuele Giuseppe Esposito wrote: On 04/02/2022 11:07, Jon Doron wrote: 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 --- docs/hyperv.txt | 15 +++ hw/hyperv/hyperv.c| 242 ++ 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, 450 insertions(+), 8 deletions(-) diff --git a/docs/hyperv.txt b/docs/hyperv.txt index 0417c183a3..7abc1b2d89 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 . +Whe enabled, this enlightenment provides additional communication facilities When Done +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 88c9cc1334..c86e2aa02e 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -730,3 +730,245 @@ 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; Add a line here between field and function definition. Done +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, , 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, ); +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(_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(_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, _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, _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); +
Re: [PATCH v1 3/4] hyperv: Add support to process syndbg commands
On 04/02/2022 11:07, Jon Doron wrote: > 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 > --- > docs/hyperv.txt | 15 +++ > hw/hyperv/hyperv.c| 242 ++ > 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, 450 insertions(+), 8 deletions(-) > > diff --git a/docs/hyperv.txt b/docs/hyperv.txt > index 0417c183a3..7abc1b2d89 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 . > +Whe enabled, this enlightenment provides additional communication facilities When > +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 88c9cc1334..c86e2aa02e 100644 > --- a/hw/hyperv/hyperv.c > +++ b/hw/hyperv/hyperv.c > @@ -730,3 +730,245 @@ 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; Add a line here between field and function definition. > +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, , 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, ); > +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(_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(_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, _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, _len, 1); > +if (!debug_data_out || out_len < sizeof(*debug_data_out)) { > +ret = HV_STATUS_INSUFFICIENT_MEMORY; > +