diff options
Diffstat (limited to 'include/hw')
-rw-r--r-- | include/hw/intc/loongarch_dintc.h | 36 | ||||
-rw-r--r-- | include/hw/loongarch/virt.h | 34 | ||||
-rw-r--r-- | include/hw/pci-host/ls7a.h | 2 | ||||
-rw-r--r-- | include/hw/ppc/pnv.h | 38 | ||||
-rw-r--r-- | include/hw/ppc/pnv_chip.h | 8 | ||||
-rw-r--r-- | include/hw/ppc/pnv_chiptod.h | 2 | ||||
-rw-r--r-- | include/hw/ppc/pnv_xscom.h | 49 | ||||
-rw-r--r-- | include/hw/ppc/ppc.h | 1 | ||||
-rw-r--r-- | include/hw/vfio/vfio-container-base.h | 279 | ||||
-rw-r--r-- | include/hw/vfio/vfio-container-legacy.h | 39 | ||||
-rw-r--r-- | include/hw/vfio/vfio-container.h | 286 | ||||
-rw-r--r-- | include/hw/vfio/vfio-cpr.h | 15 | ||||
-rw-r--r-- | include/hw/vfio/vfio-device.h | 12 |
13 files changed, 486 insertions, 315 deletions
diff --git a/include/hw/intc/loongarch_dintc.h b/include/hw/intc/loongarch_dintc.h new file mode 100644 index 0000000..0b0b534 --- /dev/null +++ b/include/hw/intc/loongarch_dintc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch direct interrupt controller definitions + * + * Copyright (C) 2025 Loongson Technology Corporation Limited + */ + +#include "qom/object.h" +#include "hw/sysbus.h" +#include "hw/loongarch/virt.h" + + +#define NR_VECTORS 256 + +#define TYPE_LOONGARCH_DINTC "loongarch_dintc" +OBJECT_DECLARE_TYPE(LoongArchDINTCState, LoongArchDINTCClass, LOONGARCH_DINTC) + +typedef struct DINTCCore { + CPUState *cpu; + qemu_irq parent_irq; + uint64_t arch_id; +} DINTCCore; + +struct LoongArchDINTCState { + SysBusDevice parent_obj; + MemoryRegion dintc_mmio; + DINTCCore *cpu; + uint32_t num_cpu; +}; + +struct LoongArchDINTCClass { + SysBusDeviceClass parent_class; + + DeviceRealize parent_realize; + DeviceUnrealize parent_unrealize; +}; diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 602feab..cd97bdf 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -13,6 +13,27 @@ #include "hw/block/flash.h" #include "hw/loongarch/boot.h" +#define IOCSRF_TEMP 0 +#define IOCSRF_NODECNT 1 +#define IOCSRF_MSI 2 +#define IOCSRF_EXTIOI 3 +#define IOCSRF_CSRIPI 4 +#define IOCSRF_FREQCSR 5 +#define IOCSRF_FREQSCALE 6 +#define IOCSRF_DVFSV1 7 +#define IOCSRF_GMOD 9 +#define IOCSRF_VM 11 +#define IOCSRF_DMSI 15 + +#define VERSION_REG 0x0 +#define FEATURE_REG 0x8 +#define VENDOR_REG 0x10 +#define CPUNAME_REG 0x20 +#define MISC_FUNC_REG 0x420 +#define IOCSRM_EXTIOI_EN 48 +#define IOCSRM_EXTIOI_INT_ENCODE 49 +#define IOCSRM_DMSI_EN 51 + #define LOONGARCH_MAX_CPUS 256 #define VIRT_FWCFG_BASE 0x1e020000UL @@ -50,6 +71,7 @@ struct LoongArchVirtMachineState { Notifier powerdown_notifier; OnOffAuto acpi; OnOffAuto veiointc; + OnOffAuto dmsi; char *oem_id; char *oem_table_id; DeviceState *acpi_ged; @@ -65,6 +87,9 @@ struct LoongArchVirtMachineState { DeviceState *extioi; struct memmap_entry *memmap_table; unsigned int memmap_entries; + uint64_t misc_feature; + uint64_t misc_status; + DeviceState *dintc; }; #define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt") @@ -72,6 +97,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE) void virt_acpi_setup(LoongArchVirtMachineState *lvms); void virt_fdt_setup(LoongArchVirtMachineState *lvms); +static inline bool virt_has_dmsi(LoongArchVirtMachineState *lvms) +{ + if (!(lvms->misc_feature & BIT(IOCSRF_DMSI))) { + return false; + } + + return true; +} + static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms) { if (lvms->veiointc == ON_OFF_AUTO_OFF) { diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index 79d4ea8..bfdbfe3 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -24,6 +24,8 @@ #define VIRT_PCH_REG_BASE 0x10000000UL #define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE) #define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL +#define VIRT_DINTC_SIZE 0x100000UL +#define VIRT_DINTC_BASE 0x2FE00000UL #define VIRT_PCH_REG_SIZE 0x400 #define VIRT_PCH_MSI_SIZE 0x8 diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index d8fca07..cbdddfc 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -33,6 +33,7 @@ typedef struct PnvChip PnvChip; typedef struct Pnv8Chip Pnv8Chip; typedef struct Pnv9Chip Pnv9Chip; typedef struct Pnv10Chip Pnv10Chip; +typedef struct Pnv10Chip Pnv11Chip; #define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP #define PNV_CHIP_TYPE_NAME(cpu_model) cpu_model PNV_CHIP_TYPE_SUFFIX @@ -57,6 +58,10 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9, DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, TYPE_PNV_CHIP_POWER10) +#define TYPE_PNV_CHIP_POWER11 PNV_CHIP_TYPE_NAME("power11_v2.0") +DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER11, + TYPE_PNV_CHIP_POWER11) + PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id); PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); @@ -252,4 +257,37 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor); #define PNV10_HOMER_BASE(chip) \ (0x300ffd800000ll + ((uint64_t)(chip)->chip_id) * PNV_HOMER_SIZE) +/* Power11 */ +#define PNV11_XSCOM_SIZE PNV10_XSCOM_SIZE +#define PNV11_XSCOM_BASE(chip) PNV10_XSCOM_BASE(chip) + +#define PNV11_LPCM_SIZE PNV10_LPCM_SIZE +#define PNV11_LPCM_BASE(chip) PNV10_LPCM_BASE(chip) + +#define PNV11_PSIHB_ESB_SIZE PNV10_PSIHB_ESB_SIZE +#define PNV11_PSIHB_ESB_BASE(chip) PNV10_PSIHB_ESB_BASE(chip) + +#define PNV11_PSIHB_SIZE PNV10_PSIHB_SIZE +#define PNV11_PSIHB_BASE(chip) PNV10_PSIHB_BASE(chip) + +#define PNV11_XIVE2_IC_SIZE PNV10_XIVE2_IC_SIZE +#define PNV11_XIVE2_IC_BASE(chip) PNV10_XIVE2_IC_BASE(chip) + +#define PNV11_XIVE2_TM_SIZE PNV10_XIVE2_TM_SIZE +#define PNV11_XIVE2_TM_BASE(chip) PNV10_XIVE2_TM_BASE(chip) + +#define PNV11_XIVE2_NVC_SIZE PNV10_XIVE2_NVC_SIZE +#define PNV11_XIVE2_NVC_BASE(chip) PNV10_XIVE2_NVC_BASE(chip) + +#define PNV11_XIVE2_NVPG_SIZE PNV10_XIVE2_NVPG_SIZE +#define PNV11_XIVE2_NVPG_BASE(chip) PNV10_XIVE2_NVPG_BASE(chip) + +#define PNV11_XIVE2_ESB_SIZE PNV10_XIVE2_ESB_SIZE +#define PNV11_XIVE2_ESB_BASE(chip) PNV10_XIVE2_ESB_BASE(chip) + +#define PNV11_XIVE2_END_SIZE PNV10_XIVE2_END_SIZE +#define PNV11_XIVE2_END_BASE(chip) PNV10_XIVE2_END_BASE(chip) + +#define PNV11_OCC_SENSOR_BASE(chip) PNV10_OCC_SENSOR_BASE(chip) + #endif /* PPC_PNV_H */ diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h index 24ce37a..a5b8c49 100644 --- a/include/hw/ppc/pnv_chip.h +++ b/include/hw/ppc/pnv_chip.h @@ -141,6 +141,13 @@ struct Pnv10Chip { #define PNV10_PIR2CHIP(pir) (((pir) >> 8) & 0x7f) #define PNV10_PIR2THREAD(pir) (((pir) & 0x7f)) +#define TYPE_PNV11_CHIP "pnv11-chip" +DECLARE_INSTANCE_CHECKER(Pnv11Chip, PNV11_CHIP, + TYPE_PNV11_CHIP) + +/* Power11 core is same as Power10 */ +typedef struct Pnv10Chip Pnv11Chip; + struct PnvChipClass { /*< private >*/ SysBusDeviceClass parent_class; @@ -163,6 +170,7 @@ struct PnvChipClass { void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu); void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu); void (*intc_print_info)(PnvChip *chip, PowerPCCPU *cpu, GString *buf); + void* (*intc_get)(PnvChip *chip); ISABus *(*isa_create)(PnvChip *chip, Error **errp); void (*dt_populate)(PnvChip *chip, void *fdt); void (*pic_print_info)(PnvChip *chip, GString *buf); diff --git a/include/hw/ppc/pnv_chiptod.h b/include/hw/ppc/pnv_chiptod.h index fde569b..466b065 100644 --- a/include/hw/ppc/pnv_chiptod.h +++ b/include/hw/ppc/pnv_chiptod.h @@ -17,6 +17,8 @@ OBJECT_DECLARE_TYPE(PnvChipTOD, PnvChipTODClass, PNV_CHIPTOD) DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV9_CHIPTOD, TYPE_PNV9_CHIPTOD) #define TYPE_PNV10_CHIPTOD TYPE_PNV_CHIPTOD "-POWER10" DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV10_CHIPTOD, TYPE_PNV10_CHIPTOD) +#define TYPE_PNV11_CHIPTOD TYPE_PNV_CHIPTOD "-POWER11" +DECLARE_INSTANCE_CHECKER(PnvChipTOD, PNV11_CHIPTOD, TYPE_PNV11_CHIPTOD) enum tod_state { tod_error = 0, diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index b14549d..610b075 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -207,6 +207,55 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_PIB_SPIC_BASE 0xc0000 #define PNV10_XSCOM_PIB_SPIC_SIZE 0x20 +/* + * Power11 core is same as Power10 + */ +#define PNV11_XSCOM_EC_BASE(core) PNV10_XSCOM_EC_BASE(core) + +#define PNV11_XSCOM_ADU_BASE PNV10_XSCOM_ADU_BASE +#define PNV11_XSCOM_ADU_SIZE PNV10_XSCOM_ADU_SIZE + +#define PNV11_XSCOM_QME_BASE(core) PNV10_XSCOM_QME_BASE(core) + +#define PNV11_XSCOM_EQ_BASE(core) PNV10_XSCOM_EQ_BASE(core) + +#define PNV11_XSCOM_PSIHB_BASE PNV10_XSCOM_PSIHB_BASE +#define PNV11_XSCOM_PSIHB_SIZE PNV10_XSCOM_PSIHB_SIZE + +#define PNV11_XSCOM_I2CM_BASE PNV10_XSCOM_I2CM_BASE +#define PNV11_XSCOM_I2CM_SIZE PNV10_XSCOM_I2CM_SIZE + +#define PNV11_XSCOM_CHIPTOD_BASE PNV10_XSCOM_CHIPTOD_BASE +#define PNV11_XSCOM_CHIPTOD_SIZE PNV10_XSCOM_CHIPTOD_SIZE + +#define PNV11_XSCOM_OCC_BASE PNV10_XSCOM_OCC_BASE +#define PNV11_XSCOM_OCC_SIZE PNV10_XSCOM_OCC_SIZE + +#define PNV11_XSCOM_SBE_CTRL_BASE PNV10_XSCOM_SBE_CTRL_BASE +#define PNV11_XSCOM_SBE_CTRL_SIZE PNV10_XSCOM_SBE_CTRL_SIZE + +#define PNV11_XSCOM_SBE_MBOX_BASE PNV10_XSCOM_SBE_MBOX_BASE +#define PNV11_XSCOM_SBE_MBOX_SIZE PNV10_XSCOM_SBE_MBOX_SIZE + +#define PNV11_XSCOM_PBA_BASE PNV10_XSCOM_PBA_BASE +#define PNV11_XSCOM_PBA_SIZE PNV10_XSCOM_PBA_SIZE + +#define PNV11_XSCOM_XIVE2_BASE PNV10_XSCOM_XIVE2_BASE +#define PNV11_XSCOM_XIVE2_SIZE PNV10_XSCOM_XIVE2_SIZE + +#define PNV11_XSCOM_N1_CHIPLET_CTRL_REGS_BASE \ + PNV10_XSCOM_N1_CHIPLET_CTRL_REGS_BASE +#define PNV11_XSCOM_CHIPLET_CTRL_REGS_SIZE PNV10_XSCOM_CHIPLET_CTRL_REGS_SIZE + +#define PNV11_XSCOM_N1_PB_SCOM_EQ_BASE PNV10_XSCOM_N1_PB_SCOM_EQ_BASE +#define PNV11_XSCOM_N1_PB_SCOM_EQ_SIZE PNV10_XSCOM_N1_PB_SCOM_EQ_SIZE + +#define PNV11_XSCOM_N1_PB_SCOM_ES_BASE PNV10_XSCOM_N1_PB_SCOM_ES_BASE +#define PNV11_XSCOM_N1_PB_SCOM_ES_SIZE PNV10_XSCOM_N1_PB_SCOM_ES_SIZE + +#define PNV11_XSCOM_PIB_SPIC_BASE PNV10_XSCOM_PIB_SPIC_BASE +#define PNV11_XSCOM_PIB_SPIC_SIZE PNV10_XSCOM_PIB_SPIC_SIZE + void pnv_xscom_init(PnvChip *chip, uint64_t size, hwaddr addr); int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset, uint64_t xscom_base, uint64_t xscom_size, diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h index 8a14d62..cb51d70 100644 --- a/include/hw/ppc/ppc.h +++ b/include/hw/ppc/ppc.h @@ -52,6 +52,7 @@ struct ppc_tb_t { #define PPC_DECR_UNDERFLOW_LEVEL (1 << 4) /* Decr interrupt active when * the most significant bit is 1. */ +#define PPC_TIMER_PPE (1 << 5) /* Enable PPE support */ uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset); void cpu_ppc_tb_init(CPUPPCState *env, uint32_t freq); diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h deleted file mode 100644 index acbd48a..0000000 --- a/include/hw/vfio/vfio-container-base.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * VFIO BASE CONTAINER - * - * Copyright (C) 2023 Intel Corporation. - * Copyright Red Hat, Inc. 2023 - * - * Authors: Yi Liu <yi.l.liu@intel.com> - * Eric Auger <eric.auger@redhat.com> - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -#ifndef HW_VFIO_VFIO_CONTAINER_BASE_H -#define HW_VFIO_VFIO_CONTAINER_BASE_H - -#include "system/memory.h" - -typedef struct VFIODevice VFIODevice; -typedef struct VFIOIOMMUClass VFIOIOMMUClass; - -typedef struct { - unsigned long *bitmap; - hwaddr size; - hwaddr pages; -} VFIOBitmap; - -typedef struct VFIOAddressSpace { - AddressSpace *as; - QLIST_HEAD(, VFIOContainerBase) containers; - QLIST_ENTRY(VFIOAddressSpace) list; -} VFIOAddressSpace; - -/* - * This is the base object for vfio container backends - */ -struct VFIOContainerBase { - Object parent_obj; - - VFIOAddressSpace *space; - MemoryListener listener; - Error *error; - bool initialized; - uint64_t dirty_pgsizes; - uint64_t max_dirty_bitmap_size; - unsigned long pgsizes; - unsigned int dma_max_mappings; - bool dirty_pages_supported; - bool dirty_pages_started; /* Protected by BQL */ - QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; - QLIST_HEAD(, VFIORamDiscardListener) vrdl_list; - QLIST_ENTRY(VFIOContainerBase) next; - QLIST_HEAD(, VFIODevice) device_list; - GList *iova_ranges; - NotifierWithReturn cpr_reboot_notifier; -}; - -#define TYPE_VFIO_IOMMU "vfio-iommu" -OBJECT_DECLARE_TYPE(VFIOContainerBase, VFIOIOMMUClass, VFIO_IOMMU) - -typedef struct VFIOGuestIOMMU { - VFIOContainerBase *bcontainer; - IOMMUMemoryRegion *iommu_mr; - hwaddr iommu_offset; - IOMMUNotifier n; - QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; -} VFIOGuestIOMMU; - -typedef struct VFIORamDiscardListener { - VFIOContainerBase *bcontainer; - MemoryRegion *mr; - hwaddr offset_within_address_space; - hwaddr size; - uint64_t granularity; - RamDiscardListener listener; - QLIST_ENTRY(VFIORamDiscardListener) next; -} VFIORamDiscardListener; - -VFIOAddressSpace *vfio_address_space_get(AddressSpace *as); -void vfio_address_space_put(VFIOAddressSpace *space); -void vfio_address_space_insert(VFIOAddressSpace *space, - VFIOContainerBase *bcontainer); - -int vfio_container_dma_map(VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - void *vaddr, bool readonly, MemoryRegion *mr); -int vfio_container_dma_unmap(VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - IOMMUTLBEntry *iotlb, bool unmap_all); -bool vfio_container_add_section_window(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, - Error **errp); -void vfio_container_del_section_window(VFIOContainerBase *bcontainer, - MemoryRegionSection *section); -int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start, Error **errp); -bool vfio_container_dirty_tracking_is_started( - const VFIOContainerBase *bcontainer); -bool vfio_container_devices_dirty_tracking_is_supported( - const VFIOContainerBase *bcontainer); -int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, - uint64_t iova, uint64_t size, ram_addr_t ram_addr, Error **errp); - -GList *vfio_container_get_iova_ranges(const VFIOContainerBase *bcontainer); - -static inline uint64_t -vfio_container_get_page_size_mask(const VFIOContainerBase *bcontainer) -{ - assert(bcontainer); - return bcontainer->pgsizes; -} - -#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy" -#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr" -#define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd" -#define TYPE_VFIO_IOMMU_USER TYPE_VFIO_IOMMU "-user" - -struct VFIOIOMMUClass { - ObjectClass parent_class; - - /** - * @setup - * - * Perform basic setup of the container, including configuring IOMMU - * capabilities, IOVA ranges, supported page sizes, etc. - * - * @bcontainer: #VFIOContainerBase - * @errp: pointer to Error*, to store an error if it happens. - * - * Returns true to indicate success and false for error. - */ - bool (*setup)(VFIOContainerBase *bcontainer, Error **errp); - - /** - * @listener_begin - * - * Called at the beginning of an address space update transaction. - * See #MemoryListener. - * - * @bcontainer: #VFIOContainerBase - */ - void (*listener_begin)(VFIOContainerBase *bcontainer); - - /** - * @listener_commit - * - * Called at the end of an address space update transaction, - * See #MemoryListener. - * - * @bcontainer: #VFIOContainerBase - */ - void (*listener_commit)(VFIOContainerBase *bcontainer); - - /** - * @dma_map - * - * Map an address range into the container. Note that the memory region is - * referenced within an RCU read lock region across this call. - * - * @bcontainer: #VFIOContainerBase to use - * @iova: start address to map - * @size: size of the range to map - * @vaddr: process virtual address of mapping - * @readonly: true if mapping should be readonly - * @mr: the memory region for this mapping - * - * Returns 0 to indicate success and -errno otherwise. - */ - int (*dma_map)(const VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - void *vaddr, bool readonly, MemoryRegion *mr); - /** - * @dma_map_file - * - * Map a file range for the container. - * - * @bcontainer: #VFIOContainerBase to use for map - * @iova: start address to map - * @size: size of the range to map - * @fd: descriptor of the file to map - * @start: starting file offset of the range to map - * @readonly: map read only if true - */ - int (*dma_map_file)(const VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - int fd, unsigned long start, bool readonly); - /** - * @dma_unmap - * - * Unmap an address range from the container. - * - * @bcontainer: #VFIOContainerBase to use for unmap - * @iova: start address to unmap - * @size: size of the range to unmap - * @iotlb: The IOMMU TLB mapping entry (or NULL) - * @unmap_all: if set, unmap the entire address space - * - * Returns 0 to indicate success and -errno otherwise. - */ - int (*dma_unmap)(const VFIOContainerBase *bcontainer, - hwaddr iova, ram_addr_t size, - IOMMUTLBEntry *iotlb, bool unmap_all); - - - /** - * @attach_device - * - * Associate the given device with a container and do some related - * initialization of the device context. - * - * @name: name of the device - * @vbasedev: the device - * @as: address space to use - * @errp: pointer to Error*, to store an error if it happens. - * - * Returns true to indicate success and false for error. - */ - bool (*attach_device)(const char *name, VFIODevice *vbasedev, - AddressSpace *as, Error **errp); - - /* - * @detach_device - * - * Detach the given device from its container and clean up any necessary - * state. - * - * @vbasedev: the device to disassociate - */ - void (*detach_device)(VFIODevice *vbasedev); - - /* migration feature */ - - /** - * @set_dirty_page_tracking - * - * Start or stop dirty pages tracking on VFIO container - * - * @bcontainer: #VFIOContainerBase on which to de/activate dirty - * page tracking - * @start: indicates whether to start or stop dirty pages tracking - * @errp: pointer to Error*, to store an error if it happens. - * - * Returns zero to indicate success and negative for error. - */ - int (*set_dirty_page_tracking)(const VFIOContainerBase *bcontainer, - bool start, Error **errp); - /** - * @query_dirty_bitmap - * - * Get bitmap of dirty pages from container - * - * @bcontainer: #VFIOContainerBase from which to get dirty pages - * @vbmap: #VFIOBitmap internal bitmap structure - * @iova: iova base address - * @size: size of iova range - * @errp: pointer to Error*, to store an error if it happens. - * - * Returns zero to indicate success and negative for error. - */ - int (*query_dirty_bitmap)(const VFIOContainerBase *bcontainer, - VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp); - /* PCI specific */ - int (*pci_hot_reset)(VFIODevice *vbasedev, bool single); - - /* SPAPR specific */ - bool (*add_window)(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, - Error **errp); - void (*del_window)(VFIOContainerBase *bcontainer, - MemoryRegionSection *section); - void (*release)(VFIOContainerBase *bcontainer); -}; - -VFIORamDiscardListener *vfio_find_ram_discard_listener( - VFIOContainerBase *bcontainer, MemoryRegionSection *section); - -void vfio_container_region_add(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, bool cpr_remap); - -#endif /* HW_VFIO_VFIO_CONTAINER_BASE_H */ diff --git a/include/hw/vfio/vfio-container-legacy.h b/include/hw/vfio/vfio-container-legacy.h new file mode 100644 index 0000000..74a72df --- /dev/null +++ b/include/hw/vfio/vfio-container-legacy.h @@ -0,0 +1,39 @@ +/* + * VFIO container + * + * Copyright Red Hat, Inc. 2025 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_VFIO_CONTAINER_LEGACY_H +#define HW_VFIO_CONTAINER_LEGACY_H + +#include "hw/vfio/vfio-container.h" +#include "hw/vfio/vfio-cpr.h" + +typedef struct VFIOLegacyContainer VFIOLegacyContainer; +typedef struct VFIODevice VFIODevice; + +typedef struct VFIOGroup { + int fd; + int groupid; + VFIOLegacyContainer *container; + QLIST_HEAD(, VFIODevice) device_list; + QLIST_ENTRY(VFIOGroup) next; + QLIST_ENTRY(VFIOGroup) container_next; + bool ram_block_discard_allowed; +} VFIOGroup; + +struct VFIOLegacyContainer { + VFIOContainer parent_obj; + + int fd; /* /dev/vfio/vfio, empowered by the attached groups */ + unsigned iommu_type; + QLIST_HEAD(, VFIOGroup) group_list; + VFIOContainerCPR cpr; +}; + +OBJECT_DECLARE_SIMPLE_TYPE(VFIOLegacyContainer, VFIO_IOMMU_LEGACY); + +#endif /* HW_VFIO_CONTAINER_LEGACY_H */ diff --git a/include/hw/vfio/vfio-container.h b/include/hw/vfio/vfio-container.h index 240f566..b8fb2b8 100644 --- a/include/hw/vfio/vfio-container.h +++ b/include/hw/vfio/vfio-container.h @@ -1,39 +1,279 @@ /* - * VFIO container + * VFIO BASE CONTAINER * - * Copyright Red Hat, Inc. 2025 + * Copyright (C) 2023 Intel Corporation. + * Copyright Red Hat, Inc. 2023 + * + * Authors: Yi Liu <yi.l.liu@intel.com> + * Eric Auger <eric.auger@redhat.com> * * SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef HW_VFIO_CONTAINER_H -#define HW_VFIO_CONTAINER_H +#ifndef HW_VFIO_VFIO_CONTAINER_H +#define HW_VFIO_VFIO_CONTAINER_H -#include "hw/vfio/vfio-container-base.h" -#include "hw/vfio/vfio-cpr.h" +#include "system/memory.h" -typedef struct VFIOContainer VFIOContainer; typedef struct VFIODevice VFIODevice; +typedef struct VFIOIOMMUClass VFIOIOMMUClass; -typedef struct VFIOGroup { - int fd; - int groupid; - VFIOContainer *container; - QLIST_HEAD(, VFIODevice) device_list; - QLIST_ENTRY(VFIOGroup) next; - QLIST_ENTRY(VFIOGroup) container_next; - bool ram_block_discard_allowed; -} VFIOGroup; +typedef struct { + unsigned long *bitmap; + hwaddr size; + hwaddr pages; +} VFIOBitmap; +typedef struct VFIOAddressSpace { + AddressSpace *as; + QLIST_HEAD(, VFIOContainer) containers; + QLIST_ENTRY(VFIOAddressSpace) list; +} VFIOAddressSpace; + +/* + * This is the base object for vfio container backends + */ struct VFIOContainer { - VFIOContainerBase parent_obj; + Object parent_obj; - int fd; /* /dev/vfio/vfio, empowered by the attached groups */ - unsigned iommu_type; - QLIST_HEAD(, VFIOGroup) group_list; - VFIOContainerCPR cpr; + VFIOAddressSpace *space; + MemoryListener listener; + Error *error; + bool initialized; + uint64_t dirty_pgsizes; + uint64_t max_dirty_bitmap_size; + unsigned long pgsizes; + unsigned int dma_max_mappings; + bool dirty_pages_supported; + bool dirty_pages_started; /* Protected by BQL */ + QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; + QLIST_HEAD(, VFIORamDiscardListener) vrdl_list; + QLIST_ENTRY(VFIOContainer) next; + QLIST_HEAD(, VFIODevice) device_list; + GList *iova_ranges; + NotifierWithReturn cpr_reboot_notifier; }; -OBJECT_DECLARE_SIMPLE_TYPE(VFIOContainer, VFIO_IOMMU_LEGACY); +#define TYPE_VFIO_IOMMU "vfio-iommu" +OBJECT_DECLARE_TYPE(VFIOContainer, VFIOIOMMUClass, VFIO_IOMMU) + +typedef struct VFIOGuestIOMMU { + VFIOContainer *bcontainer; + IOMMUMemoryRegion *iommu_mr; + hwaddr iommu_offset; + IOMMUNotifier n; + QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; +} VFIOGuestIOMMU; + +typedef struct VFIORamDiscardListener { + VFIOContainer *bcontainer; + MemoryRegion *mr; + hwaddr offset_within_address_space; + hwaddr size; + uint64_t granularity; + RamDiscardListener listener; + QLIST_ENTRY(VFIORamDiscardListener) next; +} VFIORamDiscardListener; + +VFIOAddressSpace *vfio_address_space_get(AddressSpace *as); +void vfio_address_space_put(VFIOAddressSpace *space); +void vfio_address_space_insert(VFIOAddressSpace *space, + VFIOContainer *bcontainer); + +int vfio_container_dma_map(VFIOContainer *bcontainer, + hwaddr iova, ram_addr_t size, + void *vaddr, bool readonly, MemoryRegion *mr); +int vfio_container_dma_unmap(VFIOContainer *bcontainer, + hwaddr iova, ram_addr_t size, + IOMMUTLBEntry *iotlb, bool unmap_all); +bool vfio_container_add_section_window(VFIOContainer *bcontainer, + MemoryRegionSection *section, + Error **errp); +void vfio_container_del_section_window(VFIOContainer *bcontainer, + MemoryRegionSection *section); +int vfio_container_set_dirty_page_tracking(VFIOContainer *bcontainer, + bool start, Error **errp); +bool vfio_container_dirty_tracking_is_started( + const VFIOContainer *bcontainer); +bool vfio_container_devices_dirty_tracking_is_supported( + const VFIOContainer *bcontainer); +int vfio_container_query_dirty_bitmap(const VFIOContainer *bcontainer, + uint64_t iova, uint64_t size, ram_addr_t ram_addr, Error **errp); + +GList *vfio_container_get_iova_ranges(const VFIOContainer *bcontainer); + +static inline uint64_t +vfio_container_get_page_size_mask(const VFIOContainer *bcontainer) +{ + assert(bcontainer); + return bcontainer->pgsizes; +} + +#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy" +#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr" +#define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd" +#define TYPE_VFIO_IOMMU_USER TYPE_VFIO_IOMMU "-user" + +struct VFIOIOMMUClass { + ObjectClass parent_class; + + /** + * @setup + * + * Perform basic setup of the container, including configuring IOMMU + * capabilities, IOVA ranges, supported page sizes, etc. + * + * @bcontainer: #VFIOContainer + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns true to indicate success and false for error. + */ + bool (*setup)(VFIOContainer *bcontainer, Error **errp); + + /** + * @listener_begin + * + * Called at the beginning of an address space update transaction. + * See #MemoryListener. + * + * @bcontainer: #VFIOContainer + */ + void (*listener_begin)(VFIOContainer *bcontainer); + + /** + * @listener_commit + * + * Called at the end of an address space update transaction, + * See #MemoryListener. + * + * @bcontainer: #VFIOContainer + */ + void (*listener_commit)(VFIOContainer *bcontainer); + + /** + * @dma_map + * + * Map an address range into the container. Note that the memory region is + * referenced within an RCU read lock region across this call. + * + * @bcontainer: #VFIOContainer to use + * @iova: start address to map + * @size: size of the range to map + * @vaddr: process virtual address of mapping + * @readonly: true if mapping should be readonly + * @mr: the memory region for this mapping + * + * Returns 0 to indicate success and -errno otherwise. + */ + int (*dma_map)(const VFIOContainer *bcontainer, + hwaddr iova, ram_addr_t size, + void *vaddr, bool readonly, MemoryRegion *mr); + /** + * @dma_map_file + * + * Map a file range for the container. + * + * @bcontainer: #VFIOContainer to use for map + * @iova: start address to map + * @size: size of the range to map + * @fd: descriptor of the file to map + * @start: starting file offset of the range to map + * @readonly: map read only if true + */ + int (*dma_map_file)(const VFIOContainer *bcontainer, + hwaddr iova, ram_addr_t size, + int fd, unsigned long start, bool readonly); + /** + * @dma_unmap + * + * Unmap an address range from the container. + * + * @bcontainer: #VFIOContainer to use for unmap + * @iova: start address to unmap + * @size: size of the range to unmap + * @iotlb: The IOMMU TLB mapping entry (or NULL) + * @unmap_all: if set, unmap the entire address space + * + * Returns 0 to indicate success and -errno otherwise. + */ + int (*dma_unmap)(const VFIOContainer *bcontainer, + hwaddr iova, ram_addr_t size, + IOMMUTLBEntry *iotlb, bool unmap_all); + + + /** + * @attach_device + * + * Associate the given device with a container and do some related + * initialization of the device context. + * + * @name: name of the device + * @vbasedev: the device + * @as: address space to use + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns true to indicate success and false for error. + */ + bool (*attach_device)(const char *name, VFIODevice *vbasedev, + AddressSpace *as, Error **errp); + + /* + * @detach_device + * + * Detach the given device from its container and clean up any necessary + * state. + * + * @vbasedev: the device to disassociate + */ + void (*detach_device)(VFIODevice *vbasedev); + + /* migration feature */ + + /** + * @set_dirty_page_tracking + * + * Start or stop dirty pages tracking on VFIO container + * + * @bcontainer: #VFIOContainer on which to de/activate dirty + * page tracking + * @start: indicates whether to start or stop dirty pages tracking + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns zero to indicate success and negative for error. + */ + int (*set_dirty_page_tracking)(const VFIOContainer *bcontainer, + bool start, Error **errp); + /** + * @query_dirty_bitmap + * + * Get bitmap of dirty pages from container + * + * @bcontainer: #VFIOContainer from which to get dirty pages + * @vbmap: #VFIOBitmap internal bitmap structure + * @iova: iova base address + * @size: size of iova range + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns zero to indicate success and negative for error. + */ + int (*query_dirty_bitmap)(const VFIOContainer *bcontainer, + VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp); + /* PCI specific */ + int (*pci_hot_reset)(VFIODevice *vbasedev, bool single); + + /* SPAPR specific */ + bool (*add_window)(VFIOContainer *bcontainer, + MemoryRegionSection *section, + Error **errp); + void (*del_window)(VFIOContainer *bcontainer, + MemoryRegionSection *section); + void (*release)(VFIOContainer *bcontainer); +}; + +VFIORamDiscardListener *vfio_find_ram_discard_listener( + VFIOContainer *bcontainer, MemoryRegionSection *section); + +void vfio_container_region_add(VFIOContainer *bcontainer, + MemoryRegionSection *section, bool cpr_remap); -#endif /* HW_VFIO_CONTAINER_H */ +#endif /* HW_VFIO_VFIO_CONTAINER_H */ diff --git a/include/hw/vfio/vfio-cpr.h b/include/hw/vfio/vfio-cpr.h index d37daff..26ee0c4 100644 --- a/include/hw/vfio/vfio-cpr.h +++ b/include/hw/vfio/vfio-cpr.h @@ -12,15 +12,15 @@ #include "migration/misc.h" #include "system/memory.h" +struct VFIOLegacyContainer; struct VFIOContainer; -struct VFIOContainerBase; struct VFIOGroup; struct VFIODevice; struct VFIOPCIDevice; struct VFIOIOMMUFDContainer; struct IOMMUFDBackend; -typedef int (*dma_map_fn)(const struct VFIOContainerBase *bcontainer, +typedef int (*dma_map_fn)(const struct VFIOContainer *bcontainer, hwaddr iova, ram_addr_t size, void *vaddr, bool readonly, MemoryRegion *mr); @@ -42,9 +42,10 @@ typedef struct VFIOPCICPR { NotifierWithReturn transfer_notifier; } VFIOPCICPR; -bool vfio_legacy_cpr_register_container(struct VFIOContainer *container, +bool vfio_legacy_cpr_register_container(struct VFIOLegacyContainer *container, Error **errp); -void vfio_legacy_cpr_unregister_container(struct VFIOContainer *container); +void vfio_legacy_cpr_unregister_container( + struct VFIOLegacyContainer *container); int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier, MigrationEvent *e, Error **errp); @@ -61,14 +62,14 @@ void vfio_cpr_load_device(struct VFIODevice *vbasedev); int vfio_cpr_group_get_device_fd(int d, const char *name); -bool vfio_cpr_container_match(struct VFIOContainer *container, +bool vfio_cpr_container_match(struct VFIOLegacyContainer *container, struct VFIOGroup *group, int fd); -void vfio_cpr_giommu_remap(struct VFIOContainerBase *bcontainer, +void vfio_cpr_giommu_remap(struct VFIOContainer *bcontainer, MemoryRegionSection *section); bool vfio_cpr_ram_discard_register_listener( - struct VFIOContainerBase *bcontainer, MemoryRegionSection *section); + struct VFIOContainer *bcontainer, MemoryRegionSection *section); void vfio_cpr_save_vector_fd(struct VFIOPCIDevice *vdev, const char *name, int nr, int fd); diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h index e7e6243..7e9aed6 100644 --- a/include/hw/vfio/vfio-device.h +++ b/include/hw/vfio/vfio-device.h @@ -18,8 +18,8 @@ * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) */ -#ifndef HW_VFIO_VFIO_COMMON_H -#define HW_VFIO_VFIO_COMMON_H +#ifndef HW_VFIO_VFIO_DEVICE_H +#define HW_VFIO_VFIO_DEVICE_H #include "system/memory.h" #include "qemu/queue.h" @@ -27,7 +27,7 @@ #include <linux/vfio.h> #endif #include "system/system.h" -#include "hw/vfio/vfio-container-base.h" +#include "hw/vfio/vfio-container.h" #include "hw/vfio/vfio-cpr.h" #include "system/host_iommu_device.h" #include "system/iommufd.h" @@ -54,7 +54,7 @@ typedef struct VFIODevice { QLIST_ENTRY(VFIODevice) container_next; QLIST_ENTRY(VFIODevice) global_next; struct VFIOGroup *group; - VFIOContainerBase *bcontainer; + VFIOContainer *bcontainer; char *sysfsdev; char *name; DeviceState *dev; @@ -252,7 +252,7 @@ struct VFIODeviceIOOps { void *data, bool post); }; -void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainerBase *bcontainer, +void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainer *bcontainer, struct vfio_device_info *info); void vfio_device_unprepare(VFIODevice *vbasedev); @@ -288,4 +288,4 @@ void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, int vfio_device_get_aw_bits(VFIODevice *vdev); void vfio_kvm_device_close(void); -#endif /* HW_VFIO_VFIO_COMMON_H */ +#endif /* HW_VFIO_VFIO_DEVICE_H */ |