From c192fca9f62b732b5abde4c3633b13e839d654dc Mon Sep 17 00:00:00 2001 From: Sandeep Gundlupet Raju Date: Fri, 19 Jan 2024 13:41:59 -0700 Subject: qemu: Add Xen 4.18 patches Add Xen 4.18 patches and limit patches to target recipes only. Signed-off-by: Sandeep Gundlupet Raju Signed-off-by: Mark Hatle --- .../recipes-devtools/qemu/qemu-xen_8.1.inc | 19 ++ ...ate-virtio-mmio-devices-during-initializa.patch | 116 +++++++++ ...tialize-RAM-and-add-hi-low-memory-regions.patch | 124 ++++++++++ ..._set_irq-and-xendevicemodel_set_irq_level.patch | 55 +++++ ...plugging-emulated-devices-skip-virtio-dev.patch | 70 ++++++ .../0005-softmmu-physmem-Split-ram_block_add.patch | 117 +++++++++ ...-add-pseudo-RAM-region-for-grant-mappings.patch | 153 ++++++++++++ ...-qemu_map_ram_ptr-use-qemu_ram_ptr_length.patch | 117 +++++++++ ..._ram_addr_from_mapcache-return-1-in-case-.patch | 49 ++++ ...-add-MemoryRegion-map-and-unmap-callbacks.patch | 155 ++++++++++++ ...-map-and-unmap-callbacks-for-grant-region.patch | 262 +++++++++++++++++++++ .../0011-hw-arm-Add-grant-mapping.patch | 30 +++ .../qemu/qemu-xilinx_2024%.bbappend | 2 +- .../recipes-devtools/qemu/qemu_8.1%.bbappend | 4 +- 14 files changed, 1270 insertions(+), 3 deletions(-) create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xen_8.1.inc create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0001-xen_arm-Create-virtio-mmio-devices-during-initializa.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0002-xen_arm-Initialize-RAM-and-add-hi-low-memory-regions.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0003-Xen-Fix-xen_set_irq-and-xendevicemodel_set_irq_level.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0004-xen-when-unplugging-emulated-devices-skip-virtio-dev.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0005-softmmu-physmem-Split-ram_block_add.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0006-xen-add-pseudo-RAM-region-for-grant-mappings.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0007-softmmu-let-qemu_map_ram_ptr-use-qemu_ram_ptr_length.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0008-xen-let-xen_ram_addr_from_mapcache-return-1-in-case-.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0009-memory-add-MemoryRegion-map-and-unmap-callbacks.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch create mode 100644 meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0011-hw-arm-Add-grant-mapping.patch (limited to 'meta-xilinx-virtualization') diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xen_8.1.inc b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xen_8.1.inc new file mode 100644 index 00000000..3cf6dae7 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xen_8.1.inc @@ -0,0 +1,19 @@ +# Xen-4.18 specific changes are only applicable on the target +SRC_URI_XEN = "" +SRC_URI_XEN:class-target = " \ + file://0001-xen_arm-Create-virtio-mmio-devices-during-initializa.patch \ + file://0002-xen_arm-Initialize-RAM-and-add-hi-low-memory-regions.patch \ + file://0003-Xen-Fix-xen_set_irq-and-xendevicemodel_set_irq_level.patch \ + file://0004-xen-when-unplugging-emulated-devices-skip-virtio-dev.patch \ + file://0005-softmmu-physmem-Split-ram_block_add.patch \ + file://0006-xen-add-pseudo-RAM-region-for-grant-mappings.patch \ + file://0007-softmmu-let-qemu_map_ram_ptr-use-qemu_ram_ptr_length.patch \ + file://0008-xen-let-xen_ram_addr_from_mapcache-return-1-in-case-.patch \ + file://0009-memory-add-MemoryRegion-map-and-unmap-callbacks.patch \ + file://0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch \ + file://0011-hw-arm-Add-grant-mapping.patch \ + " + +FILESEXTRAPATHS:prepend:class-target := "${THISDIR}/qemu-xilinx-8.1:" + +SRC_URI .= "${@bb.utils.contains('DISTRO_FEATURES', 'xen', '${SRC_URI_XEN}', '', d)}" diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0001-xen_arm-Create-virtio-mmio-devices-during-initializa.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0001-xen_arm-Create-virtio-mmio-devices-during-initializa.patch new file mode 100644 index 00000000..1757e9e2 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0001-xen_arm-Create-virtio-mmio-devices-during-initializa.patch @@ -0,0 +1,116 @@ +From b9291457ca2eb4340c71d2eed08fde83916c9fa4 Mon Sep 17 00:00:00 2001 +From: Oleksandr Tyshchenko +Date: Tue, 29 Aug 2023 21:35:17 -0700 +Subject: [PATCH 01/11] xen_arm: Create virtio-mmio devices during + initialization + +In order to use virtio backends we need to allocate virtio-mmio +parameters (irq and base) and register corresponding buses. + +Use the constants defined in public header arch-arm.h to be +aligned with the toolstack. So the number of current supported +virtio-mmio devices is 10. + +For the interrupts triggering use already existing on Arm +device-model hypercall. + +The toolstack should then insert the same amount of device nodes +into guest device-tree. + +Signed-off-by: Oleksandr Tyshchenko +Signed-off-by: Vikram Garhwal +Reviewed-by: Stefano Stabellini +Signed-off-by: Stefano Stabellini +--- + hw/arm/xen_arm.c | 35 +++++++++++++++++++++++++++++++++++ + include/hw/xen/xen_native.h | 16 ++++++++++++++++ + 2 files changed, 51 insertions(+) + +diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c +index 1d3e6d481a..7393b37355 100644 +--- a/hw/arm/xen_arm.c ++++ b/hw/arm/xen_arm.c +@@ -26,6 +26,7 @@ + #include "qapi/qapi-commands-migration.h" + #include "qapi/visitor.h" + #include "hw/boards.h" ++#include "hw/irq.h" + #include "hw/sysbus.h" + #include "sysemu/block-backend.h" + #include "sysemu/tpm_backend.h" +@@ -59,6 +60,38 @@ struct XenArmState { + } cfg; + }; + ++/* ++ * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under Xen ++ * repository. ++ * ++ * Origin: git://xenbits.xen.org/xen.git 2128143c114c ++ */ ++#define VIRTIO_MMIO_DEV_SIZE 0x200 ++ ++#define NR_VIRTIO_MMIO_DEVICES \ ++ (GUEST_VIRTIO_MMIO_SPI_LAST - GUEST_VIRTIO_MMIO_SPI_FIRST) ++ ++static void xen_set_irq(void *opaque, int irq, int level) ++{ ++ xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level); ++} ++ ++static void xen_create_virtio_mmio_devices(XenArmState *xam) ++{ ++ int i; ++ ++ for (i = 0; i < NR_VIRTIO_MMIO_DEVICES; i++) { ++ hwaddr base = GUEST_VIRTIO_MMIO_BASE + i * VIRTIO_MMIO_DEV_SIZE; ++ qemu_irq irq = qemu_allocate_irq(xen_set_irq, NULL, ++ GUEST_VIRTIO_MMIO_SPI_FIRST + i); ++ ++ sysbus_create_simple("virtio-mmio", base, irq); ++ ++ DPRINTF("Created virtio-mmio device %d: irq %d base 0x%lx\n", ++ i, GUEST_VIRTIO_MMIO_SPI_FIRST + i, base); ++ } ++} ++ + void arch_handle_ioreq(XenIOState *state, ioreq_t *req) + { + hw_error("Invalid ioreq type 0x%x\n", req->type); +@@ -110,6 +143,8 @@ static void xen_arm_init(MachineState *machine) + + xen_register_ioreq(xam->state, machine->smp.cpus, &xen_memory_listener); + ++ xen_create_virtio_mmio_devices(xam); ++ + #ifdef CONFIG_TPM + if (xam->cfg.tpm_base_addr) { + xen_enable_tpm(xam); +diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h +index 4dce905fde..a4b1aa9e5d 100644 +--- a/include/hw/xen/xen_native.h ++++ b/include/hw/xen/xen_native.h +@@ -523,4 +523,20 @@ static inline int xen_set_ioreq_server_state(domid_t dom, + enable); + } + ++#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500 ++static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod, ++ domid_t domid, uint32_t irq, ++ unsigned int level) ++{ ++ return 0; ++} ++#endif ++ ++#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700 ++#define GUEST_VIRTIO_MMIO_BASE xen_mk_ullong(0x02000000) ++#define GUEST_VIRTIO_MMIO_SIZE xen_mk_ullong(0x00100000) ++#define GUEST_VIRTIO_MMIO_SPI_FIRST 33 ++#define GUEST_VIRTIO_MMIO_SPI_LAST 43 ++#endif ++ + #endif /* QEMU_HW_XEN_NATIVE_H */ +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0002-xen_arm-Initialize-RAM-and-add-hi-low-memory-regions.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0002-xen_arm-Initialize-RAM-and-add-hi-low-memory-regions.patch new file mode 100644 index 00000000..f88db620 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0002-xen_arm-Initialize-RAM-and-add-hi-low-memory-regions.patch @@ -0,0 +1,124 @@ +From 70a74795c5071bf591e6e557b7c8c492ead0e675 Mon Sep 17 00:00:00 2001 +From: Oleksandr Tyshchenko +Date: Tue, 29 Aug 2023 21:35:18 -0700 +Subject: [PATCH 02/11] xen_arm: Initialize RAM and add hi/low memory regions + +In order to use virtio backends we need to initialize RAM for the +xen-mapcache (which is responsible for mapping guest memory using foreign +mapping) to work. Calculate and add hi/low memory regions based on +machine->ram_size. + +Use the constants defined in public header arch-arm.h to be aligned with the xen +toolstack. + +While using this machine, the toolstack should then pass real ram_size using +"-m" arg. If "-m" is not given, create a QEMU machine without IOREQ and other +emulated devices like TPM and VIRTIO. This is done to keep this QEMU machine +usable for /etc/init.d/xencommons. + +Signed-off-by: Oleksandr Tyshchenko +Signed-off-by: Vikram Garhwal +Reviewed-by: Stefano Stabellini +Signed-off-by: Stefano Stabellini +--- + hw/arm/xen_arm.c | 45 +++++++++++++++++++++++++++++++++++++ + include/hw/xen/xen_native.h | 8 +++++++ + 2 files changed, 53 insertions(+) + +diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c +index 7393b37355..f83b983ec5 100644 +--- a/hw/arm/xen_arm.c ++++ b/hw/arm/xen_arm.c +@@ -60,6 +60,8 @@ struct XenArmState { + } cfg; + }; + ++static MemoryRegion ram_lo, ram_hi; ++ + /* + * VIRTIO_MMIO_DEV_SIZE is imported from tools/libs/light/libxl_arm.c under Xen + * repository. +@@ -92,6 +94,39 @@ static void xen_create_virtio_mmio_devices(XenArmState *xam) + } + } + ++static void xen_init_ram(MachineState *machine) ++{ ++ MemoryRegion *sysmem = get_system_memory(); ++ ram_addr_t block_len, ram_size[GUEST_RAM_BANKS]; ++ ++ if (machine->ram_size <= GUEST_RAM0_SIZE) { ++ ram_size[0] = machine->ram_size; ++ ram_size[1] = 0; ++ block_len = GUEST_RAM0_BASE + ram_size[0]; ++ } else { ++ ram_size[0] = GUEST_RAM0_SIZE; ++ ram_size[1] = machine->ram_size - GUEST_RAM0_SIZE; ++ block_len = GUEST_RAM1_BASE + ram_size[1]; ++ } ++ ++ memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len, ++ &error_fatal); ++ ++ memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo", &ram_memory, ++ GUEST_RAM0_BASE, ram_size[0]); ++ memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, &ram_lo); ++ DPRINTF("Initialized region xen.ram.lo: base 0x%llx size 0x%lx\n", ++ GUEST_RAM0_BASE, ram_size[0]); ++ ++ if (ram_size[1] > 0) { ++ memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi", &ram_memory, ++ GUEST_RAM1_BASE, ram_size[1]); ++ memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, &ram_hi); ++ DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n", ++ GUEST_RAM1_BASE, ram_size[1]); ++ } ++} ++ + void arch_handle_ioreq(XenIOState *state, ioreq_t *req) + { + hw_error("Invalid ioreq type 0x%x\n", req->type); +@@ -141,6 +176,14 @@ static void xen_arm_init(MachineState *machine) + + xam->state = g_new0(XenIOState, 1); + ++ if (machine->ram_size == 0) { ++ DPRINTF("ram_size not specified. QEMU machine started without IOREQ" ++ "(no emulated devices including Virtio)\n"); ++ return; ++ } ++ ++ xen_init_ram(machine); ++ + xen_register_ioreq(xam->state, machine->smp.cpus, &xen_memory_listener); + + xen_create_virtio_mmio_devices(xam); +@@ -188,6 +231,8 @@ static void xen_arm_machine_class_init(ObjectClass *oc, void *data) + mc->init = xen_arm_init; + mc->max_cpus = 1; + mc->default_machine_opts = "accel=xen"; ++ /* Set explicitly here to make sure that real ram_size is passed */ ++ mc->default_ram_size = 0; + + #ifdef CONFIG_TPM + object_class_property_add(oc, "tpm-base-addr", "uint64_t", +diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h +index a4b1aa9e5d..5d2718261f 100644 +--- a/include/hw/xen/xen_native.h ++++ b/include/hw/xen/xen_native.h +@@ -539,4 +539,12 @@ static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod, + #define GUEST_VIRTIO_MMIO_SPI_LAST 43 + #endif + ++#if defined(__i386__) || defined(__x86_64__) ++#define GUEST_RAM_BANKS 2 ++#define GUEST_RAM0_BASE 0x40000000ULL /* 3GB of low RAM @ 1GB */ ++#define GUEST_RAM0_SIZE 0xc0000000ULL ++#define GUEST_RAM1_BASE 0x0200000000ULL /* 1016GB of RAM @ 8GB */ ++#define GUEST_RAM1_SIZE 0xfe00000000ULL ++#endif ++ + #endif /* QEMU_HW_XEN_NATIVE_H */ +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0003-Xen-Fix-xen_set_irq-and-xendevicemodel_set_irq_level.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0003-Xen-Fix-xen_set_irq-and-xendevicemodel_set_irq_level.patch new file mode 100644 index 00000000..c6945d54 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0003-Xen-Fix-xen_set_irq-and-xendevicemodel_set_irq_level.patch @@ -0,0 +1,55 @@ +From 14b9dbd7f0261ae7a36bef251924ba211beef17a Mon Sep 17 00:00:00 2001 +From: Vikram Garhwal +Date: Wed, 1 Nov 2023 14:07:23 -0700 +Subject: [PATCH 03/11] Xen: Fix xen_set_irq() and + xendevicemodel_set_irq_level() + +Remove '=' from 'if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500'. +Because xendevicemodel_set_irq_level() was introduced in 4.15 version. + +Also, update xendevicemodel_set_irq_level() to return -1 for older versions. + +Signed-off-by: Vikram Garhwal +Reviewed-by: Stefano Stabellini +--- + hw/arm/xen_arm.c | 4 +++- + include/hw/xen/xen_native.h | 4 ++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c +index f83b983ec5..a5631529d0 100644 +--- a/hw/arm/xen_arm.c ++++ b/hw/arm/xen_arm.c +@@ -75,7 +75,9 @@ static MemoryRegion ram_lo, ram_hi; + + static void xen_set_irq(void *opaque, int irq, int level) + { +- xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level); ++ if (xendevicemodel_set_irq_level(xen_dmod, xen_domid, irq, level)) { ++ error_report("xendevicemodel_set_irq_level failed"); ++ } + } + + static void xen_create_virtio_mmio_devices(XenArmState *xam) +diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h +index 5d2718261f..6f09c48823 100644 +--- a/include/hw/xen/xen_native.h ++++ b/include/hw/xen/xen_native.h +@@ -523,12 +523,12 @@ static inline int xen_set_ioreq_server_state(domid_t dom, + enable); + } + +-#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41500 ++#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41500 + static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod, + domid_t domid, uint32_t irq, + unsigned int level) + { +- return 0; ++ return -1; + } + #endif + +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0004-xen-when-unplugging-emulated-devices-skip-virtio-dev.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0004-xen-when-unplugging-emulated-devices-skip-virtio-dev.patch new file mode 100644 index 00000000..da2f042b --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0004-xen-when-unplugging-emulated-devices-skip-virtio-dev.patch @@ -0,0 +1,70 @@ +From 02507086b3ad9beb9c669aae54fcb4857cd61ef8 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Tue, 16 Mar 2021 14:00:33 +0100 +Subject: [PATCH 04/11] xen: when unplugging emulated devices skip virtio + devices + +Virtio devices should never be unplugged at boot time, as they are +similar to pci passthrough devices. + +Signed-off-by: Juergen Gross +Signed-off-by: Vikram Garhwal +--- + docs/system/i386/xen.rst | 3 --- + hw/i386/xen/xen_platform.c | 10 ++++++++-- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/docs/system/i386/xen.rst b/docs/system/i386/xen.rst +index f06765e88c..b86d57af6e 100644 +--- a/docs/system/i386/xen.rst ++++ b/docs/system/i386/xen.rst +@@ -52,9 +52,6 @@ It is necessary to use the pc machine type, as the q35 machine uses AHCI instead + of legacy IDE, and AHCI disks are not unplugged through the Xen PV unplug + mechanism. + +-VirtIO devices can also be used; Linux guests may need to be dissuaded from +-umplugging them by adding 'xen_emul_unplug=never' on their command line. +- + Properties + ---------- + +diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c +index 17457ff3de..0187b73eeb 100644 +--- a/hw/i386/xen/xen_platform.c ++++ b/hw/i386/xen/xen_platform.c +@@ -28,6 +28,7 @@ + #include "hw/ide/pci.h" + #include "hw/pci/pci.h" + #include "migration/vmstate.h" ++#include "hw/virtio/virtio-bus.h" + #include "net/net.h" + #include "trace.h" + #include "sysemu/xen.h" +@@ -129,10 +130,11 @@ static bool pci_device_is_passthrough(PCIDevice *d) + + static void unplug_nic(PCIBus *b, PCIDevice *d, void *o) + { +- /* We have to ignore passthrough devices */ ++ /* We have to ignore passthrough devices and virtio devices. */ + if (pci_get_word(d->config + PCI_CLASS_DEVICE) == + PCI_CLASS_NETWORK_ETHERNET +- && !pci_device_is_passthrough(d)) { ++ && !pci_device_is_passthrough(d) ++ && !qdev_get_child_bus(&d->qdev, TYPE_VIRTIO_BUS)) { + object_unparent(OBJECT(d)); + } + } +@@ -208,6 +210,10 @@ static void unplug_disks(PCIBus *b, PCIDevice *d, void *opaque) + /* We have to ignore passthrough devices */ + if (pci_device_is_passthrough(d)) + return; ++ /* Ignore virtio devices */ ++ if (qdev_get_child_bus(&d->qdev, TYPE_VIRTIO_BUS)) { ++ return; ++ } + + switch (pci_get_word(d->config + PCI_CLASS_DEVICE)) { + case PCI_CLASS_STORAGE_IDE: +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0005-softmmu-physmem-Split-ram_block_add.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0005-softmmu-physmem-Split-ram_block_add.patch new file mode 100644 index 00000000..3c39dd19 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0005-softmmu-physmem-Split-ram_block_add.patch @@ -0,0 +1,117 @@ +From d4774a0e5e1ebed605c5d49e81433fd371d0b680 Mon Sep 17 00:00:00 2001 +From: Vikram Garhwal +Date: Tue, 17 Oct 2023 20:22:26 +0000 +Subject: [PATCH 05/11] softmmu: physmem: Split ram_block_add() + +Extract ram block list update to a new function ram_block_add_list(). This is +done to support grant mappings which adds a memory region for granted memory and +updates the ram_block list. + +Signed-off-by: Juergen Gross +Signed-off-by: Vikram Garhwal +Reviewed-by: Stefano Stabellini +--- + include/exec/ram_addr.h | 1 + + softmmu/physmem.c | 62 ++++++++++++++++++++++++++--------------- + 2 files changed, 40 insertions(+), 23 deletions(-) + +diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h +index 9f2e3893f5..76fa360463 100644 +--- a/include/exec/ram_addr.h ++++ b/include/exec/ram_addr.h +@@ -139,6 +139,7 @@ void qemu_ram_free(RAMBlock *block); + int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp); + + void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length); ++void ram_block_add_list(RAMBlock *new_block); + + /* Clear whole block of mem */ + static inline void qemu_ram_block_writeback(RAMBlock *block) +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index 3df73542e1..f73629733e 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -1786,12 +1786,47 @@ static void dirty_memory_extend(ram_addr_t old_ram_size, + } + } + ++static void ram_block_add_list_locked(RAMBlock *new_block) ++ { ++ RAMBlock *block; ++ RAMBlock *last_block = NULL; ++ ++ /* ++ * Keep the list sorted from biggest to smallest block. Unlike QTAILQ, ++ * QLIST (which has an RCU-friendly variant) does not have insertion at ++ * tail, so save the last element in last_block. ++ */ ++ RAMBLOCK_FOREACH(block) { ++ last_block = block; ++ if (block->max_length < new_block->max_length) { ++ break; ++ } ++ } ++ if (block) { ++ QLIST_INSERT_BEFORE_RCU(block, new_block, next); ++ } else if (last_block) { ++ QLIST_INSERT_AFTER_RCU(last_block, new_block, next); ++ } else { /* list is empty */ ++ QLIST_INSERT_HEAD_RCU(&ram_list.blocks, new_block, next); ++ } ++ ram_list.mru_block = NULL; ++ ++ /* Write list before version */ ++ smp_wmb(); ++ ram_list.version++; ++} ++ ++void ram_block_add_list(RAMBlock *new_block) ++{ ++ qemu_mutex_lock_ramlist(); ++ ram_block_add_list_locked(new_block); ++ qemu_mutex_unlock_ramlist(); ++} ++ + static void ram_block_add(RAMBlock *new_block, Error **errp) + { + const bool noreserve = qemu_ram_is_noreserve(new_block); + const bool shared = qemu_ram_is_shared(new_block); +- RAMBlock *block; +- RAMBlock *last_block = NULL; + ram_addr_t old_ram_size, new_ram_size; + Error *err = NULL; + +@@ -1829,28 +1864,9 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) + if (new_ram_size > old_ram_size) { + dirty_memory_extend(old_ram_size, new_ram_size); + } +- /* Keep the list sorted from biggest to smallest block. Unlike QTAILQ, +- * QLIST (which has an RCU-friendly variant) does not have insertion at +- * tail, so save the last element in last_block. +- */ +- RAMBLOCK_FOREACH(block) { +- last_block = block; +- if (block->max_length < new_block->max_length) { +- break; +- } +- } +- if (block) { +- QLIST_INSERT_BEFORE_RCU(block, new_block, next); +- } else if (last_block) { +- QLIST_INSERT_AFTER_RCU(last_block, new_block, next); +- } else { /* list is empty */ +- QLIST_INSERT_HEAD_RCU(&ram_list.blocks, new_block, next); +- } +- ram_list.mru_block = NULL; ++ ++ ram_block_add_list_locked(new_block); + +- /* Write list before version */ +- smp_wmb(); +- ram_list.version++; + qemu_mutex_unlock_ramlist(); + + cpu_physical_memory_set_dirty_range(new_block->offset, +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0006-xen-add-pseudo-RAM-region-for-grant-mappings.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0006-xen-add-pseudo-RAM-region-for-grant-mappings.patch new file mode 100644 index 00000000..a43748fe --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0006-xen-add-pseudo-RAM-region-for-grant-mappings.patch @@ -0,0 +1,153 @@ +From 637d10471fef76a7ab0e8f5631ea3c85ff5ce9db Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 20 May 2021 11:19:58 +0200 +Subject: [PATCH 06/11] xen: add pseudo RAM region for grant mappings + +Add a memory region which can be used to automatically map granted +memory. It is starting at 0x8000000000000000ULL in order to be able to +distinguish it from normal RAM. + +For this reason the xen.ram memory region is expanded, which has no +further impact as it is used just as a container of the real RAM +regions and now the grant region. + +Signed-off-by: Juergen Gross +Signed-off-by: Vikram Garhwal +Reviewed-by: Stefano Stabellini +--- + hw/i386/xen/xen-hvm.c | 3 +++ + hw/xen/xen-hvm-common.c | 4 ++-- + hw/xen/xen-mapcache.c | 27 +++++++++++++++++++++++++++ + include/hw/xen/xen-hvm-common.h | 2 ++ + include/hw/xen/xen_pvdev.h | 3 +++ + include/sysemu/xen-mapcache.h | 3 +++ + 6 files changed, 40 insertions(+), 2 deletions(-) + +diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c +index f42621e674..67a55558a6 100644 +--- a/hw/i386/xen/xen-hvm.c ++++ b/hw/i386/xen/xen-hvm.c +@@ -172,6 +172,9 @@ static void xen_ram_init(PCMachineState *pcms, + x86ms->above_4g_mem_size); + memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi); + } ++ ++ /* Add grant mappings as a pseudo RAM region. */ ++ ram_grants = *xen_init_grant_ram(); + } + + static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size) +diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c +index 565dc39c8f..b7255977a5 100644 +--- a/hw/xen/xen-hvm-common.c ++++ b/hw/xen/xen-hvm-common.c +@@ -9,7 +9,7 @@ + #include "hw/boards.h" + #include "hw/xen/arch_hvm.h" + +-MemoryRegion ram_memory; ++MemoryRegion ram_memory, ram_grants; + + void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, + Error **errp) +@@ -26,7 +26,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, + return; + } + +- if (mr == &ram_memory) { ++ if (mr == &ram_memory || mr == &ram_grants) { + return; + } + +diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c +index f7d974677d..8115c44c00 100644 +--- a/hw/xen/xen-mapcache.c ++++ b/hw/xen/xen-mapcache.c +@@ -14,7 +14,9 @@ + + #include + ++#include "hw/xen/xen-hvm-common.h" + #include "hw/xen/xen_native.h" ++#include "hw/xen/xen_pvdev.h" + #include "qemu/bitmap.h" + + #include "sysemu/runstate.h" +@@ -597,3 +599,28 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr, + mapcache_unlock(); + return p; + } ++ ++MemoryRegion *xen_init_grant_ram(void) ++{ ++ RAMBlock *block; ++ ++ memory_region_init(&ram_grants, NULL, "xen.grants", ++ XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE); ++ block = g_malloc0(sizeof(*block)); ++ block->mr = &ram_grants; ++ block->used_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE; ++ block->max_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE; ++ block->fd = -1; ++ block->page_size = XC_PAGE_SIZE; ++ block->host = (void *)XEN_GRANT_ADDR_OFF; ++ block->offset = XEN_GRANT_ADDR_OFF; ++ block->flags = RAM_PREALLOC; ++ ram_grants.ram_block = block; ++ ram_grants.ram = true; ++ ram_grants.terminates = true; ++ ram_block_add_list(block); ++ memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF, ++ &ram_grants); ++ ++ return &ram_grants; ++} +diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h +index 4e9904f1a6..0d300ba898 100644 +--- a/include/hw/xen/xen-hvm-common.h ++++ b/include/hw/xen/xen-hvm-common.h +@@ -17,6 +17,8 @@ + #include + + extern MemoryRegion ram_memory; ++ ++extern MemoryRegion ram_grants; + extern MemoryListener xen_io_listener; + extern DeviceListener xen_device_listener; + +diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h +index ddad4b9f36..0f1b5edfa9 100644 +--- a/include/hw/xen/xen_pvdev.h ++++ b/include/hw/xen/xen_pvdev.h +@@ -80,4 +80,7 @@ int xen_pv_send_notify(struct XenLegacyDevice *xendev); + void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level, + const char *fmt, ...) G_GNUC_PRINTF(3, 4); + ++#define XEN_GRANT_ADDR_OFF 0x8000000000000000ULL ++#define XEN_MAX_VIRTIO_GRANTS 65536 ++ + #endif /* QEMU_HW_XEN_PVDEV_H */ +diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h +index c8e7c2f6cf..f4bedb1c11 100644 +--- a/include/sysemu/xen-mapcache.h ++++ b/include/sysemu/xen-mapcache.h +@@ -10,6 +10,7 @@ + #define XEN_MAPCACHE_H + + #include "exec/cpu-common.h" ++#include "exec/ram_addr.h" + + typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset, + ram_addr_t size); +@@ -25,6 +26,8 @@ void xen_invalidate_map_cache(void); + uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr, + hwaddr new_phys_addr, + hwaddr size); ++MemoryRegion *xen_init_grant_ram(void); ++ + #else + + static inline void xen_map_cache_init(phys_offset_to_gaddr_t f, +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0007-softmmu-let-qemu_map_ram_ptr-use-qemu_ram_ptr_length.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0007-softmmu-let-qemu_map_ram_ptr-use-qemu_ram_ptr_length.patch new file mode 100644 index 00000000..ee400e2c --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0007-softmmu-let-qemu_map_ram_ptr-use-qemu_ram_ptr_length.patch @@ -0,0 +1,117 @@ +From 82139e7e4bdcf5ca51b2ac90c63e4af699e3eb6f Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 20 May 2021 11:54:48 +0200 +Subject: [PATCH 07/11] softmmu: let qemu_map_ram_ptr() use + qemu_ram_ptr_length() + +qemu_map_ram_ptr() and qemu_ram_ptr_length() share quite some code, so +modify qemu_ram_ptr_length() a little bit and use it for +qemu_map_ram_ptr(), too. + +Signed-off-by: Juergen Gross +Signed-off-by: Vikram Garhwal +Reviewed-by: Stefano Stabellini +--- + softmmu/physmem.c | 58 +++++++++++++++++++---------------------------- + 1 file changed, 23 insertions(+), 35 deletions(-) + +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index f73629733e..a934e44fe7 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -2123,38 +2123,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) + } + #endif /* !_WIN32 */ + +-/* Return a host pointer to ram allocated with qemu_ram_alloc. +- * This should not be used for general purpose DMA. Use address_space_map +- * or address_space_rw instead. For local memory (e.g. video ram) that the +- * device owns, use memory_region_get_ram_ptr. +- * +- * Called within RCU critical section. +- */ +-void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr) +-{ +- RAMBlock *block = ram_block; +- +- if (block == NULL) { +- block = qemu_get_ram_block(addr); +- addr -= block->offset; +- } +- +- if (xen_enabled() && block->host == NULL) { +- /* We need to check if the requested address is in the RAM +- * because we don't want to map the entire memory in QEMU. +- * In that case just map until the end of the page. +- */ +- if (block->offset == 0) { +- return xen_map_cache(addr, 0, 0, false); +- } +- +- block->host = xen_map_cache(block->offset, block->max_length, 1, false); +- } +- return ramblock_ptr(block, addr); +-} +- +-/* Return a host pointer to guest's ram. Similar to qemu_map_ram_ptr +- * but takes a size argument. ++/* ++ * Return a host pointer to guest's ram. + * + * Called within RCU critical section. + */ +@@ -2162,7 +2132,9 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr, + hwaddr *size, bool lock) + { + RAMBlock *block = ram_block; +- if (*size == 0) { ++ hwaddr len = 0; ++ ++ if (size && *size == 0) { + return NULL; + } + +@@ -2170,7 +2142,10 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr, + block = qemu_get_ram_block(addr); + addr -= block->offset; + } +- *size = MIN(*size, block->max_length - addr); ++ if (size) { ++ *size = MIN(*size, block->max_length - addr); ++ len = *size; ++ } + + if (xen_enabled() && block->host == NULL) { + /* We need to check if the requested address is in the RAM +@@ -2178,7 +2153,7 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr, + * In that case just map the requested area. + */ + if (block->offset == 0) { +- return xen_map_cache(addr, *size, lock, lock); ++ return xen_map_cache(addr, len, lock, lock); + } + + block->host = xen_map_cache(block->offset, block->max_length, 1, lock); +@@ -2187,6 +2162,19 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr, + return ramblock_ptr(block, addr); + } + ++/* ++ * Return a host pointer to ram allocated with qemu_ram_alloc. ++ * This should not be used for general purpose DMA. Use address_space_map ++ * or address_space_rw instead. For local memory (e.g. video ram) that the ++ * device owns, use memory_region_get_ram_ptr. ++ * ++ * Called within RCU critical section. ++ */ ++void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr) ++{ ++ return qemu_ram_ptr_length(ram_block, addr, NULL, false); ++} ++ + /* Return the offset of a hostpointer within a ramblock */ + ram_addr_t qemu_ram_block_host_offset(RAMBlock *rb, void *host) + { +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0008-xen-let-xen_ram_addr_from_mapcache-return-1-in-case-.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0008-xen-let-xen_ram_addr_from_mapcache-return-1-in-case-.patch new file mode 100644 index 00000000..c1e9abd9 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0008-xen-let-xen_ram_addr_from_mapcache-return-1-in-case-.patch @@ -0,0 +1,49 @@ +From 857bcafe8beb5a0cd78c070f432108049661a56d Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 20 May 2021 13:31:32 +0200 +Subject: [PATCH 08/11] xen: let xen_ram_addr_from_mapcache() return -1 in case + of not found entry + +Today xen_ram_addr_from_mapcache() will either abort() or return 0 in +case it can't find a matching entry for a pointer value. Both cases +are bad, so change that to return an invalid address instead. + +Signed-off-by: Juergen Gross +Reviewed-by: Stefano Stabellini +--- + hw/xen/xen-mapcache.c | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c +index 8115c44c00..8a61c7dde6 100644 +--- a/hw/xen/xen-mapcache.c ++++ b/hw/xen/xen-mapcache.c +@@ -404,13 +404,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr) + } + } + if (!found) { +- fprintf(stderr, "%s, could not find %p\n", __func__, ptr); +- QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { +- DPRINTF(" "HWADDR_FMT_plx" -> %p is present\n", reventry->paddr_index, +- reventry->vaddr_req); +- } +- abort(); +- return 0; ++ mapcache_unlock(); ++ return RAM_ADDR_INVALID; + } + + entry = &mapcache->entry[paddr_index % mapcache->nr_buckets]; +@@ -418,8 +413,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr) + entry = entry->next; + } + if (!entry) { +- DPRINTF("Trying to find address %p that is not in the mapcache!\n", ptr); +- raddr = 0; ++ raddr = RAM_ADDR_INVALID; + } else { + raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) + + ((unsigned long) ptr - (unsigned long) entry->vaddr_base); +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0009-memory-add-MemoryRegion-map-and-unmap-callbacks.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0009-memory-add-MemoryRegion-map-and-unmap-callbacks.patch new file mode 100644 index 00000000..fa18ef16 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0009-memory-add-MemoryRegion-map-and-unmap-callbacks.patch @@ -0,0 +1,155 @@ +From 364a11be6274336ec9b0f06f3272f964d27c9349 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 27 May 2021 15:27:55 +0200 +Subject: [PATCH 09/11] memory: add MemoryRegion map and unmap callbacks + +In order to support mapping and unmapping guest memory dynamically to +and from qemu during address_space_[un]map() operations add the map() +and unmap() callbacks to MemoryRegionOps. + +Those will be used e.g. for Xen grant mappings when performing guest +I/Os. + +Signed-off-by: Juergen Gross +Signed-off-by: Vikram Garhwal +--- + include/exec/memory.h | 21 ++++++++++++++++++ + softmmu/physmem.c | 50 +++++++++++++++++++++++++++++++++---------- + 2 files changed, 60 insertions(+), 11 deletions(-) + +diff --git a/include/exec/memory.h b/include/exec/memory.h +index 68284428f8..55414417ab 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -274,6 +274,27 @@ struct MemoryRegionOps { + unsigned size, + MemTxAttrs attrs); + ++ /* ++ * Dynamically create mapping. @addr is the guest address to map; @plen ++ * is the pointer to the usable length of the buffer. ++ * @mr contents can be changed in case a new memory region is created for ++ * the mapping. ++ * Returns the buffer address for accessing the data. ++ */ ++ void *(*map)(MemoryRegion **mr, ++ hwaddr addr, ++ hwaddr *plen, ++ bool is_write, ++ MemTxAttrs attrs); ++ ++ /* Unmap an area obtained via map() before. */ ++ void (*unmap)(MemoryRegion *mr, ++ void *buffer, ++ ram_addr_t addr, ++ hwaddr len, ++ bool is_write, ++ hwaddr access_len); ++ + enum device_endian endianness; + /* Guest-visible constraints: */ + struct { +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index a934e44fe7..a1e2030424 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -3070,6 +3070,7 @@ void *address_space_map(AddressSpace *as, + hwaddr len = *plen; + hwaddr l, xlat; + MemoryRegion *mr; ++ void *ptr = NULL; + FlatView *fv; + + if (len == 0) { +@@ -3103,12 +3104,20 @@ void *address_space_map(AddressSpace *as, + return bounce.buffer; + } + +- + memory_region_ref(mr); ++ ++ if (mr->ops && mr->ops->map) { ++ ptr = mr->ops->map(&mr, addr, plen, is_write, attrs); ++ } ++ + *plen = flatview_extend_translation(fv, addr, len, mr, xlat, + l, is_write, attrs); + fuzz_dma_read_cb(addr, *plen, mr); +- return qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); ++ if (ptr == NULL) { ++ ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); ++ } ++ ++ return ptr; + } + + /* Unmaps a memory region previously mapped by address_space_map(). +@@ -3124,11 +3133,16 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, + + mr = memory_region_from_host(buffer, &addr1); + assert(mr != NULL); +- if (is_write) { +- invalidate_and_set_dirty(mr, addr1, access_len); +- } +- if (xen_enabled()) { +- xen_invalidate_map_cache_entry(buffer); ++ ++ if (mr->ops && mr->ops->unmap) { ++ mr->ops->unmap(mr, buffer, addr1, len, is_write, access_len); ++ } else { ++ if (is_write) { ++ invalidate_and_set_dirty(mr, addr1, access_len); ++ } ++ if (xen_enabled()) { ++ xen_invalidate_map_cache_entry(buffer); ++ } + } + memory_region_unref(mr); + return; +@@ -3201,10 +3215,18 @@ int64_t address_space_cache_init(MemoryRegionCache *cache, + * doing this if we found actual RAM, which behaves the same + * regardless of attributes; so UNSPECIFIED is fine. + */ ++ if (mr->ops && mr->ops->map) { ++ cache->ptr = mr->ops->map(&mr, addr, &l, is_write, ++ MEMTXATTRS_UNSPECIFIED); ++ } ++ + l = flatview_extend_translation(cache->fv, addr, len, mr, + cache->xlat, l, is_write, + MEMTXATTRS_UNSPECIFIED); +- cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, true); ++ if (!cache->ptr) { ++ cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, ++ true); ++ } + } else { + cache->ptr = NULL; + } +@@ -3226,14 +3248,20 @@ void address_space_cache_invalidate(MemoryRegionCache *cache, + + void address_space_cache_destroy(MemoryRegionCache *cache) + { +- if (!cache->mrs.mr) { ++ MemoryRegion *mr = cache->mrs.mr; ++ ++ if (!mr) { + return; + } + +- if (xen_enabled()) { ++ if (mr->ops && mr->ops->unmap) { ++ mr->ops->unmap(mr, cache->ptr, cache->xlat, cache->len, ++ cache->is_write, cache->len); ++ } else if (xen_enabled()) { + xen_invalidate_map_cache_entry(cache->ptr); + } +- memory_region_unref(cache->mrs.mr); ++ ++ memory_region_unref(mr); + flatview_unref(cache->fv); + cache->mrs.mr = NULL; + cache->fv = NULL; +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch new file mode 100644 index 00000000..48dcf7d7 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0010-xen-add-map-and-unmap-callbacks-for-grant-region.patch @@ -0,0 +1,262 @@ +From 90496d4c71e3b9334aebca118661bf72631ed0f0 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Fri, 26 Aug 2022 13:57:06 +0200 +Subject: [PATCH 10/11] xen: add map and unmap callbacks for grant region + +Add the callbacks for mapping/unmapping guest memory via grants to the +special grant memory region. + +Signed-off-by: Juergen Gross +Signed-off-by: Vikram Garhwal +--- + hw/xen/xen-mapcache.c | 176 +++++++++++++++++++++++++++++++++++++++++- + softmmu/physmem.c | 11 ++- + 2 files changed, 182 insertions(+), 5 deletions(-) + +diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c +index 8a61c7dde6..e071328fc5 100644 +--- a/hw/xen/xen-mapcache.c ++++ b/hw/xen/xen-mapcache.c +@@ -9,6 +9,8 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/queue.h" ++#include "qemu/thread.h" + #include "qemu/units.h" + #include "qemu/error-report.h" + +@@ -23,6 +25,8 @@ + #include "sysemu/xen-mapcache.h" + #include "trace.h" + ++#include ++#include + + //#define MAPCACHE_DEBUG + +@@ -385,7 +389,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, + return p; + } + +-ram_addr_t xen_ram_addr_from_mapcache(void *ptr) ++static ram_addr_t xen_ram_addr_from_mapcache_try(void *ptr) + { + MapCacheEntry *entry = NULL; + MapCacheRev *reventry; +@@ -594,10 +598,179 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr, + return p; + } + ++struct XENMappedGrantRegion { ++ void *addr; ++ unsigned int pages; ++ unsigned int refs; ++ unsigned int prot; ++ uint32_t idx; ++ QLIST_ENTRY(XENMappedGrantRegion) list; ++}; ++ ++static xengnttab_handle *xen_region_gnttabdev; ++static QLIST_HEAD(GrantRegionList, XENMappedGrantRegion) xen_grant_mappings = ++ QLIST_HEAD_INITIALIZER(xen_grant_mappings); ++static QemuMutex xen_map_mutex; ++ ++static void *xen_map_grant_dyn(MemoryRegion **mr, hwaddr addr, hwaddr *plen, ++ bool is_write, MemTxAttrs attrs) ++{ ++ unsigned int page_off = addr & (XC_PAGE_SIZE - 1); ++ unsigned int i; ++ unsigned int total_grants = 0; ++ unsigned int nrefs = (page_off + *plen + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT; ++ uint32_t ref = (addr - XEN_GRANT_ADDR_OFF) >> XC_PAGE_SHIFT; ++ uint32_t *refs = NULL; ++ unsigned int prot = PROT_READ; ++ struct XENMappedGrantRegion *mgr = NULL; ++ ++ if (is_write) { ++ prot |= PROT_WRITE; ++ } ++ ++ qemu_mutex_lock(&xen_map_mutex); ++ ++ QLIST_FOREACH(mgr, &xen_grant_mappings, list) { ++ if (mgr->idx == ref && ++ mgr->pages == nrefs && ++ (mgr->prot & prot) == prot) { ++ break; ++ } ++ ++ total_grants += mgr->pages; ++ } ++ ++ if (!mgr) { ++ if (nrefs + total_grants >= XEN_MAX_VIRTIO_GRANTS) { ++ qemu_mutex_unlock(&xen_map_mutex); ++ return NULL; ++ } ++ ++ mgr = g_new(struct XENMappedGrantRegion, 1); ++ ++ if (nrefs == 1) { ++ refs = &ref; ++ } else { ++ refs = g_new(uint32_t, nrefs); ++ for (i = 0; i < nrefs; i++) { ++ refs[i] = ref + i; ++ } ++ } ++ mgr->addr = xengnttab_map_domain_grant_refs(xen_region_gnttabdev, nrefs, ++ xen_domid, refs, prot); ++ if (mgr->addr) { ++ mgr->pages = nrefs; ++ mgr->refs = 1; ++ mgr->prot = prot; ++ mgr->idx = ref; ++ ++ QLIST_INSERT_HEAD(&xen_grant_mappings, mgr, list); ++ } else { ++ g_free(mgr); ++ mgr = NULL; ++ } ++ } else { ++ mgr->refs++; ++ } ++ ++ qemu_mutex_unlock(&xen_map_mutex); ++ ++ if (nrefs > 1) { ++ g_free(refs); ++ } ++ ++ return mgr ? mgr->addr + page_off : NULL; ++} ++ ++static void xen_unmap_grant_dyn(MemoryRegion *mr, void *buffer, ram_addr_t addr, ++ hwaddr len, bool is_write, hwaddr access_len) ++{ ++ unsigned int page_off = (unsigned long)buffer & (XC_PAGE_SIZE - 1); ++ unsigned int nrefs = (page_off + len + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT; ++ unsigned int prot = PROT_READ; ++ struct XENMappedGrantRegion *mgr = NULL; ++ ++ if (is_write) { ++ prot |= PROT_WRITE; ++ } ++ ++ qemu_mutex_lock(&xen_map_mutex); ++ ++ QLIST_FOREACH(mgr, &xen_grant_mappings, list) { ++ if (mgr->addr == buffer - page_off && ++ mgr->pages == nrefs && ++ (mgr->prot & prot) == prot) { ++ break; ++ } ++ } ++ if (mgr) { ++ mgr->refs--; ++ if (!mgr->refs) { ++ xengnttab_unmap(xen_region_gnttabdev, mgr->addr, nrefs); ++ ++ QLIST_REMOVE(mgr, list); ++ g_free(mgr); ++ } ++ } else { ++ error_report("xen_unmap_grant_dyn() trying to unmap unknown buffer"); ++ } ++ ++ qemu_mutex_unlock(&xen_map_mutex); ++} ++ ++static ram_addr_t xen_ram_addr_from_grant_cache(void *ptr) ++{ ++ unsigned int page_off = (unsigned long)ptr & (XC_PAGE_SIZE - 1); ++ struct XENMappedGrantRegion *mgr = NULL; ++ ram_addr_t raddr = RAM_ADDR_INVALID; ++ ++ qemu_mutex_lock(&xen_map_mutex); ++ ++ QLIST_FOREACH(mgr, &xen_grant_mappings, list) { ++ if (mgr->addr == ptr - page_off) { ++ break; ++ } ++ } ++ ++ if (mgr) { ++ raddr = (mgr->idx << XC_PAGE_SHIFT) + page_off + XEN_GRANT_ADDR_OFF; ++ } ++ ++ qemu_mutex_unlock(&xen_map_mutex); ++ ++ return raddr; ++} ++ ++ram_addr_t xen_ram_addr_from_mapcache(void *ptr) ++{ ++ ram_addr_t raddr; ++ ++ raddr = xen_ram_addr_from_mapcache_try(ptr); ++ if (raddr == RAM_ADDR_INVALID) { ++ raddr = xen_ram_addr_from_grant_cache(ptr); ++ } ++ ++ return raddr; ++} ++ ++static const struct MemoryRegionOps xen_grant_mr_ops = { ++ .map = xen_map_grant_dyn, ++ .unmap = xen_unmap_grant_dyn, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ + MemoryRegion *xen_init_grant_ram(void) + { + RAMBlock *block; + ++ qemu_mutex_init(&xen_map_mutex); ++ ++ xen_region_gnttabdev = xengnttab_open(NULL, 0); ++ if (xen_region_gnttabdev == NULL) { ++ fprintf(stderr, "can't open gnttab device\n"); ++ return NULL; ++ } ++ + memory_region_init(&ram_grants, NULL, "xen.grants", + XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE); + block = g_malloc0(sizeof(*block)); +@@ -612,6 +785,7 @@ MemoryRegion *xen_init_grant_ram(void) + ram_grants.ram_block = block; + ram_grants.ram = true; + ram_grants.terminates = true; ++ ram_grants.ops = &xen_grant_mr_ops; + ram_block_add_list(block); + memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF, + &ram_grants); +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index a1e2030424..e1057304f1 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -2210,13 +2210,16 @@ RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, + + if (xen_enabled()) { + ram_addr_t ram_addr; ++ + RCU_READ_LOCK_GUARD(); + ram_addr = xen_ram_addr_from_mapcache(ptr); +- block = qemu_get_ram_block(ram_addr); +- if (block) { +- *offset = ram_addr - block->offset; ++ if (ram_addr != RAM_ADDR_INVALID) { ++ block = qemu_get_ram_block(ram_addr); ++ if (block) { ++ *offset = ram_addr - block->offset; ++ } ++ return block; + } +- return block; + } + + RCU_READ_LOCK_GUARD(); +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0011-hw-arm-Add-grant-mapping.patch b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0011-hw-arm-Add-grant-mapping.patch new file mode 100644 index 00000000..fb5450e6 --- /dev/null +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx-8.1/0011-hw-arm-Add-grant-mapping.patch @@ -0,0 +1,30 @@ +From b1eaba758a9000061fc53a934c348d6ef8dcdf64 Mon Sep 17 00:00:00 2001 +From: Vikram Garhwal +Date: Tue, 31 Jan 2023 21:46:43 +0000 +Subject: [PATCH 11/11] hw: arm: Add grant mapping. + +Enable grant ram mapping support for Xenpvh machine on ARM. + +Signed-off-by: Vikram Garhwal +Reviewed-by: Stefano Stabellini +--- + hw/arm/xen_arm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c +index a5631529d0..1587e2a43b 100644 +--- a/hw/arm/xen_arm.c ++++ b/hw/arm/xen_arm.c +@@ -127,6 +127,9 @@ static void xen_init_ram(MachineState *machine) + DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n", + GUEST_RAM1_BASE, ram_size[1]); + } ++ ++ DPRINTF("init grant ram mapping for XEN\n"); ++ ram_grants = *xen_init_grant_ram(); + } + + void arch_handle_ioreq(XenIOState *state, ioreq_t *req) +-- +2.39.2 + diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx_2024%.bbappend b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx_2024%.bbappend index b1e94b5a..2f8e55aa 100644 --- a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx_2024%.bbappend +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu-xilinx_2024%.bbappend @@ -1,5 +1,5 @@ require qemu-tpm.inc -#require qemu-xen.inc +require qemu-xen_8.1.inc # We do not want QEMU, on the target to be configured with OpenGL PACKAGECONFIG:remove:class-target:petalinux = "virglrenderer epoxy gtk+" diff --git a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu_8.1%.bbappend b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu_8.1%.bbappend index b1e94b5a..95b1902b 100644 --- a/meta-xilinx-virtualization/recipes-devtools/qemu/qemu_8.1%.bbappend +++ b/meta-xilinx-virtualization/recipes-devtools/qemu/qemu_8.1%.bbappend @@ -1,5 +1,5 @@ require qemu-tpm.inc -#require qemu-xen.inc +require qemu-xen_8.1.inc # We do not want QEMU, on the target to be configured with OpenGL -PACKAGECONFIG:remove:class-target:petalinux = "virglrenderer epoxy gtk+" +PACKAGECONFIG:remove:class-target = "virglrenderer epoxy gtk+" -- cgit v1.2.3-54-g00ecf