Re: [PATCH v1 3/4] hyperv: Add support to process syndbg commands

2022-02-16 Thread Jon Doron

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

2022-02-16 Thread Emanuele Giuseppe Esposito



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;
> +