Revision | b1b87327a903e298b3b4c79da0beed31b57fb594 (tree) |
---|---|
Time | 2022-01-20 20:47:52 |
Author | Gavin Shan <gshan@redh...> |
Commiter | Peter Maydell |
hw/arm/virt: Support for virtio-mem-pci
This supports virtio-mem-pci device on "virt" platform, by simply
following the implementation on x86.
Co-developed-by: David Hildenbrand <david@redhat.com>
Co-developed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Message-id: 20220111063329.74447-3-gshan@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
@@ -28,6 +28,7 @@ config ARM_VIRT | ||
28 | 28 | select ACPI_HW_REDUCED |
29 | 29 | select ACPI_APEI |
30 | 30 | select ACPI_VIOT |
31 | + select VIRTIO_MEM_SUPPORTED | |
31 | 32 | |
32 | 33 | config CHEETAH |
33 | 34 | bool |
@@ -71,9 +71,11 @@ | ||
71 | 71 | #include "hw/arm/smmuv3.h" |
72 | 72 | #include "hw/acpi/acpi.h" |
73 | 73 | #include "target/arm/internals.h" |
74 | +#include "hw/mem/memory-device.h" | |
74 | 75 | #include "hw/mem/pc-dimm.h" |
75 | 76 | #include "hw/mem/nvdimm.h" |
76 | 77 | #include "hw/acpi/generic_event_device.h" |
78 | +#include "hw/virtio/virtio-mem-pci.h" | |
77 | 79 | #include "hw/virtio/virtio-iommu.h" |
78 | 80 | #include "hw/char/pl011.h" |
79 | 81 | #include "qemu/guest-random.h" |
@@ -2501,6 +2503,64 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, | ||
2501 | 2503 | dev, &error_abort); |
2502 | 2504 | } |
2503 | 2505 | |
2506 | +static void virt_virtio_md_pci_pre_plug(HotplugHandler *hotplug_dev, | |
2507 | + DeviceState *dev, Error **errp) | |
2508 | +{ | |
2509 | + HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev); | |
2510 | + Error *local_err = NULL; | |
2511 | + | |
2512 | + if (!hotplug_dev2 && dev->hotplugged) { | |
2513 | + /* | |
2514 | + * Without a bus hotplug handler, we cannot control the plug/unplug | |
2515 | + * order. We should never reach this point when hotplugging on ARM. | |
2516 | + * However, it's nice to add a safety net, similar to what we have | |
2517 | + * on x86. | |
2518 | + */ | |
2519 | + error_setg(errp, "hotplug of virtio based memory devices not supported" | |
2520 | + " on this bus."); | |
2521 | + return; | |
2522 | + } | |
2523 | + /* | |
2524 | + * First, see if we can plug this memory device at all. If that | |
2525 | + * succeeds, branch of to the actual hotplug handler. | |
2526 | + */ | |
2527 | + memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), NULL, | |
2528 | + &local_err); | |
2529 | + if (!local_err && hotplug_dev2) { | |
2530 | + hotplug_handler_pre_plug(hotplug_dev2, dev, &local_err); | |
2531 | + } | |
2532 | + error_propagate(errp, local_err); | |
2533 | +} | |
2534 | + | |
2535 | +static void virt_virtio_md_pci_plug(HotplugHandler *hotplug_dev, | |
2536 | + DeviceState *dev, Error **errp) | |
2537 | +{ | |
2538 | + HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev); | |
2539 | + Error *local_err = NULL; | |
2540 | + | |
2541 | + /* | |
2542 | + * Plug the memory device first and then branch off to the actual | |
2543 | + * hotplug handler. If that one fails, we can easily undo the memory | |
2544 | + * device bits. | |
2545 | + */ | |
2546 | + memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev)); | |
2547 | + if (hotplug_dev2) { | |
2548 | + hotplug_handler_plug(hotplug_dev2, dev, &local_err); | |
2549 | + if (local_err) { | |
2550 | + memory_device_unplug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev)); | |
2551 | + } | |
2552 | + } | |
2553 | + error_propagate(errp, local_err); | |
2554 | +} | |
2555 | + | |
2556 | +static void virt_virtio_md_pci_unplug_request(HotplugHandler *hotplug_dev, | |
2557 | + DeviceState *dev, Error **errp) | |
2558 | +{ | |
2559 | + /* We don't support hot unplug of virtio based memory devices */ | |
2560 | + error_setg(errp, "virtio based memory devices cannot be unplugged."); | |
2561 | +} | |
2562 | + | |
2563 | + | |
2504 | 2564 | static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, |
2505 | 2565 | DeviceState *dev, Error **errp) |
2506 | 2566 | { |
@@ -2508,6 +2568,8 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, | ||
2508 | 2568 | |
2509 | 2569 | if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { |
2510 | 2570 | virt_memory_pre_plug(hotplug_dev, dev, errp); |
2571 | + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { | |
2572 | + virt_virtio_md_pci_pre_plug(hotplug_dev, dev, errp); | |
2511 | 2573 | } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { |
2512 | 2574 | hwaddr db_start = 0, db_end = 0; |
2513 | 2575 | char *resv_prop_str; |
@@ -2559,6 +2621,11 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, | ||
2559 | 2621 | if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { |
2560 | 2622 | virt_memory_plug(hotplug_dev, dev, errp); |
2561 | 2623 | } |
2624 | + | |
2625 | + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { | |
2626 | + virt_virtio_md_pci_plug(hotplug_dev, dev, errp); | |
2627 | + } | |
2628 | + | |
2562 | 2629 | if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { |
2563 | 2630 | PCIDevice *pdev = PCI_DEVICE(dev); |
2564 | 2631 |
@@ -2615,6 +2682,8 @@ static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, | ||
2615 | 2682 | { |
2616 | 2683 | if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { |
2617 | 2684 | virt_dimm_unplug_request(hotplug_dev, dev, errp); |
2685 | + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { | |
2686 | + virt_virtio_md_pci_unplug_request(hotplug_dev, dev, errp); | |
2618 | 2687 | } else { |
2619 | 2688 | error_setg(errp, "device unplug request for unsupported device" |
2620 | 2689 | " type: %s", object_get_typename(OBJECT(dev))); |
@@ -2639,6 +2708,7 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, | ||
2639 | 2708 | |
2640 | 2709 | if (device_is_dynamic_sysbus(mc, dev) || |
2641 | 2710 | object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || |
2711 | + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI) || | |
2642 | 2712 | object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { |
2643 | 2713 | return HOTPLUG_HANDLER(machine); |
2644 | 2714 | } |
@@ -146,7 +146,7 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) | ||
146 | 146 | * The memory block size corresponds mostly to the section size. |
147 | 147 | * |
148 | 148 | * This allows e.g., to add 20MB with a section size of 128MB on x86_64, and |
149 | - * a section size of 1GB on arm64 (as long as the start address is properly | |
149 | + * a section size of 512MB on arm64 (as long as the start address is properly | |
150 | 150 | * aligned, similar to ordinary DIMMs). |
151 | 151 | * |
152 | 152 | * We can change this at any time and maybe even make it configurable if |
@@ -155,6 +155,8 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) | ||
155 | 155 | */ |
156 | 156 | #if defined(TARGET_X86_64) || defined(TARGET_I386) |
157 | 157 | #define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB)) |
158 | +#elif defined(TARGET_ARM) | |
159 | +#define VIRTIO_MEM_USABLE_EXTENT (2 * (512 * MiB)) | |
158 | 160 | #else |
159 | 161 | #error VIRTIO_MEM_USABLE_EXTENT not defined |
160 | 162 | #endif |