From cfcacbab38e43200264c06135946b1c5096c393a Mon Sep 17 00:00:00 2001 From: Jiqian Chen Date: Wed, 6 Nov 2024 14:14:18 +0800 Subject: [PATCH 1/3] xen/passthrough: use gsi to map pirq when dom0 is PVH In PVH dom0, when passthrough a device to domU, QEMU code xen_pt_realize->xc_physdev_map_pirq wants to use gsi, but in current codes the gsi number is got from file /sys/bus/pci/devices//irq, that is wrong, because irq is not equal with gsi, they are in different spaces, so pirq mapping fails. To solve above problem, use new interface of Xen, xc_pcidev_get_gsi to get gsi and use xc_physdev_map_pirq_gsi to map pirq when dom0 is PVH. Signed-off-by: Jiqian Chen Signed-off-by: Huang Rui Signed-off-by: Jiqian Chen Acked-by: Anthony PERARD Reviewed-by: Stewart Hildebrand Message-Id: <20241106061418.3655304-1-Jiqian.Chen@amd.com> Signed-off-by: Anthony PERARD --- hw/xen/xen_pt.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ include/hw/pci/pci.h | 4 +++ 2 files changed, 64 insertions(+) diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index e2bd4c7d41..9487f68f2e 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -766,6 +766,57 @@ static void xen_pt_destroy(PCIDevice *d) { } /* init */ +#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 42000 +static bool xen_pt_need_gsi(void) +{ + FILE *fp; + int len; + /* + * The max length of guest_type is "PVH"+'\n'+'\0', it is 5, + * so here set the length of type to be twice. + */ + char type[10]; + const char *guest_type = "/sys/hypervisor/guest_type"; + + fp = fopen(guest_type, "r"); + if (!fp) { + error_report("Cannot open %s: %s", guest_type, strerror(errno)); + return false; + } + + if (fgets(type, sizeof(type), fp)) { + len = strlen(type); + if (len) { + type[len - 1] = '\0'; + if (!strcmp(type, "PVH")) { + fclose(fp); + return true; + } + } + } + + fclose(fp); + return false; +} + +static int xen_pt_map_pirq_for_gsi(PCIDevice *d, int *pirq) +{ + int gsi; + XenPCIPassthroughState *s = XEN_PT_DEVICE(d); + + gsi = xc_pcidev_get_gsi(xen_xc, + PCI_SBDF(s->real_device.domain, + s->real_device.bus, + s->real_device.dev, + s->real_device.func)); + if (gsi >= 0) { + return xc_physdev_map_pirq_gsi(xen_xc, xen_domid, gsi, pirq); + } + + return gsi; +} +#endif + static void xen_pt_realize(PCIDevice *d, Error **errp) { ERRP_GUARD(); @@ -847,7 +898,16 @@ static void xen_pt_realize(PCIDevice *d, Error **errp) goto out; } +#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 42000 + if (xen_pt_need_gsi()) { + rc = xen_pt_map_pirq_for_gsi(d, &pirq); + } else { + rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq); + } +#else rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq); +#endif + if (rc < 0) { XEN_PT_ERR(d, "Mapping machine irq %u to pirq %i failed, (err: %d)\n", machine_irq, pirq, errno); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index c220cc8449..822fbacdf0 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -23,6 +23,10 @@ extern bool pci_available; #define PCI_SLOT_MAX 32 #define PCI_FUNC_MAX 8 +#define PCI_SBDF(seg, bus, dev, func) \ + ((((uint32_t)(seg)) << 16) | \ + (PCI_BUILD_BDF(bus, PCI_DEVFN(dev, func)))) + /* Class, Vendor and Device IDs from Linux's pci_ids.h */ #include "hw/pci/pci_ids.h" From 4173b3d83752d9547c188db0d99ade08a1adb1fc Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 7 Feb 2025 14:37:24 +0000 Subject: [PATCH 2/3] hw/xen: Add "mode" parameter to xen-block devices Block devices don't work in PV Grub (0.9x) if there is no mode specified. It complains: "Error ENOENT when reading the mode" Signed-off-by: David Woodhouse Message-Id: <20250207143724.30792-2-dwmw2@infradead.org> Signed-off-by: Anthony PERARD --- hw/block/xen-block.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 2098286b5f..ec04102b66 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -408,6 +408,8 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) } xen_device_backend_printf(xendev, "info", "%u", blockdev->info); + xen_device_backend_printf(xendev, "mode", + (blockdev->info & VDISK_READONLY) ? "r" : "w"); xen_device_frontend_printf(xendev, "virtual-device", "%lu", vdev->number); From 68adcc784bad13421ac7211c316a751fb99fcb94 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 6 Feb 2025 20:49:15 +0100 Subject: [PATCH 3/3] xen: No need to flush the mapcache for grants On IOREQ_TYPE_INVALIDATE we need to invalidate the mapcache for regular mappings. Since recently we started reusing the mapcache also to keep track of grants mappings. However, there is no need to remove grant mappings on IOREQ_TYPE_INVALIDATE requests, we shouldn't do that. So remove the function call. Fixes: 9ecdd4bf08 (xen: mapcache: Add support for grant mappings) Cc: qemu-stable@nongnu.org Reported-by: Olaf Hering Reviewed-by: Edgar E. Iglesias Signed-off-by: Stefano Stabellini Signed-off-by: Edgar E. Iglesias Reviewed-by: Anthony PERARD Message-Id: <20250206194915.3357743-2-edgar.iglesias@gmail.com> Signed-off-by: Anthony PERARD --- hw/xen/xen-mapcache.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c index 00bfbcc6fb..698b5c53ed 100644 --- a/hw/xen/xen-mapcache.c +++ b/hw/xen/xen-mapcache.c @@ -700,7 +700,6 @@ void xen_invalidate_map_cache(void) bdrv_drain_all(); xen_invalidate_map_cache_single(mapcache); - xen_invalidate_map_cache_single(mapcache_grants); } static uint8_t *xen_replace_cache_entry_unlocked(MapCache *mc,