Re: Concerns regarding e17bebd049 ("dump: Set correct vaddr for ELF dump")
Hi Stephen, Like you have said the reason is as I wrote in the commit message, without "fixing" the vaddr GDB is messing up mapping and working with the generated core file. This patch is almost 4 years old, perhaps some changes to GDB has been introduced to resolve this, I have not checked since then. As I'm no longer using this feature and have not worked and tested it in a long while, so I have no obligations to this change, but perhaps someone else might be using it... -- Jon. On 19/09/2023, Stephen Brennan wrote: Hello all, I've started working on better support and documentation around hypervisor vmcores in the Drgn debugger[1]. Of course there's quite a lot of different implementations out there, but recently I'm looking at Qemu kdump and ELF vmcores generated via dump-guest-memory, and one thing caught my eye. I generated a ELF vmcore without the paging option enabled, and without the guest note loaded, and the resulting core dump's program header looked like this: $ eu-readelf -l dumpfile2 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align NOTE 0x000168 0x 0x 0x001980 0x001980 0x0 LOAD 0x001ae8 0x 0x 0x8000 0x8000 0x0 LOAD 0x80001ae8 0xfffc 0xfffc 0x04 0x04 0x0 In particular, the "VirtAddr" field for the loadable segment shows a confusing address - it appears to reuse the segment's physical address, despite the fact that there's no actual corresponding mapping. By comparison, the /proc/kcore and /proc/vmcore ELF vmcores use the VirtAddr in the program header to represent the real virtual memory mappings in use by the kernel. Debuggers can directly use these without needing to walk page tables. If there is no virtual memory mapping information available, I would have expected a placeholder value such as ... or ... to take the place of VirtAddr here so a debugger can detect the lack of virtual mappings and know that it needs to use architecture-specific details (and the vmcoreinfo) to find the page tables and accurately determine memory mappings. As it is, this program header seems to advertise to a debugger, "yes, we have the virtual memory mappings" when in fact, that's not the case. It seems that this behavior was introduced in e17bebd049 ("dump: Set correct vaddr for ELF dump")[2], a small commit I'll reproduce below. The justification seems to be that it fixes an issue reading the vmcore with GDB, but I wonder if that's not a GDB bug which should have been fixed with them? If GDB aims to support ELF kernel core dumps, presumably it should be handling physical addresses separately from virtual addresses. And if GDB doesn't aim for this, but you'd like to con it into reading your core dump, presumably the onus is on you to edit the ELF VirtAddr field to suit your needs? It should be QEMU's primary goal to produce a *correct* vmcore, not work around limitations or bugs in GDB. I'd like to propose reverting this, since it makes it impossible to interpret QEMU ELF vmcores, unless you discard all the virtual addresses in the program headers, and unconditionally do all the page table walks yourself. But I wanted to see if there was some justification for this behavior that I missed. Thanks, Stephen [1]: https://github.com/osandov/drgn [2]: https://lore.kernel.org/qemu-devel/20181225125344.4482-1-ari...@gmail.com/ --- commit e17bebd049d78f489c2cff755e2b66a0536a156e Author: Jon Doron Date: Wed Jan 9 10:22:03 2019 +0200 dump: Set correct vaddr for ELF dump vaddr needs to be equal to the paddr since the dump file represents the physical memory image. Without setting vaddr correctly, GDB would load all the different memory regions on top of each other to vaddr 0, thus making GDB showing the wrong memory data for a given address. Signed-off-by: Jon Doron Message-Id: <20190109082203.27142-1-ari...@gmail.com> Reviewed-by: Marc-André Lureau Tested-by: Marc-André Lureau Acked-by: Laszlo Ersek diff --git a/dump.c b/dump.c index ef1d8025c9..107a67165a 100644 --- a/dump.c +++ b/dump.c @@ -192,7 +192,7 @@ static void write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, phdr.p_paddr = cpu_to_dump64(s, memory_mapping->phys_addr); phdr.p_filesz = cpu_to_dump64(s, filesz); phdr.p_memsz = cpu_to_dump64(s, memory_mapping->length); -phdr.p_vaddr = cpu_to_dump64(s, memory_mapping->virt_addr); +phdr.p_vaddr = cpu_to_dump64(s, memory_mapping->virt_addr) ?: phdr.p_paddr; assert(memory_mapping->length >= filesz); @@ -216,7 +216,8 @@ static void write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, phdr.p_paddr = cpu_to_dump32(s, memory_mapping->phys_addr); p
[PATCH v3 1/4] hyperv: SControl is optional to enable SynIc
SynIc can be enabled regardless of the SControl mechanisim which can register a GSI for a given SintRoute. This behaviour can achived by setting enabling SIMP and then the guest will poll on the message slot. Once there is another message pending the host will set the message slot with the pending flag. When the guest polls from the message slot, in case the pending flag is set it will write to the HV_X64_MSR_EOM indicating it has cleared the slot and we can try and push our message again. Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 109 +++-- 1 file changed, 76 insertions(+), 33 deletions(-) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index cb1074f234..8b832566c1 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -27,13 +27,16 @@ struct SynICState { CPUState *cs; -bool enabled; +bool sctl_enabled; hwaddr msg_page_addr; hwaddr event_page_addr; MemoryRegion msg_page_mr; MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; + +QemuMutex sint_routes_mutex; +QLIST_HEAD(, HvSintRoute) sint_routes; }; #define TYPE_SYNIC "hyperv-synic" @@ -51,11 +54,11 @@ static SynICState *get_synic(CPUState *cs) return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); } -static void synic_update(SynICState *synic, bool enable, +static void synic_update(SynICState *synic, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { -synic->enabled = enable; +synic->sctl_enabled = sctl_enable; if (synic->msg_page_addr != msg_page_addr) { if (synic->msg_page_addr) { memory_region_del_subregion(get_system_memory(), @@ -80,7 +83,7 @@ static void synic_update(SynICState *synic, bool enable, } } -void hyperv_synic_update(CPUState *cs, bool enable, +void hyperv_synic_update(CPUState *cs, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { SynICState *synic = get_synic(cs); @@ -89,7 +92,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, return; } -synic_update(synic, enable, msg_page_addr, event_page_addr); +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); } static void synic_realize(DeviceState *dev, Error **errp) @@ -110,16 +113,20 @@ static void synic_realize(DeviceState *dev, Error **errp) sizeof(*synic->event_page), &error_abort); synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); +qemu_mutex_init(&synic->sint_routes_mutex); +QLIST_INIT(&synic->sint_routes); g_free(msgp_name); g_free(eventp_name); } + static void synic_reset(DeviceState *dev) { SynICState *synic = SYNIC(dev); memset(synic->msg_page, 0, sizeof(*synic->msg_page)); memset(synic->event_page, 0, sizeof(*synic->event_page)); synic_update(synic, false, 0, 0); +assert(QLIST_EMPTY(&synic->sint_routes)); } static void synic_class_init(ObjectClass *klass, void *data) @@ -214,6 +221,7 @@ struct HvSintRoute { HvSintStagedMessage *staged_msg; unsigned refcount; +QLIST_ENTRY(HvSintRoute) link; }; static CPUState *hyperv_find_vcpu(uint32_t vp_index) @@ -259,7 +267,7 @@ static void cpu_post_msg(CPUState *cs, run_on_cpu_data data) assert(staged_msg->state == HV_STAGED_MSG_BUSY); -if (!synic->enabled || !synic->msg_page_addr) { +if (!synic->msg_page_addr) { staged_msg->status = -ENXIO; goto posted; } @@ -343,7 +351,7 @@ int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno) if (eventno > HV_EVENT_FLAGS_COUNT) { return -EINVAL; } -if (!synic->enabled || !synic->event_page_addr) { +if (!synic->sctl_enabled || !synic->event_page_addr) { return -ENXIO; } @@ -364,11 +372,12 @@ int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno) HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, HvSintMsgCb cb, void *cb_data) { -HvSintRoute *sint_route; -EventNotifier *ack_notifier; +HvSintRoute *sint_route = NULL; +EventNotifier *ack_notifier = NULL; int r, gsi; CPUState *cs; SynICState *synic; +bool ack_event_initialized = false; cs = hyperv_find_vcpu(vp_index); if (!cs) { @@ -381,57 +390,77 @@ HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, } sint_route = g_new0(HvSintRoute, 1); -r = event_notifier_init(&sint_route->sint_set_notifier, false); -if (r) { -goto err; +if (!sint_route) { +return NULL; } +sint_route->synic =
[PATCH v3 3/4] hyperv: Add support to process syndbg commands
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| 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
[PATCH v3 0/4] HyperV: Synthetic Debugging device
This patchset adds support for the synthetic debugging device. HyperV supports a special transport layer for the kernel debugger when running in HyperV. This patchset add supports for this device so you could have a setup fast windows kernel debugging. At this point of time, DHCP is not implmeneted so to set this up few things need to be noted. The scenario I used to test is having 2 VMs in the same virtual network i.e a Debugger VM with the NIC: -nic tap,model=virtio,mac=02:ca:01:01:01:01,script=/etc/qemu-ifup And it's IP is going to be static 192.168.53.12 And the VM we want to debug, to which we need to have the englightments and vmbus configured: -cpu host,hv-relaxed,hv_spinlocks=0x1fff,hv_time,+vmx,invtsc,hv-vapic,hv-vpindex,hv-synic,hv-syndbg \ -device vmbus-bridge \ -device hv-syndbg,host_ip=192.168.53.12,host_port=5,use_hcalls=false \ -nic tap,model=virtio,mac=02:ca:01:01:01:02,script=/etc/qemu-ifup \ Then in the debuggee VM we would setup the kernel debugging in the following way: If the VM is older than Win8: * Copy the proper platform kdvm.dll (make sure it's called kdvm.dll even if platform is 32bit) bcdedit /set {GUID} dbgtransport kdvm.dll bcdedit /set {GUID} loadoptions host_ip="1.2.3.4",host_port="5",nodhcp bcdedit /set {GUID} debug on bcdedit /set {GUID} halbreakpoint on Win8 and late: bcdedit /dbgsettings net hostip:7.7.7.7 port:5 nodhcp This is all the setup that is required to get the synthetic debugger configured correctly. v3: Fixed review from Paolo changes from QLIST*RCU to non RCU Jon Doron (4): hyperv: SControl is optional to enable SynIc hyperv: Add definitions for syndbg hyperv: Add support to process syndbg commands hw: hyperv: Initial commit for Synthetic Debugging device docs/hyperv.txt | 15 ++ hw/hyperv/Kconfig| 5 + hw/hyperv/hyperv.c | 352 --- hw/hyperv/meson.build| 1 + hw/hyperv/syndbg.c | 402 +++ include/hw/hyperv/hyperv-proto.h | 52 include/hw/hyperv/hyperv.h | 58 + target/i386/cpu.c| 2 + target/i386/cpu.h| 7 + target/i386/kvm/hyperv-proto.h | 37 +++ target/i386/kvm/hyperv-stub.c| 6 + target/i386/kvm/hyperv.c | 52 +++- target/i386/kvm/kvm.c| 76 +- 13 files changed, 1024 insertions(+), 41 deletions(-) create mode 100644 hw/hyperv/syndbg.c -- 2.35.1
[PATCH v3 4/4] hw: hyperv: Initial commit for Synthetic Debugging device
Signed-off-by: Jon Doron --- hw/hyperv/Kconfig | 5 + hw/hyperv/meson.build | 1 + hw/hyperv/syndbg.c| 402 ++ 3 files changed, 408 insertions(+) create mode 100644 hw/hyperv/syndbg.c diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig index 3fbfe41c9e..fcf65903bd 100644 --- a/hw/hyperv/Kconfig +++ b/hw/hyperv/Kconfig @@ -11,3 +11,8 @@ config VMBUS bool default y depends on HYPERV + +config SYNDBG +bool +default y +depends on VMBUS diff --git a/hw/hyperv/meson.build b/hw/hyperv/meson.build index 1367e2994f..b43f119ea5 100644 --- a/hw/hyperv/meson.build +++ b/hw/hyperv/meson.build @@ -1,3 +1,4 @@ specific_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c')) specific_ss.add(when: 'CONFIG_HYPERV_TESTDEV', if_true: files('hyperv_testdev.c')) specific_ss.add(when: 'CONFIG_VMBUS', if_true: files('vmbus.c')) +specific_ss.add(when: 'CONFIG_SYNDBG', if_true: files('syndbg.c')) diff --git a/hw/hyperv/syndbg.c b/hw/hyperv/syndbg.c new file mode 100644 index 00..8816bc4082 --- /dev/null +++ b/hw/hyperv/syndbg.c @@ -0,0 +1,402 @@ +/* + * QEMU Hyper-V Synthetic Debugging device + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/ctype.h" +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qemu/sockets.h" +#include "qemu-common.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/loader.h" +#include "cpu.h" +#include "hw/hyperv/hyperv.h" +#include "hw/hyperv/vmbus-bridge.h" +#include "hw/hyperv/hyperv-proto.h" +#include "net/net.h" +#include "net/eth.h" +#include "net/checksum.h" +#include "trace.h" + +#define TYPE_HV_SYNDBG "hv-syndbg" + +typedef struct HvSynDbg { +DeviceState parent_obj; + +char *host_ip; +uint16_t host_port; +bool use_hcalls; + +uint32_t target_ip; +struct sockaddr_in servaddr; +int socket; +bool has_data_pending; +uint64_t pending_page_gpa; +} HvSynDbg; + +#define HVSYNDBG(obj) OBJECT_CHECK(HvSynDbg, (obj), TYPE_HV_SYNDBG) + +/* returns NULL unless there is exactly one HV Synth debug device */ +static HvSynDbg *hv_syndbg_find(void) +{ +/* Returns NULL unless there is exactly one hvsd device */ +return HVSYNDBG(object_resolve_path_type("", TYPE_HV_SYNDBG, NULL)); +} + +static void set_pending_state(HvSynDbg *syndbg, bool has_pending) +{ +hwaddr out_len; +void *out_data; + +syndbg->has_data_pending = has_pending; + +if (!syndbg->pending_page_gpa) { +return; +} + +out_len = 1; +out_data = cpu_physical_memory_map(syndbg->pending_page_gpa, &out_len, 1); +if (out_data) { +*(uint8_t *)out_data = !!has_pending; +cpu_physical_memory_unmap(out_data, out_len, 1, out_len); +} +} + +static bool get_udb_pkt_data(void *p, uint32_t len, uint32_t *data_ofs, + uint32_t *src_ip) +{ +uint32_t offset, curr_len = len; + +if (curr_len < sizeof(struct eth_header) || +(be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto) != ETH_P_IP)) { +return false; +} +offset = sizeof(struct eth_header); +curr_len -= sizeof(struct eth_header); + +if (curr_len < sizeof(struct ip_header) || +PKT_GET_IP_HDR(p)->ip_p != IP_PROTO_UDP) { +return false; +} +offset += PKT_GET_IP_HDR_LEN(p); +curr_len -= PKT_GET_IP_HDR_LEN(p); + +if (curr_len < sizeof(struct udp_header)) { +return false; +} + +offset += sizeof(struct udp_header); +*data_ofs = offset; +*src_ip = PKT_GET_IP_HDR(p)->ip_src; +return true; +} + +static uint16_t handle_send_msg(HvSynDbg *syndbg, uint64_t ingpa, +uint32_t count, bool is_raw, +uint32_t *pending_count) +{ +uint16_t ret; +hwaddr data_len; +void *debug_data = NULL; +uint32_t udp_data_ofs = 0; +const void *pkt_data; +int sent_count; + +data_len = count; +debug_data = cpu_physical_memory_map(ingpa, &data_len, 0); +if (!debug_data || data_len < count) { +ret = HV_STATUS_INSUFFICIENT_MEMORY; +goto cleanup; +} + +if (is_raw && +!get_udb_pkt_data(debug_data, count, &udp_data_ofs, + &syndbg->target_ip)) { +ret = HV_STATUS_SUCCESS; +goto cleanup; +} + +pkt_data = (const void *)((uintptr_t)debug_data + udp_data_ofs); +sent_count = qemu_sendto(syndbg->socket, pkt_data, count - udp_data_ofs, +
[PATCH v3 2/4] hyperv: Add definitions for syndbg
Add all required definitions for hyperv synthetic debugger interface. Signed-off-by: Jon Doron --- include/hw/hyperv/hyperv-proto.h | 52 target/i386/kvm/hyperv-proto.h | 37 +++ 2 files changed, 89 insertions(+) diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-proto.h index 21dc28aee9..4a2297307b 100644 --- a/include/hw/hyperv/hyperv-proto.h +++ b/include/hw/hyperv/hyperv-proto.h @@ -24,12 +24,17 @@ #define HV_STATUS_INVALID_PORT_ID 17 #define HV_STATUS_INVALID_CONNECTION_ID 18 #define HV_STATUS_INSUFFICIENT_BUFFERS19 +#define HV_STATUS_NOT_ACKNOWLEDGED20 +#define HV_STATUS_NO_DATA 27 /* * Hypercall numbers */ #define HV_POST_MESSAGE 0x005c #define HV_SIGNAL_EVENT 0x005d +#define HV_POST_DEBUG_DATA0x0069 +#define HV_RETRIEVE_DEBUG_DATA0x006a +#define HV_RESET_DEBUG_SESSION0x006b #define HV_HYPERCALL_FAST (1u << 16) /* @@ -127,4 +132,51 @@ struct hyperv_event_flags_page { struct hyperv_event_flags slot[HV_SINT_COUNT]; }; +/* + * Kernel debugger structures + */ + +/* Options flags for hyperv_reset_debug_session */ +#define HV_DEBUG_PURGE_INCOMING_DATA0x0001 +#define HV_DEBUG_PURGE_OUTGOING_DATA0x0002 +struct hyperv_reset_debug_session_input { +uint32_t options; +} __attribute__ ((__packed__)); + +struct hyperv_reset_debug_session_output { +uint32_t host_ip; +uint32_t target_ip; +uint16_t host_port; +uint16_t target_port; +uint8_t host_mac[6]; +uint8_t target_mac[6]; +} __attribute__ ((__packed__)); + +/* Options for hyperv_post_debug_data */ +#define HV_DEBUG_POST_LOOP 0x0001 + +struct hyperv_post_debug_data_input { +uint32_t count; +uint32_t options; +/*uint8_t data[HV_HYP_PAGE_SIZE - 2 * sizeof(uint32_t)];*/ +} __attribute__ ((__packed__)); + +struct hyperv_post_debug_data_output { +uint32_t pending_count; +} __attribute__ ((__packed__)); + +/* Options for hyperv_retrieve_debug_data */ +#define HV_DEBUG_RETRIEVE_LOOP 0x0001 +#define HV_DEBUG_RETRIEVE_TEST_ACTIVITY 0x0002 + +struct hyperv_retrieve_debug_data_input { +uint32_t count; +uint32_t options; +uint64_t timeout; +} __attribute__ ((__packed__)); + +struct hyperv_retrieve_debug_data_output { +uint32_t retrieved_count; +uint32_t remaining_count; +} __attribute__ ((__packed__)); #endif diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index 89f81afda7..e40e59411c 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -19,6 +19,9 @@ #define HV_CPUID_ENLIGHTMENT_INFO 0x4004 #define HV_CPUID_IMPLEMENT_LIMITS 0x4005 #define HV_CPUID_NESTED_FEATURES 0x400A +#define HV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS0x4080 +#define HV_CPUID_SYNDBG_INTERFACE 0x4081 +#define HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x4082 #define HV_CPUID_MIN 0x4005 #define HV_CPUID_MAX 0x4000 #define HV_HYPERVISOR_PRESENT_BIT 0x8000 @@ -55,8 +58,14 @@ #define HV_GUEST_IDLE_STATE_AVAILABLE (1u << 5) #define HV_FREQUENCY_MSRS_AVAILABLE (1u << 8) #define HV_GUEST_CRASH_MSR_AVAILABLE(1u << 10) +#define HV_FEATURE_DEBUG_MSRS_AVAILABLE (1u << 11) #define HV_STIMER_DIRECT_MODE_AVAILABLE (1u << 19) +/* + * HV_CPUID_FEATURES.EBX bits + */ +#define HV_PARTITION_DEBUGGING_ALLOWED (1u << 12) + /* * HV_CPUID_ENLIGHTMENT_INFO.EAX bits */ @@ -72,6 +81,11 @@ #define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14) #define HV_NO_NONARCH_CORESHARING (1u << 18) +/* + * HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits + */ +#define HV_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING(1u << 1) + /* * Basic virtualized MSRs */ @@ -130,6 +144,18 @@ #define HV_X64_MSR_STIMER3_CONFIG 0x40B6 #define HV_X64_MSR_STIMER3_COUNT0x40B7 +/* + * Hyper-V Synthetic debug options MSR + */ +#define HV_X64_MSR_SYNDBG_CONTROL 0x40F1 +#define HV_X64_MSR_SYNDBG_STATUS0x40F2 +#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x40F3 +#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x40F4 +#define HV_X64_MSR_SYNDBG_PENDING_BUFFER0x40F5 +#define HV_X64_MSR_SYNDBG_OPTIONS 0x40FF + +#define HV_X64_SYNDBG_OPTION_USE_HCALLS BIT(2) + /* * Guest crash notification MSRs */ @@ -168,5 +194,16 @@ #define HV_STIMER_COUNT 4 +/* + * Synthetic debugger control definitions + */ +#define HV_SYNDBG_CONTROL_SEND (1u <<
Re: [PATCH v2 1/4] hyperv: SControl is optional to enable SynIc
Thanks! is there an estimate when will this patchset be merged? On Thu, Feb 24, 2022, 18:36 Emanuele Giuseppe Esposito wrote: > > > On 16/02/2022 11:24, Jon Doron wrote: > > SynIc can be enabled regardless of the SControl mechanisim which can > > register a GSI for a given SintRoute. > > > > This behaviour can achived by setting enabling SIMP and then the guest > > will poll on the message slot. > > > > Once there is another message pending the host will set the message slot > > with the pending flag. > > When the guest polls from the message slot, in case the pending flag is > > set it will write to the HV_X64_MSR_EOM indicating it has cleared the > > slot and we can try and push our message again. > > > > Signed-off-by: Jon Doron > > --- > > hw/hyperv/hyperv.c | 109 +++-- > > 1 file changed, 76 insertions(+), 33 deletions(-) > > > > diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c > > index cb1074f234..aaba6b4901 100644 > > --- a/hw/hyperv/hyperv.c > > +++ b/hw/hyperv/hyperv.c > > @@ -27,13 +27,16 @@ struct SynICState { > > > > CPUState *cs; > > > > -bool enabled; > > +bool sctl_enabled; > > hwaddr msg_page_addr; > > hwaddr event_page_addr; > > MemoryRegion msg_page_mr; > > MemoryRegion event_page_mr; > > struct hyperv_message_page *msg_page; > > struct hyperv_event_flags_page *event_page; > > + > > +QemuMutex sint_routes_mutex; > > +QLIST_HEAD(, HvSintRoute) sint_routes; > > }; > > > > #define TYPE_SYNIC "hyperv-synic" > > @@ -51,11 +54,11 @@ static SynICState *get_synic(CPUState *cs) > > return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); > > } > > > > -static void synic_update(SynICState *synic, bool enable, > > +static void synic_update(SynICState *synic, bool sctl_enable, > > hwaddr msg_page_addr, hwaddr event_page_addr) > > { > > > > -synic->enabled = enable; > > +synic->sctl_enabled = sctl_enable; > > if (synic->msg_page_addr != msg_page_addr) { > > if (synic->msg_page_addr) { > > memory_region_del_subregion(get_system_memory(), > > @@ -80,7 +83,7 @@ static void synic_update(SynICState *synic, bool > enable, > > } > > } > > > > -void hyperv_synic_update(CPUState *cs, bool enable, > > +void hyperv_synic_update(CPUState *cs, bool sctl_enable, > > hwaddr msg_page_addr, hwaddr event_page_addr) > > { > > SynICState *synic = get_synic(cs); > > @@ -89,7 +92,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, > > return; > > } > > > > -synic_update(synic, enable, msg_page_addr, event_page_addr); > > +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); > > } > > > > static void synic_realize(DeviceState *dev, Error **errp) > > @@ -110,16 +113,20 @@ static void synic_realize(DeviceState *dev, Error > **errp) > > sizeof(*synic->event_page), &error_abort); > > synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); > > synic->event_page = > memory_region_get_ram_ptr(&synic->event_page_mr); > > +qemu_mutex_init(&synic->sint_routes_mutex); > > +QLIST_INIT(&synic->sint_routes); > > > > g_free(msgp_name); > > g_free(eventp_name); > > } > > + > > static void synic_reset(DeviceState *dev) > > { > > SynICState *synic = SYNIC(dev); > > memset(synic->msg_page, 0, sizeof(*synic->msg_page)); > > memset(synic->event_page, 0, sizeof(*synic->event_page)); > > synic_update(synic, false, 0, 0); > > +assert(QLIST_EMPTY(&synic->sint_routes)); > > } > > > > static void synic_class_init(ObjectClass *klass, void *data) > > @@ -214,6 +221,7 @@ struct HvSintRoute { > > HvSintStagedMessage *staged_msg; > > > > unsigned refcount; > > +QLIST_ENTRY(HvSintRoute) link; > > }; > > > > static CPUState *hyperv_find_vcpu(uint32_t vp_index) > > @@ -259,7 +267,7 @@ static void cpu_post_msg(CPUState *cs, > run_on_cpu_data data) > > > > assert(staged_msg->state == HV_STAGED_MSG_BUSY); > > > > -if (!synic->enabled || !synic->msg_page_addr) { > > +if (!synic->msg_page_addr) { > > staged_
Re: [PATCH v2 4/4] hw: hyperv: Initial commit for Synthetic Debugging device
ping On Wed, Feb 16, 2022, 12:25 Jon Doron wrote: > Signed-off-by: Jon Doron > --- > hw/hyperv/Kconfig | 5 + > hw/hyperv/meson.build | 1 + > hw/hyperv/syndbg.c| 402 ++ > 3 files changed, 408 insertions(+) > create mode 100644 hw/hyperv/syndbg.c > > diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig > index 3fbfe41c9e..fcf65903bd 100644 > --- a/hw/hyperv/Kconfig > +++ b/hw/hyperv/Kconfig > @@ -11,3 +11,8 @@ config VMBUS > bool > default y > depends on HYPERV > + > +config SYNDBG > +bool > +default y > +depends on VMBUS > diff --git a/hw/hyperv/meson.build b/hw/hyperv/meson.build > index 1367e2994f..b43f119ea5 100644 > --- a/hw/hyperv/meson.build > +++ b/hw/hyperv/meson.build > @@ -1,3 +1,4 @@ > specific_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c')) > specific_ss.add(when: 'CONFIG_HYPERV_TESTDEV', if_true: > files('hyperv_testdev.c')) > specific_ss.add(when: 'CONFIG_VMBUS', if_true: files('vmbus.c')) > +specific_ss.add(when: 'CONFIG_SYNDBG', if_true: files('syndbg.c')) > diff --git a/hw/hyperv/syndbg.c b/hw/hyperv/syndbg.c > new file mode 100644 > index 00..8816bc4082 > --- /dev/null > +++ b/hw/hyperv/syndbg.c > @@ -0,0 +1,402 @@ > +/* > + * QEMU Hyper-V Synthetic Debugging device > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or > later. > + * See the COPYING file in the top-level directory. > + */ > + > +#include "qemu/ctype.h" > +#include "qemu/osdep.h" > +#include "qemu/error-report.h" > +#include "qemu/main-loop.h" > +#include "qemu/sockets.h" > +#include "qemu-common.h" > +#include "qapi/error.h" > +#include "migration/vmstate.h" > +#include "hw/qdev-properties.h" > +#include "hw/loader.h" > +#include "cpu.h" > +#include "hw/hyperv/hyperv.h" > +#include "hw/hyperv/vmbus-bridge.h" > +#include "hw/hyperv/hyperv-proto.h" > +#include "net/net.h" > +#include "net/eth.h" > +#include "net/checksum.h" > +#include "trace.h" > + > +#define TYPE_HV_SYNDBG "hv-syndbg" > + > +typedef struct HvSynDbg { > +DeviceState parent_obj; > + > +char *host_ip; > +uint16_t host_port; > +bool use_hcalls; > + > +uint32_t target_ip; > +struct sockaddr_in servaddr; > +int socket; > +bool has_data_pending; > +uint64_t pending_page_gpa; > +} HvSynDbg; > + > +#define HVSYNDBG(obj) OBJECT_CHECK(HvSynDbg, (obj), TYPE_HV_SYNDBG) > + > +/* returns NULL unless there is exactly one HV Synth debug device */ > +static HvSynDbg *hv_syndbg_find(void) > +{ > +/* Returns NULL unless there is exactly one hvsd device */ > +return HVSYNDBG(object_resolve_path_type("", TYPE_HV_SYNDBG, NULL)); > +} > + > +static void set_pending_state(HvSynDbg *syndbg, bool has_pending) > +{ > +hwaddr out_len; > +void *out_data; > + > +syndbg->has_data_pending = has_pending; > + > +if (!syndbg->pending_page_gpa) { > +return; > +} > + > +out_len = 1; > +out_data = cpu_physical_memory_map(syndbg->pending_page_gpa, > &out_len, 1); > +if (out_data) { > +*(uint8_t *)out_data = !!has_pending; > +cpu_physical_memory_unmap(out_data, out_len, 1, out_len); > +} > +} > + > +static bool get_udb_pkt_data(void *p, uint32_t len, uint32_t *data_ofs, > + uint32_t *src_ip) > +{ > +uint32_t offset, curr_len = len; > + > +if (curr_len < sizeof(struct eth_header) || > +(be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto) != ETH_P_IP)) { > +return false; > +} > +offset = sizeof(struct eth_header); > +curr_len -= sizeof(struct eth_header); > + > +if (curr_len < sizeof(struct ip_header) || > +PKT_GET_IP_HDR(p)->ip_p != IP_PROTO_UDP) { > +return false; > +} > +offset += PKT_GET_IP_HDR_LEN(p); > +curr_len -= PKT_GET_IP_HDR_LEN(p); > + > +if (curr_len < sizeof(struct udp_header)) { > +return false; > +} > + > +offset += sizeof(struct udp_header); > +*data_ofs = offset; > +*src_ip = PKT_GET_IP_HDR(p)->ip_src; > +return true; > +} > + > +static uint16_t handle_send_msg(HvSynDbg *syndbg, uint64_t ingpa, > +uint32_t count, bool is_raw, > +uint32_t *pend
Re: [PATCH v1 2/4] hyperv: Add definitions for syndbg
On 16/02/2022, Emanuele Giuseppe Esposito wrote: On 04/02/2022 11:07, Jon Doron wrote: Add all required definitions for hyperv synthetic debugger interface. Signed-off-by: Jon Doron --- include/hw/hyperv/hyperv-proto.h | 52 target/i386/kvm/hyperv-proto.h | 37 +++ 2 files changed, 89 insertions(+) diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-proto.h index 21dc28aee9..94c9658eb0 100644 --- a/include/hw/hyperv/hyperv-proto.h +++ b/include/hw/hyperv/hyperv-proto.h @@ -24,12 +24,17 @@ #define HV_STATUS_INVALID_PORT_ID 17 #define HV_STATUS_INVALID_CONNECTION_ID 18 #define HV_STATUS_INSUFFICIENT_BUFFERS19 +#define HV_STATUS_NOT_ACKNOWLEDGED20 +#define HV_STATUS_NO_DATA 27 /* * Hypercall numbers */ #define HV_POST_MESSAGE 0x005c #define HV_SIGNAL_EVENT 0x005d +#define HV_POST_DEBUG_DATA0x0069 +#define HV_RETREIVE_DEBUG_DATA0x006a s/RETREIVE/RETRIEVE? Done +#define HV_RESET_DEBUG_SESSION0x006b #define HV_HYPERCALL_FAST (1u << 16) /* @@ -127,4 +132,51 @@ struct hyperv_event_flags_page { struct hyperv_event_flags slot[HV_SINT_COUNT]; }; +/* + * Kernel debugger structures + */ + +/* Options flags for hyperv_reset_debug_session */ +#define HV_DEBUG_PURGE_INCOMING_DATA0x0001 +#define HV_DEBUG_PURGE_OUTGOING_DATA0x0002 +struct hyperv_reset_debug_session_input { +uint32_t options; +} __attribute__ ((__packed__)); + +struct hyperv_reset_debug_session_output { +uint32_t host_ip; +uint32_t target_ip; +uint16_t host_port; +uint16_t target_port; +uint8_t host_mac[6]; +uint8_t target_mac[6]; +} __attribute__ ((__packed__)); + +/* Options for hyperv_post_debug_data */ +#define HV_DEBUG_POST_LOOP 0x0001 + +struct hyperv_post_debug_data_input { +uint32_t count; +uint32_t options; +/*uint8_t data[HV_HYP_PAGE_SIZE - 2 * sizeof(uint32_t)];*/ What is this comment for? It's a reference how the data really looks like. +} __attribute__ ((__packed__)); + +struct hyperv_post_debug_data_output { +uint32_t pending_count; +} __attribute__ ((__packed__)); + +/* Options for hyperv_retrieve_debug_data */ +#define HV_DEBUG_RETRIEVE_LOOP 0x0001 +#define HV_DEBUG_RETRIEVE_TEST_ACTIVITY 0x0002 + +struct hyperv_retrieve_debug_data_input { +uint32_t count; +uint32_t options; +uint64_t timeout; +} __attribute__ ((__packed__)); + +struct hyperv_retrieve_debug_data_output { +uint32_t retrieved_count; +uint32_t remaining_count; +} __attribute__ ((__packed__)); #endif diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index 89f81afda7..9480bcdf04 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -19,6 +19,9 @@ #define HV_CPUID_ENLIGHTMENT_INFO 0x4004 #define HV_CPUID_IMPLEMENT_LIMITS 0x4005 #define HV_CPUID_NESTED_FEATURES 0x400A +#define HV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS0x4080 +#define HV_CPUID_SYNDBG_INTERFACE 0x4081 +#define HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x4082 #define HV_CPUID_MIN 0x4005 #define HV_CPUID_MAX 0x4000 #define HV_HYPERVISOR_PRESENT_BIT 0x8000 @@ -55,8 +58,14 @@ #define HV_GUEST_IDLE_STATE_AVAILABLE (1u << 5) #define HV_FREQUENCY_MSRS_AVAILABLE (1u << 8) #define HV_GUEST_CRASH_MSR_AVAILABLE(1u << 10) +#define HV_FEATURE_DEBUG_MSRS_AVAILABLE (1u << 11) #define HV_STIMER_DIRECT_MODE_AVAILABLE (1u << 19) +/* + * HV_CPUID_FEATURES.EBX bits + */ +#define HV_PARTITION_DEUBGGING_ALLOWED (1u << 12) s/DEUBGGING/DEBUGGING Done + /* * HV_CPUID_ENLIGHTMENT_INFO.EAX bits */ @@ -72,6 +81,11 @@ #define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14) #define HV_NO_NONARCH_CORESHARING (1u << 18) +/* + * HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits + */ +#define HV_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING(1u << 1) + /* * Basic virtualized MSRs */ @@ -130,6 +144,18 @@ #define HV_X64_MSR_STIMER3_CONFIG 0x40B6 #define HV_X64_MSR_STIMER3_COUNT0x40B7 +/* + * Hyper-V Synthetic debug options MSR + */ +#define HV_X64_MSR_SYNDBG_CONTROL 0x40F1 +#define HV_X64_MSR_SYNDBG_STATUS0x40F2 +#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x40F3 +#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x40F4 +#define HV_X64_MSR_SYNDBG_PENDING_BUFFER0x40F5 +#define HV_X64_MSR_SYNDBG_OPTIONS 0x40FF + +#define HV_X64_SYNDBG_OPTION_USE_HCALLS
Re: [PATCH v1 4/4] hw: hyperv: Initial commit for Synthetic Debugging device
On 16/02/2022, Emanuele Giuseppe Esposito wrote: + +static uint16_t handle_recv_msg(HvSynDbg *syndbg, uint64_t outgpa, +uint32_t count, bool is_raw, uint32_t options, +uint64_t timeout, uint32_t *retrieved_count) +{ +uint16_t ret; +uint8_t data_buf[TARGET_PAGE_SIZE - UDP_PKT_HEADER_SIZE]; +hwaddr out_len; +void *out_data = NULL; +ssize_t recv_byte_count; + +/* TODO: Handle options and timeout */ +(void)options; +(void)timeout; + +if (!syndbg->has_data_pending) { +recv_byte_count = 0; +} else { +recv_byte_count = qemu_recv(syndbg->socket, data_buf, +MIN(sizeof(data_buf), count), MSG_WAITALL); +if (recv_byte_count == -1) { +ret = HV_STATUS_INVALID_PARAMETER; +goto cleanup; +} +} + +if (!recv_byte_count) { +*retrieved_count = 0; +ret = HV_STATUS_NO_DATA; +goto cleanup; +} + +set_pending_state(syndbg, false); + +out_len = recv_byte_count; +if (is_raw) { +out_len += UDP_PKT_HEADER_SIZE; +} +out_data = cpu_physical_memory_map(outgpa, &out_len, 1); +if (!out_data) { +ret = HV_STATUS_INSUFFICIENT_MEMORY; +goto cleanup; +} + +if (is_raw && +!create_udp_pkt(syndbg, out_data, +recv_byte_count + UDP_PKT_HEADER_SIZE, +data_buf, recv_byte_count)) { +ret = HV_STATUS_INSUFFICIENT_MEMORY; +goto cleanup; +} else if (!is_raw) { +memcpy(out_data, data_buf, recv_byte_count); +} + +*retrieved_count = recv_byte_count; +if (is_raw) { +*retrieved_count += UDP_PKT_HEADER_SIZE; +} +ret = HV_STATUS_SUCCESS; +cleanup: +if (out_data) { +cpu_physical_memory_unmap(out_data, out_len, 1, out_len); +} Same nitpick as done in patch 1, I think you can use more gotos labels instead of adding if statements. Done + +return ret; +} +
Re: [PATCH v1 1/4] hyperv: SControl is optional to enable SynIc
On 16/02/2022, Emanuele Giuseppe Esposito wrote: On 04/02/2022 11:07, Jon Doron wrote: SynIc can be enabled regardless of the SControl mechanisim which can register a GSI for a given SintRoute. This behaviour can achived by setting enabling SIMP and then the guest will poll on the message slot. Once there is another message pending the host will set the message slot with the pending flag. When the guest polls from the message slot, incase the pending flag is s/incase/in case Done set it will write to the HV_X64_MSR_EOM indicating it has cleared the slow and we can try and push our message again. what do you mean by "the slow"? Just a typo to slot :) fixed Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 233 - include/hw/hyperv/hyperv.h | 2 + 2 files changed, 153 insertions(+), 82 deletions(-) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index cb1074f234..88c9cc1334 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -27,18 +27,70 @@ struct SynICState { CPUState *cs; -bool enabled; +bool sctl_enabled; hwaddr msg_page_addr; hwaddr event_page_addr; MemoryRegion msg_page_mr; MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; + +QemuMutex sint_routes_mutex; +QLIST_HEAD(, HvSintRoute) sint_routes; }; #define TYPE_SYNIC "hyperv-synic" OBJECT_DECLARE_SIMPLE_TYPE(SynICState, SYNIC) +/* + * KVM has its own message producers (SynIC timers). To guarantee + * serialization with both KVM vcpu and the guest cpu, the messages are first + * staged in an intermediate area and then posted to the SynIC message page in + * the vcpu thread. + */ +typedef struct HvSintStagedMessage { +/* message content staged by hyperv_post_msg */ +struct hyperv_message msg; +/* callback + data (r/o) to complete the processing in a BH */ +HvSintMsgCb cb; +void *cb_data; +/* message posting status filled by cpu_post_msg */ +int status; +/* passing the buck: */ +enum { +/* initial state */ +HV_STAGED_MSG_FREE, +/* + * hyperv_post_msg (e.g. in main loop) grabs the staged area (FREE -> + * BUSY), copies msg, and schedules cpu_post_msg on the assigned cpu + */ +HV_STAGED_MSG_BUSY, +/* + * cpu_post_msg (vcpu thread) tries to copy staged msg to msg slot, + * notify the guest, records the status, marks the posting done (BUSY + * -> POSTED), and schedules sint_msg_bh BH + */ +HV_STAGED_MSG_POSTED, +/* + * sint_msg_bh (BH) verifies that the posting is done, runs the + * callback, and starts over (POSTED -> FREE) + */ +} state; +} HvSintStagedMessage; + +struct HvSintRoute { +uint32_t sint; +SynICState *synic; +int gsi; +EventNotifier sint_set_notifier; +EventNotifier sint_ack_notifier; + +HvSintStagedMessage *staged_msg; + +unsigned refcount; +QLIST_ENTRY(HvSintRoute) link; +}; + static bool synic_enabled; Why did you move this struct above? I think it was done purposefully to separate synic_* functions from the others below (sint_*). Done bool hyperv_is_synic_enabled(void) @@ -51,11 +103,11 @@ static SynICState *get_synic(CPUState *cs) return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); } -static void synic_update(SynICState *synic, bool enable, +static void synic_update(SynICState *synic, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { -synic->enabled = enable; +synic->sctl_enabled = sctl_enable; if (synic->msg_page_addr != msg_page_addr) { if (synic->msg_page_addr) { memory_region_del_subregion(get_system_memory(), @@ -80,7 +132,7 @@ static void synic_update(SynICState *synic, bool enable, } } -void hyperv_synic_update(CPUState *cs, bool enable, +void hyperv_synic_update(CPUState *cs, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { SynICState *synic = get_synic(cs); @@ -89,7 +141,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, return; } -synic_update(synic, enable, msg_page_addr, event_page_addr); +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); } static void synic_realize(DeviceState *dev, Error **errp) @@ -110,16 +162,20 @@ static void synic_realize(DeviceState *dev, Error **errp) sizeof(*synic->event_page), &error_abort); synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); +qemu_mutex_init(&synic->sint_routes_mutex); +QLIST_INIT(&synic->sint_routes); g_free(msgp_name); g_free(eventp_name); } + s
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, &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(*debu
[PATCH v2 3/4] hyperv: Add support to process syndbg commands
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| 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 aaba6b4901..86d295395e 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
[PATCH v2 0/4] HyperV: Synthetic Debugging device
This patchset adds support for the synthetic debugging device. HyperV supports a special transport layer for the kernel debugger when running in HyperV. This patchset add supports for this device so you could have a setup fast windows kernel debugging. At this point of time, DHCP is not implmeneted so to set this up few things need to be noted. The scenario I used to test is having 2 VMs in the same virtual network i.e a Debugger VM with the NIC: -nic tap,model=virtio,mac=02:ca:01:01:01:01,script=/etc/qemu-ifup And it's IP is going to be static 192.168.53.12 And the VM we want to debug, to which we need to have the englightments and vmbus configured: -cpu host,hv-relaxed,hv_spinlocks=0x1fff,hv_time,+vmx,invtsc,hv-vapic,hv-vpindex,hv-synic,hv-syndbg \ -device vmbus-bridge \ -device hv-syndbg,host_ip=192.168.53.12,host_port=5,use_hcalls=false \ -nic tap,model=virtio,mac=02:ca:01:01:01:02,script=/etc/qemu-ifup \ Then in the debuggee VM we would setup the kernel debugging in the following way: If the VM is older than Win8: * Copy the proper platform kdvm.dll (make sure it's called kdvm.dll even if platform is 32bit) bcdedit /set {GUID} dbgtransport kdvm.dll bcdedit /set {GUID} loadoptions host_ip="1.2.3.4",host_port="5",nodhcp bcdedit /set {GUID} debug on bcdedit /set {GUID} halbreakpoint on Win8 and late: bcdedit /dbgsettings net hostip:7.7.7.7 port:5 nodhcp This is all the setup that is required to get the synthetic debugger configured correctly. Jon Doron (4): hyperv: SControl is optional to enable SynIc hyperv: Add definitions for syndbg hyperv: Add support to process syndbg commands hw: hyperv: Initial commit for Synthetic Debugging device docs/hyperv.txt | 15 ++ hw/hyperv/Kconfig| 5 + hw/hyperv/hyperv.c | 352 --- hw/hyperv/meson.build| 1 + hw/hyperv/syndbg.c | 402 +++ include/hw/hyperv/hyperv-proto.h | 52 include/hw/hyperv/hyperv.h | 58 + target/i386/cpu.c| 2 + target/i386/cpu.h| 7 + target/i386/kvm/hyperv-proto.h | 37 +++ target/i386/kvm/hyperv-stub.c| 6 + target/i386/kvm/hyperv.c | 52 +++- target/i386/kvm/kvm.c| 76 +- 13 files changed, 1024 insertions(+), 41 deletions(-) create mode 100644 hw/hyperv/syndbg.c -- 2.35.1
[PATCH v2 2/4] hyperv: Add definitions for syndbg
Add all required definitions for hyperv synthetic debugger interface. Signed-off-by: Jon Doron --- include/hw/hyperv/hyperv-proto.h | 52 target/i386/kvm/hyperv-proto.h | 37 +++ 2 files changed, 89 insertions(+) diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-proto.h index 21dc28aee9..4a2297307b 100644 --- a/include/hw/hyperv/hyperv-proto.h +++ b/include/hw/hyperv/hyperv-proto.h @@ -24,12 +24,17 @@ #define HV_STATUS_INVALID_PORT_ID 17 #define HV_STATUS_INVALID_CONNECTION_ID 18 #define HV_STATUS_INSUFFICIENT_BUFFERS19 +#define HV_STATUS_NOT_ACKNOWLEDGED20 +#define HV_STATUS_NO_DATA 27 /* * Hypercall numbers */ #define HV_POST_MESSAGE 0x005c #define HV_SIGNAL_EVENT 0x005d +#define HV_POST_DEBUG_DATA0x0069 +#define HV_RETRIEVE_DEBUG_DATA0x006a +#define HV_RESET_DEBUG_SESSION0x006b #define HV_HYPERCALL_FAST (1u << 16) /* @@ -127,4 +132,51 @@ struct hyperv_event_flags_page { struct hyperv_event_flags slot[HV_SINT_COUNT]; }; +/* + * Kernel debugger structures + */ + +/* Options flags for hyperv_reset_debug_session */ +#define HV_DEBUG_PURGE_INCOMING_DATA0x0001 +#define HV_DEBUG_PURGE_OUTGOING_DATA0x0002 +struct hyperv_reset_debug_session_input { +uint32_t options; +} __attribute__ ((__packed__)); + +struct hyperv_reset_debug_session_output { +uint32_t host_ip; +uint32_t target_ip; +uint16_t host_port; +uint16_t target_port; +uint8_t host_mac[6]; +uint8_t target_mac[6]; +} __attribute__ ((__packed__)); + +/* Options for hyperv_post_debug_data */ +#define HV_DEBUG_POST_LOOP 0x0001 + +struct hyperv_post_debug_data_input { +uint32_t count; +uint32_t options; +/*uint8_t data[HV_HYP_PAGE_SIZE - 2 * sizeof(uint32_t)];*/ +} __attribute__ ((__packed__)); + +struct hyperv_post_debug_data_output { +uint32_t pending_count; +} __attribute__ ((__packed__)); + +/* Options for hyperv_retrieve_debug_data */ +#define HV_DEBUG_RETRIEVE_LOOP 0x0001 +#define HV_DEBUG_RETRIEVE_TEST_ACTIVITY 0x0002 + +struct hyperv_retrieve_debug_data_input { +uint32_t count; +uint32_t options; +uint64_t timeout; +} __attribute__ ((__packed__)); + +struct hyperv_retrieve_debug_data_output { +uint32_t retrieved_count; +uint32_t remaining_count; +} __attribute__ ((__packed__)); #endif diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index 89f81afda7..e40e59411c 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -19,6 +19,9 @@ #define HV_CPUID_ENLIGHTMENT_INFO 0x4004 #define HV_CPUID_IMPLEMENT_LIMITS 0x4005 #define HV_CPUID_NESTED_FEATURES 0x400A +#define HV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS0x4080 +#define HV_CPUID_SYNDBG_INTERFACE 0x4081 +#define HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x4082 #define HV_CPUID_MIN 0x4005 #define HV_CPUID_MAX 0x4000 #define HV_HYPERVISOR_PRESENT_BIT 0x8000 @@ -55,8 +58,14 @@ #define HV_GUEST_IDLE_STATE_AVAILABLE (1u << 5) #define HV_FREQUENCY_MSRS_AVAILABLE (1u << 8) #define HV_GUEST_CRASH_MSR_AVAILABLE(1u << 10) +#define HV_FEATURE_DEBUG_MSRS_AVAILABLE (1u << 11) #define HV_STIMER_DIRECT_MODE_AVAILABLE (1u << 19) +/* + * HV_CPUID_FEATURES.EBX bits + */ +#define HV_PARTITION_DEBUGGING_ALLOWED (1u << 12) + /* * HV_CPUID_ENLIGHTMENT_INFO.EAX bits */ @@ -72,6 +81,11 @@ #define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14) #define HV_NO_NONARCH_CORESHARING (1u << 18) +/* + * HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits + */ +#define HV_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING(1u << 1) + /* * Basic virtualized MSRs */ @@ -130,6 +144,18 @@ #define HV_X64_MSR_STIMER3_CONFIG 0x40B6 #define HV_X64_MSR_STIMER3_COUNT0x40B7 +/* + * Hyper-V Synthetic debug options MSR + */ +#define HV_X64_MSR_SYNDBG_CONTROL 0x40F1 +#define HV_X64_MSR_SYNDBG_STATUS0x40F2 +#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x40F3 +#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x40F4 +#define HV_X64_MSR_SYNDBG_PENDING_BUFFER0x40F5 +#define HV_X64_MSR_SYNDBG_OPTIONS 0x40FF + +#define HV_X64_SYNDBG_OPTION_USE_HCALLS BIT(2) + /* * Guest crash notification MSRs */ @@ -168,5 +194,16 @@ #define HV_STIMER_COUNT 4 +/* + * Synthetic debugger control definitions + */ +#define HV_SYNDBG_CONTROL_SEND (1u <<
[PATCH v2 4/4] hw: hyperv: Initial commit for Synthetic Debugging device
Signed-off-by: Jon Doron --- hw/hyperv/Kconfig | 5 + hw/hyperv/meson.build | 1 + hw/hyperv/syndbg.c| 402 ++ 3 files changed, 408 insertions(+) create mode 100644 hw/hyperv/syndbg.c diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig index 3fbfe41c9e..fcf65903bd 100644 --- a/hw/hyperv/Kconfig +++ b/hw/hyperv/Kconfig @@ -11,3 +11,8 @@ config VMBUS bool default y depends on HYPERV + +config SYNDBG +bool +default y +depends on VMBUS diff --git a/hw/hyperv/meson.build b/hw/hyperv/meson.build index 1367e2994f..b43f119ea5 100644 --- a/hw/hyperv/meson.build +++ b/hw/hyperv/meson.build @@ -1,3 +1,4 @@ specific_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c')) specific_ss.add(when: 'CONFIG_HYPERV_TESTDEV', if_true: files('hyperv_testdev.c')) specific_ss.add(when: 'CONFIG_VMBUS', if_true: files('vmbus.c')) +specific_ss.add(when: 'CONFIG_SYNDBG', if_true: files('syndbg.c')) diff --git a/hw/hyperv/syndbg.c b/hw/hyperv/syndbg.c new file mode 100644 index 00..8816bc4082 --- /dev/null +++ b/hw/hyperv/syndbg.c @@ -0,0 +1,402 @@ +/* + * QEMU Hyper-V Synthetic Debugging device + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/ctype.h" +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qemu/sockets.h" +#include "qemu-common.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/loader.h" +#include "cpu.h" +#include "hw/hyperv/hyperv.h" +#include "hw/hyperv/vmbus-bridge.h" +#include "hw/hyperv/hyperv-proto.h" +#include "net/net.h" +#include "net/eth.h" +#include "net/checksum.h" +#include "trace.h" + +#define TYPE_HV_SYNDBG "hv-syndbg" + +typedef struct HvSynDbg { +DeviceState parent_obj; + +char *host_ip; +uint16_t host_port; +bool use_hcalls; + +uint32_t target_ip; +struct sockaddr_in servaddr; +int socket; +bool has_data_pending; +uint64_t pending_page_gpa; +} HvSynDbg; + +#define HVSYNDBG(obj) OBJECT_CHECK(HvSynDbg, (obj), TYPE_HV_SYNDBG) + +/* returns NULL unless there is exactly one HV Synth debug device */ +static HvSynDbg *hv_syndbg_find(void) +{ +/* Returns NULL unless there is exactly one hvsd device */ +return HVSYNDBG(object_resolve_path_type("", TYPE_HV_SYNDBG, NULL)); +} + +static void set_pending_state(HvSynDbg *syndbg, bool has_pending) +{ +hwaddr out_len; +void *out_data; + +syndbg->has_data_pending = has_pending; + +if (!syndbg->pending_page_gpa) { +return; +} + +out_len = 1; +out_data = cpu_physical_memory_map(syndbg->pending_page_gpa, &out_len, 1); +if (out_data) { +*(uint8_t *)out_data = !!has_pending; +cpu_physical_memory_unmap(out_data, out_len, 1, out_len); +} +} + +static bool get_udb_pkt_data(void *p, uint32_t len, uint32_t *data_ofs, + uint32_t *src_ip) +{ +uint32_t offset, curr_len = len; + +if (curr_len < sizeof(struct eth_header) || +(be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto) != ETH_P_IP)) { +return false; +} +offset = sizeof(struct eth_header); +curr_len -= sizeof(struct eth_header); + +if (curr_len < sizeof(struct ip_header) || +PKT_GET_IP_HDR(p)->ip_p != IP_PROTO_UDP) { +return false; +} +offset += PKT_GET_IP_HDR_LEN(p); +curr_len -= PKT_GET_IP_HDR_LEN(p); + +if (curr_len < sizeof(struct udp_header)) { +return false; +} + +offset += sizeof(struct udp_header); +*data_ofs = offset; +*src_ip = PKT_GET_IP_HDR(p)->ip_src; +return true; +} + +static uint16_t handle_send_msg(HvSynDbg *syndbg, uint64_t ingpa, +uint32_t count, bool is_raw, +uint32_t *pending_count) +{ +uint16_t ret; +hwaddr data_len; +void *debug_data = NULL; +uint32_t udp_data_ofs = 0; +const void *pkt_data; +int sent_count; + +data_len = count; +debug_data = cpu_physical_memory_map(ingpa, &data_len, 0); +if (!debug_data || data_len < count) { +ret = HV_STATUS_INSUFFICIENT_MEMORY; +goto cleanup; +} + +if (is_raw && +!get_udb_pkt_data(debug_data, count, &udp_data_ofs, + &syndbg->target_ip)) { +ret = HV_STATUS_SUCCESS; +goto cleanup; +} + +pkt_data = (const void *)((uintptr_t)debug_data + udp_data_ofs); +sent_count = qemu_sendto(syndbg->socket, pkt_data, count - udp_data_ofs, +
[PATCH v2 1/4] hyperv: SControl is optional to enable SynIc
SynIc can be enabled regardless of the SControl mechanisim which can register a GSI for a given SintRoute. This behaviour can achived by setting enabling SIMP and then the guest will poll on the message slot. Once there is another message pending the host will set the message slot with the pending flag. When the guest polls from the message slot, in case the pending flag is set it will write to the HV_X64_MSR_EOM indicating it has cleared the slot and we can try and push our message again. Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 109 +++-- 1 file changed, 76 insertions(+), 33 deletions(-) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index cb1074f234..aaba6b4901 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -27,13 +27,16 @@ struct SynICState { CPUState *cs; -bool enabled; +bool sctl_enabled; hwaddr msg_page_addr; hwaddr event_page_addr; MemoryRegion msg_page_mr; MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; + +QemuMutex sint_routes_mutex; +QLIST_HEAD(, HvSintRoute) sint_routes; }; #define TYPE_SYNIC "hyperv-synic" @@ -51,11 +54,11 @@ static SynICState *get_synic(CPUState *cs) return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); } -static void synic_update(SynICState *synic, bool enable, +static void synic_update(SynICState *synic, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { -synic->enabled = enable; +synic->sctl_enabled = sctl_enable; if (synic->msg_page_addr != msg_page_addr) { if (synic->msg_page_addr) { memory_region_del_subregion(get_system_memory(), @@ -80,7 +83,7 @@ static void synic_update(SynICState *synic, bool enable, } } -void hyperv_synic_update(CPUState *cs, bool enable, +void hyperv_synic_update(CPUState *cs, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { SynICState *synic = get_synic(cs); @@ -89,7 +92,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, return; } -synic_update(synic, enable, msg_page_addr, event_page_addr); +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); } static void synic_realize(DeviceState *dev, Error **errp) @@ -110,16 +113,20 @@ static void synic_realize(DeviceState *dev, Error **errp) sizeof(*synic->event_page), &error_abort); synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); +qemu_mutex_init(&synic->sint_routes_mutex); +QLIST_INIT(&synic->sint_routes); g_free(msgp_name); g_free(eventp_name); } + static void synic_reset(DeviceState *dev) { SynICState *synic = SYNIC(dev); memset(synic->msg_page, 0, sizeof(*synic->msg_page)); memset(synic->event_page, 0, sizeof(*synic->event_page)); synic_update(synic, false, 0, 0); +assert(QLIST_EMPTY(&synic->sint_routes)); } static void synic_class_init(ObjectClass *klass, void *data) @@ -214,6 +221,7 @@ struct HvSintRoute { HvSintStagedMessage *staged_msg; unsigned refcount; +QLIST_ENTRY(HvSintRoute) link; }; static CPUState *hyperv_find_vcpu(uint32_t vp_index) @@ -259,7 +267,7 @@ static void cpu_post_msg(CPUState *cs, run_on_cpu_data data) assert(staged_msg->state == HV_STAGED_MSG_BUSY); -if (!synic->enabled || !synic->msg_page_addr) { +if (!synic->msg_page_addr) { staged_msg->status = -ENXIO; goto posted; } @@ -343,7 +351,7 @@ int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno) if (eventno > HV_EVENT_FLAGS_COUNT) { return -EINVAL; } -if (!synic->enabled || !synic->event_page_addr) { +if (!synic->sctl_enabled || !synic->event_page_addr) { return -ENXIO; } @@ -364,11 +372,12 @@ int hyperv_set_event_flag(HvSintRoute *sint_route, unsigned eventno) HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, HvSintMsgCb cb, void *cb_data) { -HvSintRoute *sint_route; -EventNotifier *ack_notifier; +HvSintRoute *sint_route = NULL; +EventNotifier *ack_notifier = NULL; int r, gsi; CPUState *cs; SynICState *synic; +bool ack_event_initialized = false; cs = hyperv_find_vcpu(vp_index); if (!cs) { @@ -381,57 +390,77 @@ HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, } sint_route = g_new0(HvSintRoute, 1); -r = event_notifier_init(&sint_route->sint_set_notifier, false); -if (r) { -goto err; +if (!sint_route) { +return NULL; } +sint_route->synic =
Re: [PATCH v1 0/4] HyperV: Synthetic Debugging device
On 04/02/2022, Jon Doron wrote: Ping This patchset adds support for the synthetic debugging device. HyperV supports a special transport layer for the kernel debugger when running in HyperV. This patchset add supports for this device so you could have a setup fast windows kernel debugging. At this point of time, DHCP is not implmeneted so to set this up few things need to be noted. The scenario I used to test is having 2 VMs in the same virtual network i.e a Debugger VM with the NIC: -nic tap,model=virtio,mac=02:ca:01:01:01:01,script=/etc/qemu-ifup And it's IP is going to be static 192.168.53.12 And the VM we want to debug, to which we need to have the englightments and vmbus configured: -cpu host,hv-relaxed,hv_spinlocks=0x1fff,hv_time,+vmx,invtsc,hv-vapic,hv-vpindex,hv-synic,hv-syndbg \ -device vmbus-bridge \ -device hv-syndbg,host_ip=192.168.53.12,host_port=5,use_hcalls=false \ -nic tap,model=virtio,mac=02:ca:01:01:01:02,script=/etc/qemu-ifup \ Then in the debuggee VM we would setup the kernel debugging in the following way: If the VM is older than Win8: * Copy the proper platform kdvm.dll (make sure it's called kdvm.dll even if platform is 32bit) bcdedit /set {GUID} dbgtransport kdvm.dll bcdedit /set {GUID} loadoptions host_ip="1.2.3.4",host_port="5",nodhcp bcdedit /set {GUID} debug on bcdedit /set {GUID} halbreakpoint on Win8 and late: bcdedit /dbgsettings net hostip:7.7.7.7 port:5 nodhcp This is all the setup that is required to get the synthetic debugger configured correctly. Jon Doron (4): hyperv: SControl is optional to enable SynIc hyperv: Add definitions for syndbg hyperv: Add support to process syndbg commands hw: hyperv: Initial commit for Synthetic Debugging device docs/hyperv.txt | 15 + hw/hyperv/Kconfig| 5 + hw/hyperv/hyperv.c | 475 +-- hw/hyperv/meson.build| 1 + hw/hyperv/syndbg.c | 407 ++ include/hw/hyperv/hyperv-proto.h | 52 include/hw/hyperv/hyperv.h | 60 target/i386/cpu.c| 2 + target/i386/cpu.h| 7 + target/i386/kvm/hyperv-proto.h | 37 +++ target/i386/kvm/hyperv-stub.c| 6 + target/i386/kvm/hyperv.c | 52 +++- target/i386/kvm/kvm.c| 76 - 13 files changed, 1105 insertions(+), 90 deletions(-) create mode 100644 hw/hyperv/syndbg.c -- 2.34.1
[PATCH v1 4/4] hw: hyperv: Initial commit for Synthetic Debugging device
Signed-off-by: Jon Doron --- hw/hyperv/Kconfig | 5 + hw/hyperv/meson.build | 1 + hw/hyperv/syndbg.c| 407 ++ 3 files changed, 413 insertions(+) create mode 100644 hw/hyperv/syndbg.c diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig index 3fbfe41c9e..fcf65903bd 100644 --- a/hw/hyperv/Kconfig +++ b/hw/hyperv/Kconfig @@ -11,3 +11,8 @@ config VMBUS bool default y depends on HYPERV + +config SYNDBG +bool +default y +depends on VMBUS diff --git a/hw/hyperv/meson.build b/hw/hyperv/meson.build index 1367e2994f..b43f119ea5 100644 --- a/hw/hyperv/meson.build +++ b/hw/hyperv/meson.build @@ -1,3 +1,4 @@ specific_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c')) specific_ss.add(when: 'CONFIG_HYPERV_TESTDEV', if_true: files('hyperv_testdev.c')) specific_ss.add(when: 'CONFIG_VMBUS', if_true: files('vmbus.c')) +specific_ss.add(when: 'CONFIG_SYNDBG', if_true: files('syndbg.c')) diff --git a/hw/hyperv/syndbg.c b/hw/hyperv/syndbg.c new file mode 100644 index 00..837eb33458 --- /dev/null +++ b/hw/hyperv/syndbg.c @@ -0,0 +1,407 @@ +/* + * QEMU Hyper-V Synthetic Debugging device + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/ctype.h" +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qemu/sockets.h" +#include "qemu-common.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/loader.h" +#include "cpu.h" +#include "hw/hyperv/hyperv.h" +#include "hw/hyperv/vmbus-bridge.h" +#include "hw/hyperv/hyperv-proto.h" +#include "net/net.h" +#include "net/eth.h" +#include "net/checksum.h" +#include "trace.h" + +#define TYPE_HV_SYNDBG "hv-syndbg" + +typedef struct HvSynDbg { +DeviceState parent_obj; + +char *host_ip; +uint16_t host_port; +bool use_hcalls; + +uint32_t target_ip; +struct sockaddr_in servaddr; +int socket; +bool has_data_pending; +uint64_t pending_page_gpa; +} HvSynDbg; + +#define HVSYNDBG(obj) OBJECT_CHECK(HvSynDbg, (obj), TYPE_HV_SYNDBG) + +/* returns NULL unless there is exactly one HV Synth debug device */ +static HvSynDbg *hv_syndbg_find(void) +{ +/* Returns NULL unless there is exactly one hvsd device */ +return HVSYNDBG(object_resolve_path_type("", TYPE_HV_SYNDBG, NULL)); +} + +static void set_pending_state(HvSynDbg *syndbg, bool has_pending) +{ +hwaddr out_len; +void *out_data; + +syndbg->has_data_pending = has_pending; + +if (!syndbg->pending_page_gpa) { +return; +} + +out_len = 1; +out_data = cpu_physical_memory_map(syndbg->pending_page_gpa, &out_len, 1); +if (out_data) { +*(uint8_t *)out_data = !!has_pending; +cpu_physical_memory_unmap(out_data, out_len, 1, out_len); +} +} + +static bool get_udb_pkt_data(void *p, uint32_t len, uint32_t *data_ofs, + uint32_t *src_ip) +{ +uint32_t offset, curr_len = len; + +if (curr_len < sizeof(struct eth_header) || +(be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto) != ETH_P_IP)) { +return false; +} +offset = sizeof(struct eth_header); +curr_len -= sizeof(struct eth_header); + +if (curr_len < sizeof(struct ip_header) || +PKT_GET_IP_HDR(p)->ip_p != IP_PROTO_UDP) { +return false; +} +offset += PKT_GET_IP_HDR_LEN(p); +curr_len -= PKT_GET_IP_HDR_LEN(p); + +if (curr_len < sizeof(struct udp_header)) { +return false; +} + +offset += sizeof(struct udp_header); +*data_ofs = offset; +*src_ip = PKT_GET_IP_HDR(p)->ip_src; +return true; +} + +static uint16_t handle_send_msg(HvSynDbg *syndbg, uint64_t ingpa, +uint32_t count, bool is_raw, +uint32_t *pending_count) +{ +uint16_t ret; +hwaddr data_len; +void *debug_data = NULL; +uint32_t udp_data_ofs = 0; +const void *pkt_data; +int sent_count; + +data_len = count; +debug_data = cpu_physical_memory_map(ingpa, &data_len, 0); +if (!debug_data || data_len < count) { +ret = HV_STATUS_INSUFFICIENT_MEMORY; +goto cleanup; +} + +if (is_raw && +!get_udb_pkt_data(debug_data, count, &udp_data_ofs, + &syndbg->target_ip)) { +ret = HV_STATUS_SUCCESS; +goto cleanup; +} + +pkt_data = (const void *)((uintptr_t)debug_data + udp_data_ofs); +sent_count = qemu_sendto(syndbg->socket, pkt_data, count - udp_data_ofs, +
[PATCH v1 2/4] hyperv: Add definitions for syndbg
Add all required definitions for hyperv synthetic debugger interface. Signed-off-by: Jon Doron --- include/hw/hyperv/hyperv-proto.h | 52 target/i386/kvm/hyperv-proto.h | 37 +++ 2 files changed, 89 insertions(+) diff --git a/include/hw/hyperv/hyperv-proto.h b/include/hw/hyperv/hyperv-proto.h index 21dc28aee9..94c9658eb0 100644 --- a/include/hw/hyperv/hyperv-proto.h +++ b/include/hw/hyperv/hyperv-proto.h @@ -24,12 +24,17 @@ #define HV_STATUS_INVALID_PORT_ID 17 #define HV_STATUS_INVALID_CONNECTION_ID 18 #define HV_STATUS_INSUFFICIENT_BUFFERS19 +#define HV_STATUS_NOT_ACKNOWLEDGED20 +#define HV_STATUS_NO_DATA 27 /* * Hypercall numbers */ #define HV_POST_MESSAGE 0x005c #define HV_SIGNAL_EVENT 0x005d +#define HV_POST_DEBUG_DATA0x0069 +#define HV_RETREIVE_DEBUG_DATA0x006a +#define HV_RESET_DEBUG_SESSION0x006b #define HV_HYPERCALL_FAST (1u << 16) /* @@ -127,4 +132,51 @@ struct hyperv_event_flags_page { struct hyperv_event_flags slot[HV_SINT_COUNT]; }; +/* + * Kernel debugger structures + */ + +/* Options flags for hyperv_reset_debug_session */ +#define HV_DEBUG_PURGE_INCOMING_DATA0x0001 +#define HV_DEBUG_PURGE_OUTGOING_DATA0x0002 +struct hyperv_reset_debug_session_input { +uint32_t options; +} __attribute__ ((__packed__)); + +struct hyperv_reset_debug_session_output { +uint32_t host_ip; +uint32_t target_ip; +uint16_t host_port; +uint16_t target_port; +uint8_t host_mac[6]; +uint8_t target_mac[6]; +} __attribute__ ((__packed__)); + +/* Options for hyperv_post_debug_data */ +#define HV_DEBUG_POST_LOOP 0x0001 + +struct hyperv_post_debug_data_input { +uint32_t count; +uint32_t options; +/*uint8_t data[HV_HYP_PAGE_SIZE - 2 * sizeof(uint32_t)];*/ +} __attribute__ ((__packed__)); + +struct hyperv_post_debug_data_output { +uint32_t pending_count; +} __attribute__ ((__packed__)); + +/* Options for hyperv_retrieve_debug_data */ +#define HV_DEBUG_RETRIEVE_LOOP 0x0001 +#define HV_DEBUG_RETRIEVE_TEST_ACTIVITY 0x0002 + +struct hyperv_retrieve_debug_data_input { +uint32_t count; +uint32_t options; +uint64_t timeout; +} __attribute__ ((__packed__)); + +struct hyperv_retrieve_debug_data_output { +uint32_t retrieved_count; +uint32_t remaining_count; +} __attribute__ ((__packed__)); #endif diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index 89f81afda7..9480bcdf04 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -19,6 +19,9 @@ #define HV_CPUID_ENLIGHTMENT_INFO 0x4004 #define HV_CPUID_IMPLEMENT_LIMITS 0x4005 #define HV_CPUID_NESTED_FEATURES 0x400A +#define HV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS0x4080 +#define HV_CPUID_SYNDBG_INTERFACE 0x4081 +#define HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x4082 #define HV_CPUID_MIN 0x4005 #define HV_CPUID_MAX 0x4000 #define HV_HYPERVISOR_PRESENT_BIT 0x8000 @@ -55,8 +58,14 @@ #define HV_GUEST_IDLE_STATE_AVAILABLE (1u << 5) #define HV_FREQUENCY_MSRS_AVAILABLE (1u << 8) #define HV_GUEST_CRASH_MSR_AVAILABLE(1u << 10) +#define HV_FEATURE_DEBUG_MSRS_AVAILABLE (1u << 11) #define HV_STIMER_DIRECT_MODE_AVAILABLE (1u << 19) +/* + * HV_CPUID_FEATURES.EBX bits + */ +#define HV_PARTITION_DEUBGGING_ALLOWED (1u << 12) + /* * HV_CPUID_ENLIGHTMENT_INFO.EAX bits */ @@ -72,6 +81,11 @@ #define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14) #define HV_NO_NONARCH_CORESHARING (1u << 18) +/* + * HV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits + */ +#define HV_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING(1u << 1) + /* * Basic virtualized MSRs */ @@ -130,6 +144,18 @@ #define HV_X64_MSR_STIMER3_CONFIG 0x40B6 #define HV_X64_MSR_STIMER3_COUNT0x40B7 +/* + * Hyper-V Synthetic debug options MSR + */ +#define HV_X64_MSR_SYNDBG_CONTROL 0x40F1 +#define HV_X64_MSR_SYNDBG_STATUS0x40F2 +#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x40F3 +#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x40F4 +#define HV_X64_MSR_SYNDBG_PENDING_BUFFER0x40F5 +#define HV_X64_MSR_SYNDBG_OPTIONS 0x40FF + +#define HV_X64_SYNDBG_OPTION_USE_HCALLS BIT(2) + /* * Guest crash notification MSRs */ @@ -168,5 +194,16 @@ #define HV_STIMER_COUNT 4 +/* + * Synthetic debugger control definitions + */ +#define HV_SYNDBG_CONTROL_SEND (1u <<
[PATCH v1 1/4] hyperv: SControl is optional to enable SynIc
SynIc can be enabled regardless of the SControl mechanisim which can register a GSI for a given SintRoute. This behaviour can achived by setting enabling SIMP and then the guest will poll on the message slot. Once there is another message pending the host will set the message slot with the pending flag. When the guest polls from the message slot, incase the pending flag is set it will write to the HV_X64_MSR_EOM indicating it has cleared the slow and we can try and push our message again. Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 233 - include/hw/hyperv/hyperv.h | 2 + 2 files changed, 153 insertions(+), 82 deletions(-) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index cb1074f234..88c9cc1334 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -27,18 +27,70 @@ struct SynICState { CPUState *cs; -bool enabled; +bool sctl_enabled; hwaddr msg_page_addr; hwaddr event_page_addr; MemoryRegion msg_page_mr; MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; + +QemuMutex sint_routes_mutex; +QLIST_HEAD(, HvSintRoute) sint_routes; }; #define TYPE_SYNIC "hyperv-synic" OBJECT_DECLARE_SIMPLE_TYPE(SynICState, SYNIC) +/* + * KVM has its own message producers (SynIC timers). To guarantee + * serialization with both KVM vcpu and the guest cpu, the messages are first + * staged in an intermediate area and then posted to the SynIC message page in + * the vcpu thread. + */ +typedef struct HvSintStagedMessage { +/* message content staged by hyperv_post_msg */ +struct hyperv_message msg; +/* callback + data (r/o) to complete the processing in a BH */ +HvSintMsgCb cb; +void *cb_data; +/* message posting status filled by cpu_post_msg */ +int status; +/* passing the buck: */ +enum { +/* initial state */ +HV_STAGED_MSG_FREE, +/* + * hyperv_post_msg (e.g. in main loop) grabs the staged area (FREE -> + * BUSY), copies msg, and schedules cpu_post_msg on the assigned cpu + */ +HV_STAGED_MSG_BUSY, +/* + * cpu_post_msg (vcpu thread) tries to copy staged msg to msg slot, + * notify the guest, records the status, marks the posting done (BUSY + * -> POSTED), and schedules sint_msg_bh BH + */ +HV_STAGED_MSG_POSTED, +/* + * sint_msg_bh (BH) verifies that the posting is done, runs the + * callback, and starts over (POSTED -> FREE) + */ +} state; +} HvSintStagedMessage; + +struct HvSintRoute { +uint32_t sint; +SynICState *synic; +int gsi; +EventNotifier sint_set_notifier; +EventNotifier sint_ack_notifier; + +HvSintStagedMessage *staged_msg; + +unsigned refcount; +QLIST_ENTRY(HvSintRoute) link; +}; + static bool synic_enabled; bool hyperv_is_synic_enabled(void) @@ -51,11 +103,11 @@ static SynICState *get_synic(CPUState *cs) return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); } -static void synic_update(SynICState *synic, bool enable, +static void synic_update(SynICState *synic, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { -synic->enabled = enable; +synic->sctl_enabled = sctl_enable; if (synic->msg_page_addr != msg_page_addr) { if (synic->msg_page_addr) { memory_region_del_subregion(get_system_memory(), @@ -80,7 +132,7 @@ static void synic_update(SynICState *synic, bool enable, } } -void hyperv_synic_update(CPUState *cs, bool enable, +void hyperv_synic_update(CPUState *cs, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { SynICState *synic = get_synic(cs); @@ -89,7 +141,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, return; } -synic_update(synic, enable, msg_page_addr, event_page_addr); +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); } static void synic_realize(DeviceState *dev, Error **errp) @@ -110,16 +162,20 @@ static void synic_realize(DeviceState *dev, Error **errp) sizeof(*synic->event_page), &error_abort); synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); +qemu_mutex_init(&synic->sint_routes_mutex); +QLIST_INIT(&synic->sint_routes); g_free(msgp_name); g_free(eventp_name); } + static void synic_reset(DeviceState *dev) { SynICState *synic = SYNIC(dev); memset(synic->msg_page, 0, sizeof(*synic->msg_page)); memset(synic->event_page, 0, sizeof(*synic->event_page)); synic_update(synic, false, 0, 0); +assert(QLIST_EMPTY(&synic->sint_routes)); } static void s
[PATCH v1 3/4] hyperv: Add support to process syndbg commands
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 +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; +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
[PATCH v1 0/4] HyperV: Synthetic Debugging device
This patchset adds support for the synthetic debugging device. HyperV supports a special transport layer for the kernel debugger when running in HyperV. This patchset add supports for this device so you could have a setup fast windows kernel debugging. At this point of time, DHCP is not implmeneted so to set this up few things need to be noted. The scenario I used to test is having 2 VMs in the same virtual network i.e a Debugger VM with the NIC: -nic tap,model=virtio,mac=02:ca:01:01:01:01,script=/etc/qemu-ifup And it's IP is going to be static 192.168.53.12 And the VM we want to debug, to which we need to have the englightments and vmbus configured: -cpu host,hv-relaxed,hv_spinlocks=0x1fff,hv_time,+vmx,invtsc,hv-vapic,hv-vpindex,hv-synic,hv-syndbg \ -device vmbus-bridge \ -device hv-syndbg,host_ip=192.168.53.12,host_port=5,use_hcalls=false \ -nic tap,model=virtio,mac=02:ca:01:01:01:02,script=/etc/qemu-ifup \ Then in the debuggee VM we would setup the kernel debugging in the following way: If the VM is older than Win8: * Copy the proper platform kdvm.dll (make sure it's called kdvm.dll even if platform is 32bit) bcdedit /set {GUID} dbgtransport kdvm.dll bcdedit /set {GUID} loadoptions host_ip="1.2.3.4",host_port="5",nodhcp bcdedit /set {GUID} debug on bcdedit /set {GUID} halbreakpoint on Win8 and late: bcdedit /dbgsettings net hostip:7.7.7.7 port:5 nodhcp This is all the setup that is required to get the synthetic debugger configured correctly. Jon Doron (4): hyperv: SControl is optional to enable SynIc hyperv: Add definitions for syndbg hyperv: Add support to process syndbg commands hw: hyperv: Initial commit for Synthetic Debugging device docs/hyperv.txt | 15 + hw/hyperv/Kconfig| 5 + hw/hyperv/hyperv.c | 475 +-- hw/hyperv/meson.build| 1 + hw/hyperv/syndbg.c | 407 ++ include/hw/hyperv/hyperv-proto.h | 52 include/hw/hyperv/hyperv.h | 60 target/i386/cpu.c| 2 + target/i386/cpu.h| 7 + target/i386/kvm/hyperv-proto.h | 37 +++ target/i386/kvm/hyperv-stub.c| 6 + target/i386/kvm/hyperv.c | 52 +++- target/i386/kvm/kvm.c| 76 - 13 files changed, 1105 insertions(+), 90 deletions(-) create mode 100644 hw/hyperv/syndbg.c -- 2.34.1
Re: [PATCH v4 0/1] hw/hyperv/vmbus: Is it maintained?
On 13/11/2021, Maciej S. Szmigiero wrote: On 12.11.2021 21:39, Roman Kagan wrote: On Fri, Nov 12, 2021 at 09:32:31PM +0300, Vladimir Sementsov-Ogievskiy wrote: Add Den and Roman (his new address) Thanks, I missed it on the list indeed. 06.11.2021 16:41, Philippe Mathieu-Daudé wrote: This is the 4th time I send this patch. Is the VMBus infrastructure used / maintained? Should we deprecate & remove? I think it's fair to say it's not maintained. The whole hw/hyperv/vmbus.c was submitted as a part of the work by Jon to enable some obscure windows debugging feature which only worked in presence of VMBus. It was mostly taken from the respective branch of the (now effectively abandoned) downstream tree with an implementation of the core VMBus infrastructure and the devices using it; however, none of the actual VMBus devices ever made it into the mainline tree. The VMBus code works fine, is mostly self-contained and by being a part of the upstream QEMU it does benefit from any improvements done there and so it is much less likely to bit-rot with time. I am still committed to upstreaming a Hyper-V Dynamic Memory Protocol driver (which uses VMBus), however had been preempted by higher-priority work for now. Thanks, Maciej Hi guys, Sorry for the late reply, like Roman I also never got to submit the RFC for the Synth debugger device which requires the VMBus, I do hope to get to it at some point and VMBus is a required part for it. In the last year or so I have not had much time to spend on this but I do hope to get back to finishing what I have started. I'm not really sure I have the time or knowledge to maintain VMBus :( but I'll do my best to answer any questions as well. -- Jon.
Re: Who uses TYPE_VMBUS_DEVICE?
Hi Eduardo, Sorry for the late reply, in general there are also hv-net and hv-scsi implementations from Roman Kagan, which have not been merged in... I have a WIP component which does not use vmbus but Windows needs it to exist and function in order for it to work (it's the synthetic debugger interface for HyperV) On Sat, Oct 10, 2020 at 12:28 AM Eduardo Habkost wrote: > > On Fri, Oct 09, 2020 at 11:05:31PM +0200, Maciej S. Szmigiero wrote: > > Hi Eduardo, > > > > On 09.10.2020 21:39, Eduardo Habkost wrote: > > > Hi, > > > > > > I've just stumbled upon hw/hyperv/vmbus.c and I'm a bit confused: > > > I haven't found any subclasses of the abstract type > > > TYPE_VMBUS_DEVICE in the QEMU tree. > > > > > > I see a few patches in qemu-devel implementing a few vmbus > > > devices, but none were merged to qemu.git master. Are there any > > > short term plans to merge vmbus device implementations in QEMU? > > > > > > > Perhaps this depends on your definition of "short term". > > At least one VMBus driver (hv-balloon) is being actively worked on > > (by me). > > Good to know, thanks! > > > > > Also, a working VMBus implementation (even without any downstream > > devices) is apparently required for high-performance Windows > > kernel debugging interfaces. > > Other code might be required, but TYPE_VMBUS_DEVICE seems to be > dead code (which can't be executed or tested at all) unless a > concrete class exists. > > -- > Eduardo >
Re: [PATCH] hw/hyperv: Fix 32-bit build error for vmbus.
Hi Richard, I have already submitted this 7 weeks ago https://patchew.org/QEMU/20200715084326.678715-1-ari...@gmail.com/20200715084326.678715-3-ari...@gmail.com/ On Sun, Sep 6, 2020 at 8:01 AM Richard Henderson wrote: > > ../qemu/hw/hyperv/vmbus.c: In function ‘gpadl_iter_io’: > ../qemu/hw/hyperv/vmbus.c:383:13: error: cast to pointer from integer of > different size [-Werror=int-to-pointer-cast] > 383 | p = (void *)(((uintptr_t)iter->map & TARGET_PAGE_MASK) | > off_in_page); > | ^ > cc1: all warnings being treated as errors > > Fixes: 0d71f7082d7 ("vmbus: vmbus implementation") > Signed-off-by: Richard Henderson > --- > Cc: Jon Doron > --- > hw/hyperv/vmbus.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c > index 75af6b83dd..3482e9c6cb 100644 > --- a/hw/hyperv/vmbus.c > +++ b/hw/hyperv/vmbus.c > @@ -380,7 +380,8 @@ static ssize_t gpadl_iter_io(GpadlIter *iter, void *buf, > uint32_t len) > } > } > > -p = (void *)(((uintptr_t)iter->map & TARGET_PAGE_MASK) | > off_in_page); > +p = (void *)(uintptr_t) > +(((uintptr_t)iter->map & TARGET_PAGE_MASK) | off_in_page); > if (iter->dir == DMA_DIRECTION_FROM_DEVICE) { > memcpy(p, buf, cplen); > } else { > -- > 2.25.1 >
Re: [PATCH v1 1/1] hyperv: Enable SCONTROL if SYNIC is enabled
I think both patches are On Mon, Aug 10, 2020, 20:27 Paolo Bonzini wrote: > On 17/07/20 14:56, Jon Doron wrote: > > Based on an analysis of the HyperV firmwares (Gen1 and Gen2) it seems > > like the SCONTROL is not being set to the ENABLED state as like we have > > thought. > > > > Also from a test done by Vitaly Kuznetsov, running a nested HyperV it > > was concluded that the first access to the SCONTROL MSR with a read > > resulted with the value of 0x1, aka HV_SYNIC_CONTROL_ENABLE. > > > > It's important to note that this diverges from the value states in the > > HyperV TLFS of 0. > > > > Signed-off-by: Jon Doron > > --- > > target/i386/kvm.c | 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/target/i386/kvm.c b/target/i386/kvm.c > > index b8455c89ed..6a62e8ae94 100644 > > --- a/target/i386/kvm.c > > +++ b/target/i386/kvm.c > > @@ -1904,6 +1904,8 @@ void kvm_arch_reset_vcpu(X86CPU *cpu) > > > > if (hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNIC)) { > > int i; > > + > > +env->msr_hv_synic_control = HV_SYNIC_ENABLE; > > for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) { > > env->msr_hv_synic_sint[i] = HV_SINT_MASKED; > > } > > > > Are both patches needed or only the Hyper-V one? > > Paolo > >
[PATCH v1 1/1] hyperv: Enable SCONTROL if SYNIC is enabled
Based on an analysis of the HyperV firmwares (Gen1 and Gen2) it seems like the SCONTROL is not being set to the ENABLED state as like we have thought. Also from a test done by Vitaly Kuznetsov, running a nested HyperV it was concluded that the first access to the SCONTROL MSR with a read resulted with the value of 0x1, aka HV_SYNIC_CONTROL_ENABLE. It's important to note that this diverges from the value states in the HyperV TLFS of 0. Signed-off-by: Jon Doron --- target/i386/kvm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/i386/kvm.c b/target/i386/kvm.c index b8455c89ed..6a62e8ae94 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -1904,6 +1904,8 @@ void kvm_arch_reset_vcpu(X86CPU *cpu) if (hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNIC)) { int i; + +env->msr_hv_synic_control = HV_SYNIC_ENABLE; for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) { env->msr_hv_synic_sint[i] = HV_SINT_MASKED; } -- 2.24.1
[PATCH v1 0/1] hyperv: Enable SCONTROL if SYNIC is enabled
Based on an analysis of the HyperV firmwares (Gen1 and Gen2) it seems like the SCONTROL is not being set to the ENABLED state as like we have thought. Also from a test done by Vitaly Kuznetsov, running a nested HyperV it was concluded that the first access to the SCONTROL MSR with a read resulted with the value of 0x1, aka HV_SYNIC_CONTROL_ENABLE. It's important to note that this diverges from the value states in the HyperV TLFS of 0. Jon Doron (1): hyperv: Enable SCONTROL if SYNIC is enabled target/i386/kvm.c | 2 ++ 1 file changed, 2 insertions(+) -- 2.24.1
[PATCH v5 2/2] hw: hyperv: vmbus: Fix 32bit compilation
Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 34392e892a..c28bb4201b 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -383,7 +383,8 @@ static ssize_t gpadl_iter_io(GpadlIter *iter, void *buf, uint32_t len) } } -p = (void *)(((uintptr_t)iter->map & TARGET_PAGE_MASK) | off_in_page); +p = (void *)(uintptr_t)(((uintptr_t)iter->map & TARGET_PAGE_MASK) | +off_in_page); if (iter->dir == DMA_DIRECTION_FROM_DEVICE) { memcpy(p, buf, cplen); } else { -- 2.24.1
[PATCH v5 0/2] hyperv: vmbus: ACPI various corrections
After doing further tests and looking at the latest HyperV ACPI DSDT. Do minor fix to our VMBus ACPI entry. v5: * Rebased on latest master * Added a patch to fix 32bit compliation on VMBus v4: * Removed the patch which adds _ADR definition to the VMBus * Correct the change which moves the VMBus under the SB v3: Removed accidental change for the dct submodule head v2: Renamed irq0 to irq now that there is a single IRQ required Jon Doron (2): acpi: i386: Move VMBus DSDT entry to SB hw: hyperv: vmbus: Fix 32bit compilation hw/hyperv/vmbus.c| 3 ++- hw/i386/acpi-build.c | 12 +++- 2 files changed, 9 insertions(+), 6 deletions(-) -- 2.24.1
[PATCH v5 1/2] acpi: i386: Move VMBus DSDT entry to SB
Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b7bc2a..7708a27f70 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -975,7 +975,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) static void build_isa_devices_aml(Aml *table) { -VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Object *obj = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous); Aml *scope; @@ -986,10 +985,6 @@ static void build_isa_devices_aml(Aml *table) build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); isa_build_aml(ISA_BUS(obj), scope); -if (vmbus_bridge) { -aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); -} - aml_append(table, scope); } @@ -1485,6 +1480,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1526,6 +1522,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, } } +if (vmbus_bridge) { +sb_scope = aml_scope("_SB"); +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +aml_append(dsdt, sb_scope); +} + if (pcmc->legacy_cpu_hotplug) { build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base); } else { -- 2.24.1
Re: [PATCH v4 0/2] hyperv: vmbus: ACPI various corrections
Sure thing I'll try to take a look at it this weekend. Jon. On Mon, Jul 13, 2020, 11:44 Igor Mammedov wrote: > On Thu, 25 Jun 2020 07:50:09 +0300 > Jon Doron wrote: > > > After doing further tests and looking at the latest HyperV ACPI DSDT. > > Do minor fix to our VMBus ACPI entry. > > Jon, > vmbus feature needs a testcase, could you look into it please? > (see tests/qtest/bios-tables-test.c for an example. > also look into comment blob at the top for the propper process > for acpi patches/tests) > > > > v4: > > * Removed the patch which adds _ADR definition to the VMBus > > * Correct the change which moves the VMBus under the SB > > > > v3: > > Removed accidental change for the dct submodule head > > > > v2: > > Renamed irq0 to irq now that there is a single IRQ required > > > > Jon Doron (2): > > hyperv: vmbus: Remove the 2nd IRQ > > acpi: i386: Move VMBus DSDT entry to SB > > > > hw/hyperv/vmbus.c| 3 +-- > > hw/i386/acpi-build.c | 16 > > include/hw/hyperv/vmbus-bridge.h | 3 +-- > > 3 files changed, 10 insertions(+), 12 deletions(-) > > > >
Re: [Bug 1885247] [NEW] Build error in Intel 32-bit hosts
Is there a container I can download which has your build environment? On Fri, Jun 26, 2020 at 12:27 PM Philippe Mathieu-Daudé wrote: > > On 6/26/20 11:20 AM, Thomas Huth wrote: > > On 26/06/2020 11.13, Philippe Mathieu-Daudé wrote: > >> On 6/26/20 9:37 AM, Aleksandar Markovic wrote: > >>> пет, 26. јун 2020. у 09:11 Aleksandar Markovic > >>> <1885...@bugs.launchpad.net> је написао/ла: > > Public bug reported: > > The code base is on master, checked out on Thursday June25th 2020, > 0250c595c9d. The build procedure: > > $ mkdir build-gcc > $ cd build-gcc > $ ../configure > $ make > > The build error message is: > > CC x86_64-softmmu/hw/hyperv/hyperv.o > CC x86_64-softmmu/hw/hyperv/hyperv_testdev.o > CC x86_64-softmmu/hw/hyperv/vmbus.o > /home/rtrk/Build/qemu-master/hw/hyperv/vmbus.c: In function > ‘gpadl_iter_io’: > /home/rtrk/Build/qemu-master/hw/hyperv/vmbus.c:386:13: error: cast > to pointer from integer of different size [-Werror=int-to-pointer-cast] > p = (void *)(((uintptr_t)iter->map & TARGET_PAGE_MASK) | > off_in_page); > ^ > cc1: all warnings being treated as errors > make[1]: *** [/home/rtrk/Build/qemu-master/rules.mak:69: > hw/hyperv/vmbus.o] Error 1 > make: *** [Makefile:527: x86_64-softmmu/all] Error 2 > >> > >> FWIW there is no CI job covering x86 KVM on 32-bit host build. > >> Should this be covered? I guess the problem is no CI services > >> provide 32-bit x86... > > > > You can certainly provide either a container, or install the 32-bit > > libraries in a 64-bit environment. Then run > > > > PKG_CONFIG_LIBDIR=... ./configure --extra-cflags=-m32 > > > > and it should be possible to build 32-bit binaries, too. > > > > Alternatively, we could add a cross-compilation job that builds with > > i686-w64-mingw32 in 32-bit. > > Oh, this case is covered: > https://app.shippable.com/github/qemu/qemu/runs/2437/2/console > > But this doesn't use KVM ;) >
[PATCH v4 2/2] acpi: i386: Move VMBus DSDT entry to SB
Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 91af0d2d0d..1f938a53b2 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1091,7 +1091,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); -VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1112,10 +,6 @@ static void build_isa_devices_aml(Aml *table) isa_build_aml(ISA_BUS(obj), scope); } -if (vmbus_bridge) { -aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); -} - aml_append(table, scope); } @@ -1660,6 +1655,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1702,6 +1698,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, } } +if (vmbus_bridge) { +sb_scope = aml_scope("_SB"); +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +aml_append(dsdt, sb_scope); +} + if (pcmc->legacy_cpu_hotplug) { build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base); } else { -- 2.24.1
[PATCH v4 0/2] hyperv: vmbus: ACPI various corrections
After doing further tests and looking at the latest HyperV ACPI DSDT. Do minor fix to our VMBus ACPI entry. v4: * Removed the patch which adds _ADR definition to the VMBus * Correct the change which moves the VMBus under the SB v3: Removed accidental change for the dct submodule head v2: Renamed irq0 to irq now that there is a single IRQ required Jon Doron (2): hyperv: vmbus: Remove the 2nd IRQ acpi: i386: Move VMBus DSDT entry to SB hw/hyperv/vmbus.c| 3 +-- hw/i386/acpi-build.c | 16 include/hw/hyperv/vmbus-bridge.h | 3 +-- 3 files changed, 10 insertions(+), 12 deletions(-) -- 2.24.1
[PATCH v4 1/2] hyperv: vmbus: Remove the 2nd IRQ
It seems like Windows does not really require 2 IRQs to have a functioning VMBus. Signed-off-by: Jon Doron Reviewed-by: Igor Mammedov --- hw/hyperv/vmbus.c| 3 +-- hw/i386/acpi-build.c | 4 +--- include/hw/hyperv/vmbus-bridge.h | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index f371240176..a8bcb41026 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2741,8 +2741,7 @@ static const VMStateDescription vmstate_vmbus_bridge = { }; static Property vmbus_bridge_props[] = { -DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), -DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), +DEFINE_PROP_UINT8("irq", VMBusBridge, irq, 7), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 900f786d08..91af0d2d0d 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1082,9 +1082,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); crs = aml_resource_template(); -aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); -/* FIXME: newer HyperV gets by with only one IRQ */ -aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq)); aml_append(dev, aml_name_decl("_CRS", crs)); return dev; diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index c0a06d832c..33f93de64d 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -19,8 +19,7 @@ typedef struct VMBus VMBus; typedef struct VMBusBridge { SysBusDevice parent_obj; -uint8_t irq0; -uint8_t irq1; +uint8_t irq; VMBus *bus; } VMBusBridge; -- 2.24.1
Re: [PATCH v3 3/3] acpi: i386: Move VMBus DSDT entry to SB
On 25/06/2020, Jon Doron wrote: On 23/06/2020, Igor Mammedov wrote: On Thu, 18 Jun 2020 06:00:27 +0300 Jon Doron wrote: Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6d9df38e31..38be9e5a58 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1092,7 +1092,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); -VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1113,10 +1112,6 @@ static void build_isa_devices_aml(Aml *table) isa_build_aml(ISA_BUS(obj), scope); } -if (vmbus_bridge) { -aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); -} - aml_append(table, scope); } @@ -1661,6 +1656,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1675,6 +1671,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); @@ -1692,6 +1691,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); why are you duplicating instead of putting one if () block after if (misc->is_piix4) { } else { } ? Well it seems like Windows is very "picky" about where you declare the VMBS not sure why if i had moved it to the suggested location as such if (misc->is_piix4) { } else { } if (vmbus_bridge) { aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); aml_append(dsdt, sb_scope); } Windows would BSOD right away with ACPI error. Same goes for declaring it before PCI0 device... -- Jon. Never mind did a silly mistake ill send a new set shortly
Re: [PATCH v3 3/3] acpi: i386: Move VMBus DSDT entry to SB
On 23/06/2020, Igor Mammedov wrote: On Thu, 18 Jun 2020 06:00:27 +0300 Jon Doron wrote: Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6d9df38e31..38be9e5a58 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1092,7 +1092,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); -VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1113,10 +1112,6 @@ static void build_isa_devices_aml(Aml *table) isa_build_aml(ISA_BUS(obj), scope); } -if (vmbus_bridge) { -aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); -} - aml_append(table, scope); } @@ -1661,6 +1656,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1675,6 +1671,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); @@ -1692,6 +1691,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); why are you duplicating instead of putting one if () block after if (misc->is_piix4) { } else { } ? Well it seems like Windows is very "picky" about where you declare the VMBS not sure why if i had moved it to the suggested location as such if (misc->is_piix4) { } else { } if (vmbus_bridge) { aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); aml_append(dsdt, sb_scope); } Windows would BSOD right away with ACPI error. Same goes for declaring it before PCI0 device... -- Jon.
Re: [PATCH v3 2/3] i386: acpi: vmbus: Add _ADR definition
On 23/06/2020, Igor Mammedov wrote: On Thu, 18 Jun 2020 06:00:26 +0300 Jon Doron wrote: It seems like latest HyperV sets _ADR to 0 in the ACPI for the VMBS that's a hardly a good reason to add this. To me looks like a pointless addition, _ADR mostly is used when device resides on a bus with standard ennumeration algorithm (i.e. PCI, ...). Value is also wrong for the bus it's placed currently, and with the next patch it won't make a sense altogether. Pls, drop this patch unless Windows refuses to work without it. Windows seems to handle fine without this. Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 91af0d2d0d..6d9df38e31 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1061,6 +1061,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) dev = aml_device("VMBS"); aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_ADR", aml_int(0x0))); aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS")));
[PATCH v3 3/3] acpi: i386: Move VMBus DSDT entry to SB
Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6d9df38e31..38be9e5a58 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1092,7 +1092,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); -VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1113,10 +1112,6 @@ static void build_isa_devices_aml(Aml *table) isa_build_aml(ISA_BUS(obj), scope); } -if (vmbus_bridge) { -aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); -} - aml_append(table, scope); } @@ -1661,6 +1656,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1675,6 +1671,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); @@ -1692,6 +1691,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); -- 2.24.1
[PATCH v3 1/3] hyperv: vmbus: Remove the 2nd IRQ
It seems like Windows does not really require 2 IRQs to have a functioning VMBus. Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c| 3 +-- hw/i386/acpi-build.c | 4 +--- include/hw/hyperv/vmbus-bridge.h | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index f371240176..a8bcb41026 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2741,8 +2741,7 @@ static const VMStateDescription vmstate_vmbus_bridge = { }; static Property vmbus_bridge_props[] = { -DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), -DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), +DEFINE_PROP_UINT8("irq", VMBusBridge, irq, 7), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 900f786d08..91af0d2d0d 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1082,9 +1082,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); crs = aml_resource_template(); -aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); -/* FIXME: newer HyperV gets by with only one IRQ */ -aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq)); aml_append(dev, aml_name_decl("_CRS", crs)); return dev; diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index c0a06d832c..33f93de64d 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -19,8 +19,7 @@ typedef struct VMBus VMBus; typedef struct VMBusBridge { SysBusDevice parent_obj; -uint8_t irq0; -uint8_t irq1; +uint8_t irq; VMBus *bus; } VMBusBridge; -- 2.24.1
[PATCH v3 2/3] i386: acpi: vmbus: Add _ADR definition
It seems like latest HyperV sets _ADR to 0 in the ACPI for the VMBS Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 91af0d2d0d..6d9df38e31 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1061,6 +1061,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) dev = aml_device("VMBS"); aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_ADR", aml_int(0x0))); aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); -- 2.24.1
[PATCH v3 0/3] hyperv: vmbus: ACPI various corrections
After doing further tests and looking at the latest HyperV ACPI DSDT. Do minor fix to our VMBus ACPI entry. v3: Removed accidental change for the dct submodule head v2: Renamed irq0 to irq now that there is a single IRQ required Jon Doron (3): hyperv: vmbus: Remove the 2nd IRQ i386: acpi: vmbus: Add _ADR definition acpi: i386: Move VMBus DSDT entry to SB hw/hyperv/vmbus.c| 3 +-- hw/i386/acpi-build.c | 17 + include/hw/hyperv/vmbus-bridge.h | 3 +-- 3 files changed, 11 insertions(+), 12 deletions(-) -- 2.24.1
[PATCH v2 3/3] acpi: i386: Move VMBus DSDT entry to SB
Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6d9df38e31..38be9e5a58 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1092,7 +1092,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); -VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1113,10 +1112,6 @@ static void build_isa_devices_aml(Aml *table) isa_build_aml(ISA_BUS(obj), scope); } -if (vmbus_bridge) { -aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); -} - aml_append(table, scope); } @@ -1661,6 +1656,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1675,6 +1671,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); @@ -1692,6 +1691,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); -- 2.24.1
[PATCH v2 2/3] i386: acpi: vmbus: Add _ADR definition
It seems like latest HyperV sets _ADR to 0 in the ACPI for the VMBS Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 91af0d2d0d..6d9df38e31 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1061,6 +1061,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) dev = aml_device("VMBS"); aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_ADR", aml_int(0x0))); aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); -- 2.24.1
[PATCH v2 1/3] hyperv: vmbus: Remove the 2nd IRQ
It seems like Windows does not really require 2 IRQs to have a functioning VMBus. Signed-off-by: Jon Doron --- dtc | 2 +- hw/hyperv/vmbus.c| 3 +-- hw/i386/acpi-build.c | 4 +--- include/hw/hyperv/vmbus-bridge.h | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/dtc b/dtc index 85e5d83984..88f18909db 16 --- a/dtc +++ b/dtc @@ -1 +1 @@ -Subproject commit 85e5d839847af54efab170f2b1331b2a6421e647 +Subproject commit 88f18909db731a627456f26d779445f84e449536 diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index f371240176..a8bcb41026 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2741,8 +2741,7 @@ static const VMStateDescription vmstate_vmbus_bridge = { }; static Property vmbus_bridge_props[] = { -DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), -DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), +DEFINE_PROP_UINT8("irq", VMBusBridge, irq, 7), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 900f786d08..91af0d2d0d 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1082,9 +1082,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); crs = aml_resource_template(); -aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); -/* FIXME: newer HyperV gets by with only one IRQ */ -aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq)); aml_append(dev, aml_name_decl("_CRS", crs)); return dev; diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index c0a06d832c..33f93de64d 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -19,8 +19,7 @@ typedef struct VMBus VMBus; typedef struct VMBusBridge { SysBusDevice parent_obj; -uint8_t irq0; -uint8_t irq1; +uint8_t irq; VMBus *bus; } VMBusBridge; -- 2.24.1
[PATCH v2 0/3] hyperv: vmbus: ACPI various corrections
After doing further tests and looking at the latest HyperV ACPI DSDT. Do minor fix to our VMBus ACPI entry. v2: Renamed irq0 to irq now that there is a single IRQ required Jon Doron (3): hyperv: vmbus: Remove the 2nd IRQ i386: acpi: vmbus: Add _ADR definition acpi: i386: Move VMBus DSDT entry to SB dtc | 2 +- hw/hyperv/vmbus.c| 3 +-- hw/i386/acpi-build.c | 17 + include/hw/hyperv/vmbus-bridge.h | 3 +-- 4 files changed, 12 insertions(+), 13 deletions(-) -- 2.24.1
[PATCH v1 3/3] acpi: i386: Move VMBus DSDT entry to SB
Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 508f5d9dd7..2c97358d5b 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1092,7 +1092,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); -VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1113,10 +1112,6 @@ static void build_isa_devices_aml(Aml *table) isa_build_aml(ISA_BUS(obj), scope); } -if (vmbus_bridge) { -aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); -} - aml_append(table, scope); } @@ -1661,6 +1656,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, PCIBus *bus = NULL; TPMIf *tpm = tpm_find(); int i; +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); dsdt = init_aml_allocator(); @@ -1675,6 +1671,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); @@ -1692,6 +1691,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(dev, build_q35_osc_method()); aml_append(sb_scope, dev); +if (vmbus_bridge) { +aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); +} aml_append(dsdt, sb_scope); build_hpet_aml(dsdt); -- 2.24.1
[PATCH v1 2/3] i386: acpi: vmbus: Add _ADR definition
It seems like latest HyperV sets _ADR to 0 in the ACPI for the VMBS Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index dce680e97c..508f5d9dd7 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1061,6 +1061,7 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) dev = aml_device("VMBS"); aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_ADR", aml_int(0x0))); aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); -- 2.24.1
[PATCH v1 0/3] hyperv: vmbus: ACPI various corrections
After doing further tests and looking at the latest HyperV ACPI DSDT. Do minor fix to our VMBus ACPI entry. Jon Doron (3): hyperv: vmbus: Remove the 2nd IRQ i386: acpi: vmbus: Add _ADR definition acpi: i386: Move VMBus DSDT entry to SB hw/hyperv/vmbus.c| 1 - hw/i386/acpi-build.c | 15 --- include/hw/hyperv/vmbus-bridge.h | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) -- 2.24.1
[PATCH v1 1/3] hyperv: vmbus: Remove the 2nd IRQ
It seems like Windows does not really require 2 IRQs to have a functioning VMBus. Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c| 1 - hw/i386/acpi-build.c | 2 -- include/hw/hyperv/vmbus-bridge.h | 1 - 3 files changed, 4 deletions(-) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index f371240176..1a3738a03b 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2742,7 +2742,6 @@ static const VMStateDescription vmstate_vmbus_bridge = { static Property vmbus_bridge_props[] = { DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), -DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 900f786d08..dce680e97c 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1083,8 +1083,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) crs = aml_resource_template(); aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); -/* FIXME: newer HyperV gets by with only one IRQ */ -aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); aml_append(dev, aml_name_decl("_CRS", crs)); return dev; diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index c0a06d832c..0369dabc03 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -20,7 +20,6 @@ typedef struct VMBusBridge { SysBusDevice parent_obj; uint8_t irq0; -uint8_t irq1; VMBus *bus; } VMBusBridge; -- 2.24.1
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 14/06/2020, Maciej S. Szmigiero wrote: Hi Jon, On 14.06.2020 16:11, Jon Doron wrote: On 28/05/2020, Jon Doron wrote: On 28/05/2020, Igor Mammedov wrote: On Thu, 28 May 2020 08:26:42 +0300 Jon Doron wrote: On 22/05/2020, Igor Mammedow wrote: On Thu, 21 May 2020 18:02:07 +0200 Paolo Bonzini wrote: On 13/05/20 17:34, Igor Mammedov wrote: > I'd rather avoid using random IRQ numbers (considering we are > dealing with black-box here). So if it's really necessary to have > IRQ described here, I'd suggest to implement them in device model > so they would be reserved and QEMU would error out in a sane way if > IRQ conflict is detected. We don't generally detect ISA IRQ conflicts though, do we? that I don't know that's why I'm not suggesting how to do it. The point is hard-coding in AML random IRQs is not right thing to do, (especially with the lack of 'any' spec), as minimum AML should pull it from device model and that probably should be configurable and set by board. Other thing is: I haven't looked at VMBus device model in detail, but DSDT part aren't matching device though (device model is not ISA device hence AML part shouldn't be on in ISA scope), where to put it is open question. There were other issues with AML code, I've commented on, so I was waiting on respin with comments addressed. I don't think that this patch is good enough for merging. But it seems like the current patch does match what's Microsoft HyperV is publishing in it's APCI tables. I dont think it's correct for us to "fix" Microsoft emulation even if it's wrong, since that's what Windows probably expects to see... I tried looking where Microsoft uses the ACPI tables to identify the VMBus but without much luck in order to understand how flexible a change would be for the OS to still detect the VMBus device, but in general I think "correcting" something that is emulated 1:1 because there is no spec is the right way. I'd agree, if removing nonsense would break VMBus detection (does it?). if something is that doesn't make sense but has to stay because it is need to make windows happy, that's fine , just add annotate is with comment, so it won't confuse anyone why that code exists there later on. I suggest to: 1. try dropping _PS* & _STA as it doesn't actually does anything and _PS3 is plain wrong 2. drop one IRQ, newer hyper-v seems to be doing fine with only one 3. it's not ISA device, I'd suggest to move into _SB scope 4. I don't know much about IRQs but git grep DEFINE_PROP_ | grep -i iqr yields nothing so I'm not sure if it's acceptable. Typically it's board that assigns IRQ and not device, for Sysbus devices (see: sysbus_init_irq/sysbus_connect_irq). So I'd leave it upto Paolo or someone else to decide/comment on. Sounds like a plan, I'll try to come up with the test results (at least for Windows 10 guest which is what I have setup) and update this thread with the results. -- Jon. Paolo Hi guys, Sorry for the delay... So first ill clarify what was the test, the test was to see the device "Microsoft Hyper-V Virtual Machine Bus" in Windows Device Manager under "System devices" with a state of "working properly". It seems like it's ok to drop all the _PS* and _STA. It seems to be functioning with single IRQ as well, it is worth noting that even when i dropped the entire _CRS (so no IRQs resources are required, the device was still showing that it's functioning, but I suspect this might affect the child devices like hv-net and hv-scsi). I guess you tested a single Windows version, correct? It may be that requirements differ between Windows versions, just as you say below about the required enlightenments. Yes I have tested only a single version, but from the looks of it there is only a single IRQ in the HyperV APCI table that I have looked at, and I believe the one you have pasted as well in the past, so that change sounds reasonable to me. As for the enlightenments dont you prefer to have all those as mandatory for VMBus in order not to run into the issue I have encountered? With that said I did run into a small issue I set-up Win10 1903 (aka 19H1) and it seems like VMBus now requires to have the following features enabled: HV_VP_RUNTIME_AVAILABLE HV_TIME_REF_COUNT_AVAILABLE HV_SYNIC_AVAILABLE HV_SYNTIMERS_AVAILABLE HV_APIC_ACCESS_AVAILABLE HV_HYPERCALL_AVAILABLE HV_VP_INDEX_AVAILABLE So notice that previously only SYNIC and VPINDEX was needed, now you need the whole thing so you need to run qemu with something like -cpu host,hv-relaxed,hv_spinlocks=0x1fff,hv_time,hv-vapic,hv-vpindex,hv-synic,hv-runtime,hv-stimer The validation was done in winhv!WinHvpCheckPartitionPrivileges . Paolo I noticed you have done a PULL reques
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 14/06/2020, Jon Doron wrote: On 28/05/2020, Jon Doron wrote: On 28/05/2020, Igor Mammedov wrote: On Thu, 28 May 2020 08:26:42 +0300 Jon Doron wrote: On 22/05/2020, Igor Mammedow wrote: On Thu, 21 May 2020 18:02:07 +0200 Paolo Bonzini wrote: On 13/05/20 17:34, Igor Mammedov wrote: I'd rather avoid using random IRQ numbers (considering we are dealing with black-box here). So if it's really necessary to have IRQ described here, I'd suggest to implement them in device model so they would be reserved and QEMU would error out in a sane way if IRQ conflict is detected. We don't generally detect ISA IRQ conflicts though, do we? that I don't know that's why I'm not suggesting how to do it. The point is hard-coding in AML random IRQs is not right thing to do, (especially with the lack of 'any' spec), as minimum AML should pull it from device model and that probably should be configurable and set by board. Other thing is: I haven't looked at VMBus device model in detail, but DSDT part aren't matching device though (device model is not ISA device hence AML part shouldn't be on in ISA scope), where to put it is open question. There were other issues with AML code, I've commented on, so I was waiting on respin with comments addressed. I don't think that this patch is good enough for merging. But it seems like the current patch does match what's Microsoft HyperV is publishing in it's APCI tables. I dont think it's correct for us to "fix" Microsoft emulation even if it's wrong, since that's what Windows probably expects to see... I tried looking where Microsoft uses the ACPI tables to identify the VMBus but without much luck in order to understand how flexible a change would be for the OS to still detect the VMBus device, but in general I think "correcting" something that is emulated 1:1 because there is no spec is the right way. I'd agree, if removing nonsense would break VMBus detection (does it?). if something is that doesn't make sense but has to stay because it is need to make windows happy, that's fine , just add annotate is with comment, so it won't confuse anyone why that code exists there later on. I suggest to: 1. try dropping _PS* & _STA as it doesn't actually does anything and _PS3 is plain wrong 2. drop one IRQ, newer hyper-v seems to be doing fine with only one 3. it's not ISA device, I'd suggest to move into _SB scope 4. I don't know much about IRQs but git grep DEFINE_PROP_ | grep -i iqr yields nothing so I'm not sure if it's acceptable. Typically it's board that assigns IRQ and not device, for Sysbus devices (see: sysbus_init_irq/sysbus_connect_irq). So I'd leave it upto Paolo or someone else to decide/comment on. Sounds like a plan, I'll try to come up with the test results (at least for Windows 10 guest which is what I have setup) and update this thread with the results. -- Jon. Paolo Hi guys, Sorry for the delay... So first ill clarify what was the test, the test was to see the device "Microsoft Hyper-V Virtual Machine Bus" in Windows Device Manager under "System devices" with a state of "working properly". It seems like it's ok to drop all the _PS* and _STA. It seems to be functioning with single IRQ as well, it is worth noting that even when i dropped the entire _CRS (so no IRQs resources are required, the device was still showing that it's functioning, but I suspect this might affect the child devices like hv-net and hv-scsi). With that said I did run into a small issue I set-up Win10 1903 (aka 19H1) and it seems like VMBus now requires to have the following features enabled: HV_VP_RUNTIME_AVAILABLE HV_TIME_REF_COUNT_AVAILABLE HV_SYNIC_AVAILABLE HV_SYNTIMERS_AVAILABLE HV_APIC_ACCESS_AVAILABLE HV_HYPERCALL_AVAILABLE HV_VP_INDEX_AVAILABLE So notice that previously only SYNIC and VPINDEX was needed, now you need the whole thing so you need to run qemu with something like -cpu host,hv-relaxed,hv_spinlocks=0x1fff,hv_time,hv-vapic,hv-vpindex,hv-synic,hv-runtime,hv-stimer The validation was done in winhv!WinHvpCheckPartitionPrivileges . Paolo I noticed you have done a PULL request, would you like to wait on it and we will submit a version with a single IRQ (selectable by user property) and go with Igor's suggestion dropping _PS* and _STA (though like I said before I prefer to mimic the original HyperV with it's bugs, but I'll leave this decision to you). Also today VMBus only verifies SYNIC is enabled I'm not sure how but I wonder if we want to some how exports from the CPU which other HV features are enabled so we can verify all the required ones are set, would appreciate if you have any suggestions here. Cheers, -- Jon. I got the latest DSDT from one of the latest builds 19041
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 28/05/2020, Jon Doron wrote: On 28/05/2020, Igor Mammedov wrote: On Thu, 28 May 2020 08:26:42 +0300 Jon Doron wrote: On 22/05/2020, Igor Mammedow wrote: On Thu, 21 May 2020 18:02:07 +0200 Paolo Bonzini wrote: On 13/05/20 17:34, Igor Mammedov wrote: > I'd rather avoid using random IRQ numbers (considering we are > dealing with black-box here). So if it's really necessary to have > IRQ described here, I'd suggest to implement them in device model > so they would be reserved and QEMU would error out in a sane way if > IRQ conflict is detected. We don't generally detect ISA IRQ conflicts though, do we? that I don't know that's why I'm not suggesting how to do it. The point is hard-coding in AML random IRQs is not right thing to do, (especially with the lack of 'any' spec), as minimum AML should pull it from device model and that probably should be configurable and set by board. Other thing is: I haven't looked at VMBus device model in detail, but DSDT part aren't matching device though (device model is not ISA device hence AML part shouldn't be on in ISA scope), where to put it is open question. There were other issues with AML code, I've commented on, so I was waiting on respin with comments addressed. I don't think that this patch is good enough for merging. But it seems like the current patch does match what's Microsoft HyperV is publishing in it's APCI tables. I dont think it's correct for us to "fix" Microsoft emulation even if it's wrong, since that's what Windows probably expects to see... I tried looking where Microsoft uses the ACPI tables to identify the VMBus but without much luck in order to understand how flexible a change would be for the OS to still detect the VMBus device, but in general I think "correcting" something that is emulated 1:1 because there is no spec is the right way. I'd agree, if removing nonsense would break VMBus detection (does it?). if something is that doesn't make sense but has to stay because it is need to make windows happy, that's fine , just add annotate is with comment, so it won't confuse anyone why that code exists there later on. I suggest to: 1. try dropping _PS* & _STA as it doesn't actually does anything and _PS3 is plain wrong 2. drop one IRQ, newer hyper-v seems to be doing fine with only one 3. it's not ISA device, I'd suggest to move into _SB scope 4. I don't know much about IRQs but git grep DEFINE_PROP_ | grep -i iqr yields nothing so I'm not sure if it's acceptable. Typically it's board that assigns IRQ and not device, for Sysbus devices (see: sysbus_init_irq/sysbus_connect_irq). So I'd leave it upto Paolo or someone else to decide/comment on. Sounds like a plan, I'll try to come up with the test results (at least for Windows 10 guest which is what I have setup) and update this thread with the results. -- Jon. Paolo Hi guys, Sorry for the delay... So first ill clarify what was the test, the test was to see the device "Microsoft Hyper-V Virtual Machine Bus" in Windows Device Manager under "System devices" with a state of "working properly". It seems like it's ok to drop all the _PS* and _STA. It seems to be functioning with single IRQ as well, it is worth noting that even when i dropped the entire _CRS (so no IRQs resources are required, the device was still showing that it's functioning, but I suspect this might affect the child devices like hv-net and hv-scsi). With that said I did run into a small issue I set-up Win10 1903 (aka 19H1) and it seems like VMBus now requires to have the following features enabled: HV_VP_RUNTIME_AVAILABLE HV_TIME_REF_COUNT_AVAILABLE HV_SYNIC_AVAILABLE HV_SYNTIMERS_AVAILABLE HV_APIC_ACCESS_AVAILABLE HV_HYPERCALL_AVAILABLE HV_VP_INDEX_AVAILABLE So notice that previously only SYNIC and VPINDEX was needed, now you need the whole thing so you need to run qemu with something like -cpu host,hv-relaxed,hv_spinlocks=0x1fff,hv_time,hv-vapic,hv-vpindex,hv-synic,hv-runtime,hv-stimer The validation was done in winhv!WinHvpCheckPartitionPrivileges . Paolo I noticed you have done a PULL request, would you like to wait on it and we will submit a version with a single IRQ (selectable by user property) and go with Igor's suggestion dropping _PS* and _STA (though like I said before I prefer to mimic the original HyperV with it's bugs, but I'll leave this decision to you). Also today VMBus only verifies SYNIC is enabled I'm not sure how but I wonder if we want to some how exports from the CPU which other HV features are enabled so we can verify all the required ones are set, would appreciate if you have any suggestions here. Cheers, -- Jon.
[v1] docs: Add to gdbstub documentation the PhyMemMode
The PhyMemMode gdb extension command was missing from the gdb.rst document. Signed-off-by: Jon Doron --- docs/system/gdb.rst | 20 1 file changed, 20 insertions(+) diff --git a/docs/system/gdb.rst b/docs/system/gdb.rst index a40145fcf8..abda961e2b 100644 --- a/docs/system/gdb.rst +++ b/docs/system/gdb.rst @@ -87,3 +87,23 @@ three commands you can query and set the single step behavior: (gdb) maintenance packet Qqemu.sstep=0x5 sending: "qemu.sstep=0x5" received: "OK" + + +Another feature that QEMU gdbstub provides is to toggle the memory GDB +works with, by default GDB will show the current process memory respecting +the virtual address translation. + +If you want to examine/change the physical memory you can set the gdbstub +to work with the physical memory rather with the virtual one. + +The memory mode can be checked by sending the following command: + +``maintenance packet qqemu.PhyMemMode`` +This will return either 0 or 1, 1 indicates you are currently in the +physical memory mode. + +``maintenance packet Qqemu.PhyMemMode:1`` +This will change the memory mode to physical memory. + +``maintenance packet Qqemu.PhyMemMode:0`` +This will change it back to normal memory mode. -- 2.25.1
Re: [PATCH-for-5.0] gdbstub: Use correct address space with Qqemu.PhyMemMode packet
On 01/06/2020, Alex Bennée wrote: Jon Doron writes: On 31/05/2020, Peter Maydell wrote: On Sun, 31 May 2020 at 17:42, Jon Doron wrote: On 31/05/2020, Philippe Mathieu-Daudé wrote: >On 3/30/20 6:41 PM, Peter Maydell wrote: >> PS: do we have any documentation of this new command ? >> ab4752ec8d9 has the implementation but no documentation... > >Jon, do you have documentation on the Qqemu.PhyMemMode packet? Hi, there is no documentation for this mode, but in general the idea was very simple. I want to have GDB the option to see the physical memory and examine it and have this option toggled. This was useful to me when I was working on nested virtual machine and I wanted to examine different states of the VMCS12 and EPTs. I used this in the following commands: // Enable maint packet Qqemu.PhyMemMode:1 // Disable maint packet Qqemu.PhyMemMode:0 docs/system/gdb.rst would be the place to document QEMU-specific extensions to the gdb protocol (there's an "advanced debugging options" section where we document things like the single-step stuff you can also change via 'maint packet'). thanks -- PMM Thanks, I'll know for next time, when I did all that work and re-factored gdbstub, that doc did not exist. The documentation existed in our old texinfo docs, however they have been recently updated to rst and are now considerably easier to find and hack on now. Perhaps Peter can just add the documentation to this commit? Please don't impose extra burden on our overworked maintainer when he's already given review feedback. Generally maintainers have more work to do than time to do it in so the easiest way to expedite patches with features you want added is to send well formed complete patches which can be easily merged. Otherwise patches tend to end up deep in a pile of "must get around to that when I can". -- Alex Bennée No problem, I'll revise a patch to the rst and send it. Thanks, -- Jon.
Re: [PATCH-for-5.0] gdbstub: Use correct address space with Qqemu.PhyMemMode packet
On 31/05/2020, Peter Maydell wrote: On Sun, 31 May 2020 at 17:42, Jon Doron wrote: On 31/05/2020, Philippe Mathieu-Daudé wrote: >On 3/30/20 6:41 PM, Peter Maydell wrote: >> PS: do we have any documentation of this new command ? >> ab4752ec8d9 has the implementation but no documentation... > >Jon, do you have documentation on the Qqemu.PhyMemMode packet? Hi, there is no documentation for this mode, but in general the idea was very simple. I want to have GDB the option to see the physical memory and examine it and have this option toggled. This was useful to me when I was working on nested virtual machine and I wanted to examine different states of the VMCS12 and EPTs. I used this in the following commands: // Enable maint packet Qqemu.PhyMemMode:1 // Disable maint packet Qqemu.PhyMemMode:0 docs/system/gdb.rst would be the place to document QEMU-specific extensions to the gdb protocol (there's an "advanced debugging options" section where we document things like the single-step stuff you can also change via 'maint packet'). thanks -- PMM Thanks, I'll know for next time, when I did all that work and re-factored gdbstub, that doc did not exist. Perhaps Peter can just add the documentation to this commit? -- Jon.
Re: [PATCH-for-5.0] gdbstub: Use correct address space with Qqemu.PhyMemMode packet
On 31/05/2020, Philippe Mathieu-Daudé wrote: On 3/30/20 6:41 PM, Peter Maydell wrote: On Mon, 30 Mar 2020 at 17:21, Philippe Mathieu-Daudé wrote: On 3/30/20 6:08 PM, Peter Maydell wrote: On Mon, 30 Mar 2020 at 16:30, Philippe Mathieu-Daudé wrote: Since commit 3f940dc98, we added support for vAttach packet to select a particular thread/cpu/core. However when using the GDB physical memory mode, it is not clear which CPU address space is used. Since the CPU address space is stored in CPUState::as, use address_space_rw() instead of cpu_physical_memory_rw(). Fixes: ab4752ec8d9 Signed-off-by: Philippe Mathieu-Daudé --- gdbstub.c | 7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 013fb1ac0f..3baaef50e3 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -69,11 +69,8 @@ static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr, #ifndef CONFIG_USER_ONLY if (phy_memory_mode) { -if (is_write) { -cpu_physical_memory_write(addr, buf, len); -} else { -cpu_physical_memory_read(addr, buf, len); -} +address_space_rw(cpu->as, addr, MEMTXATTRS_UNSPECIFIED, + buf, len, is_write); return 0; There's an argument here for using int asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED); AddressSpace *as = cpu_get_address_space(cpu, asidx); though it will effectively boil down to the same thing in the end as there's no way for the gdbstub to specify whether it wanted eg the Arm secure or non-secure physical address space. https://static.docs.arm.com/ihi0074/a/debug_interface_v6_0_architecture_specification_IHI0074A.pdf * Configuration of hypervisor noninvasive debug. This field can have one of the following values: - 0b00 Separate controls for hypervisor noninvasive debug are not implemented, or no hypervisor is implemented. For ARMv7 PEs that implement the Virtualization Extensions, and for ARMv8 PEs that implement EL2, if separate controls for hypervisor debug visibility are not implemented, the hypervisor debug visibility is indicated by the relevant Non-secure debug visibility fields NSNID and NSID. OK so for ARM "noninvasive debug is not implemented" and we would use the core secure address space? I'm not very familiar with the debug interface (we don't model it in QEMU), but I think that is the wrong end of it. These are bits in AUTHSTATUS, which is a read-only register provided by the CPU to the debugger. It basically says "am I, the CPU, going to permit you, the debugger, to debug code running in secure mode, or in EL2". (The CPU gets to decide this: for security some h/w will not want any random with access to the jtag debug port to be able to just read out code from the secure world, for instance.) What the debugger gets to control is bits in the CSW register in the "MEM-AP"; it can use these to specify the size of a memory access it wants to make to the guest, and also the 'type', which is IMPDEF but typically lets the debugger say "code access vs data access", "privileged vs usermode" and "secure vs non-secure". The equivalent in the QEMU world is that the debugger can specify the memory transaction attributes. The question is whether the gdb protocol provides any equivalent of that: if it doesn't then gdbstub.c has to make up an attribute and use that. Instead of MEMTXATTRS_UNSPECIFIED I should use a crafted MemTxAttrs with .secure = 1, .unspecified = 1? You shouldn't set 'unspecified = 1', because that indicates "this is MEMTXATTRS_UNSPECIFIED". The default set of unspecified-attributes are probably good enough, though, so you can just use MEMTXATTRS_UNSPECIFIED. The idea of this command is to use the CPU AS but not the MMU/MPU, maybe it doesn't make sense... The trouble is that the command isn't precise enough. "read/write to physical memory" is fine if the CPU has exactly one physical address space, but it's ambiguous if the CPU has more than one physical address space. Either we need the user to be able to tell us which one they wanted somehow (which for QEMU more or less means that they should tell us what tx attributes they wanted), or we need to make an arbitrary decision. PS: do we have any documentation of this new command ? ab4752ec8d9 has the implementation but no documentation... Jon, do you have documentation on the Qqemu.PhyMemMode packet? thanks -- PMM Hi, there is no documentation for this mode, but in general the idea was very simple. I want to have GDB the option to see the physical memory and examine it and have this option toggled. This was useful to me when I was working on nested virtual machine and I wanted to examine different states of the VMCS12 and EPTs. I used this in the following commands: // Enable maint packet Qqemu.PhyMemMode:1 // Disable maint packet Qqemu.PhyMemMode:0 It was mostly used part of a GDB script I played with to help me find the VMCS12 and EPTs. The
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 28/05/2020, Igor Mammedov wrote: On Thu, 28 May 2020 08:26:42 +0300 Jon Doron wrote: On 22/05/2020, Igor Mammedow wrote: >On Thu, 21 May 2020 18:02:07 +0200 >Paolo Bonzini wrote: > >> On 13/05/20 17:34, Igor Mammedov wrote: >> > I'd rather avoid using random IRQ numbers (considering we are >> > dealing with black-box here). So if it's really necessary to have >> > IRQ described here, I'd suggest to implement them in device model >> > so they would be reserved and QEMU would error out in a sane way if >> > IRQ conflict is detected. >> >> We don't generally detect ISA IRQ conflicts though, do we? > >that I don't know that's why I'm not suggesting how to do it. >The point is hard-coding in AML random IRQs is not right thing to do, >(especially with the lack of 'any' spec), as minimum AML should pull >it from device model and that probably should be configurable and set >by board. > >Other thing is: >I haven't looked at VMBus device model in detail, but DSDT part aren't >matching device though (device model is not ISA device hence AML part >shouldn't be on in ISA scope), where to put it is open question. >There were other issues with AML code, I've commented on, so I was >waiting on respin with comments addressed. >I don't think that this patch is good enough for merging. > > But it seems like the current patch does match what's Microsoft HyperV is publishing in it's APCI tables. I dont think it's correct for us to "fix" Microsoft emulation even if it's wrong, since that's what Windows probably expects to see... I tried looking where Microsoft uses the ACPI tables to identify the VMBus but without much luck in order to understand how flexible a change would be for the OS to still detect the VMBus device, but in general I think "correcting" something that is emulated 1:1 because there is no spec is the right way. I'd agree, if removing nonsense would break VMBus detection (does it?). if something is that doesn't make sense but has to stay because it is need to make windows happy, that's fine , just add annotate is with comment, so it won't confuse anyone why that code exists there later on. I suggest to: 1. try dropping _PS* & _STA as it doesn't actually does anything and _PS3 is plain wrong 2. drop one IRQ, newer hyper-v seems to be doing fine with only one 3. it's not ISA device, I'd suggest to move into _SB scope 4. I don't know much about IRQs but git grep DEFINE_PROP_ | grep -i iqr yields nothing so I'm not sure if it's acceptable. Typically it's board that assigns IRQ and not device, for Sysbus devices (see: sysbus_init_irq/sysbus_connect_irq). So I'd leave it upto Paolo or someone else to decide/comment on. Sounds like a plan, I'll try to come up with the test results (at least for Windows 10 guest which is what I have setup) and update this thread with the results. -- Jon. >> >> Paolo >> >
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 28/05/2020, Jon Doron wrote: On 22/05/2020, Igor Mammedow wrote: On Thu, 21 May 2020 18:02:07 +0200 Paolo Bonzini wrote: On 13/05/20 17:34, Igor Mammedov wrote: I'd rather avoid using random IRQ numbers (considering we are dealing with black-box here). So if it's really necessary to have IRQ described here, I'd suggest to implement them in device model so they would be reserved and QEMU would error out in a sane way if IRQ conflict is detected. We don't generally detect ISA IRQ conflicts though, do we? that I don't know that's why I'm not suggesting how to do it. The point is hard-coding in AML random IRQs is not right thing to do, (especially with the lack of 'any' spec), as minimum AML should pull it from device model and that probably should be configurable and set by board. Other thing is: I haven't looked at VMBus device model in detail, but DSDT part aren't matching device though (device model is not ISA device hence AML part shouldn't be on in ISA scope), where to put it is open question. There were other issues with AML code, I've commented on, so I was waiting on respin with comments addressed. I don't think that this patch is good enough for merging. But it seems like the current patch does match what's Microsoft HyperV is publishing in it's APCI tables. I dont think it's correct for us to "fix" Microsoft emulation even if it's wrong, since that's what Windows probably expects to see... I tried looking where Microsoft uses the ACPI tables to identify the VMBus but without much luck in order to understand how flexible a change would be for the OS to still detect the VMBus device, but in general I think "correcting" something that is emulated 1:1 because there is no spec is the right way. Bah sorry meant to say: In general correcting some virtual emulated device which is current is matching 1:1 is wrong, I think the right way to handle this type of things is to copy them 1:1 and not try to "fix" or "correct" them since that's what Windows expects. Paolo
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 22/05/2020, Igor Mammedow wrote: On Thu, 21 May 2020 18:02:07 +0200 Paolo Bonzini wrote: On 13/05/20 17:34, Igor Mammedov wrote: > I'd rather avoid using random IRQ numbers (considering we are > dealing with black-box here). So if it's really necessary to have > IRQ described here, I'd suggest to implement them in device model > so they would be reserved and QEMU would error out in a sane way if > IRQ conflict is detected. We don't generally detect ISA IRQ conflicts though, do we? that I don't know that's why I'm not suggesting how to do it. The point is hard-coding in AML random IRQs is not right thing to do, (especially with the lack of 'any' spec), as minimum AML should pull it from device model and that probably should be configurable and set by board. Other thing is: I haven't looked at VMBus device model in detail, but DSDT part aren't matching device though (device model is not ISA device hence AML part shouldn't be on in ISA scope), where to put it is open question. There were other issues with AML code, I've commented on, so I was waiting on respin with comments addressed. I don't think that this patch is good enough for merging. But it seems like the current patch does match what's Microsoft HyperV is publishing in it's APCI tables. I dont think it's correct for us to "fix" Microsoft emulation even if it's wrong, since that's what Windows probably expects to see... I tried looking where Microsoft uses the ACPI tables to identify the VMBus but without much luck in order to understand how flexible a change would be for the OS to still detect the VMBus device, but in general I think "correcting" something that is emulated 1:1 because there is no spec is the right way. Paolo
Re: [PATCH v4 0/6] hyperv: VMBus implementation
On 21/05/2020, Paolo Bonzini wrote: On 24/04/20 14:34, Jon Doron wrote: This is a rebase of the old patchset from Roman for HyperV VMBus implementation. How to use: -device vmbus-bridge Later on new paravirtualized devices can be implemented on top of it (Network/SCSI/etc.) VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. v4: Decided to ditch the patch that envolves handling of EOM as there is still a discussion going on with it in the KVM mailing list. v3: Fixed an error asan v2: Rebased on top of latest patchset from Roman and Maciej Jon Doron (6): hyperv: expose API to determine if synic is enabled vmbus: add vmbus protocol definitions vmbus: vmbus implementation i386:pc: whitelist dynamic vmbus-bridge i386: Hyper-V VMBus ACPI DSDT entry vmbus: add infrastructure to save/load vmbus requests Makefile.objs|1 + hw/hyperv/Kconfig|5 + hw/hyperv/Makefile.objs |1 + hw/hyperv/hyperv.c |8 + hw/hyperv/trace-events | 18 + hw/hyperv/vmbus.c| 2778 ++ hw/i386/acpi-build.c | 43 + hw/i386/pc_piix.c|2 + hw/i386/pc_q35.c |2 + include/hw/hyperv/hyperv.h |1 + include/hw/hyperv/vmbus-bridge.h | 35 + include/hw/hyperv/vmbus-proto.h | 222 +++ include/hw/hyperv/vmbus.h| 230 +++ 13 files changed, 3346 insertions(+) create mode 100644 hw/hyperv/trace-events create mode 100644 hw/hyperv/vmbus.c create mode 100644 include/hw/hyperv/vmbus-bridge.h create mode 100644 include/hw/hyperv/vmbus-proto.h create mode 100644 include/hw/hyperv/vmbus.h Queued, thanks. I'll take a look at the EOM handling threads next. Paolo Hi Paolo, there is no need to look at the EOM, we have scraped it as you can see in v4 :)
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 13/05/2020, Igor Mammedov wrote: Do you guys know perhaps which module is reading the ACPI configuration for VMBus? vmbus.sys / vmbkmcl.sys / winhv.sys? is it the kernel or HAL? I dont have any real HyperV Windows to play with... Roman, do you remember when is this information being used? Do we need a full emulation setup (aka your hv-scsi / hv-net) patches in order to see Windows working this ACPI entry? Thanks, -- Jon. On Mon, 11 May 2020 23:11:23 +0300 Roman Kagan wrote: On Thu, May 07, 2020 at 06:14:25AM +0300, Jon Doron wrote: > Igor it seems like the IRQ being used is 5 and not 7 & 13 like in the > current patch. HyperV using irq 5 doesn't mean QEMU has to too. Especially so as no guest was noticed to use the irqs in ACPI. I'd rather try and test if the guest requires any those at all. > Seems like it needs to reside in the _CRS like you said. They already are there. > Seems like it has all those _STA/_DIS/_PS0 just like the way it's currently > in the patch (unless I'm missing something). Right, but, as you can see, they are pretty dumb, so the question is whether they are necessary or the guests can do without (Linux apparently can). Agreed with all of above, Instead of blind copying dubious AML, we should try to figure out what's really necessary of it and throw away the rest. Thanks, Roman. > Notice _PS3 is not a Method. > > So just to summarize the changes i need to do: > 1. Change from 2 IRQs to single one (and use 5 as the default) > 2. IRQs needs to be under _CRS. > 3. You mentioned you want under a different location than the ISA bug where > would you want it to be? > > Please let me know if there is anything else. > > Thanks, > -- Jon. > > On 06/05/2020, Maciej S. Szmigiero wrote: > > On 05.05.2020 17:38, Jon Doron wrote: > > > On 05/05/2020, Igor Mammedov wrote: > > > > > > I dont know what were the original intentions of the original patch authors (at this point I simply rebased it, and to be honest I did not need this patch to get where I was going to, but it was part of the original patchset). > > > > > > But I'm willing to do any changes so we can keep going forward with this. > > > > > > > On Fri, 24 Apr 2020 15:34:43 +0300 > > > > Jon Doron wrote: > > > > > > > > > Guest OS uses ACPI to discover VMBus presence. Add a corresponding > > > > > entry to DSDT in case VMBus has been enabled. > > > > > > > > > > Experimentally Windows guests were found to require this entry to > > > > > include two IRQ resources. They seem to never be used but they still > > > > > have to be there. > > > > > > > > > > Make IRQ numbers user-configurable via corresponding properties; use 7 > > > > > and 13 by default. > > > > well, it seems that at least linux guest driver uses one IRQ, > > > > abeit not from ACPI descriptior > > > > > > > > perhaps it's what hyperv host puts into _CRS. > > > > Could you dump ACPI tables and check how hyperv describes vmbus in acpi? > > > > > > > > > > > > > > I can no longer get to the HyperV computer I had (in the office so hopefully if someone else has access to HyperV machine and willing to reply here with the dumped ACPI tables that would be great). > > > > > > > Here is a VMBus ACPI device description from Hyper-V in Windows Server 2019: > > > > Device (\_SB.VMOD.VMBS) > > { > >Name (STA, 0x0F) > >Name (_ADR, Zero) // _ADR: Address > >Name (_DDN, "VMBUS") // _DDN: DOS Device Name > >Name (_HID, "VMBus") // _HID: Hardware ID > >Name (_UID, Zero) // _UID: Unique ID > >Method (_DIS, 0, NotSerialized) // _DIS: Disable Device > >{ > > STA &= 0x0D > >} > > > >Method (_PS0, 0, NotSerialized) // _PS0: Power State 0 > >{ > > STA |= 0x0F > >} > > > >Method (_STA, 0, NotSerialized) // _STA: Status > >{ > > Return (STA) /* \_SB_.VMOD.VMBS.STA_ */ > >} > > > >Name (_PS3, Zero) // _PS3: Power State 3 > >Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings > >{ > > IRQ (Edge, ActiveHigh, Exclusive, ) > > {5} > >}) > > } > > > > It seems to use just IRQ 5. > > > > Maciej >
Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
On 12/05/2020, Jon Doron wrote: On 12/05/2020, Roman Kagan wrote: On Thu, Apr 09, 2020 at 06:35:18AM +0300, Jon Doron wrote: On 08/04/2020, Roman Kagan wrote: On Wed, Apr 08, 2020 at 07:16:39AM +0300, Jon Doron wrote: > Well I have implemented the hyperv synthetic kernel debugger interface, but > on Windows 10 it requires to have a working VMBus (it's not really using it, > but without a function vmbus that will answer to the initiate contact then > the kdnet will simply be stuck in a loop. I tried to google for this interface but the only thing I managed to find was this https://withinrafael.com/2015/02/01/how-to-set-up-synthetic-kernel-debugging-for-hyper-v-virtual-machines/ Is this what you're trying to implement? Are there any more authoritative descriptions of the feature? The document doesn't quite explain the inner workings of the feature, but it looks like the regular network debugging interface, except that IP is forwarded by the hypervisor app, so that the debugger has to connect to the host and avoid setting up full-fledged network connectivity to the guest. That would be essentially hv-net + slirp. OTOH you say it doesn't use VMBus so I'm confused... Thanks, Roman. > In addition to that Michael Kelley from Microsoft has informed us that > Microsoft might be dropped the synthetic kernel debugger interface sometime > in the future, and it seems like the new mode is simply to use hvnet device > for the communication (which is again much faster). Yes that's indeed the interface I have implemented this part of the patch it not full ready for commit, but I think we can keep going with the VMBUS. Based on your previous reply it sounds like there is not a real issue with the current patch of ACPI DSDT entry, right? Thanks, -- Jon. I suggest referring to the KVM patches I have already submitted that Paolo said will probably get in soon. https://patchwork.kernel.org/patch/11507663/
Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
On 12/05/2020, Roman Kagan wrote: On Thu, Apr 09, 2020 at 06:35:18AM +0300, Jon Doron wrote: On 08/04/2020, Roman Kagan wrote: > On Wed, Apr 08, 2020 at 07:16:39AM +0300, Jon Doron wrote: > > Well I have implemented the hyperv synthetic kernel debugger interface, but > > on Windows 10 it requires to have a working VMBus (it's not really using it, > > but without a function vmbus that will answer to the initiate contact then > > the kdnet will simply be stuck in a loop. I tried to google for this interface but the only thing I managed to find was this https://withinrafael.com/2015/02/01/how-to-set-up-synthetic-kernel-debugging-for-hyper-v-virtual-machines/ Is this what you're trying to implement? Are there any more authoritative descriptions of the feature? The document doesn't quite explain the inner workings of the feature, but it looks like the regular network debugging interface, except that IP is forwarded by the hypervisor app, so that the debugger has to connect to the host and avoid setting up full-fledged network connectivity to the guest. That would be essentially hv-net + slirp. OTOH you say it doesn't use VMBus so I'm confused... Thanks, Roman. > > In addition to that Michael Kelley from Microsoft has informed us that > > Microsoft might be dropped the synthetic kernel debugger interface sometime > > in the future, and it seems like the new mode is simply to use hvnet device > > for the communication (which is again much faster). Yes that's indeed the interface I have implemented this part of the patch it not full ready for commit, but I think we can keep going with the VMBUS. Based on your previous reply it sounds like there is not a real issue with the current patch of ACPI DSDT entry, right? Thanks, -- Jon.
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
Thank you Maciej :) Igor it seems like the IRQ being used is 5 and not 7 & 13 like in the current patch. Seems like it needs to reside in the _CRS like you said. Seems like it has all those _STA/_DIS/_PS0 just like the way it's currently in the patch (unless I'm missing something). Notice _PS3 is not a Method. So just to summarize the changes i need to do: 1. Change from 2 IRQs to single one (and use 5 as the default) 2. IRQs needs to be under _CRS. 3. You mentioned you want under a different location than the ISA bug where would you want it to be? Please let me know if there is anything else. Thanks, -- Jon. On 06/05/2020, Maciej S. Szmigiero wrote: On 05.05.2020 17:38, Jon Doron wrote: On 05/05/2020, Igor Mammedov wrote: I dont know what were the original intentions of the original patch authors (at this point I simply rebased it, and to be honest I did not need this patch to get where I was going to, but it was part of the original patchset). But I'm willing to do any changes so we can keep going forward with this. On Fri, 24 Apr 2020 15:34:43 +0300 Jon Doron wrote: Guest OS uses ACPI to discover VMBus presence. Add a corresponding entry to DSDT in case VMBus has been enabled. Experimentally Windows guests were found to require this entry to include two IRQ resources. They seem to never be used but they still have to be there. Make IRQ numbers user-configurable via corresponding properties; use 7 and 13 by default. well, it seems that at least linux guest driver uses one IRQ, abeit not from ACPI descriptior perhaps it's what hyperv host puts into _CRS. Could you dump ACPI tables and check how hyperv describes vmbus in acpi? I can no longer get to the HyperV computer I had (in the office so hopefully if someone else has access to HyperV machine and willing to reply here with the dumped ACPI tables that would be great). Here is a VMBus ACPI device description from Hyper-V in Windows Server 2019: Device (\_SB.VMOD.VMBS) { Name (STA, 0x0F) Name (_ADR, Zero) // _ADR: Address Name (_DDN, "VMBUS") // _DDN: DOS Device Name Name (_HID, "VMBus") // _HID: Hardware ID Name (_UID, Zero) // _UID: Unique ID Method (_DIS, 0, NotSerialized) // _DIS: Disable Device { STA &= 0x0D } Method (_PS0, 0, NotSerialized) // _PS0: Power State 0 { STA |= 0x0F } Method (_STA, 0, NotSerialized) // _STA: Status { Return (STA) /* \_SB_.VMOD.VMBS.STA_ */ } Name (_PS3, Zero) // _PS3: Power State 3 Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { IRQ (Edge, ActiveHigh, Exclusive, ) {5} }) } It seems to use just IRQ 5. Maciej
Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
On 05/05/2020, Igor Mammedov wrote: I dont know what were the original intentions of the original patch authors (at this point I simply rebased it, and to be honest I did not need this patch to get where I was going to, but it was part of the original patchset). But I'm willing to do any changes so we can keep going forward with this. On Fri, 24 Apr 2020 15:34:43 +0300 Jon Doron wrote: Guest OS uses ACPI to discover VMBus presence. Add a corresponding entry to DSDT in case VMBus has been enabled. Experimentally Windows guests were found to require this entry to include two IRQ resources. They seem to never be used but they still have to be there. Make IRQ numbers user-configurable via corresponding properties; use 7 and 13 by default. well, it seems that at least linux guest driver uses one IRQ, abeit not from ACPI descriptior perhaps it's what hyperv host puts into _CRS. Could you dump ACPI tables and check how hyperv describes vmbus in acpi? I can no longer get to the HyperV computer I had (in the office so hopefully if someone else has access to HyperV machine and willing to reply here with the dumped ACPI tables that would be great). also what if vmbus irq collides with an irq that is already taken, it would be better to initialize and consume irqs it climes to use so in case if conflict one would get a error. Sounds right. I tried to see if there is any place in acpi that checks if an IRQ is taken or not but could not find any, can you point me out to a place where it's done? If not then I guess we need a function that iterates through all registered IRQs so we can find if we have a conflict. Probably the best places to put it is where you build the acpi aml, but that would really make the code more complicated (i.e build_append_int_noprefix and aml_interrupt). In case I have not understood you right please let me know. Signed-off-by: Evgeny Yakovlev Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c| 7 ++ hw/i386/acpi-build.c | 43 include/hw/hyperv/vmbus-bridge.h | 3 +++ 3 files changed, 53 insertions(+) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 1f5873ab60..0df7afe0ca 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2641,6 +2641,12 @@ static const VMStateDescription vmstate_vmbus_bridge = { }, }; +static Property vmbus_bridge_props[] = { +DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), +DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), +DEFINE_PROP_END_OF_LIST() +}; + static void vmbus_bridge_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); @@ -2651,6 +2657,7 @@ static void vmbus_bridge_class_init(ObjectClass *klass, void *data) sk->explicit_ofw_unit_address = vmbus_bridge_ofw_unit_address; set_bit(DEVICE_CATEGORY_BRIDGE, k->categories); k->vmsd = &vmstate_vmbus_bridge; +device_class_set_props(k, vmbus_bridge_props); /* override SysBusDevice's default */ k->user_creatable = true; } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2a7e55bae7..d235074fb8 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -50,6 +50,7 @@ #include "hw/mem/nvdimm.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "hw/hyperv/vmbus-bridge.h" /* Supported chipsets: */ #include "hw/southbridge/piix.h" @@ -1270,9 +1271,47 @@ static Aml *build_com_device_aml(uint8_t uid) return dev; } +static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) +{ +Aml *dev; +Aml *method; +Aml *crs; + +dev = aml_device("VMBS"); +aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); +aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); +aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); + +method = aml_method("_DIS", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_and(aml_name("STA"), aml_int(0xD), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_PS0", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_or(aml_name("STA"), aml_int(0xF), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_STA", 0, AML_NOTSERIALIZED); +aml_append(method, aml_return(aml_name("STA"))); +aml_append(dev, method); do you reaaly need all that _STA/_DIS/_PS0, does it work without thouse methods? + +aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); should be method + +
[PATCH v4 6/6] vmbus: add infrastructure to save/load vmbus requests
This can be allow to include controller-specific data while saving/loading in-flight scsi requests of the vmbus scsi controller. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c | 99 +++ include/hw/hyperv/vmbus.h | 3 ++ 2 files changed, 102 insertions(+) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 0df7afe0ca..ab72a59a4a 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -1272,6 +1272,105 @@ void vmbus_free_req(void *req) g_free(req); } +static const VMStateDescription vmstate_sgent = { +.name = "vmbus/sgentry", +.version_id = 0, +.minimum_version_id = 0, +.fields = (VMStateField[]) { +VMSTATE_UINT64(base, ScatterGatherEntry), +VMSTATE_UINT64(len, ScatterGatherEntry), +VMSTATE_END_OF_LIST() +} +}; + +typedef struct VMBusChanReqSave { +uint16_t chan_idx; +uint16_t pkt_type; +uint32_t msglen; +void *msg; +uint64_t transaction_id; +bool need_comp; +uint32_t num; +ScatterGatherEntry *sgl; +} VMBusChanReqSave; + +static const VMStateDescription vmstate_vmbus_chan_req = { +.name = "vmbus/vmbus_chan_req", +.version_id = 0, +.minimum_version_id = 0, +.fields = (VMStateField[]) { +VMSTATE_UINT16(chan_idx, VMBusChanReqSave), +VMSTATE_UINT16(pkt_type, VMBusChanReqSave), +VMSTATE_UINT32(msglen, VMBusChanReqSave), +VMSTATE_VBUFFER_ALLOC_UINT32(msg, VMBusChanReqSave, 0, NULL, msglen), +VMSTATE_UINT64(transaction_id, VMBusChanReqSave), +VMSTATE_BOOL(need_comp, VMBusChanReqSave), +VMSTATE_UINT32(num, VMBusChanReqSave), +VMSTATE_STRUCT_VARRAY_POINTER_UINT32(sgl, VMBusChanReqSave, num, + vmstate_sgent, ScatterGatherEntry), +VMSTATE_END_OF_LIST() +} +}; + +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req) +{ +VMBusChanReqSave req_save; + +req_save.chan_idx = req->chan->subchan_idx; +req_save.pkt_type = req->pkt_type; +req_save.msglen = req->msglen; +req_save.msg = req->msg; +req_save.transaction_id = req->transaction_id; +req_save.need_comp = req->need_comp; +req_save.num = req->sgl.nsg; +req_save.sgl = g_memdup(req->sgl.sg, +req_save.num * sizeof(ScatterGatherEntry)); + +vmstate_save_state(f, &vmstate_vmbus_chan_req, &req_save, NULL); + +g_free(req_save.sgl); +} + +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size) +{ +VMBusChanReqSave req_save; +VMBusChanReq *req = NULL; +VMBusChannel *chan = NULL; +uint32_t i; + +vmstate_load_state(f, &vmstate_vmbus_chan_req, &req_save, 0); + +if (req_save.chan_idx >= dev->num_channels) { +error_report("%s: %u(chan_idx) > %u(num_channels)", __func__, + req_save.chan_idx, dev->num_channels); +goto out; +} +chan = &dev->channels[req_save.chan_idx]; + +if (vmbus_channel_reserve(chan, 0, req_save.msglen)) { +goto out; +} + +req = vmbus_alloc_req(chan, size, req_save.pkt_type, req_save.msglen, + req_save.transaction_id, req_save.need_comp); +if (req_save.msglen) { +memcpy(req->msg, req_save.msg, req_save.msglen); +} + +for (i = 0; i < req_save.num; i++) { +qemu_sglist_add(&req->sgl, req_save.sgl[i].base, req_save.sgl[i].len); +} + +out: +if (req_save.msglen) { +g_free(req_save.msg); +} +if (req_save.num) { +g_free(req_save.sgl); +} +return req; +} + static void channel_event_cb(EventNotifier *e) { VMBusChannel *chan = container_of(e, VMBusChannel, notifier); diff --git a/include/hw/hyperv/vmbus.h b/include/hw/hyperv/vmbus.h index 63a5b807b6..9219f34d6b 100644 --- a/include/hw/hyperv/vmbus.h +++ b/include/hw/hyperv/vmbus.h @@ -224,4 +224,7 @@ int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, unsigned iov_cnt, size_t accessed); +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req); +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size); + #endif -- 2.24.1
[PATCH v4 2/6] vmbus: add vmbus protocol definitions
Add a header with data structures and constants used in Hyper-V VMBus hypervisor <-> guest interactions. Based on the respective stuff from Linux kernel. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- include/hw/hyperv/vmbus-proto.h | 222 1 file changed, 222 insertions(+) create mode 100644 include/hw/hyperv/vmbus-proto.h diff --git a/include/hw/hyperv/vmbus-proto.h b/include/hw/hyperv/vmbus-proto.h new file mode 100644 index 00..4628d3b323 --- /dev/null +++ b/include/hw/hyperv/vmbus-proto.h @@ -0,0 +1,222 @@ +/* + * QEMU Hyper-V VMBus support + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_HYPERV_VMBUS_PROTO_H +#define HW_HYPERV_VMBUS_PROTO_H + +#define VMBUS_VERSION_WS2008((0 << 16) | (13)) +#define VMBUS_VERSION_WIN7 ((1 << 16) | (1)) +#define VMBUS_VERSION_WIN8 ((2 << 16) | (4)) +#define VMBUS_VERSION_WIN8_1((3 << 16) | (0)) +#define VMBUS_VERSION_WIN10 ((4 << 16) | (0)) +#define VMBUS_VERSION_INVAL -1 +#define VMBUS_VERSION_CURRENT VMBUS_VERSION_WIN10 + +#define VMBUS_MESSAGE_CONNECTION_ID 1 +#define VMBUS_EVENT_CONNECTION_ID 2 +#define VMBUS_MONITOR_CONNECTION_ID 3 +#define VMBUS_SINT 2 + +#define VMBUS_MSG_INVALID 0 +#define VMBUS_MSG_OFFERCHANNEL 1 +#define VMBUS_MSG_RESCIND_CHANNELOFFER 2 +#define VMBUS_MSG_REQUESTOFFERS 3 +#define VMBUS_MSG_ALLOFFERS_DELIVERED 4 +#define VMBUS_MSG_OPENCHANNEL 5 +#define VMBUS_MSG_OPENCHANNEL_RESULT6 +#define VMBUS_MSG_CLOSECHANNEL 7 +#define VMBUS_MSG_GPADL_HEADER 8 +#define VMBUS_MSG_GPADL_BODY9 +#define VMBUS_MSG_GPADL_CREATED 10 +#define VMBUS_MSG_GPADL_TEARDOWN11 +#define VMBUS_MSG_GPADL_TORNDOWN12 +#define VMBUS_MSG_RELID_RELEASED13 +#define VMBUS_MSG_INITIATE_CONTACT 14 +#define VMBUS_MSG_VERSION_RESPONSE 15 +#define VMBUS_MSG_UNLOAD16 +#define VMBUS_MSG_UNLOAD_RESPONSE 17 +#define VMBUS_MSG_COUNT 18 + +#define VMBUS_MESSAGE_SIZE_ALIGNsizeof(uint64_t) + +#define VMBUS_PACKET_INVALID0x0 +#define VMBUS_PACKET_SYNCH 0x1 +#define VMBUS_PACKET_ADD_XFER_PAGESET 0x2 +#define VMBUS_PACKET_RM_XFER_PAGESET0x3 +#define VMBUS_PACKET_ESTABLISH_GPADL0x4 +#define VMBUS_PACKET_TEARDOWN_GPADL 0x5 +#define VMBUS_PACKET_DATA_INBAND0x6 +#define VMBUS_PACKET_DATA_USING_XFER_PAGES 0x7 +#define VMBUS_PACKET_DATA_USING_GPADL 0x8 +#define VMBUS_PACKET_DATA_USING_GPA_DIRECT 0x9 +#define VMBUS_PACKET_CANCEL_REQUEST 0xa +#define VMBUS_PACKET_COMP 0xb +#define VMBUS_PACKET_DATA_USING_ADDITIONAL_PKT 0xc +#define VMBUS_PACKET_ADDITIONAL_DATA0xd + +#define VMBUS_CHANNEL_USER_DATA_SIZE120 + +#define VMBUS_OFFER_MONITOR_ALLOCATED 0x1 +#define VMBUS_OFFER_INTERRUPT_DEDICATED 0x1 + +#define VMBUS_RING_BUFFER_FEAT_PENDING_SZ (1ul << 0) + +#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 0x1 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES 0x2 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS 0x4 +#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x10 +#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100 +#define VMBUS_CHANNEL_PARENT_OFFER0x200 +#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400 +#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER0x2000 + +#define VMBUS_PACKET_FLAG_REQUEST_COMPLETION1 + +typedef struct vmbus_message_header { +uint32_t message_type; +uint32_t _padding; +} vmbus_message_header; + +typedef struct vmbus_message_initiate_contact { +vmbus_message_header header; +uint32_t version_requested; +uint32_t target_vcpu; +uint64_t interrupt_page; +uint64_t monitor_page1; +uint64_t monitor_page2; +} vmbus_message_initiate_contact; + +typedef struct vmbus_message_version_response { +vmbus_message_header header; +uint8_t version_supported; +uint8_t status; +} vmbus_message_version_response; + +typedef struct vmbus_message_offer_channel { +vmbus_message_header header; +uint8_t type_uuid[16]; +uint8_t instance_uuid[16]; +uint64_t _reserved1; +uint64_t _reserved2; +uint16_t channel_flags; +uint16_t mmio_size_mb; +uint8_t user_data[VMBUS_CHANNEL_USER_DATA_SIZE]; +uint16_t sub_channel_index; +uint16_t _reserved3; +uint32_t child_relid; +uint8_t monitor_id;
[PATCH v4 3/6] vmbus: vmbus implementation
Add the VMBus infrastructure -- bus, devices, root bridge, vmbus state machine, vmbus channel interactions, etc. VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. TODO: - split into smaller palatable pieces - more comments - check and handle corner cases Kudos to Evgeny Yakovlev (formerly eyakov...@virtuozzo.com) and Andrey Smetatin (formerly asmeta...@virtuozzo.com) for research and prototyping. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- Makefile.objs|1 + hw/hyperv/Kconfig|5 + hw/hyperv/Makefile.objs |1 + hw/hyperv/trace-events | 18 + hw/hyperv/vmbus.c| 2672 ++ include/hw/hyperv/vmbus-bridge.h | 32 + include/hw/hyperv/vmbus.h| 227 +++ 7 files changed, 2956 insertions(+) create mode 100644 hw/hyperv/trace-events create mode 100644 hw/hyperv/vmbus.c create mode 100644 include/hw/hyperv/vmbus-bridge.h create mode 100644 include/hw/hyperv/vmbus.h diff --git a/Makefile.objs b/Makefile.objs index a7c967633a..1ef80ce58f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -151,6 +151,7 @@ trace-events-subdirs += hw/block/dataplane trace-events-subdirs += hw/char trace-events-subdirs += hw/dma trace-events-subdirs += hw/hppa +trace-events-subdirs += hw/hyperv trace-events-subdirs += hw/i2c trace-events-subdirs += hw/i386 trace-events-subdirs += hw/i386/xen diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig index a1fa8ff9be..3fbfe41c9e 100644 --- a/hw/hyperv/Kconfig +++ b/hw/hyperv/Kconfig @@ -6,3 +6,8 @@ config HYPERV_TESTDEV bool default y if TEST_DEVICES depends on HYPERV + +config VMBUS +bool +default y +depends on HYPERV diff --git a/hw/hyperv/Makefile.objs b/hw/hyperv/Makefile.objs index edaca2f763..5b614e040c 100644 --- a/hw/hyperv/Makefile.objs +++ b/hw/hyperv/Makefile.objs @@ -1,2 +1,3 @@ obj-y += hyperv.o obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o +obj-$(CONFIG_VMBUS) += vmbus.o diff --git a/hw/hyperv/trace-events b/hw/hyperv/trace-events new file mode 100644 index 00..ba5bd62d61 --- /dev/null +++ b/hw/hyperv/trace-events @@ -0,0 +1,18 @@ +# vmbus +vmbus_recv_message(uint32_t type, uint32_t size) "type %d size %d" +vmbus_signal_event(void) "" +vmbus_channel_notify_guest(uint32_t chan_id) "channel #%d" +vmbus_post_msg(uint32_t type, uint32_t size) "type %d size %d" +vmbus_msg_cb(int status) "message status %d" +vmbus_process_incoming_message(uint32_t message_type) "type %d" +vmbus_initiate_contact(uint16_t major, uint16_t minor, uint32_t vcpu, uint64_t monitor_page1, uint64_t monitor_page2, uint64_t interrupt_page) "version %d.%d target vp %d mon pages 0x%"PRIx64",0x%"PRIx64" int page 0x%"PRIx64 +vmbus_send_offer(uint32_t chan_id, void *dev) "channel #%d dev %p" +vmbus_terminate_offers(void) "" +vmbus_gpadl_header(uint32_t gpadl_id, uint16_t num_gfns) "gpadl #%d gfns %d" +vmbus_gpadl_body(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_created(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_teardown(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_torndown(uint32_t gpadl_id) "gpadl #%d" +vmbus_open_channel(uint32_t chan_id, uint32_t gpadl_id, uint32_t target_vp) "channel #%d gpadl #%d target vp %d" +vmbus_channel_open(uint32_t chan_id, uint32_t status) "channel #%d status %d" +vmbus_close_channel(uint32_t chan_id) "channel #%d" diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c new file mode 100644 index 00..1f5873ab60 --- /dev/null +++ b/hw/hyperv/vmbus.c @@ -0,0 +1,2672 @@ +/* + * QEMU Hyper-V VMBus + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-prope
[PATCH v4 4/6] i386:pc: whitelist dynamic vmbus-bridge
As vmbus-bridge is derived from sysbus device, it has to be whitelisted to be allowed to be created with -device. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/i386/pc_piix.c | 2 ++ hw/i386/pc_q35.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 9cceae3e2c..6daa0770fa 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -60,6 +60,7 @@ #include "migration/global_state.h" #include "migration/misc.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" #define MAX_IDE_BUS 2 @@ -417,6 +418,7 @@ static void pc_i440fx_machine_options(MachineClass *m) m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } static void pc_i440fx_5_0_machine_options(MachineClass *m) diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index d37c425e22..faaa39ced2 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -53,6 +53,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" /* ICH9 AHCI has 6 ports */ @@ -346,6 +347,7 @@ static void pc_q35_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); m->max_cpus = 288; } -- 2.24.1
[PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry
Guest OS uses ACPI to discover VMBus presence. Add a corresponding entry to DSDT in case VMBus has been enabled. Experimentally Windows guests were found to require this entry to include two IRQ resources. They seem to never be used but they still have to be there. Make IRQ numbers user-configurable via corresponding properties; use 7 and 13 by default. Signed-off-by: Evgeny Yakovlev Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c| 7 ++ hw/i386/acpi-build.c | 43 include/hw/hyperv/vmbus-bridge.h | 3 +++ 3 files changed, 53 insertions(+) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 1f5873ab60..0df7afe0ca 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2641,6 +2641,12 @@ static const VMStateDescription vmstate_vmbus_bridge = { }, }; +static Property vmbus_bridge_props[] = { +DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), +DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), +DEFINE_PROP_END_OF_LIST() +}; + static void vmbus_bridge_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); @@ -2651,6 +2657,7 @@ static void vmbus_bridge_class_init(ObjectClass *klass, void *data) sk->explicit_ofw_unit_address = vmbus_bridge_ofw_unit_address; set_bit(DEVICE_CATEGORY_BRIDGE, k->categories); k->vmsd = &vmstate_vmbus_bridge; +device_class_set_props(k, vmbus_bridge_props); /* override SysBusDevice's default */ k->user_creatable = true; } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2a7e55bae7..d235074fb8 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -50,6 +50,7 @@ #include "hw/mem/nvdimm.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "hw/hyperv/vmbus-bridge.h" /* Supported chipsets: */ #include "hw/southbridge/piix.h" @@ -1270,9 +1271,47 @@ static Aml *build_com_device_aml(uint8_t uid) return dev; } +static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) +{ +Aml *dev; +Aml *method; +Aml *crs; + +dev = aml_device("VMBS"); +aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); +aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); +aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); + +method = aml_method("_DIS", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_and(aml_name("STA"), aml_int(0xD), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_PS0", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_or(aml_name("STA"), aml_int(0xF), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_STA", 0, AML_NOTSERIALIZED); +aml_append(method, aml_return(aml_name("STA"))); +aml_append(dev, method); + +aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); + +crs = aml_resource_template(); +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); +/* FIXME: newer HyperV gets by with only one IRQ */ +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); +aml_append(dev, aml_name_decl("_CRS", crs)); + +return dev; +} + static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1296,6 +1335,10 @@ static void build_isa_devices_aml(Aml *table) build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); } +if (vmbus_bridge) { +aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); +} + aml_append(table, scope); } diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index 9cc8f780de..c0a06d832c 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -19,6 +19,9 @@ typedef struct VMBus VMBus; typedef struct VMBusBridge { SysBusDevice parent_obj; +uint8_t irq0; +uint8_t irq1; + VMBus *bus; } VMBusBridge; -- 2.24.1
[PATCH v4 1/6] hyperv: expose API to determine if synic is enabled
Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 8 include/hw/hyperv/hyperv.h | 1 + 2 files changed, 9 insertions(+) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index 8ca3706f5b..ddf4f32c60 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -37,6 +37,13 @@ typedef struct SynICState { #define TYPE_SYNIC "hyperv-synic" #define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC) +static bool synic_enabled; + +bool hyperv_is_synic_enabled(void) +{ +return synic_enabled; +} + static SynICState *get_synic(CPUState *cs) { return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); @@ -133,6 +140,7 @@ void hyperv_synic_add(CPUState *cs) object_property_add_child(OBJECT(cs), "synic", obj, &error_abort); object_unref(obj); object_property_set_bool(obj, true, "realized", &error_abort); +synic_enabled = true; } void hyperv_synic_reset(CPUState *cs) diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h index 597381cb01..a63ee0003c 100644 --- a/include/hw/hyperv/hyperv.h +++ b/include/hw/hyperv/hyperv.h @@ -79,5 +79,6 @@ void hyperv_synic_add(CPUState *cs); void hyperv_synic_reset(CPUState *cs); void hyperv_synic_update(CPUState *cs, bool enable, hwaddr msg_page_addr, hwaddr event_page_addr); +bool hyperv_is_synic_enabled(void); #endif -- 2.24.1
[PATCH v4 0/6] hyperv: VMBus implementation
This is a rebase of the old patchset from Roman for HyperV VMBus implementation. How to use: -device vmbus-bridge Later on new paravirtualized devices can be implemented on top of it (Network/SCSI/etc.) VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. v4: Decided to ditch the patch that envolves handling of EOM as there is still a discussion going on with it in the KVM mailing list. v3: Fixed an error asan v2: Rebased on top of latest patchset from Roman and Maciej Jon Doron (6): hyperv: expose API to determine if synic is enabled vmbus: add vmbus protocol definitions vmbus: vmbus implementation i386:pc: whitelist dynamic vmbus-bridge i386: Hyper-V VMBus ACPI DSDT entry vmbus: add infrastructure to save/load vmbus requests Makefile.objs|1 + hw/hyperv/Kconfig|5 + hw/hyperv/Makefile.objs |1 + hw/hyperv/hyperv.c |8 + hw/hyperv/trace-events | 18 + hw/hyperv/vmbus.c| 2778 ++ hw/i386/acpi-build.c | 43 + hw/i386/pc_piix.c|2 + hw/i386/pc_q35.c |2 + include/hw/hyperv/hyperv.h |1 + include/hw/hyperv/vmbus-bridge.h | 35 + include/hw/hyperv/vmbus-proto.h | 222 +++ include/hw/hyperv/vmbus.h| 230 +++ 13 files changed, 3346 insertions(+) create mode 100644 hw/hyperv/trace-events create mode 100644 hw/hyperv/vmbus.c create mode 100644 include/hw/hyperv/vmbus-bridge.h create mode 100644 include/hw/hyperv/vmbus-proto.h create mode 100644 include/hw/hyperv/vmbus.h -- 2.24.1
Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
On 08/04/2020, Roman Kagan wrote: On Wed, Apr 08, 2020 at 07:16:39AM +0300, Jon Doron wrote: On 07/04/2020, Maciej S. Szmigiero wrote: > On 07.04.2020 20:56, Roman Kagan wrote: > > On Mon, Apr 06, 2020 at 11:20:39AM +0300, Jon Doron wrote: > > > Well I want it to be merged in :-) > > > > Hmm I'm curious why, it has little to offer over virtio. > > > > Anyway the series you've posted seems to be based on a fairly old > > version. > > > > The one in openvz repo is more recent. It's still in need for > > improvement, too, but should be testable at least. Well I have implemented the hyperv synthetic kernel debugger interface, but on Windows 10 it requires to have a working VMBus (it's not really using it, but without a function vmbus that will answer to the initiate contact then the kdnet will simply be stuck in a loop. I see, thanks, I've never heard of this before. With the synthetic kernel debugger interface you can debug older OS (Win7 up to latest Win10). The benefit is that its much faster than all other interfaces. I guess you compare it to debugging via serial port. I wonder where the difference comes from? I thought the transport didn't require any significant throughput, and latency-wise the (emulated) serial port was just as good as any other. Am I missing something? Thanks, Roman. Well kdcom is sending out UART through the virtual serial port, this results in very slow speeds (try it out if you get a chance), because of that most Windows kernel developers use VMWare with a combination of a tool called VirtualKD which implements it's own debug transport on the Windows part and patches the hypervisor (aka VMWare) to get the VMExits. This way it can transfer more and bigger blocks faster, to the debugger. With the synthetic debugger interface in-place (which you can use since Windows 7) all these tricks are not really required, you just need to implement it :P . Thanks, -- Jon. In addition to that Michael Kelley from Microsoft has informed us that Microsoft might be dropped the synthetic kernel debugger interface sometime in the future, and it seems like the new mode is simply to use hvnet device for the communication (which is again much faster). Cheers, -- Jon. > > Isn't the one at > https://src.openvz.org/projects/UP/repos/qemu/commits?until=refs%2Fheads%2Fvmbus > the latest one? > > It seems to be last changed in October 2019 - is there a > later one? > > > Thanks, > > Roman. > > Thanks, > Maciej
Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
On 07/04/2020, Maciej S. Szmigiero wrote: On 07.04.2020 20:56, Roman Kagan wrote: On Mon, Apr 06, 2020 at 11:20:39AM +0300, Jon Doron wrote: Well I want it to be merged in :-) Hmm I'm curious why, it has little to offer over virtio. Anyway the series you've posted seems to be based on a fairly old version. The one in openvz repo is more recent. It's still in need for improvement, too, but should be testable at least. Well I have implemented the hyperv synthetic kernel debugger interface, but on Windows 10 it requires to have a working VMBus (it's not really using it, but without a function vmbus that will answer to the initiate contact then the kdnet will simply be stuck in a loop. With the synthetic kernel debugger interface you can debug older OS (Win7 up to latest Win10). The benefit is that its much faster than all other interfaces. In addition to that Michael Kelley from Microsoft has informed us that Microsoft might be dropped the synthetic kernel debugger interface sometime in the future, and it seems like the new mode is simply to use hvnet device for the communication (which is again much faster). Cheers, -- Jon. Isn't the one at https://src.openvz.org/projects/UP/repos/qemu/commits?until=refs%2Fheads%2Fvmbus the latest one? It seems to be last changed in October 2019 - is there a later one? Thanks, Roman. Thanks, Maciej
[PATCH v3 4/7] vmbus: vmbus implementation
Add the VMBus infrastructure -- bus, devices, root bridge, vmbus state machine, vmbus channel interactions, etc. VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. TODO: - split into smaller palatable pieces - more comments - check and handle corner cases Kudos to Evgeny Yakovlev (formerly eyakov...@virtuozzo.com) and Andrey Smetatin (formerly asmeta...@virtuozzo.com) for research and prototyping. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- Makefile.objs|1 + hw/hyperv/Kconfig|5 + hw/hyperv/Makefile.objs |1 + hw/hyperv/trace-events | 18 + hw/hyperv/vmbus.c| 2672 ++ include/hw/hyperv/vmbus-bridge.h | 32 + include/hw/hyperv/vmbus.h| 227 +++ 7 files changed, 2956 insertions(+) create mode 100644 hw/hyperv/trace-events create mode 100644 hw/hyperv/vmbus.c create mode 100644 include/hw/hyperv/vmbus-bridge.h create mode 100644 include/hw/hyperv/vmbus.h diff --git a/Makefile.objs b/Makefile.objs index a7c967633a..1ef80ce58f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -151,6 +151,7 @@ trace-events-subdirs += hw/block/dataplane trace-events-subdirs += hw/char trace-events-subdirs += hw/dma trace-events-subdirs += hw/hppa +trace-events-subdirs += hw/hyperv trace-events-subdirs += hw/i2c trace-events-subdirs += hw/i386 trace-events-subdirs += hw/i386/xen diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig index a1fa8ff9be..3fbfe41c9e 100644 --- a/hw/hyperv/Kconfig +++ b/hw/hyperv/Kconfig @@ -6,3 +6,8 @@ config HYPERV_TESTDEV bool default y if TEST_DEVICES depends on HYPERV + +config VMBUS +bool +default y +depends on HYPERV diff --git a/hw/hyperv/Makefile.objs b/hw/hyperv/Makefile.objs index edaca2f763..5b614e040c 100644 --- a/hw/hyperv/Makefile.objs +++ b/hw/hyperv/Makefile.objs @@ -1,2 +1,3 @@ obj-y += hyperv.o obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o +obj-$(CONFIG_VMBUS) += vmbus.o diff --git a/hw/hyperv/trace-events b/hw/hyperv/trace-events new file mode 100644 index 00..ba5bd62d61 --- /dev/null +++ b/hw/hyperv/trace-events @@ -0,0 +1,18 @@ +# vmbus +vmbus_recv_message(uint32_t type, uint32_t size) "type %d size %d" +vmbus_signal_event(void) "" +vmbus_channel_notify_guest(uint32_t chan_id) "channel #%d" +vmbus_post_msg(uint32_t type, uint32_t size) "type %d size %d" +vmbus_msg_cb(int status) "message status %d" +vmbus_process_incoming_message(uint32_t message_type) "type %d" +vmbus_initiate_contact(uint16_t major, uint16_t minor, uint32_t vcpu, uint64_t monitor_page1, uint64_t monitor_page2, uint64_t interrupt_page) "version %d.%d target vp %d mon pages 0x%"PRIx64",0x%"PRIx64" int page 0x%"PRIx64 +vmbus_send_offer(uint32_t chan_id, void *dev) "channel #%d dev %p" +vmbus_terminate_offers(void) "" +vmbus_gpadl_header(uint32_t gpadl_id, uint16_t num_gfns) "gpadl #%d gfns %d" +vmbus_gpadl_body(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_created(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_teardown(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_torndown(uint32_t gpadl_id) "gpadl #%d" +vmbus_open_channel(uint32_t chan_id, uint32_t gpadl_id, uint32_t target_vp) "channel #%d gpadl #%d target vp %d" +vmbus_channel_open(uint32_t chan_id, uint32_t status) "channel #%d status %d" +vmbus_close_channel(uint32_t chan_id) "channel #%d" diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c new file mode 100644 index 00..1f5873ab60 --- /dev/null +++ b/hw/hyperv/vmbus.c @@ -0,0 +1,2672 @@ +/* + * QEMU Hyper-V VMBus + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-prope
[PATCH v3 6/7] i386: Hyper-V VMBus ACPI DSDT entry
Guest OS uses ACPI to discover VMBus presence. Add a corresponding entry to DSDT in case VMBus has been enabled. Experimentally Windows guests were found to require this entry to include two IRQ resources. They seem to never be used but they still have to be there. Make IRQ numbers user-configurable via corresponding properties; use 7 and 13 by default. Signed-off-by: Evgeny Yakovlev Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c| 7 ++ hw/i386/acpi-build.c | 43 include/hw/hyperv/vmbus-bridge.h | 3 +++ 3 files changed, 53 insertions(+) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 1f5873ab60..0df7afe0ca 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2641,6 +2641,12 @@ static const VMStateDescription vmstate_vmbus_bridge = { }, }; +static Property vmbus_bridge_props[] = { +DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), +DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), +DEFINE_PROP_END_OF_LIST() +}; + static void vmbus_bridge_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); @@ -2651,6 +2657,7 @@ static void vmbus_bridge_class_init(ObjectClass *klass, void *data) sk->explicit_ofw_unit_address = vmbus_bridge_ofw_unit_address; set_bit(DEVICE_CATEGORY_BRIDGE, k->categories); k->vmsd = &vmstate_vmbus_bridge; +device_class_set_props(k, vmbus_bridge_props); /* override SysBusDevice's default */ k->user_creatable = true; } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2a7e55bae7..d235074fb8 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -50,6 +50,7 @@ #include "hw/mem/nvdimm.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "hw/hyperv/vmbus-bridge.h" /* Supported chipsets: */ #include "hw/southbridge/piix.h" @@ -1270,9 +1271,47 @@ static Aml *build_com_device_aml(uint8_t uid) return dev; } +static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) +{ +Aml *dev; +Aml *method; +Aml *crs; + +dev = aml_device("VMBS"); +aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); +aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); +aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); + +method = aml_method("_DIS", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_and(aml_name("STA"), aml_int(0xD), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_PS0", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_or(aml_name("STA"), aml_int(0xF), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_STA", 0, AML_NOTSERIALIZED); +aml_append(method, aml_return(aml_name("STA"))); +aml_append(dev, method); + +aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); + +crs = aml_resource_template(); +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); +/* FIXME: newer HyperV gets by with only one IRQ */ +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); +aml_append(dev, aml_name_decl("_CRS", crs)); + +return dev; +} + static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1296,6 +1335,10 @@ static void build_isa_devices_aml(Aml *table) build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); } +if (vmbus_bridge) { +aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); +} + aml_append(table, scope); } diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index 9cc8f780de..c0a06d832c 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -19,6 +19,9 @@ typedef struct VMBus VMBus; typedef struct VMBusBridge { SysBusDevice parent_obj; +uint8_t irq0; +uint8_t irq1; + VMBus *bus; } VMBusBridge; -- 2.24.1
[PATCH v3 5/7] i386:pc: whitelist dynamic vmbus-bridge
As vmbus-bridge is derived from sysbus device, it has to be whitelisted to be allowed to be created with -device. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/i386/pc_piix.c | 2 ++ hw/i386/pc_q35.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 9cceae3e2c..6daa0770fa 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -60,6 +60,7 @@ #include "migration/global_state.h" #include "migration/misc.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" #define MAX_IDE_BUS 2 @@ -417,6 +418,7 @@ static void pc_i440fx_machine_options(MachineClass *m) m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } static void pc_i440fx_5_0_machine_options(MachineClass *m) diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index d37c425e22..faaa39ced2 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -53,6 +53,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" /* ICH9 AHCI has 6 ports */ @@ -346,6 +347,7 @@ static void pc_q35_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); m->max_cpus = 288; } -- 2.24.1
[PATCH v3 2/7] hyperv: SControl is optional to enable SynIc
SynIc can be enabled regardless of the SControl mechanisim which can register a GSI for a given SintRoute. This behaviour can achived by setting enabling SIMP and then the guest will poll on the message slot. Once there is another message pending the host will set the message slot with the pending flag. When the guest polls from the message slot, incase the pending flag is set it will write to the HV_X64_MSR_EOM indicating it has cleared the slow and we can try and push our message again. Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 242 - include/hw/hyperv/hyperv.h | 2 + target/i386/hyperv.c | 2 + 3 files changed, 164 insertions(+), 82 deletions(-) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index ddf4f32c60..1dc577a0ab 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -20,18 +20,72 @@ #include "qemu/rcu_queue.h" #include "hw/hyperv/hyperv.h" +/* + * KVM has its own message producers (SynIC timers). To guarantee + * serialization with both KVM vcpu and the guest cpu, the messages are first + * staged in an intermediate area and then posted to the SynIC message page in + * the vcpu thread. + */ +typedef struct HvSintStagedMessage { +/* message content staged by hyperv_post_msg */ +struct hyperv_message msg; +/* callback + data (r/o) to complete the processing in a BH */ +HvSintMsgCb cb; +void *cb_data; +/* message posting status filled by cpu_post_msg */ +int status; +/* passing the buck: */ +enum { +/* initial state */ +HV_STAGED_MSG_FREE, +/* + * hyperv_post_msg (e.g. in main loop) grabs the staged area (FREE -> + * BUSY), copies msg, and schedules cpu_post_msg on the assigned cpu + */ +HV_STAGED_MSG_BUSY, +/* + * cpu_post_msg (vcpu thread) tries to copy staged msg to msg slot, + * notify the guest, records the status, marks the posting done (BUSY + * -> POSTED), and schedules sint_msg_bh BH + */ +HV_STAGED_MSG_POSTED, +/* + * sint_msg_bh (BH) verifies that the posting is done, runs the + * callback, and starts over (POSTED -> FREE) + */ +} state; +} HvSintStagedMessage; + +struct SynICState; + +struct HvSintRoute { +uint32_t sint; +struct SynICState *synic; +int gsi; +EventNotifier sint_set_notifier; +EventNotifier sint_ack_notifier; + +HvSintStagedMessage *staged_msg; + +unsigned refcount; +QLIST_ENTRY(HvSintRoute) link; +}; + typedef struct SynICState { DeviceState parent_obj; CPUState *cs; -bool enabled; +bool sctl_enabled; hwaddr msg_page_addr; hwaddr event_page_addr; MemoryRegion msg_page_mr; MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; + +QemuMutex sint_routes_mutex; +QLIST_HEAD(, HvSintRoute) sint_routes; } SynICState; #define TYPE_SYNIC "hyperv-synic" @@ -49,11 +103,11 @@ static SynICState *get_synic(CPUState *cs) return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); } -static void synic_update(SynICState *synic, bool enable, +static void synic_update(SynICState *synic, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { -synic->enabled = enable; +synic->sctl_enabled = sctl_enable; if (synic->msg_page_addr != msg_page_addr) { if (synic->msg_page_addr) { memory_region_del_subregion(get_system_memory(), @@ -78,7 +132,7 @@ static void synic_update(SynICState *synic, bool enable, } } -void hyperv_synic_update(CPUState *cs, bool enable, +void hyperv_synic_update(CPUState *cs, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { SynICState *synic = get_synic(cs); @@ -87,7 +141,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, return; } -synic_update(synic, enable, msg_page_addr, event_page_addr); +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); } static void synic_realize(DeviceState *dev, Error **errp) @@ -108,16 +162,20 @@ static void synic_realize(DeviceState *dev, Error **errp) sizeof(*synic->event_page), &error_abort); synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); +qemu_mutex_init(&synic->sint_routes_mutex); +QLIST_INIT(&synic->sint_routes); g_free(msgp_name); g_free(eventp_name); } + static void synic_reset(DeviceState *dev) { SynICState *synic = SYNIC(dev); memset(synic->msg_page, 0, sizeof(*synic->msg_page)); memset(synic->event_page, 0, sizeof(*synic->event_page)); synic_update(synic, false,
[PATCH v3 7/7] vmbus: add infrastructure to save/load vmbus requests
This can be allow to include controller-specific data while saving/loading in-flight scsi requests of the vmbus scsi controller. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c | 99 +++ include/hw/hyperv/vmbus.h | 3 ++ 2 files changed, 102 insertions(+) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 0df7afe0ca..ab72a59a4a 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -1272,6 +1272,105 @@ void vmbus_free_req(void *req) g_free(req); } +static const VMStateDescription vmstate_sgent = { +.name = "vmbus/sgentry", +.version_id = 0, +.minimum_version_id = 0, +.fields = (VMStateField[]) { +VMSTATE_UINT64(base, ScatterGatherEntry), +VMSTATE_UINT64(len, ScatterGatherEntry), +VMSTATE_END_OF_LIST() +} +}; + +typedef struct VMBusChanReqSave { +uint16_t chan_idx; +uint16_t pkt_type; +uint32_t msglen; +void *msg; +uint64_t transaction_id; +bool need_comp; +uint32_t num; +ScatterGatherEntry *sgl; +} VMBusChanReqSave; + +static const VMStateDescription vmstate_vmbus_chan_req = { +.name = "vmbus/vmbus_chan_req", +.version_id = 0, +.minimum_version_id = 0, +.fields = (VMStateField[]) { +VMSTATE_UINT16(chan_idx, VMBusChanReqSave), +VMSTATE_UINT16(pkt_type, VMBusChanReqSave), +VMSTATE_UINT32(msglen, VMBusChanReqSave), +VMSTATE_VBUFFER_ALLOC_UINT32(msg, VMBusChanReqSave, 0, NULL, msglen), +VMSTATE_UINT64(transaction_id, VMBusChanReqSave), +VMSTATE_BOOL(need_comp, VMBusChanReqSave), +VMSTATE_UINT32(num, VMBusChanReqSave), +VMSTATE_STRUCT_VARRAY_POINTER_UINT32(sgl, VMBusChanReqSave, num, + vmstate_sgent, ScatterGatherEntry), +VMSTATE_END_OF_LIST() +} +}; + +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req) +{ +VMBusChanReqSave req_save; + +req_save.chan_idx = req->chan->subchan_idx; +req_save.pkt_type = req->pkt_type; +req_save.msglen = req->msglen; +req_save.msg = req->msg; +req_save.transaction_id = req->transaction_id; +req_save.need_comp = req->need_comp; +req_save.num = req->sgl.nsg; +req_save.sgl = g_memdup(req->sgl.sg, +req_save.num * sizeof(ScatterGatherEntry)); + +vmstate_save_state(f, &vmstate_vmbus_chan_req, &req_save, NULL); + +g_free(req_save.sgl); +} + +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size) +{ +VMBusChanReqSave req_save; +VMBusChanReq *req = NULL; +VMBusChannel *chan = NULL; +uint32_t i; + +vmstate_load_state(f, &vmstate_vmbus_chan_req, &req_save, 0); + +if (req_save.chan_idx >= dev->num_channels) { +error_report("%s: %u(chan_idx) > %u(num_channels)", __func__, + req_save.chan_idx, dev->num_channels); +goto out; +} +chan = &dev->channels[req_save.chan_idx]; + +if (vmbus_channel_reserve(chan, 0, req_save.msglen)) { +goto out; +} + +req = vmbus_alloc_req(chan, size, req_save.pkt_type, req_save.msglen, + req_save.transaction_id, req_save.need_comp); +if (req_save.msglen) { +memcpy(req->msg, req_save.msg, req_save.msglen); +} + +for (i = 0; i < req_save.num; i++) { +qemu_sglist_add(&req->sgl, req_save.sgl[i].base, req_save.sgl[i].len); +} + +out: +if (req_save.msglen) { +g_free(req_save.msg); +} +if (req_save.num) { +g_free(req_save.sgl); +} +return req; +} + static void channel_event_cb(EventNotifier *e) { VMBusChannel *chan = container_of(e, VMBusChannel, notifier); diff --git a/include/hw/hyperv/vmbus.h b/include/hw/hyperv/vmbus.h index 63a5b807b6..9219f34d6b 100644 --- a/include/hw/hyperv/vmbus.h +++ b/include/hw/hyperv/vmbus.h @@ -224,4 +224,7 @@ int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, unsigned iov_cnt, size_t accessed); +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req); +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size); + #endif -- 2.24.1
[PATCH v3 3/7] vmbus: add vmbus protocol definitions
Add a header with data structures and constants used in Hyper-V VMBus hypervisor <-> guest interactions. Based on the respective stuff from Linux kernel. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- include/hw/hyperv/vmbus-proto.h | 222 1 file changed, 222 insertions(+) create mode 100644 include/hw/hyperv/vmbus-proto.h diff --git a/include/hw/hyperv/vmbus-proto.h b/include/hw/hyperv/vmbus-proto.h new file mode 100644 index 00..4628d3b323 --- /dev/null +++ b/include/hw/hyperv/vmbus-proto.h @@ -0,0 +1,222 @@ +/* + * QEMU Hyper-V VMBus support + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_HYPERV_VMBUS_PROTO_H +#define HW_HYPERV_VMBUS_PROTO_H + +#define VMBUS_VERSION_WS2008((0 << 16) | (13)) +#define VMBUS_VERSION_WIN7 ((1 << 16) | (1)) +#define VMBUS_VERSION_WIN8 ((2 << 16) | (4)) +#define VMBUS_VERSION_WIN8_1((3 << 16) | (0)) +#define VMBUS_VERSION_WIN10 ((4 << 16) | (0)) +#define VMBUS_VERSION_INVAL -1 +#define VMBUS_VERSION_CURRENT VMBUS_VERSION_WIN10 + +#define VMBUS_MESSAGE_CONNECTION_ID 1 +#define VMBUS_EVENT_CONNECTION_ID 2 +#define VMBUS_MONITOR_CONNECTION_ID 3 +#define VMBUS_SINT 2 + +#define VMBUS_MSG_INVALID 0 +#define VMBUS_MSG_OFFERCHANNEL 1 +#define VMBUS_MSG_RESCIND_CHANNELOFFER 2 +#define VMBUS_MSG_REQUESTOFFERS 3 +#define VMBUS_MSG_ALLOFFERS_DELIVERED 4 +#define VMBUS_MSG_OPENCHANNEL 5 +#define VMBUS_MSG_OPENCHANNEL_RESULT6 +#define VMBUS_MSG_CLOSECHANNEL 7 +#define VMBUS_MSG_GPADL_HEADER 8 +#define VMBUS_MSG_GPADL_BODY9 +#define VMBUS_MSG_GPADL_CREATED 10 +#define VMBUS_MSG_GPADL_TEARDOWN11 +#define VMBUS_MSG_GPADL_TORNDOWN12 +#define VMBUS_MSG_RELID_RELEASED13 +#define VMBUS_MSG_INITIATE_CONTACT 14 +#define VMBUS_MSG_VERSION_RESPONSE 15 +#define VMBUS_MSG_UNLOAD16 +#define VMBUS_MSG_UNLOAD_RESPONSE 17 +#define VMBUS_MSG_COUNT 18 + +#define VMBUS_MESSAGE_SIZE_ALIGNsizeof(uint64_t) + +#define VMBUS_PACKET_INVALID0x0 +#define VMBUS_PACKET_SYNCH 0x1 +#define VMBUS_PACKET_ADD_XFER_PAGESET 0x2 +#define VMBUS_PACKET_RM_XFER_PAGESET0x3 +#define VMBUS_PACKET_ESTABLISH_GPADL0x4 +#define VMBUS_PACKET_TEARDOWN_GPADL 0x5 +#define VMBUS_PACKET_DATA_INBAND0x6 +#define VMBUS_PACKET_DATA_USING_XFER_PAGES 0x7 +#define VMBUS_PACKET_DATA_USING_GPADL 0x8 +#define VMBUS_PACKET_DATA_USING_GPA_DIRECT 0x9 +#define VMBUS_PACKET_CANCEL_REQUEST 0xa +#define VMBUS_PACKET_COMP 0xb +#define VMBUS_PACKET_DATA_USING_ADDITIONAL_PKT 0xc +#define VMBUS_PACKET_ADDITIONAL_DATA0xd + +#define VMBUS_CHANNEL_USER_DATA_SIZE120 + +#define VMBUS_OFFER_MONITOR_ALLOCATED 0x1 +#define VMBUS_OFFER_INTERRUPT_DEDICATED 0x1 + +#define VMBUS_RING_BUFFER_FEAT_PENDING_SZ (1ul << 0) + +#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 0x1 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES 0x2 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS 0x4 +#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x10 +#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100 +#define VMBUS_CHANNEL_PARENT_OFFER0x200 +#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400 +#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER0x2000 + +#define VMBUS_PACKET_FLAG_REQUEST_COMPLETION1 + +typedef struct vmbus_message_header { +uint32_t message_type; +uint32_t _padding; +} vmbus_message_header; + +typedef struct vmbus_message_initiate_contact { +vmbus_message_header header; +uint32_t version_requested; +uint32_t target_vcpu; +uint64_t interrupt_page; +uint64_t monitor_page1; +uint64_t monitor_page2; +} vmbus_message_initiate_contact; + +typedef struct vmbus_message_version_response { +vmbus_message_header header; +uint8_t version_supported; +uint8_t status; +} vmbus_message_version_response; + +typedef struct vmbus_message_offer_channel { +vmbus_message_header header; +uint8_t type_uuid[16]; +uint8_t instance_uuid[16]; +uint64_t _reserved1; +uint64_t _reserved2; +uint16_t channel_flags; +uint16_t mmio_size_mb; +uint8_t user_data[VMBUS_CHANNEL_USER_DATA_SIZE]; +uint16_t sub_channel_index; +uint16_t _reserved3; +uint32_t child_relid; +uint8_t monitor_id;
[PATCH v3 1/7] hyperv: expose API to determine if synic is enabled
Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 8 include/hw/hyperv/hyperv.h | 1 + 2 files changed, 9 insertions(+) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index 8ca3706f5b..ddf4f32c60 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -37,6 +37,13 @@ typedef struct SynICState { #define TYPE_SYNIC "hyperv-synic" #define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC) +static bool synic_enabled; + +bool hyperv_is_synic_enabled(void) +{ +return synic_enabled; +} + static SynICState *get_synic(CPUState *cs) { return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); @@ -133,6 +140,7 @@ void hyperv_synic_add(CPUState *cs) object_property_add_child(OBJECT(cs), "synic", obj, &error_abort); object_unref(obj); object_property_set_bool(obj, true, "realized", &error_abort); +synic_enabled = true; } void hyperv_synic_reset(CPUState *cs) diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h index 597381cb01..a63ee0003c 100644 --- a/include/hw/hyperv/hyperv.h +++ b/include/hw/hyperv/hyperv.h @@ -79,5 +79,6 @@ void hyperv_synic_add(CPUState *cs); void hyperv_synic_reset(CPUState *cs); void hyperv_synic_update(CPUState *cs, bool enable, hwaddr msg_page_addr, hwaddr event_page_addr); +bool hyperv_is_synic_enabled(void); #endif -- 2.24.1
[PATCH v3 0/7] hyperv: VMBus implementation
This is a rebase of the old patchset from Roman for HyperV VMBus implementation. How to use: -device vmbus-bridge Later on new paravirtualized devices can be implemented on top of it (Network/SCSI/etc.) VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. v3: Fixed an error asan v2: Rebased on top of latest patchset from Roman and Maciej Jon Doron (7): hyperv: expose API to determine if synic is enabled hyperv: SControl is optional to enable SynIc vmbus: add vmbus protocol definitions vmbus: vmbus implementation i386:pc: whitelist dynamic vmbus-bridge i386: Hyper-V VMBus ACPI DSDT entry vmbus: add infrastructure to save/load vmbus requests Makefile.objs|1 + hw/hyperv/Kconfig|5 + hw/hyperv/Makefile.objs |1 + hw/hyperv/hyperv.c | 250 ++- hw/hyperv/trace-events | 18 + hw/hyperv/vmbus.c| 2778 ++ hw/i386/acpi-build.c | 43 + hw/i386/pc_piix.c|2 + hw/i386/pc_q35.c |2 + include/hw/hyperv/hyperv.h |3 + include/hw/hyperv/vmbus-bridge.h | 35 + include/hw/hyperv/vmbus-proto.h | 222 +++ include/hw/hyperv/vmbus.h| 230 +++ target/i386/hyperv.c |2 + 14 files changed, 3510 insertions(+), 82 deletions(-) create mode 100644 hw/hyperv/trace-events create mode 100644 hw/hyperv/vmbus.c create mode 100644 include/hw/hyperv/vmbus-bridge.h create mode 100644 include/hw/hyperv/vmbus-proto.h create mode 100644 include/hw/hyperv/vmbus.h -- 2.24.1
Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
Well I want it to be merged in :-) On Mon, Apr 6, 2020, 10:32 Roman Kagan wrote: > On Fri, Apr 03, 2020 at 11:00:27PM +0200, Maciej S. Szmigiero wrote: > > It seems to me that Roman might not be getting our e-mails since his > > new e-mail address seems to be "rvka...@yandex-team.ru". > > Indeed. I'm subscribed with my new address to qemu-devel ML but must > have missed this series. > > > @Roman, are you with us? > > Yes ;) > > So what are your plans regarding this patchset? > > Thanks, > Roman. > > > On 03.04.2020 19:18, Maciej S. Szmigiero wrote: > > > Hi Jon, > > > > > > The patches are available here: > > > https://github.com/maciejsszmigiero/qemu.git in "vmbus-patches" > branch. > > > > > > Please note that these patches don't have Roman's "Signed-off-by:" > tags, > > > so I haven't applied mine, either. > > > > > > If you are able to establish a proper SoB chain then please also add: > > > "Signed-off-by: Maciej S. Szmigiero ". > > > > > > Thanks for the effort, > > > Maciej > > > > > > On 03.04.2020 17:30, Jon Doron wrote: > > >> Thank you Maciej it seems like your version is really ahead I'll do > > >> the required work and merge it so i can submit a v2 with the latest > > >> patchset from Roman > > >> > > >> On Fri, Apr 3, 2020 at 6:06 PM Jon Doron wrote: > > >>> > > >>> Thank you Maciej, I based it on top of what Denis (d...@openvz.org) > gave me > > >>> which was this: > > >>> > https://ftp.openvz.org/virtuozzo/releases/openvz-7.0.12-288/source/SRPMS/q/qemu-kvm-vz-2.12.0-33.vz7.14.4.src.rpm > > >>> > > >>> Do you think you have a more recent version I dont mind diffing and > > >>> resubmitting a new version of the patchset? > > >>> > > >>> Thanks, > > >>> -- Jon. > > >>> > > >>> On Fri, Apr 3, 2020 at 5:56 PM Maciej S. Szmigiero > > >>> wrote: > > >>>> > > >>>> Hi Jon, > > >>>> > > >>>> On 03.04.2020 16:23, Jon Doron wrote: > > >>>>> Guest OS uses ACPI to discover vmbus presence. Add a corresponding > > >>>>> entry to DSDT in case vmbus has been enabled. > > >>>>> > > >>>>> Experimentally Windows guests were found to require this entry to > > >>>>> include two IRQ resources, so this patch adds two semi-arbitrarily > > >>>>> chosen ones (7 and 13). This results, in particular, in parallel > port > > >>>>> conflicting with vmbus. > > >>>>> > > >>>>> TODO: discover and use spare IRQs to avoid conflicts. > > >>>>> > > >>>>> Signed-off-by: Evgeny Yakovlev > > >>>>> Signed-off-by: Roman Kagan > > >>>>> Signed-off-by: Jon Doron > > >>>> > > >>>> Nice work, thanks! > > >>>> > > >>>> However, it seems to be based on the code version that was posted in > > >>>> February 2018, and not the latest version in OpenVZ qemu repository > > >>>> dated October 2019: > > >>>> > https://src.openvz.org/projects/UP/repos/qemu/commits?until=refs%2Fheads%2Fvmbus > > >>>> > > >>>> This newer version has slightly different API here and there. > > >>>> Any particular reason for selecting that older version for porting? > > >>>> > > >>>> I have actually rebased this latest version on the top of the > current > > >>>> QEMU master, and it basically seems to work fine. > > >>>> However, I haven't done extensive tests whether there isn't a > memory leak > > >>>> somewhere or so on. > > >>>> > > >>>> Maciej > > > > > >
[PATCH v2 7/7] vmbus: add infrastructure to save/load vmbus requests
This can be allow to include controller-specific data while saving/loading in-flight scsi requests of the vmbus scsi controller. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c | 99 +++ include/hw/hyperv/vmbus.h | 3 ++ 2 files changed, 102 insertions(+) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 46c6f5eebb..e16228a77c 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -1272,6 +1272,105 @@ void vmbus_free_req(void *req) g_free(req); } +static const VMStateDescription vmstate_sgent = { +.name = "vmbus/sgentry", +.version_id = 0, +.minimum_version_id = 0, +.fields = (VMStateField[]) { +VMSTATE_UINT64(base, ScatterGatherEntry), +VMSTATE_UINT64(len, ScatterGatherEntry), +VMSTATE_END_OF_LIST() +} +}; + +typedef struct VMBusChanReqSave { +uint16_t chan_idx; +uint16_t pkt_type; +uint32_t msglen; +void *msg; +uint64_t transaction_id; +bool need_comp; +uint32_t num; +ScatterGatherEntry *sgl; +} VMBusChanReqSave; + +static const VMStateDescription vmstate_vmbus_chan_req = { +.name = "vmbus/vmbus_chan_req", +.version_id = 0, +.minimum_version_id = 0, +.fields = (VMStateField[]) { +VMSTATE_UINT16(chan_idx, VMBusChanReqSave), +VMSTATE_UINT16(pkt_type, VMBusChanReqSave), +VMSTATE_UINT32(msglen, VMBusChanReqSave), +VMSTATE_VBUFFER_ALLOC_UINT32(msg, VMBusChanReqSave, 0, NULL, msglen), +VMSTATE_UINT64(transaction_id, VMBusChanReqSave), +VMSTATE_BOOL(need_comp, VMBusChanReqSave), +VMSTATE_UINT32(num, VMBusChanReqSave), +VMSTATE_STRUCT_VARRAY_POINTER_UINT32(sgl, VMBusChanReqSave, num, + vmstate_sgent, ScatterGatherEntry), +VMSTATE_END_OF_LIST() +} +}; + +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req) +{ +VMBusChanReqSave req_save; + +req_save.chan_idx = req->chan->subchan_idx; +req_save.pkt_type = req->pkt_type; +req_save.msglen = req->msglen; +req_save.msg = req->msg; +req_save.transaction_id = req->transaction_id; +req_save.need_comp = req->need_comp; +req_save.num = req->sgl.nsg; +req_save.sgl = g_memdup(req->sgl.sg, +req_save.num * sizeof(ScatterGatherEntry)); + +vmstate_save_state(f, &vmstate_vmbus_chan_req, &req_save, NULL); + +g_free(req_save.sgl); +} + +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size) +{ +VMBusChanReqSave req_save; +VMBusChanReq *req = NULL; +VMBusChannel *chan = NULL; +uint32_t i; + +vmstate_load_state(f, &vmstate_vmbus_chan_req, &req_save, 0); + +if (req_save.chan_idx >= dev->num_channels) { +error_report("%s: %u(chan_idx) > %u(num_channels)", __func__, + req_save.chan_idx, dev->num_channels); +goto out; +} +chan = &dev->channels[req_save.chan_idx]; + +if (vmbus_channel_reserve(chan, 0, req_save.msglen)) { +goto out; +} + +req = vmbus_alloc_req(chan, size, req_save.pkt_type, req_save.msglen, + req_save.transaction_id, req_save.need_comp); +if (req_save.msglen) { +memcpy(req->msg, req_save.msg, req_save.msglen); +} + +for (i = 0; i < req_save.num; i++) { +qemu_sglist_add(&req->sgl, req_save.sgl[i].base, req_save.sgl[i].len); +} + +out: +if (req_save.msglen) { +g_free(req_save.msg); +} +if (req_save.num) { +g_free(req_save.sgl); +} +return req; +} + static void channel_event_cb(EventNotifier *e) { VMBusChannel *chan = container_of(e, VMBusChannel, notifier); diff --git a/include/hw/hyperv/vmbus.h b/include/hw/hyperv/vmbus.h index 63a5b807b6..9219f34d6b 100644 --- a/include/hw/hyperv/vmbus.h +++ b/include/hw/hyperv/vmbus.h @@ -224,4 +224,7 @@ int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, unsigned iov_cnt, size_t accessed); +void vmbus_save_req(QEMUFile *f, VMBusChanReq *req); +void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size); + #endif -- 2.24.1
[PATCH v2 6/7] i386: Hyper-V VMBus ACPI DSDT entry
Guest OS uses ACPI to discover VMBus presence. Add a corresponding entry to DSDT in case VMBus has been enabled. Experimentally Windows guests were found to require this entry to include two IRQ resources. They seem to never be used but they still have to be there. Make IRQ numbers user-configurable via corresponding properties; use 7 and 13 by default. Signed-off-by: Evgeny Yakovlev Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/hyperv/vmbus.c| 7 ++ hw/i386/acpi-build.c | 43 include/hw/hyperv/vmbus-bridge.h | 3 +++ 3 files changed, 53 insertions(+) diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index 4baf1d1266..46c6f5eebb 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -2641,6 +2641,12 @@ static const VMStateDescription vmstate_vmbus_bridge = { }, }; +static Property vmbus_bridge_props[] = { +DEFINE_PROP_UINT8("irq0", VMBusBridge, irq0, 7), +DEFINE_PROP_UINT8("irq1", VMBusBridge, irq1, 13), +DEFINE_PROP_END_OF_LIST() +}; + static void vmbus_bridge_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); @@ -2651,6 +2657,7 @@ static void vmbus_bridge_class_init(ObjectClass *klass, void *data) sk->explicit_ofw_unit_address = vmbus_bridge_ofw_unit_address; set_bit(DEVICE_CATEGORY_BRIDGE, k->categories); k->vmsd = &vmstate_vmbus_bridge; +device_class_set_props(k, vmbus_bridge_props); /* override SysBusDevice's default */ k->user_creatable = true; } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2a7e55bae7..d235074fb8 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -50,6 +50,7 @@ #include "hw/mem/nvdimm.h" #include "sysemu/numa.h" #include "sysemu/reset.h" +#include "hw/hyperv/vmbus-bridge.h" /* Supported chipsets: */ #include "hw/southbridge/piix.h" @@ -1270,9 +1271,47 @@ static Aml *build_com_device_aml(uint8_t uid) return dev; } +static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) +{ +Aml *dev; +Aml *method; +Aml *crs; + +dev = aml_device("VMBS"); +aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); +aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); +aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); + +method = aml_method("_DIS", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_and(aml_name("STA"), aml_int(0xD), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_PS0", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_or(aml_name("STA"), aml_int(0xF), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_STA", 0, AML_NOTSERIALIZED); +aml_append(method, aml_return(aml_name("STA"))); +aml_append(dev, method); + +aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); + +crs = aml_resource_template(); +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq0)); +/* FIXME: newer HyperV gets by with only one IRQ */ +aml_append(crs, aml_irq_no_flags(vmbus_bridge->irq1)); +aml_append(dev, aml_name_decl("_CRS", crs)); + +return dev; +} + static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); +VMBusBridge *vmbus_bridge = vmbus_bridge_find(); bool ambiguous; Aml *scope = aml_scope("_SB.PCI0.ISA"); @@ -1296,6 +1335,10 @@ static void build_isa_devices_aml(Aml *table) build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); } +if (vmbus_bridge) { +aml_append(scope, build_vmbus_device_aml(vmbus_bridge)); +} + aml_append(table, scope); } diff --git a/include/hw/hyperv/vmbus-bridge.h b/include/hw/hyperv/vmbus-bridge.h index 9cc8f780de..c0a06d832c 100644 --- a/include/hw/hyperv/vmbus-bridge.h +++ b/include/hw/hyperv/vmbus-bridge.h @@ -19,6 +19,9 @@ typedef struct VMBus VMBus; typedef struct VMBusBridge { SysBusDevice parent_obj; +uint8_t irq0; +uint8_t irq1; + VMBus *bus; } VMBusBridge; -- 2.24.1
[PATCH v2 2/7] hyperv: SControl is optional to enable SynIc
SynIc can be enabled regardless of the SControl mechanisim which can register a GSI for a given SintRoute. This behaviour can achived by setting enabling SIMP and then the guest will poll on the message slot. Once there is another message pending the host will set the message slot with the pending flag. When the guest polls from the message slot, incase the pending flag is set it will write to the HV_X64_MSR_EOM indicating it has cleared the slow and we can try and push our message again. Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 242 - include/hw/hyperv/hyperv.h | 2 + target/i386/hyperv.c | 2 + 3 files changed, 164 insertions(+), 82 deletions(-) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index ddf4f32c60..1dc577a0ab 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -20,18 +20,72 @@ #include "qemu/rcu_queue.h" #include "hw/hyperv/hyperv.h" +/* + * KVM has its own message producers (SynIC timers). To guarantee + * serialization with both KVM vcpu and the guest cpu, the messages are first + * staged in an intermediate area and then posted to the SynIC message page in + * the vcpu thread. + */ +typedef struct HvSintStagedMessage { +/* message content staged by hyperv_post_msg */ +struct hyperv_message msg; +/* callback + data (r/o) to complete the processing in a BH */ +HvSintMsgCb cb; +void *cb_data; +/* message posting status filled by cpu_post_msg */ +int status; +/* passing the buck: */ +enum { +/* initial state */ +HV_STAGED_MSG_FREE, +/* + * hyperv_post_msg (e.g. in main loop) grabs the staged area (FREE -> + * BUSY), copies msg, and schedules cpu_post_msg on the assigned cpu + */ +HV_STAGED_MSG_BUSY, +/* + * cpu_post_msg (vcpu thread) tries to copy staged msg to msg slot, + * notify the guest, records the status, marks the posting done (BUSY + * -> POSTED), and schedules sint_msg_bh BH + */ +HV_STAGED_MSG_POSTED, +/* + * sint_msg_bh (BH) verifies that the posting is done, runs the + * callback, and starts over (POSTED -> FREE) + */ +} state; +} HvSintStagedMessage; + +struct SynICState; + +struct HvSintRoute { +uint32_t sint; +struct SynICState *synic; +int gsi; +EventNotifier sint_set_notifier; +EventNotifier sint_ack_notifier; + +HvSintStagedMessage *staged_msg; + +unsigned refcount; +QLIST_ENTRY(HvSintRoute) link; +}; + typedef struct SynICState { DeviceState parent_obj; CPUState *cs; -bool enabled; +bool sctl_enabled; hwaddr msg_page_addr; hwaddr event_page_addr; MemoryRegion msg_page_mr; MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; + +QemuMutex sint_routes_mutex; +QLIST_HEAD(, HvSintRoute) sint_routes; } SynICState; #define TYPE_SYNIC "hyperv-synic" @@ -49,11 +103,11 @@ static SynICState *get_synic(CPUState *cs) return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); } -static void synic_update(SynICState *synic, bool enable, +static void synic_update(SynICState *synic, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { -synic->enabled = enable; +synic->sctl_enabled = sctl_enable; if (synic->msg_page_addr != msg_page_addr) { if (synic->msg_page_addr) { memory_region_del_subregion(get_system_memory(), @@ -78,7 +132,7 @@ static void synic_update(SynICState *synic, bool enable, } } -void hyperv_synic_update(CPUState *cs, bool enable, +void hyperv_synic_update(CPUState *cs, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { SynICState *synic = get_synic(cs); @@ -87,7 +141,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, return; } -synic_update(synic, enable, msg_page_addr, event_page_addr); +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); } static void synic_realize(DeviceState *dev, Error **errp) @@ -108,16 +162,20 @@ static void synic_realize(DeviceState *dev, Error **errp) sizeof(*synic->event_page), &error_abort); synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); +qemu_mutex_init(&synic->sint_routes_mutex); +QLIST_INIT(&synic->sint_routes); g_free(msgp_name); g_free(eventp_name); } + static void synic_reset(DeviceState *dev) { SynICState *synic = SYNIC(dev); memset(synic->msg_page, 0, sizeof(*synic->msg_page)); memset(synic->event_page, 0, sizeof(*synic->event_page)); synic_update(synic, false,
[PATCH v2 5/7] i386:pc: whitelist dynamic vmbus-bridge
As vmbus-bridge is derived from sysbus device, it has to be whitelisted to be allowed to be created with -device. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- hw/i386/pc_piix.c | 2 ++ hw/i386/pc_q35.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 9cceae3e2c..6daa0770fa 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -60,6 +60,7 @@ #include "migration/global_state.h" #include "migration/misc.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" #define MAX_IDE_BUS 2 @@ -417,6 +418,7 @@ static void pc_i440fx_machine_options(MachineClass *m) m->default_machine_opts = "firmware=bios-256k.bin"; m->default_display = "std"; machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } static void pc_i440fx_5_0_machine_options(MachineClass *m) diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index d37c425e22..faaa39ced2 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -53,6 +53,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/numa.h" +#include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" /* ICH9 AHCI has 6 ports */ @@ -346,6 +347,7 @@ static void pc_q35_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); m->max_cpus = 288; } -- 2.24.1
[PATCH v2 3/7] vmbus: add vmbus protocol definitions
Add a header with data structures and constants used in Hyper-V VMBus hypervisor <-> guest interactions. Based on the respective stuff from Linux kernel. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- include/hw/hyperv/vmbus-proto.h | 222 1 file changed, 222 insertions(+) create mode 100644 include/hw/hyperv/vmbus-proto.h diff --git a/include/hw/hyperv/vmbus-proto.h b/include/hw/hyperv/vmbus-proto.h new file mode 100644 index 00..4628d3b323 --- /dev/null +++ b/include/hw/hyperv/vmbus-proto.h @@ -0,0 +1,222 @@ +/* + * QEMU Hyper-V VMBus support + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_HYPERV_VMBUS_PROTO_H +#define HW_HYPERV_VMBUS_PROTO_H + +#define VMBUS_VERSION_WS2008((0 << 16) | (13)) +#define VMBUS_VERSION_WIN7 ((1 << 16) | (1)) +#define VMBUS_VERSION_WIN8 ((2 << 16) | (4)) +#define VMBUS_VERSION_WIN8_1((3 << 16) | (0)) +#define VMBUS_VERSION_WIN10 ((4 << 16) | (0)) +#define VMBUS_VERSION_INVAL -1 +#define VMBUS_VERSION_CURRENT VMBUS_VERSION_WIN10 + +#define VMBUS_MESSAGE_CONNECTION_ID 1 +#define VMBUS_EVENT_CONNECTION_ID 2 +#define VMBUS_MONITOR_CONNECTION_ID 3 +#define VMBUS_SINT 2 + +#define VMBUS_MSG_INVALID 0 +#define VMBUS_MSG_OFFERCHANNEL 1 +#define VMBUS_MSG_RESCIND_CHANNELOFFER 2 +#define VMBUS_MSG_REQUESTOFFERS 3 +#define VMBUS_MSG_ALLOFFERS_DELIVERED 4 +#define VMBUS_MSG_OPENCHANNEL 5 +#define VMBUS_MSG_OPENCHANNEL_RESULT6 +#define VMBUS_MSG_CLOSECHANNEL 7 +#define VMBUS_MSG_GPADL_HEADER 8 +#define VMBUS_MSG_GPADL_BODY9 +#define VMBUS_MSG_GPADL_CREATED 10 +#define VMBUS_MSG_GPADL_TEARDOWN11 +#define VMBUS_MSG_GPADL_TORNDOWN12 +#define VMBUS_MSG_RELID_RELEASED13 +#define VMBUS_MSG_INITIATE_CONTACT 14 +#define VMBUS_MSG_VERSION_RESPONSE 15 +#define VMBUS_MSG_UNLOAD16 +#define VMBUS_MSG_UNLOAD_RESPONSE 17 +#define VMBUS_MSG_COUNT 18 + +#define VMBUS_MESSAGE_SIZE_ALIGNsizeof(uint64_t) + +#define VMBUS_PACKET_INVALID0x0 +#define VMBUS_PACKET_SYNCH 0x1 +#define VMBUS_PACKET_ADD_XFER_PAGESET 0x2 +#define VMBUS_PACKET_RM_XFER_PAGESET0x3 +#define VMBUS_PACKET_ESTABLISH_GPADL0x4 +#define VMBUS_PACKET_TEARDOWN_GPADL 0x5 +#define VMBUS_PACKET_DATA_INBAND0x6 +#define VMBUS_PACKET_DATA_USING_XFER_PAGES 0x7 +#define VMBUS_PACKET_DATA_USING_GPADL 0x8 +#define VMBUS_PACKET_DATA_USING_GPA_DIRECT 0x9 +#define VMBUS_PACKET_CANCEL_REQUEST 0xa +#define VMBUS_PACKET_COMP 0xb +#define VMBUS_PACKET_DATA_USING_ADDITIONAL_PKT 0xc +#define VMBUS_PACKET_ADDITIONAL_DATA0xd + +#define VMBUS_CHANNEL_USER_DATA_SIZE120 + +#define VMBUS_OFFER_MONITOR_ALLOCATED 0x1 +#define VMBUS_OFFER_INTERRUPT_DEDICATED 0x1 + +#define VMBUS_RING_BUFFER_FEAT_PENDING_SZ (1ul << 0) + +#define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE 0x1 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_TRANSFER_PAGES 0x2 +#define VMBUS_CHANNEL_SERVER_SUPPORTS_GPADLS 0x4 +#define VMBUS_CHANNEL_NAMED_PIPE_MODE 0x10 +#define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100 +#define VMBUS_CHANNEL_PARENT_OFFER0x200 +#define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400 +#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER0x2000 + +#define VMBUS_PACKET_FLAG_REQUEST_COMPLETION1 + +typedef struct vmbus_message_header { +uint32_t message_type; +uint32_t _padding; +} vmbus_message_header; + +typedef struct vmbus_message_initiate_contact { +vmbus_message_header header; +uint32_t version_requested; +uint32_t target_vcpu; +uint64_t interrupt_page; +uint64_t monitor_page1; +uint64_t monitor_page2; +} vmbus_message_initiate_contact; + +typedef struct vmbus_message_version_response { +vmbus_message_header header; +uint8_t version_supported; +uint8_t status; +} vmbus_message_version_response; + +typedef struct vmbus_message_offer_channel { +vmbus_message_header header; +uint8_t type_uuid[16]; +uint8_t instance_uuid[16]; +uint64_t _reserved1; +uint64_t _reserved2; +uint16_t channel_flags; +uint16_t mmio_size_mb; +uint8_t user_data[VMBUS_CHANNEL_USER_DATA_SIZE]; +uint16_t sub_channel_index; +uint16_t _reserved3; +uint32_t child_relid; +uint8_t monitor_id;
[PATCH v2 0/7] hyperv: VMBus implementation
This is a rebase of the old patchset from Roman for HyperV VMBus implementation. How to use: -device vmbus-bridge Later on new paravirtualized devices can be implemented on top of it (Network/SCSI/etc.) VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. Jon Doron (7): hyperv: expose API to determine if synic is enabled hyperv: SControl is optional to enable SynIc vmbus: add vmbus protocol definitions vmbus: vmbus implementation i386:pc: whitelist dynamic vmbus-bridge i386: Hyper-V VMBus ACPI DSDT entry vmbus: add infrastructure to save/load vmbus requests Makefile.objs|1 + hw/hyperv/Kconfig|5 + hw/hyperv/Makefile.objs |1 + hw/hyperv/hyperv.c | 250 ++- hw/hyperv/trace-events | 18 + hw/hyperv/vmbus.c| 2778 ++ hw/i386/acpi-build.c | 43 + hw/i386/pc_piix.c|2 + hw/i386/pc_q35.c |2 + include/hw/hyperv/hyperv.h |3 + include/hw/hyperv/vmbus-bridge.h | 35 + include/hw/hyperv/vmbus-proto.h | 222 +++ include/hw/hyperv/vmbus.h| 230 +++ target/i386/hyperv.c |2 + 14 files changed, 3510 insertions(+), 82 deletions(-) create mode 100644 hw/hyperv/trace-events create mode 100644 hw/hyperv/vmbus.c create mode 100644 include/hw/hyperv/vmbus-bridge.h create mode 100644 include/hw/hyperv/vmbus-proto.h create mode 100644 include/hw/hyperv/vmbus.h -- 2.24.1
[PATCH v2 1/7] hyperv: expose API to determine if synic is enabled
Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 8 include/hw/hyperv/hyperv.h | 1 + 2 files changed, 9 insertions(+) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index 8ca3706f5b..ddf4f32c60 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -37,6 +37,13 @@ typedef struct SynICState { #define TYPE_SYNIC "hyperv-synic" #define SYNIC(obj) OBJECT_CHECK(SynICState, (obj), TYPE_SYNIC) +static bool synic_enabled; + +bool hyperv_is_synic_enabled(void) +{ +return synic_enabled; +} + static SynICState *get_synic(CPUState *cs) { return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); @@ -133,6 +140,7 @@ void hyperv_synic_add(CPUState *cs) object_property_add_child(OBJECT(cs), "synic", obj, &error_abort); object_unref(obj); object_property_set_bool(obj, true, "realized", &error_abort); +synic_enabled = true; } void hyperv_synic_reset(CPUState *cs) diff --git a/include/hw/hyperv/hyperv.h b/include/hw/hyperv/hyperv.h index 597381cb01..a63ee0003c 100644 --- a/include/hw/hyperv/hyperv.h +++ b/include/hw/hyperv/hyperv.h @@ -79,5 +79,6 @@ void hyperv_synic_add(CPUState *cs); void hyperv_synic_reset(CPUState *cs); void hyperv_synic_update(CPUState *cs, bool enable, hwaddr msg_page_addr, hwaddr event_page_addr); +bool hyperv_is_synic_enabled(void); #endif -- 2.24.1
[PATCH v2 4/7] vmbus: vmbus implementation
Add the VMBus infrastructure -- bus, devices, root bridge, vmbus state machine, vmbus channel interactions, etc. VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. TODO: - split into smaller palatable pieces - more comments - check and handle corner cases Kudos to Evgeny Yakovlev (formerly eyakov...@virtuozzo.com) and Andrey Smetatin (formerly asmeta...@virtuozzo.com) for research and prototyping. Signed-off-by: Roman Kagan Signed-off-by: Maciej S. Szmigiero Signed-off-by: Jon Doron --- Makefile.objs|1 + hw/hyperv/Kconfig|5 + hw/hyperv/Makefile.objs |1 + hw/hyperv/trace-events | 18 + hw/hyperv/vmbus.c| 2672 ++ include/hw/hyperv/vmbus-bridge.h | 32 + include/hw/hyperv/vmbus.h| 227 +++ 7 files changed, 2956 insertions(+) create mode 100644 hw/hyperv/trace-events create mode 100644 hw/hyperv/vmbus.c create mode 100644 include/hw/hyperv/vmbus-bridge.h create mode 100644 include/hw/hyperv/vmbus.h diff --git a/Makefile.objs b/Makefile.objs index a7c967633a..1ef80ce58f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -151,6 +151,7 @@ trace-events-subdirs += hw/block/dataplane trace-events-subdirs += hw/char trace-events-subdirs += hw/dma trace-events-subdirs += hw/hppa +trace-events-subdirs += hw/hyperv trace-events-subdirs += hw/i2c trace-events-subdirs += hw/i386 trace-events-subdirs += hw/i386/xen diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig index a1fa8ff9be..3fbfe41c9e 100644 --- a/hw/hyperv/Kconfig +++ b/hw/hyperv/Kconfig @@ -6,3 +6,8 @@ config HYPERV_TESTDEV bool default y if TEST_DEVICES depends on HYPERV + +config VMBUS +bool +default y +depends on HYPERV diff --git a/hw/hyperv/Makefile.objs b/hw/hyperv/Makefile.objs index edaca2f763..5b614e040c 100644 --- a/hw/hyperv/Makefile.objs +++ b/hw/hyperv/Makefile.objs @@ -1,2 +1,3 @@ obj-y += hyperv.o obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o +obj-$(CONFIG_VMBUS) += vmbus.o diff --git a/hw/hyperv/trace-events b/hw/hyperv/trace-events new file mode 100644 index 00..ba5bd62d61 --- /dev/null +++ b/hw/hyperv/trace-events @@ -0,0 +1,18 @@ +# vmbus +vmbus_recv_message(uint32_t type, uint32_t size) "type %d size %d" +vmbus_signal_event(void) "" +vmbus_channel_notify_guest(uint32_t chan_id) "channel #%d" +vmbus_post_msg(uint32_t type, uint32_t size) "type %d size %d" +vmbus_msg_cb(int status) "message status %d" +vmbus_process_incoming_message(uint32_t message_type) "type %d" +vmbus_initiate_contact(uint16_t major, uint16_t minor, uint32_t vcpu, uint64_t monitor_page1, uint64_t monitor_page2, uint64_t interrupt_page) "version %d.%d target vp %d mon pages 0x%"PRIx64",0x%"PRIx64" int page 0x%"PRIx64 +vmbus_send_offer(uint32_t chan_id, void *dev) "channel #%d dev %p" +vmbus_terminate_offers(void) "" +vmbus_gpadl_header(uint32_t gpadl_id, uint16_t num_gfns) "gpadl #%d gfns %d" +vmbus_gpadl_body(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_created(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_teardown(uint32_t gpadl_id) "gpadl #%d" +vmbus_gpadl_torndown(uint32_t gpadl_id) "gpadl #%d" +vmbus_open_channel(uint32_t chan_id, uint32_t gpadl_id, uint32_t target_vp) "channel #%d gpadl #%d target vp %d" +vmbus_channel_open(uint32_t chan_id, uint32_t status) "channel #%d status %d" +vmbus_close_channel(uint32_t chan_id) "channel #%d" diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c new file mode 100644 index 00..4baf1d1266 --- /dev/null +++ b/hw/hyperv/vmbus.c @@ -0,0 +1,2672 @@ +/* + * QEMU Hyper-V VMBus + * + * Copyright (c) 2017-2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/qdev-prope
Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
Thank you Maciej it seems like your version is really ahead I'll do the required work and merge it so i can submit a v2 with the latest patchset from Roman On Fri, Apr 3, 2020 at 6:06 PM Jon Doron wrote: > > Thank you Maciej, I based it on top of what Denis (d...@openvz.org) gave me > which was this: > https://ftp.openvz.org/virtuozzo/releases/openvz-7.0.12-288/source/SRPMS/q/qemu-kvm-vz-2.12.0-33.vz7.14.4.src.rpm > > Do you think you have a more recent version I dont mind diffing and > resubmitting a new version of the patchset? > > Thanks, > -- Jon. > > On Fri, Apr 3, 2020 at 5:56 PM Maciej S. Szmigiero > wrote: > > > > Hi Jon, > > > > On 03.04.2020 16:23, Jon Doron wrote: > > > Guest OS uses ACPI to discover vmbus presence. Add a corresponding > > > entry to DSDT in case vmbus has been enabled. > > > > > > Experimentally Windows guests were found to require this entry to > > > include two IRQ resources, so this patch adds two semi-arbitrarily > > > chosen ones (7 and 13). This results, in particular, in parallel port > > > conflicting with vmbus. > > > > > > TODO: discover and use spare IRQs to avoid conflicts. > > > > > > Signed-off-by: Evgeny Yakovlev > > > Signed-off-by: Roman Kagan > > > Signed-off-by: Jon Doron > > > > Nice work, thanks! > > > > However, it seems to be based on the code version that was posted in > > February 2018, and not the latest version in OpenVZ qemu repository > > dated October 2019: > > https://src.openvz.org/projects/UP/repos/qemu/commits?until=refs%2Fheads%2Fvmbus > > > > This newer version has slightly different API here and there. > > Any particular reason for selecting that older version for porting? > > > > I have actually rebased this latest version on the top of the current > > QEMU master, and it basically seems to work fine. > > However, I haven't done extensive tests whether there isn't a memory leak > > somewhere or so on. > > > > Maciej
Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
Thank you Maciej, I based it on top of what Denis (d...@openvz.org) gave me which was this: https://ftp.openvz.org/virtuozzo/releases/openvz-7.0.12-288/source/SRPMS/q/qemu-kvm-vz-2.12.0-33.vz7.14.4.src.rpm Do you think you have a more recent version I dont mind diffing and resubmitting a new version of the patchset? Thanks, -- Jon. On Fri, Apr 3, 2020 at 5:56 PM Maciej S. Szmigiero wrote: > > Hi Jon, > > On 03.04.2020 16:23, Jon Doron wrote: > > Guest OS uses ACPI to discover vmbus presence. Add a corresponding > > entry to DSDT in case vmbus has been enabled. > > > > Experimentally Windows guests were found to require this entry to > > include two IRQ resources, so this patch adds two semi-arbitrarily > > chosen ones (7 and 13). This results, in particular, in parallel port > > conflicting with vmbus. > > > > TODO: discover and use spare IRQs to avoid conflicts. > > > > Signed-off-by: Evgeny Yakovlev > > Signed-off-by: Roman Kagan > > Signed-off-by: Jon Doron > > Nice work, thanks! > > However, it seems to be based on the code version that was posted in > February 2018, and not the latest version in OpenVZ qemu repository > dated October 2019: > https://src.openvz.org/projects/UP/repos/qemu/commits?until=refs%2Fheads%2Fvmbus > > This newer version has slightly different API here and there. > Any particular reason for selecting that older version for porting? > > I have actually rebased this latest version on the top of the current > QEMU master, and it basically seems to work fine. > However, I haven't done extensive tests whether there isn't a memory leak > somewhere or so on. > > Maciej
[PATCH v1 4/5] vmbus: vmbus implementation
Add the VMBus infrastructure -- bus, devices, root bridge, vmbus state machine, vmbus channel interactions, etc. TODO: - split into smaller palatable pieces - more comments - check and handle corner cases Kudos to Evgeny Yakovlev (formerly eyakov...@virtuozzo.com) and Andrey Smetatin (formerly asmeta...@virtuozzo.com) for research and prototyping. VMBus is a collection of technologies. At its lowest layer, it's a message passing and signaling mechanism, allowing efficient passing of messages to and from guest VMs. A layer higher, it's a mechanism for defining channels of communication, where each channel is tagged with a type (which implies a protocol) and a instance ID. A layer higher than that, it's a bus driver, serving as the basis of device enumeration within a VM, where a channel can optionally be exposed as a paravirtual device. When a server-side (paravirtual back-end) component wishes to offer a channel to a guest VM, it does so by specifying a channel type, a mode, and an instance ID. VMBus then exposes this in the guest. More information about VMBus can be found in the file vmbuskernelmodeclientlibapi.h in Microsoft's WDK. Signed-off-by: Roman Kagan Signed-off-by: Jon Doron --- Makefile.objs|1 + hw/Kconfig |1 + hw/Makefile.objs |1 + hw/i386/Kconfig |1 + hw/i386/pc_q35.c |2 + hw/vmbus/Kconfig |3 + hw/vmbus/Makefile.objs |1 + hw/vmbus/trace-events|8 + hw/vmbus/vmbus.c | 2422 ++ include/hw/vmbus/vmbus.h | 109 ++ 10 files changed, 2549 insertions(+) create mode 100644 hw/vmbus/Kconfig create mode 100644 hw/vmbus/Makefile.objs create mode 100644 hw/vmbus/trace-events create mode 100644 hw/vmbus/vmbus.c create mode 100644 include/hw/vmbus/vmbus.h diff --git a/Makefile.objs b/Makefile.objs index a7c967633a..4943e7bf73 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -185,6 +185,7 @@ trace-events-subdirs += hw/watchdog trace-events-subdirs += hw/xen trace-events-subdirs += hw/gpio trace-events-subdirs += hw/riscv +trace-events-subdirs += hw/vmbus trace-events-subdirs += migration trace-events-subdirs += net trace-events-subdirs += ui diff --git a/hw/Kconfig b/hw/Kconfig index ecf491bf04..49ace0a4b5 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -39,6 +39,7 @@ source usb/Kconfig source virtio/Kconfig source vfio/Kconfig source watchdog/Kconfig +source vmbus/Kconfig # arch Kconfig source arm/Kconfig diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 660e2b4373..9037bc8095 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -40,6 +40,7 @@ devices-dirs-$(CONFIG_MEM_DEVICE) += mem/ devices-dirs-$(CONFIG_NUBUS) += nubus/ devices-dirs-y += semihosting/ devices-dirs-y += smbios/ +devices-dirs-$(CONFIG_VMBUS) += vmbus/ endif common-obj-y += $(devices-dirs-y) diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index c93f32f657..838ec28667 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -23,6 +23,7 @@ config PC imply TPM_TIS_ISA imply VGA_PCI imply VIRTIO_VGA +imply VMBUS select FDC select I8259 select I8254 diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index d37c425e22..767c137718 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -54,6 +54,7 @@ #include "qemu/error-report.h" #include "sysemu/numa.h" #include "hw/mem/nvdimm.h" +#include "hw/vmbus/vmbus.h" /* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6 @@ -346,6 +347,7 @@ static void pc_q35_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); +machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); m->max_cpus = 288; } diff --git a/hw/vmbus/Kconfig b/hw/vmbus/Kconfig new file mode 100644 index 00..e925c2a9be --- /dev/null +++ b/hw/vmbus/Kconfig @@ -0,0 +1,3 @@ +config VMBUS +bool +depends on HYPERV diff --git a/hw/vmbus/Makefile.objs b/hw/vmbus/Makefile.objs new file mode 100644 index 00..3f0708588e --- /dev/null +++ b/hw/vmbus/Makefile.objs @@ -0,0 +1 @@ +obj-y += vmbus.o diff --git a/hw/vmbus/trace-events b/hw/vmbus/trace-events new file mode 100644 index 00..4e1c507cb8 --- /dev/null +++ b/hw/vmbus/trace-events @@ -0,0 +1,8 @@ +# vmbus +vmbus_initiate_contact(uint32_t version, uint32_t vcpu, uint64_t monitor_page1, uint64_t monitor_page2, uint64_t interrupt_page) "version requested %d, target vcpu %d, monitor pages 0x%"PRIx64" 0x%"PRIx64", interrupt page 0x%"PRIx64"" +vmbus_recv_message(uint32_t type, uint32_t size) "recvd message type %d, size %d" +vmbus_signal_event(void) "vmbus event signaled" +vmbus_signal_channel(uint32_t relid) "sign
[PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry
Guest OS uses ACPI to discover vmbus presence. Add a corresponding entry to DSDT in case vmbus has been enabled. Experimentally Windows guests were found to require this entry to include two IRQ resources, so this patch adds two semi-arbitrarily chosen ones (7 and 13). This results, in particular, in parallel port conflicting with vmbus. TODO: discover and use spare IRQs to avoid conflicts. Signed-off-by: Evgeny Yakovlev Signed-off-by: Roman Kagan Signed-off-by: Jon Doron --- hw/i386/acpi-build.c | 42 ++ 1 file changed, 42 insertions(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 2a7e55bae7..6d7fdbbe9b 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -43,6 +43,7 @@ #include "hw/acpi/tpm.h" #include "hw/acpi/vmgenid.h" #include "hw/boards.h" +#include "hw/vmbus/vmbus.h" #include "sysemu/tpm_backend.h" #include "hw/rtc/mc146818rtc_regs.h" #include "migration/vmstate.h" @@ -1270,6 +1271,43 @@ static Aml *build_com_device_aml(uint8_t uid) return dev; } +static Aml *build_vmbus_device_aml(void) +{ +Aml *dev; +Aml *method; +Aml *crs; + +dev = aml_device("VMBS"); +aml_append(dev, aml_name_decl("STA", aml_int(0xF))); +aml_append(dev, aml_name_decl("_HID", aml_string("VMBus"))); +aml_append(dev, aml_name_decl("_UID", aml_int(0x0))); +aml_append(dev, aml_name_decl("_DDN", aml_string("VMBUS"))); + +method = aml_method("_DIS", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_and(aml_name("STA"), aml_int(0xD), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_PS0", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_or(aml_name("STA"), aml_int(0xF), NULL), + aml_name("STA"))); +aml_append(dev, method); + +method = aml_method("_STA", 0, AML_NOTSERIALIZED); +aml_append(method, aml_store(aml_name("STA"), aml_local(0))); +aml_append(method, aml_return(aml_local(0))); +aml_append(dev, method); + +aml_append(dev, aml_name_decl("_PS3", aml_int(0x0))); + +crs = aml_resource_template(); +aml_append(crs, aml_irq_no_flags(7)); +aml_append(crs, aml_irq_no_flags(13)); +aml_append(dev, aml_name_decl("_CRS", crs)); + +return dev; +} + static void build_isa_devices_aml(Aml *table) { ISADevice *fdc = pc_find_fdc0(); @@ -1296,6 +1334,10 @@ static void build_isa_devices_aml(Aml *table) build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); } +if (vmbus_exists()) { +aml_append(scope, build_vmbus_device_aml()); +} + aml_append(table, scope); } -- 2.24.1
[PATCH v1 2/5] hyperv: SControl is optional to enable SynIc
SynIc can be enabled regardless of the SControl mechanisim which can register a GSI for a given SintRoute. This behaviour can achived by setting enabling SIMP and then the guest will poll on the message slot. Once there is another message pending the host will set the message slot with the pending flag. When the guest polls from the message slot, incase the pending flag is set it will write to the HV_X64_MSR_EOM indicating it has cleared the slow and we can try and push our message again. Signed-off-by: Jon Doron --- hw/hyperv/hyperv.c | 242 - include/hw/hyperv/hyperv.h | 2 + target/i386/hyperv.c | 2 + 3 files changed, 164 insertions(+), 82 deletions(-) diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c index ddf4f32c60..1dc577a0ab 100644 --- a/hw/hyperv/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -20,18 +20,72 @@ #include "qemu/rcu_queue.h" #include "hw/hyperv/hyperv.h" +/* + * KVM has its own message producers (SynIC timers). To guarantee + * serialization with both KVM vcpu and the guest cpu, the messages are first + * staged in an intermediate area and then posted to the SynIC message page in + * the vcpu thread. + */ +typedef struct HvSintStagedMessage { +/* message content staged by hyperv_post_msg */ +struct hyperv_message msg; +/* callback + data (r/o) to complete the processing in a BH */ +HvSintMsgCb cb; +void *cb_data; +/* message posting status filled by cpu_post_msg */ +int status; +/* passing the buck: */ +enum { +/* initial state */ +HV_STAGED_MSG_FREE, +/* + * hyperv_post_msg (e.g. in main loop) grabs the staged area (FREE -> + * BUSY), copies msg, and schedules cpu_post_msg on the assigned cpu + */ +HV_STAGED_MSG_BUSY, +/* + * cpu_post_msg (vcpu thread) tries to copy staged msg to msg slot, + * notify the guest, records the status, marks the posting done (BUSY + * -> POSTED), and schedules sint_msg_bh BH + */ +HV_STAGED_MSG_POSTED, +/* + * sint_msg_bh (BH) verifies that the posting is done, runs the + * callback, and starts over (POSTED -> FREE) + */ +} state; +} HvSintStagedMessage; + +struct SynICState; + +struct HvSintRoute { +uint32_t sint; +struct SynICState *synic; +int gsi; +EventNotifier sint_set_notifier; +EventNotifier sint_ack_notifier; + +HvSintStagedMessage *staged_msg; + +unsigned refcount; +QLIST_ENTRY(HvSintRoute) link; +}; + typedef struct SynICState { DeviceState parent_obj; CPUState *cs; -bool enabled; +bool sctl_enabled; hwaddr msg_page_addr; hwaddr event_page_addr; MemoryRegion msg_page_mr; MemoryRegion event_page_mr; struct hyperv_message_page *msg_page; struct hyperv_event_flags_page *event_page; + +QemuMutex sint_routes_mutex; +QLIST_HEAD(, HvSintRoute) sint_routes; } SynICState; #define TYPE_SYNIC "hyperv-synic" @@ -49,11 +103,11 @@ static SynICState *get_synic(CPUState *cs) return SYNIC(object_resolve_path_component(OBJECT(cs), "synic")); } -static void synic_update(SynICState *synic, bool enable, +static void synic_update(SynICState *synic, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { -synic->enabled = enable; +synic->sctl_enabled = sctl_enable; if (synic->msg_page_addr != msg_page_addr) { if (synic->msg_page_addr) { memory_region_del_subregion(get_system_memory(), @@ -78,7 +132,7 @@ static void synic_update(SynICState *synic, bool enable, } } -void hyperv_synic_update(CPUState *cs, bool enable, +void hyperv_synic_update(CPUState *cs, bool sctl_enable, hwaddr msg_page_addr, hwaddr event_page_addr) { SynICState *synic = get_synic(cs); @@ -87,7 +141,7 @@ void hyperv_synic_update(CPUState *cs, bool enable, return; } -synic_update(synic, enable, msg_page_addr, event_page_addr); +synic_update(synic, sctl_enable, msg_page_addr, event_page_addr); } static void synic_realize(DeviceState *dev, Error **errp) @@ -108,16 +162,20 @@ static void synic_realize(DeviceState *dev, Error **errp) sizeof(*synic->event_page), &error_abort); synic->msg_page = memory_region_get_ram_ptr(&synic->msg_page_mr); synic->event_page = memory_region_get_ram_ptr(&synic->event_page_mr); +qemu_mutex_init(&synic->sint_routes_mutex); +QLIST_INIT(&synic->sint_routes); g_free(msgp_name); g_free(eventp_name); } + static void synic_reset(DeviceState *dev) { SynICState *synic = SYNIC(dev); memset(synic->msg_page, 0, sizeof(*synic->msg_page)); memset(synic->event_page, 0, sizeof(*synic->event_page)); synic_update(synic, false,
[PATCH v1 0/5] hyperv: VMBus implementation
This is a rebase of the old patchset from Roman for HyperV VMBus implementation. How to use: -device vmbus-bridge Later on new paravirtualized devices can be implemented on top of it (Network/SCSI/etc.) Jon Doron (5): hyperv: expose API to determine if synic is enabled hyperv: SControl is optional to enable SynIc vmbus: add vmbus protocol definitions vmbus: vmbus implementation i386: Hyper-V VMBus ACPI DSDT entry Makefile.objs |1 + hw/Kconfig |1 + hw/Makefile.objs |1 + hw/hyperv/hyperv.c | 250 ++-- hw/i386/Kconfig|1 + hw/i386/acpi-build.c | 42 + hw/i386/pc_q35.c |2 + hw/vmbus/Kconfig |3 + hw/vmbus/Makefile.objs |1 + hw/vmbus/trace-events |8 + hw/vmbus/vmbus.c | 2422 include/hw/hyperv/hyperv.h |3 + include/hw/vmbus/vmbus-proto.h | 222 +++ include/hw/vmbus/vmbus.h | 109 ++ target/i386/hyperv.c |2 + 15 files changed, 2986 insertions(+), 82 deletions(-) create mode 100644 hw/vmbus/Kconfig create mode 100644 hw/vmbus/Makefile.objs create mode 100644 hw/vmbus/trace-events create mode 100644 hw/vmbus/vmbus.c create mode 100644 include/hw/vmbus/vmbus-proto.h create mode 100644 include/hw/vmbus/vmbus.h -- 2.24.1