From 491d68d9382dbb588f2ff5132ee3d87ce2f1b230 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Wed, 4 May 2016 20:53:55 +0300 Subject: [PATCH 1/3] usb:xhci: no DMA on HC reset This patch is a rough fix to a memory corruption we are observing when running VMs with xhci USB controller and OVMF firmware. Specifically, on the following call chain xhci_reset xhci_disable_slot xhci_disable_ep xhci_set_ep_state QEMU overwrites guest memory using stale guest addresses. This doesn't happen when the guest (firmware) driver sets up xhci for the first time as there are no slots configured yet. However when the firmware hands over the control to the OS some slots and endpoints are already set up with their context in the guest RAM. Now the OS' driver resets the controller again and xhci_set_ep_state then reads and writes that memory which is now owned by the OS. As a quick fix, skip calling xhci_set_ep_state in xhci_disable_ep if the device context base address array pointer is zero (indicating we're in the HC reset and no DMA is possible). Cc: qemu-stable@nongnu.org Signed-off-by: Roman Kagan Message-id: 1462384435-1034-1-git-send-email-rkagan@virtuozzo.com Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index bcde8a2f48..43ba61599a 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1531,7 +1531,10 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid, usb_packet_cleanup(&epctx->transfers[i].packet); } - xhci_set_ep_state(xhci, epctx, NULL, EP_DISABLED); + /* only touch guest RAM if we're not resetting the HC */ + if (xhci->dcbaap_low || xhci->dcbaap_high) { + xhci_set_ep_state(xhci, epctx, NULL, EP_DISABLED); + } timer_free(epctx->kick_timer); g_free(epctx); From 1f66fe5778ca906448385ee004b38381ae067755 Mon Sep 17 00:00:00 2001 From: Isaac Lozano <109lozanoi@gmail.com> Date: Sun, 17 Apr 2016 04:29:53 -0700 Subject: [PATCH 2/3] usb-mtp: fix usb_mtp_get_device_info so that libmtp on the guest doesn't complain If an application uses libmtp on the guest system, it will complain with the warning message: LIBMTP WARNING: VendorExtensionID: ffffffff LIBMTP WARNING: VendorExtensionDesc: (null) LIBMTP WARNING: this typically means the device is PTP (i.e. a camera) but not a MTP device at all. Trying to continue anyway. This is because libmtp expects a MTP Vendor Extension ID of 0x00000006 and a MTP Version of 0x0064. These numbers are taken from Microsoft's MTP Vendor Extension Identification Message page and are what most physical devices show. Signed-off-by: Isaac Lozano <109lozanoi@gmail.com> Reviewed-by: Stefan Hajnoczi Message-id: 1460892593-5908-1-git-send-email-109lozanoi@gmail.com Signed-off-by: Gerd Hoffmann --- hw/usb/dev-mtp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index bda84a64bd..1be85ae75a 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -788,8 +788,8 @@ static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c) trace_usb_mtp_op_get_device_info(s->dev.addr); usb_mtp_add_u16(d, 100); - usb_mtp_add_u32(d, 0xffffffff); - usb_mtp_add_u16(d, 0x0101); + usb_mtp_add_u32(d, 0x00000006); + usb_mtp_add_u16(d, 0x0064); usb_mtp_add_wstr(d, L""); usb_mtp_add_u16(d, 0x0000); From a277c3e094d5e9f653ccc861f59e07c94c7fe6c7 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 22 Mar 2016 08:13:20 +0100 Subject: [PATCH 3/3] usb: Support compilation without poll.h This is a hack to support compilation with Mingw-w64 which provides a libusb-1.0 package, but no poll.h. Signed-off-by: Stefan Weil Message-id: 1458630800-10088-1-git-send-email-sw@weilnetz.de Signed-off-by: Gerd Hoffmann --- hw/usb/host-libusb.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 6458a94485..8b774f4939 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -34,7 +34,9 @@ */ #include "qemu/osdep.h" +#ifndef CONFIG_WIN32 #include +#endif #include #include "qapi/error.h" @@ -204,6 +206,8 @@ static const char *err_names[] = { static libusb_context *ctx; static uint32_t loglevel; +#ifndef CONFIG_WIN32 + static void usb_host_handle_fd(void *opaque) { struct timeval tv = { 0, 0 }; @@ -223,9 +227,13 @@ static void usb_host_del_fd(int fd, void *user_data) qemu_set_fd_handler(fd, NULL, NULL, NULL); } +#endif /* !CONFIG_WIN32 */ + static int usb_host_init(void) { +#ifndef CONFIG_WIN32 const struct libusb_pollfd **poll; +#endif int i, rc; if (ctx) { @@ -236,7 +244,9 @@ static int usb_host_init(void) return -1; } libusb_set_debug(ctx, loglevel); - +#ifdef CONFIG_WIN32 + /* FIXME: add support for Windows. */ +#else libusb_set_pollfd_notifiers(ctx, usb_host_add_fd, usb_host_del_fd, ctx); @@ -247,6 +257,7 @@ static int usb_host_init(void) } } free(poll); +#endif return 0; }