Re: Concerns regarding e17bebd049 ("dump: Set correct vaddr for ELF dump")

2023-09-20 Thread Jon Doron

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);
phdr.p_filesz = cpu_to_dump32(s, filesz);
phdr.p_memsz = cpu_to_dum

[PATCH v3 1/4] hyperv: SControl is optional to enable SynIc

2022-03-15 Thread Jon Doron
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), _abort);
 synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
 synic->event_page = memory_region_get_ram_ptr(>event_page_mr);
+qemu_mutex_init(>sint_routes_mutex);
+QLIST_INIT(>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(>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(_route->sint_set_notifier, false);
-if (r) {
-goto err;
+if (!sint_route) {
+return NULL;
 }
 
+sint_route->synic = synic;
+sint_route->sint = sint;
+sint_route->refcount = 1;
 
 

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

2022-03-15 Thread Jon Doron
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, , 1);
+if (!reset_dbg_session || len < sizeof(*reset_dbg_session)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_CONNECTION_INFO;
+ret = hv_syndbg_handler(hv_syndbg_context, );
+if (ret) {
+goto cleanup;
+}
+
+reset_dbg_session->host_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->host_port = msg.u.connection_info.host_port;
+/* The following fields are only used as validation for KDVM */
+memset(_dbg_session->host_mac, 0,
+   sizeof(reset_dbg_session->host_mac));
+reset_dbg_session->target_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->target_port = msg.u.connection_info.host_port;
+memset(_dbg_session->target_mac, 0,
+   sizeof(reset_dbg_session->target_mac));
+cleanup:
+if (reset_dbg_session) {
+cpu_physical_memory_unmap(reset_dbg_session,
+  sizeof(*reset_dbg_session), 1, len);
+}
+
+return ret;
+}
+
+uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa,
+bool fast)
+{
+uint16_t ret;
+struct hyperv_retrieve_debug_data_input *debug_data_in = NULL;
+struct hyperv_retrieve_debug_data_output *debug_data_out = NULL;
+hwaddr in_len, out_len;
+HvSynDbgMsg msg;
+
+if (fast || !hv_syndbg_handler) {
+ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+goto cleanup;
+}
+
+in_len = sizeof(*debug_data_in);
+debug_data_in = cpu_physical_memory_map(ingpa, _len, 0);
+if (!debug_data_in || in_len < sizeof(*debug_data_in)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+out_len = sizeof(*debug_data_out);
+debug_data_out = cpu_physical_memory_map(outgpa, _len, 1);
+if (!debug_data_out || out_len < sizeof(*debug_data_out)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_RECV;
+msg.u.recv.buf_gpa = outgpa + sizeof(*debug_data_out);
+msg.u.recv.count = TARGET_PAGE_SIZE - sizeof(*debug_data_out);
+msg.u.recv.options = debug_data_in->options;
+msg.u.recv.timeout = debug_data_in->timeout;
+msg.u.recv.is_raw = true;
+re

[PATCH v3 0/4] HyperV: Synthetic Debugging device

2022-03-15 Thread Jon Doron
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

2022-03-15 Thread Jon Doron
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, _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, _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, _data_ofs,
+  >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,
+ MSG_NOSIGNAL, NULL, 0);
+if (sent_count == -1) {
+ret = HV_STA

[PATCH v3 2/4] hyperv: Add definitions for syndbg

2022-03-15 Thread Jon Doron
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

2022-03-06 Thread Jon Doron
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), _abort);
> >  synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
> >  synic->event_page =
> memory_region_get_ram_ptr(>event_page_mr);
> > +qemu_mutex_init(>sint_routes_mutex);
> > +QLIST_INIT(>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(>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;
> >   

Re: [PATCH v2 4/4] hw: hyperv: Initial commit for Synthetic Debugging device

2022-02-23 Thread Jon Doron
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,
> _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

Re: [PATCH v1 2/4] hyperv: Add definitions for syndbg

2022-02-16 Thread Jon Doron

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 B

Re: [PATCH v1 4/4] hw: hyperv: Initial commit for Synthetic Debugging device

2022-02-16 Thread Jon Doron

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, _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

2022-02-16 Thread Jon Doron

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), _abort);
 synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
 synic->event_page = memory_region_get_ram_ptr(>event_page_mr);
+qemu_mutex_init(>sint_routes_mutex);
+QLIST_INIT(>sint_routes);

 g_free(msgp_name);
 g_free(eventp_name);
 }
+
 static void synic_reset(DeviceState *dev)
 {
 SynIC

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

2022-02-16 Thread Jon Doron

On 16/02/2022, Emanuele Giuseppe Esposito wrote:



On 04/02/2022 11:07, Jon Doron wrote:

SynDbg commands can come from two different flows:
1. Hypercalls, in this mode the data being sent is fully
   encapsulated network packets.
2. SynDbg specific MSRs, in this mode only the data that needs to be
   transfered is passed.

Signed-off-by: Jon Doron 
---
 docs/hyperv.txt   |  15 +++
 hw/hyperv/hyperv.c| 242 ++
 include/hw/hyperv/hyperv.h|  58 
 target/i386/cpu.c |   2 +
 target/i386/cpu.h |   7 +
 target/i386/kvm/hyperv-stub.c |   6 +
 target/i386/kvm/hyperv.c  |  52 +++-
 target/i386/kvm/kvm.c |  76 ++-
 8 files changed, 450 insertions(+), 8 deletions(-)

diff --git a/docs/hyperv.txt b/docs/hyperv.txt
index 0417c183a3..7abc1b2d89 100644
--- a/docs/hyperv.txt
+++ b/docs/hyperv.txt
@@ -225,6 +225,21 @@ default (WS2016).
 Note: hv-version-id-* are not enlightenments and thus don't enable Hyper-V
 identification when specified without any other enlightenments.

+3.21. hv-syndbg
+===
+Enables Hyper-V synthetic debugger interface, this is a special interface used
+by Windows Kernel debugger to send the packets through, rather than sending
+them via serial/network .
+Whe enabled, this enlightenment provides additional communication facilities


When


Done

+to the guest: SynDbg messages.
+This new communication is used by Windows Kernel debugger rather than sending
+packets via serial/network, adding significant performance boost over the other
+comm channels.
+This enlightenment requires a VMBus device (-device vmbus-bridge,irq=15)
+and the follow enlightenments to work:
+hv-relaxed,hv_time,hv-vapic,hv-vpindex,hv-synic,hv-runtime,hv-stimer
+
+
 4. Supplementary features
 =

diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 88c9cc1334..c86e2aa02e 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -730,3 +730,245 @@ uint16_t hyperv_hcall_signal_event(uint64_t param, bool 
fast)
 }
 return HV_STATUS_INVALID_CONNECTION_ID;
 }
+
+static HvSynDbgHandler hv_syndbg_handler;
+static void *hv_syndbg_context;


Add a line here between field and function definition.


Done

+void hyperv_set_syndbg_handler(HvSynDbgHandler handler, void *context)
+{
+assert(!hv_syndbg_handler);
+hv_syndbg_handler = handler;
+hv_syndbg_context = context;
+}
+
+uint16_t hyperv_hcall_reset_dbg_session(uint64_t outgpa)
+{
+uint16_t ret;
+HvSynDbgMsg msg;
+struct hyperv_reset_debug_session_output *reset_dbg_session = NULL;
+hwaddr len;
+
+if (!hv_syndbg_handler) {
+ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+goto cleanup;
+}
+
+len = sizeof(*reset_dbg_session);
+reset_dbg_session = cpu_physical_memory_map(outgpa, , 1);
+if (!reset_dbg_session || len < sizeof(*reset_dbg_session)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_CONNECTION_INFO;
+ret = hv_syndbg_handler(hv_syndbg_context, );
+if (ret) {
+goto cleanup;
+}
+
+reset_dbg_session->host_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->host_port = msg.u.connection_info.host_port;
+/* The following fields are only used as validation for KDVM */
+memset(_dbg_session->host_mac, 0,
+   sizeof(reset_dbg_session->host_mac));
+reset_dbg_session->target_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->target_port = msg.u.connection_info.host_port;
+memset(_dbg_session->target_mac, 0,
+   sizeof(reset_dbg_session->target_mac));
+cleanup:
+if (reset_dbg_session) {
+cpu_physical_memory_unmap(reset_dbg_session,
+  sizeof(*reset_dbg_session), 1, len);
+}
+
+return ret;
+}
+
+uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa,
+bool fast)
+{
+uint16_t ret;
+struct hyperv_retrieve_debug_data_input *debug_data_in = NULL;
+struct hyperv_retrieve_debug_data_output *debug_data_out = NULL;
+hwaddr in_len, out_len;
+HvSynDbgMsg msg;
+
+if (fast || !hv_syndbg_handler) {
+ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+goto cleanup;
+}
+
+in_len = sizeof(*debug_data_in);
+debug_data_in = cpu_physical_memory_map(ingpa, _len, 0);
+if (!debug_data_in || in_len < sizeof(*debug_data_in)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+out_len = sizeof(*debug_data_out);
+debug_data_out = cpu_physical_memory_map(outgpa, _len, 1);
+if (!debug_data_out || out_len < sizeof(*debug_data_out)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_RECV;
+msg.u.recv.buf_gpa = outgpa + sizeof(*debug_data_out);
+msg.u.recv.count = TARGET_P

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

2022-02-16 Thread Jon Doron
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, , 1);
+if (!reset_dbg_session || len < sizeof(*reset_dbg_session)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_CONNECTION_INFO;
+ret = hv_syndbg_handler(hv_syndbg_context, );
+if (ret) {
+goto cleanup;
+}
+
+reset_dbg_session->host_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->host_port = msg.u.connection_info.host_port;
+/* The following fields are only used as validation for KDVM */
+memset(_dbg_session->host_mac, 0,
+   sizeof(reset_dbg_session->host_mac));
+reset_dbg_session->target_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->target_port = msg.u.connection_info.host_port;
+memset(_dbg_session->target_mac, 0,
+   sizeof(reset_dbg_session->target_mac));
+cleanup:
+if (reset_dbg_session) {
+cpu_physical_memory_unmap(reset_dbg_session,
+  sizeof(*reset_dbg_session), 1, len);
+}
+
+return ret;
+}
+
+uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa,
+bool fast)
+{
+uint16_t ret;
+struct hyperv_retrieve_debug_data_input *debug_data_in = NULL;
+struct hyperv_retrieve_debug_data_output *debug_data_out = NULL;
+hwaddr in_len, out_len;
+HvSynDbgMsg msg;
+
+if (fast || !hv_syndbg_handler) {
+ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+goto cleanup;
+}
+
+in_len = sizeof(*debug_data_in);
+debug_data_in = cpu_physical_memory_map(ingpa, _len, 0);
+if (!debug_data_in || in_len < sizeof(*debug_data_in)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+out_len = sizeof(*debug_data_out);
+debug_data_out = cpu_physical_memory_map(outgpa, _len, 1);
+if (!debug_data_out || out_len < sizeof(*debug_data_out)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_RECV;
+msg.u.recv.buf_gpa = outgpa + sizeof(*debug_data_out);
+msg.u.recv.count = TARGET_PAGE_SIZE - sizeof(*debug_data_out);
+msg.u.recv.options = debug_data_in->options;
+msg.u.recv.timeout = debug_data_in->timeout;
+msg.u.recv.is_raw = true;
+re

[PATCH v2 0/4] HyperV: Synthetic Debugging device

2022-02-16 Thread Jon Doron
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

2022-02-16 Thread Jon Doron
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

2022-02-16 Thread Jon Doron
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, _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, _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, _data_ofs,
+  >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,
+ MSG_NOSIGNAL, NULL, 0);
+if (sent_count == -1) {
+ret = HV_STA

[PATCH v2 1/4] hyperv: SControl is optional to enable SynIc

2022-02-16 Thread Jon Doron
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), _abort);
 synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
 synic->event_page = memory_region_get_ram_ptr(>event_page_mr);
+qemu_mutex_init(>sint_routes_mutex);
+QLIST_INIT(>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(>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(_route->sint_set_notifier, false);
-if (r) {
-goto err;
+if (!sint_route) {
+return NULL;
 }
 
+sint_route->synic = synic;
+sint_route->sint = sint;
+sint_route->refcount = 1;
 
 

Re: [PATCH v1 0/4] HyperV: Synthetic Debugging device

2022-02-12 Thread Jon Doron

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

2022-02-04 Thread Jon Doron
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, _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, _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, _data_ofs,
+  >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,
+ MSG_NOSIGNAL, NULL, 0);
+if (sent_count == -1) {
+ret = HV_STA

[PATCH v1 2/4] hyperv: Add definitions for syndbg

2022-02-04 Thread Jon Doron
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

2022-02-04 Thread Jon Doron
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), _abort);
 synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
 synic->event_page = memory_region_get_ram_ptr(>event_page_mr);
+qemu_mutex_init(>sint_routes_mutex);
+QLIST_INIT(>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(>sint_routes));
 }
 
 static void synic_class_init(ObjectClass *klass, void *data)
@@ -168,54 +224,

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

2022-02-04 Thread Jon Doron
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, , 1);
+if (!reset_dbg_session || len < sizeof(*reset_dbg_session)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_CONNECTION_INFO;
+ret = hv_syndbg_handler(hv_syndbg_context, );
+if (ret) {
+goto cleanup;
+}
+
+reset_dbg_session->host_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->host_port = msg.u.connection_info.host_port;
+/* The following fields are only used as validation for KDVM */
+memset(_dbg_session->host_mac, 0,
+   sizeof(reset_dbg_session->host_mac));
+reset_dbg_session->target_ip = msg.u.connection_info.host_ip;
+reset_dbg_session->target_port = msg.u.connection_info.host_port;
+memset(_dbg_session->target_mac, 0,
+   sizeof(reset_dbg_session->target_mac));
+cleanup:
+if (reset_dbg_session) {
+cpu_physical_memory_unmap(reset_dbg_session,
+  sizeof(*reset_dbg_session), 1, len);
+}
+
+return ret;
+}
+
+uint16_t hyperv_hcall_retreive_dbg_data(uint64_t ingpa, uint64_t outgpa,
+bool fast)
+{
+uint16_t ret;
+struct hyperv_retrieve_debug_data_input *debug_data_in = NULL;
+struct hyperv_retrieve_debug_data_output *debug_data_out = NULL;
+hwaddr in_len, out_len;
+HvSynDbgMsg msg;
+
+if (fast || !hv_syndbg_handler) {
+ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+goto cleanup;
+}
+
+in_len = sizeof(*debug_data_in);
+debug_data_in = cpu_physical_memory_map(ingpa, _len, 0);
+if (!debug_data_in || in_len < sizeof(*debug_data_in)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+out_len = sizeof(*debug_data_out);
+debug_data_out = cpu_physical_memory_map(outgpa, _len, 1);
+if (!debug_data_out || out_len < sizeof(*debug_data_out)) {
+ret = HV_STATUS_INSUFFICIENT_MEMORY;
+goto cleanup;
+}
+
+msg.type = HV_SYNDBG_MSG_RECV;
+msg.u.recv.buf_gpa = outgpa + sizeof(*debug_data_out);
+msg.u.recv.count = TARGET_PAGE_SIZE - sizeof(*debug_data_out);
+msg.u.recv.options = debug_data_in->options;
+msg.u.recv.timeout = debug_data_in->timeout;
+msg.u.recv.is_raw = true;
+re

[PATCH v1 0/4] HyperV: Synthetic Debugging device

2022-02-04 Thread Jon Doron
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?

2021-11-16 Thread Jon Doron

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?

2020-10-12 Thread Jon Doron
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.

2020-09-06 Thread Jon Doron
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

2020-08-10 Thread Jon Doron
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

2020-07-17 Thread Jon Doron
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

2020-07-17 Thread Jon Doron
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

2020-07-15 Thread Jon Doron
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

2020-07-15 Thread Jon Doron
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

2020-07-15 Thread Jon Doron
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, );
 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

2020-07-13 Thread Jon Doron
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

2020-06-26 Thread Jon Doron
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

2020-06-24 Thread Jon Doron
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

2020-06-24 Thread Jon Doron
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

2020-06-24 Thread Jon Doron
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

2020-06-24 Thread Jon Doron

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

2020-06-24 Thread Jon Doron

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

2020-06-24 Thread Jon Doron

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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-17 Thread Jon Doron
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

2020-06-14 Thread Jon Doron

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 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 (thoug

Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry

2020-06-14 Thread Jon Doron

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

Device (\_SB.VMOD.VMBS)
{
Name (STA, 0x0F)
Name (_ADR, Zero)  // _ADR: Address
Name (_DDN, "VMBUS")  // _DDN: DOS Device Name
Name (_HID, &

Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry

2020-06-14 Thread Jon Doron

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

2020-06-01 Thread Jon Doron
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

2020-06-01 Thread Jon Doron

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

2020-06-01 Thread Jon Doron

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

2020-05-31 Thread Jon Doron

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.



Re: [PATCH v4 5/6] i386: Hyper-V VMBus ACPI DSDT entry

2020-05-28 Thread Jon Doron

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

2020-05-27 Thread Jon Doron

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

2020-05-27 Thread Jon Doron

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

2020-05-21 Thread Jon Doron

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

2020-05-15 Thread Jon Doron

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

2020-05-12 Thread Jon Doron

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

2020-05-12 Thread Jon Doron

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

2020-05-06 Thread Jon Doron

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

2020-05-05 Thread Jon Doron

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 = _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


+
+crs = aml_resource_template();

[PATCH v4 6/6] vmbus: add infrastructure to save/load vmbus requests

2020-04-24 Thread Jon Doron
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, _vmbus_chan_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, _vmbus_chan_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 = >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(>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

2020-04-24 Thread Jon Doron
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

2020-04-24 Thread Jon Doron
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-properties.h"
+#incl

[PATCH v4 4/6] i386:pc: whitelist dynamic vmbus-bridge

2020-04-24 Thread Jon Doron
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

2020-04-24 Thread Jon Doron
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 = _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

2020-04-24 Thread Jon Doron
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, _abort);
 object_unref(obj);
 object_property_set_bool(obj, true, "realized", _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

2020-04-24 Thread Jon Doron
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

2020-04-08 Thread Jon Doron

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

2020-04-07 Thread Jon Doron

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

2020-04-06 Thread Jon Doron
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-properties.h"
+#incl

[PATCH v3 6/7] i386: Hyper-V VMBus ACPI DSDT entry

2020-04-06 Thread Jon Doron
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 = _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

2020-04-06 Thread Jon Doron
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

2020-04-06 Thread Jon Doron
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), _abort);
 synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
 synic->event_page = memory_region_get_ram_ptr(>event_page_mr);
+qemu_mutex_init(>sint_routes_mutex);
+QLIST_INIT(>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(>sint_routes));
 }

[PATCH v3 7/7] vmbus: add infrastructure to save/load vmbus requests

2020-04-06 Thread Jon Doron
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, _vmbus_chan_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, _vmbus_chan_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 = >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(>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

2020-04-06 Thread Jon Doron
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

2020-04-06 Thread Jon Doron
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, _abort);
 object_unref(obj);
 object_property_set_bool(obj, true, "realized", _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

2020-04-06 Thread Jon Doron
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

2020-04-06 Thread Jon Doron
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

2020-04-04 Thread Jon Doron
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, _vmbus_chan_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, _vmbus_chan_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 = >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(>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

2020-04-04 Thread Jon Doron
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 = _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

2020-04-04 Thread Jon Doron
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), _abort);
 synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
 synic->event_page = memory_region_get_ram_ptr(>event_page_mr);
+qemu_mutex_init(>sint_routes_mutex);
+QLIST_INIT(>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(>sint_routes));
 }

[PATCH v2 5/7] i386:pc: whitelist dynamic vmbus-bridge

2020-04-04 Thread Jon Doron
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

2020-04-04 Thread Jon Doron
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 4/7] vmbus: vmbus implementation

2020-04-04 Thread Jon Doron
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-properties.h"
+#incl

[PATCH v2 0/7] hyperv: VMBus implementation

2020-04-04 Thread Jon Doron
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

2020-04-04 Thread Jon Doron
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, _abort);
 object_unref(obj);
 object_property_set_bool(obj, true, "realized", _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




Re: [PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry

2020-04-03 Thread Jon Doron
 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

2020-04-03 Thread Jon Doron
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

2020-04-03 Thread Jon Doron
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) "signaling channel id %d&

[PATCH v1 5/5] i386: Hyper-V VMBus ACPI DSDT entry

2020-04-03 Thread Jon Doron
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

2020-04-03 Thread Jon Doron
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), _abort);
 synic->msg_page = memory_region_get_ram_ptr(>msg_page_mr);
 synic->event_page = memory_region_get_ram_ptr(>event_page_mr);
+qemu_mutex_init(>sint_routes_mutex);
+QLIST_INIT(>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(>sint_routes));
 }

[PATCH v1 0/5] hyperv: VMBus implementation

2020-04-03 Thread Jon Doron
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




  1   2   3   4   >