Re: [PATCH v4 00/15] vfio: VFIO migration support with vIOMMU
On 6/7/24 5:10 PM, Joao Martins wrote: On 06/06/2024 16:43, Cédric Le Goater wrote: Hello Joao, On 6/22/23 23:48, Joao Martins wrote: Hey, This series introduces support for vIOMMU with VFIO device migration, particurlarly related to how we do the dirty page tracking. Today vIOMMUs serve two purposes: 1) enable interrupt remaping 2) provide dma translation services for guests to provide some form of guest kernel managed DMA e.g. for nested virt based usage; (1) is specially required for big VMs with VFs with more than 255 vcpus. We tackle both and remove the migration blocker when vIOMMU is present provided the conditions are met. I have both use-cases here in one series, but I am happy to tackle them in separate series. As I found out we don't necessarily need to expose the whole vIOMMU functionality in order to just support interrupt remapping. x86 IOMMUs on Windows Server 2018[2] and Linux >=5.10, with qemu 7.1+ (or really Linux guests with commit c40c10 and since qemu commit 8646d9c773d8) can instantiate a IOMMU just for interrupt remapping without needing to be advertised/support DMA translation. AMD IOMMU in theory can provide the same, but Linux doesn't quite support the IR-only part there yet, only intel-iommu. The series is organized as following: Patches 1-5: Today we can't gather vIOMMU details before the guest establishes their first DMA mapping via the vIOMMU. So these first four patches add a way for vIOMMUs to be asked of their properties at start of day. I choose the least churn possible way for now (as opposed to a treewide conversion) and allow easy conversion a posteriori. As suggested by Peter Xu[7], I have ressurected Yi's patches[5][6] which allows us to fetch PCI backing vIOMMU attributes, without necessarily tieing the caller (VFIO or anyone else) to an IOMMU MR like I was doing in v3. Patches 6-8: Handle configs with vIOMMU interrupt remapping but without DMA translation allowed. Today the 'dma-translation' attribute is x86-iommu only, but the way this series is structured nothing stops from other vIOMMUs supporting it too as long as they use pci_setup_iommu_ops() and the necessary IOMMU MR get_attr attributes are handled. The blocker is thus relaxed when vIOMMUs are able to toggle the toggle/report DMA_TRANSLATION attribute. With the patches up to this set, we've then tackled item (1) of the second paragraph. Patches 9-15: Simplified a lot from v2 (patch 9) to only track the complete IOVA address space, leveraging the logic we use to compose the dirty ranges. The blocker is once again relaxed for vIOMMUs that advertise their IOVA addressing limits. This tackles item (2). So far I mainly use it with intel-iommu, although I have a small set of patches for virtio-iommu per Alex's suggestion in v2. Comments, suggestions welcome. Thanks for the review! I spent sometime refreshing your series on upstream QEMU (See [1]) and gave migration a try with CX-7 VF. LGTM. It doesn't seem we are far from acceptance in QEMU 9.1. Are we ? Yeah. There was a comment from Zhenzhong on the vfio_viommu_preset() here[0]. But I was looking at that to remind myself what was it that we had to change, but even with re-reading the thread I can't spot any flaw that needs change. [0] https://lore.kernel.org/qemu-devel/de2b72d2-f56b-9350-ce0f-70edfb58e...@intel.com/#r I introduced a vfio_devices_all_viommu_preset() routine to check all devices in a container and a simplified version of vfio_viommu_get_max_iova() returning the space max_iova. First, I will resend these with the changes I made : vfio/common: Extract vIOMMU code from vfio_sync_dirty_bitmap() vfio/common: Move dirty tracking ranges update to helper() I guess the PCIIOMMUOps::get_iommu_attr needs a close review. Is IOMMU_ATTR_DMA_TRANSLATION a must have ? It's sort of the 'correct way' of relaxing vIOMMU checks, because you are 100% guaranteed that the guest won't do DMA. The other outstanding thing related to that is for older kernels which is to use the directmap for dirty page tracking, but the moment a mapping is attempted the migration doesn't start or if it's in progress it gets aborted[*]: https://lore.kernel.org/qemu-devel/20230908120521.50903-1-joao.m.mart...@oracle.com/ The above link and DMA_TRANSLATION is mostly for the usecase we use that only cares about vIOMMU for interrupt remapping only and no DMA translation services. But we can't just disable dma-translation in qemu because it may crash older kernels, so it supports both old and new this way. [*] Recently I noticed you improved error reporting, so vfio_set_migration_error(-EOPNOTSUPP) probably has a better way of getting there. Yes. So, I did a little more change to improve vfio_dirty_tracking_init(). The rest is mostly VFIO internals for dirty tracking. Right. I derailed with other work and also stuff required for iommu dirty tracking that I forgot about these patches, sorry. That's fine. I am trying to sort out which patc
Re: [PATCH] aspeed/smc: Reintroduce "dram-base" property for AST2700
On 5/27/24 2:43 PM, Cédric Le Goater wrote: The Aspeed SMC device model use to have a 'sdram_base' property. It was removed by commit d177892d4a48 ("aspeed/smc: Remove unused "sdram-base" property") because previous changes simplified the DMA transaction model to use an offset in RAM and not the physical address. The AST2700 SoC has larger address space (64-bit) and a new register DMA DRAM Side Address High Part (0x7C) is introduced to deal with the high bits of the DMA address. To be able to compute the offset of the DMA transaction, as done on the other SoCs, we will need to know where the DRAM is mapped in the address space. Re-introduce a "dram-base" property to hold this value. Signed-off-by: Cédric Le Goater --- include/hw/ssi/aspeed_smc.h | 1 + hw/ssi/aspeed_smc.c | 1 + 2 files changed, 2 insertions(+) Applied to aspeed-next. Thanks, C.
Re: [PATCH] MAINTAINERS: Add reviewers for ASPEED BMCs
On 6/5/24 8:03 AM, Jamin Lin wrote: Add ASPEED members "Steven Lee", "Troy Lee" and "Jamin Lin" to be reviewers of ASPEED BMCs. Signed-off-by: Jamin Lin Signed-off-by: Troy Lee Signed-off-by: Steven Lee --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) Applied to aspeed-next. Thanks, C.
Re: [PATCH v5 00/17] Add AST2700 support
On 6/4/24 7:44 AM, Jamin Lin wrote: Changes from v1: The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC. Changes from v2: - replace is_aarch64 with is_bus64bit for sdmc patch review. - fix incorrect dram size for AST2700 Changes from v3: - Add AST2700 Evaluation board in ASPEED document - Add avocado test cases for AST2700 Evaluation board - Fix reviewers review issues and add reviewers suggestions - Implement INTC model GICINT 128 to GICINT136 for AST2700 Changes from v4: - support 64 bits dma dram address associated with review issues - support dma start length and 1 byte length unit associated with review issues - refactor intc model to fix serial console stuck issue and associated with review issues Changes from v5: - sdmc: incrementing the version of vmstate to 2. - smc: support different memory region ops for SMC flash region introduce a new "const MemoryRegionOps *" attribute in AspeedSMCClass and use it in aspeed_smc_flash_realize function. - intc: fix associated with review issues - dram size detect: change to use address space API and simplify with write transaction on the DRAM memory region of the SoC. - ast27x0_soc: update aspeed_soc_ast2700_gic function associated with review issues and rename to aspeed_soc_ast2700_gic_realize Test Version: qemu commit: https://github.com/qemu/qemu/commit/74abb45dac6979e7ff76172b7f0a24e869405184 applied patch: https://patchew.org/QEMU/20240527124315.35356-1-...@redhat.com/ Test steps: 1. Download the latest openbmc image for AST2700 from AspeedTech-BMC/openbmc repository, https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.01 link: https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.01/ast2700-default-obmc.tar.gz 2. untar ast2700-default-obmc.tar.gz ``` tar -xf ast2700-default-obmc.tar.gz ``` 3. Run and the contents of scripts as following IMGDIR=ast2700-default UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin) UBOOT_DTB_ADDR=$((0x4 + ${UBOOT_SIZE})) qemu-system-aarch64 -M ast2700-evb -nographic\ -device loader,addr=0x4,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\ -device loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\ -device loader,addr=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\ -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\ -device loader,addr=0x43000,cpu-num=0\ -device loader,addr=0x43000,cpu-num=1\ -device loader,addr=0x43000,cpu-num=2\ -device loader,addr=0x43000,cpu-num=3\ -smp 4\ -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\ -serial mon:stdio\ -snapshot Jamin Lin (17): aspeed/wdt: Add AST2700 support aspeed/sli: Add AST2700 support aspeed/sdmc: remove redundant macros aspeed/sdmc: fix coding style aspeed/sdmc: Add AST2700 support aspeed/smc: correct device description aspeed/smc: support dma start length and 1 byte length unit aspeed/smc: support 64 bits dma dram address aspeed/smc: support different memory region ops for SMC flash region aspeed/smc: Add AST2700 support aspeed/scu: Add AST2700 support aspeed/intc: Add AST2700 support aspeed/soc: Add AST2700 support aspeed: Add an AST2700 eval board aspeed/soc: fix incorrect dram size for AST2700 test/avocado/machine_aspeed.py: Add AST2700 test case docs:aspeed: Add AST2700 Evaluation board docs/system/arm/aspeed.rst | 39 +- hw/arm/aspeed.c | 32 ++ hw/arm/aspeed_ast27x0.c | 648 +++ hw/arm/meson.build | 1 + hw/intc/aspeed_intc.c| 360 + hw/intc/meson.build | 1 + hw/intc/trace-events | 13 + hw/misc/aspeed_scu.c | 306 ++- hw/misc/aspeed_sdmc.c| 220 +-- hw/misc/aspeed_sli.c | 177 + hw/misc/meson.build | 3 +- hw/misc/trace-events | 11 + hw/ssi/aspeed_smc.c | 346 - hw/ssi/trace-events | 2 +- hw/watchdog/wdt_aspeed.c | 24 ++ include/hw/arm/aspeed_soc.h | 30 +- include/hw/intc/aspeed_intc.h| 44 +++ include/hw/misc/aspeed_scu.h | 47 ++- include/hw/misc/aspeed_sdmc.h| 5 +- include/hw/misc/aspeed_sli.h | 27 ++ include/hw/ssi/aspeed_smc.h | 2 + include/hw/watchdog/wdt_aspeed.h | 3 +- tests/avocado/machine_aspeed.py | 62 +++ 23 files changed, 2345 insertions(+), 58 deletions(-) create mode 100644 hw/arm/aspeed_ast27x0.c create mode 100644 hw/intc/aspeed_intc.c create mode 100644 hw/misc/aspeed_sli.c create mode 100644 include/hw/intc/aspeed_intc.h create mode 100644 include/hw/misc/aspeed_sli.h Applied to aspeed-next. Thanks, C.
Re: [PATCH 00/26] hw/ppc: Prefer HumanReadableText over Monitor
On 6/10/24 8:20 AM, Philippe Mathieu-Daudé wrote: Hi, This series remove uses of Monitor in hw/ppc/, replacing by the more generic HumanReadableText. Care is taken to keep the commit bisectables by updating functions one by one, also easing review. Did you do any testing ? POWER[8-10] CPUs on pseries and powernv machines should be checked. A bit tedious I agree but not that long. Thanks, C. For rationale see previous series from Daniel: https://lore.kernel.org/qemu-devel/20211028155457.967291-1-berra...@redhat.com/ Regards, Phil. Philippe Mathieu-Daudé (26): hw/ppc: Avoid using Monitor in pnv_phb3_msi_pic_print_info() hw/ppc: Avoid using Monitor in icp_pic_print_info() hw/ppc: Avoid using Monitor in xive_tctx_pic_print_info() hw/ppc: Avoid using Monitor in ics_pic_print_info() hw/ppc: Avoid using Monitor in PnvChipClass::intc_print_info() hw/ppc: Avoid using Monitor in xive_end_queue_pic_print_info() hw/ppc: Avoid using Monitor in spapr_xive_end_pic_print_info() hw/ppc: Avoid using Monitor in spapr_xive_pic_print_info() hw/ppc: Avoid using Monitor in xive_source_pic_print_info() hw/ppc: Avoid using Monitor in pnv_phb4_pic_print_info() hw/ppc: Avoid using Monitor in xive_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive_end_pic_print_info() hw/ppc: Avoid using Monitor in xive_end_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive_nvt_pic_print_info() hw/ppc: Avoid using Monitor in pnv_xive_pic_print_info() hw/ppc: Avoid using Monitor in pnv_psi_pic_print_info() hw/ppc: Avoid using Monitor in xive2_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_queue_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_pic_print_info() hw/ppc: Avoid using Monitor in xive2_nvp_pic_print_info() hw/ppc: Avoid using Monitor in pnv_xive2_pic_print_info() hw/ppc: Avoid using Monitor in SpaprInterruptControllerClass::print_info() hw/ppc: Avoid using Monitor in spapr_irq_print_info() hw/ppc: Avoid using Monitor in pnv_chip_power9_pic_print_info_child() hw/ppc: Avoid using Monitor in pic_print_info() include/hw/pci-host/pnv_phb3.h | 2 +- include/hw/pci-host/pnv_phb4.h | 2 +- include/hw/ppc/pnv_chip.h | 4 +- include/hw/ppc/pnv_psi.h | 2 +- include/hw/ppc/pnv_xive.h | 4 +- include/hw/ppc/spapr_irq.h | 4 +- include/hw/ppc/xics.h | 4 +- include/hw/ppc/xive.h | 4 +- include/hw/ppc/xive2_regs.h| 8 +-- include/hw/ppc/xive_regs.h | 8 +-- hw/intc/pnv_xive.c | 38 ++-- hw/intc/pnv_xive2.c| 48 +++ hw/intc/spapr_xive.c | 41 ++--- hw/intc/xics.c | 25 hw/intc/xics_spapr.c | 7 +-- hw/intc/xive.c | 108 - hw/intc/xive2.c| 87 +- hw/pci-host/pnv_phb3_msi.c | 21 +++ hw/pci-host/pnv_phb4.c | 17 +++--- hw/ppc/pnv.c | 52 hw/ppc/pnv_psi.c | 9 ++- hw/ppc/spapr.c | 11 +++- hw/ppc/spapr_irq.c | 4 +- 23 files changed, 256 insertions(+), 254 deletions(-)
Re: [PATCH 00/26] hw/ppc: Prefer HumanReadableText over Monitor
On 6/10/24 8:20 AM, Philippe Mathieu-Daudé wrote: Hi, This series remove uses of Monitor in hw/ppc/, replacing by the more generic HumanReadableText. Care is taken to keep the commit bisectables by updating functions one by one, also easing review. For rationale see previous series from Daniel: https://lore.kernel.org/qemu-devel/20211028155457.967291-1-berra...@redhat.com/ This looks OK to me but I think there are patches in the ppc queue that will conflict. I would wait for Nick to send a PR first and then rebase. Thanks, C. Regards, Phil. Philippe Mathieu-Daudé (26): hw/ppc: Avoid using Monitor in pnv_phb3_msi_pic_print_info() hw/ppc: Avoid using Monitor in icp_pic_print_info() hw/ppc: Avoid using Monitor in xive_tctx_pic_print_info() hw/ppc: Avoid using Monitor in ics_pic_print_info() hw/ppc: Avoid using Monitor in PnvChipClass::intc_print_info() hw/ppc: Avoid using Monitor in xive_end_queue_pic_print_info() hw/ppc: Avoid using Monitor in spapr_xive_end_pic_print_info() hw/ppc: Avoid using Monitor in spapr_xive_pic_print_info() hw/ppc: Avoid using Monitor in xive_source_pic_print_info() hw/ppc: Avoid using Monitor in pnv_phb4_pic_print_info() hw/ppc: Avoid using Monitor in xive_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive_end_pic_print_info() hw/ppc: Avoid using Monitor in xive_end_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive_nvt_pic_print_info() hw/ppc: Avoid using Monitor in pnv_xive_pic_print_info() hw/ppc: Avoid using Monitor in pnv_psi_pic_print_info() hw/ppc: Avoid using Monitor in xive2_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_eas_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_queue_pic_print_info() hw/ppc: Avoid using Monitor in xive2_end_pic_print_info() hw/ppc: Avoid using Monitor in xive2_nvp_pic_print_info() hw/ppc: Avoid using Monitor in pnv_xive2_pic_print_info() hw/ppc: Avoid using Monitor in SpaprInterruptControllerClass::print_info() hw/ppc: Avoid using Monitor in spapr_irq_print_info() hw/ppc: Avoid using Monitor in pnv_chip_power9_pic_print_info_child() hw/ppc: Avoid using Monitor in pic_print_info() include/hw/pci-host/pnv_phb3.h | 2 +- include/hw/pci-host/pnv_phb4.h | 2 +- include/hw/ppc/pnv_chip.h | 4 +- include/hw/ppc/pnv_psi.h | 2 +- include/hw/ppc/pnv_xive.h | 4 +- include/hw/ppc/spapr_irq.h | 4 +- include/hw/ppc/xics.h | 4 +- include/hw/ppc/xive.h | 4 +- include/hw/ppc/xive2_regs.h| 8 +-- include/hw/ppc/xive_regs.h | 8 +-- hw/intc/pnv_xive.c | 38 ++-- hw/intc/pnv_xive2.c| 48 +++ hw/intc/spapr_xive.c | 41 ++--- hw/intc/xics.c | 25 hw/intc/xics_spapr.c | 7 +-- hw/intc/xive.c | 108 - hw/intc/xive2.c| 87 +- hw/pci-host/pnv_phb3_msi.c | 21 +++ hw/pci-host/pnv_phb4.c | 17 +++--- hw/ppc/pnv.c | 52 hw/ppc/pnv_psi.c | 9 ++- hw/ppc/spapr.c | 11 +++- hw/ppc/spapr_irq.c | 4 +- 23 files changed, 256 insertions(+), 254 deletions(-)
Re: [PATCH v4 00/15] vfio: VFIO migration support with vIOMMU
Hello Joao, On 6/22/23 23:48, Joao Martins wrote: Hey, This series introduces support for vIOMMU with VFIO device migration, particurlarly related to how we do the dirty page tracking. Today vIOMMUs serve two purposes: 1) enable interrupt remaping 2) provide dma translation services for guests to provide some form of guest kernel managed DMA e.g. for nested virt based usage; (1) is specially required for big VMs with VFs with more than 255 vcpus. We tackle both and remove the migration blocker when vIOMMU is present provided the conditions are met. I have both use-cases here in one series, but I am happy to tackle them in separate series. As I found out we don't necessarily need to expose the whole vIOMMU functionality in order to just support interrupt remapping. x86 IOMMUs on Windows Server 2018[2] and Linux >=5.10, with qemu 7.1+ (or really Linux guests with commit c40c10 and since qemu commit 8646d9c773d8) can instantiate a IOMMU just for interrupt remapping without needing to be advertised/support DMA translation. AMD IOMMU in theory can provide the same, but Linux doesn't quite support the IR-only part there yet, only intel-iommu. The series is organized as following: Patches 1-5: Today we can't gather vIOMMU details before the guest establishes their first DMA mapping via the vIOMMU. So these first four patches add a way for vIOMMUs to be asked of their properties at start of day. I choose the least churn possible way for now (as opposed to a treewide conversion) and allow easy conversion a posteriori. As suggested by Peter Xu[7], I have ressurected Yi's patches[5][6] which allows us to fetch PCI backing vIOMMU attributes, without necessarily tieing the caller (VFIO or anyone else) to an IOMMU MR like I was doing in v3. Patches 6-8: Handle configs with vIOMMU interrupt remapping but without DMA translation allowed. Today the 'dma-translation' attribute is x86-iommu only, but the way this series is structured nothing stops from other vIOMMUs supporting it too as long as they use pci_setup_iommu_ops() and the necessary IOMMU MR get_attr attributes are handled. The blocker is thus relaxed when vIOMMUs are able to toggle the toggle/report DMA_TRANSLATION attribute. With the patches up to this set, we've then tackled item (1) of the second paragraph. Patches 9-15: Simplified a lot from v2 (patch 9) to only track the complete IOVA address space, leveraging the logic we use to compose the dirty ranges. The blocker is once again relaxed for vIOMMUs that advertise their IOVA addressing limits. This tackles item (2). So far I mainly use it with intel-iommu, although I have a small set of patches for virtio-iommu per Alex's suggestion in v2. Comments, suggestions welcome. Thanks for the review! I spent sometime refreshing your series on upstream QEMU (See [1]) and gave migration a try with CX-7 VF. LGTM. It doesn't seem we are far from acceptance in QEMU 9.1. Are we ? First, I will resend these with the changes I made : vfio/common: Extract vIOMMU code from vfio_sync_dirty_bitmap() vfio/common: Move dirty tracking ranges update to helper() I guess the PCIIOMMUOps::get_iommu_attr needs a close review. Is IOMMU_ATTR_DMA_TRANSLATION a must have ? The rest is mostly VFIO internals for dirty tracking. Thanks, C. [1] https://github.com/legoater/qemu/commits/vfio-9.1 Regards, Joao Changes since v3[8]: * Pick up Yi's patches[5][6], and rework the first four patches. These are a bit better splitted, and make the new iommu_ops *optional* as opposed to a treewide conversion. Rather than returning an IOMMU MR and let VFIO operate on it to fetch attributes, we instead let the underlying IOMMU driver fetch the desired IOMMU MR and ask for the desired IOMMU attribute. Callers only care about PCI Device backing vIOMMU attributes regardless of its topology/association. (Peter Xu) These patches are a bit better splitted compared to original ones, and I've kept all the same authorship and note the changes from original where applicable. * Because of the rework of the first four patches, switch to individual attributes in the VFIOSpace that track dma_translation and the max_iova. All are expected to be unused when zero to retain the defaults of today in common code. * Improve the migration blocker message of the last patch to be more obvious that vIOMMU migration blocker is added when no vIOMMU address space limits are advertised. (Patch 15) * Cast to uintptr_t in IOMMUAttr data in intel-iommu (Philippe). * Switch to MAKE_64BIT_MASK() instead of plain left shift (Philippe). * Change diffstat of patches with scripts/git.orderfile (Philippe). Changes since v2[3]: * New patches 1-9 to be able to handle vIOMMUs without DMA translation, and introduce ways to know various IOMMU model attributes via the IOMMU MR. This is partly meant to address a comment in previous versions where we can't access the IOMMU MR prior to the DMA mapping happening. Before
Re: [PATCH] MAINTAINERS: Add reviewers for ASPEED BMCs
On 6/5/24 08:03, Jamin Lin wrote: Add ASPEED members "Steven Lee", "Troy Lee" and "Jamin Lin" to be reviewers of ASPEED BMCs. Signed-off-by: Jamin Lin Signed-off-by: Troy Lee Signed-off-by: Steven Lee Reviewed-by: Cédric Le Goater Thanks, C. --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 951556224a..0f63bcdc7d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1158,6 +1158,9 @@ F: docs/system/arm/emcraft-sf2.rst ASPEED BMCs M: Cédric Le Goater M: Peter Maydell +R: Steven Lee +R: Troy Lee +R: Jamin Lin R: Andrew Jeffery R: Joel Stanley L: qemu-...@nongnu.org
Re: [PATCH] MAINTAINERS: Add maintainers for ASPEED BMCs
On 6/5/24 05:44, Jamin Lin wrote: Add ASPEED members "Steven Lee", "Troy Lee" and "Jamin Lin" to be maintainers of ASPEED BMCs. Let's start with Reviewers. please resend. https://qemu.readthedocs.io/en/v9.0.0/devel/maintainers.html Thanks, C. Signed-off-by: Jamin Lin Signed-off-by: Troy Lee Signed-off-by: Steven Lee --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 951556224a..39651be467 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1158,6 +1158,9 @@ F: docs/system/arm/emcraft-sf2.rst ASPEED BMCs M: Cédric Le Goater M: Peter Maydell +M: Steven Lee +M: Troy Lee +M: Jamin Lin R: Andrew Jeffery R: Joel Stanley L: qemu-...@nongnu.org
Re: [PATCH 24/32] hw/sd: Subtract bootarea size from blk
On 6/3/24 14:31, Philippe Mathieu-Daudé wrote: On 3/7/23 15:25, Cédric Le Goater wrote: From: Joel Stanley The userdata size is derived from the file the user passes on the command line, but we must take into account the boot areas. Signed-off-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/sd/sd.c | 5 + 1 file changed, 5 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 6da17a8d0972..1df7c7ac9dae 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -674,6 +674,7 @@ static unsigned sd_boot_capacity_bytes(SDState *sd) static void sd_reset(DeviceState *dev) { SDState *sd = SD_CARD(dev); + SDCardClass *sc = SD_CARD_GET_CLASS(sd); uint64_t size; uint64_t sect; @@ -685,6 +686,10 @@ static void sd_reset(DeviceState *dev) } size = sect << 9; + if (sc->bootpart_offset) { + size -= sd_boot_capacity_bytes(sd) * 2; IMO this patch and sd_boot_capacity_bytes() definition from previous patch should be squashed in patch 22 where you add emmc_cmd_SEND_EXT_CSD. OK. I will check. Have you looked at the other patches ? Thanks, C. + } + sect = sd_addr_to_wpnum(size) + 1; sd->state = sd_idle_state;
Re: [PATCH 17/32] hw/sd: Add emmc_cmd_SEND_RELATIVE_ADDR() handler
On 6/3/24 14:26, Philippe Mathieu-Daudé wrote: On 3/7/23 15:24, Cédric Le Goater wrote: Signed-off-by: Cédric Le Goater --- hw/sd/sd.c | 20 1 file changed, 20 insertions(+) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index dd60a16f8c0a..5ff132139ea9 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -1053,6 +1053,25 @@ static sd_rsp_type_t sd_cmd_ALL_SEND_CID(SDState *sd, SDRequest req) return sd_r2_i; } +static void sd_emmc_set_rca(SDState *sd, uint16_t value) +{ + sd->rca = value; +} + +static sd_rsp_type_t emmc_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req) "emmc_cmd_SET_RELATIVE_ADDR". Fixed. Thanks, C. Reviewed-by: Philippe Mathieu-Daudé +{ + switch (sd->state) { + case sd_identification_state: + case sd_standby_state: + sd->state = sd_standby_state; + sd_emmc_set_rca(sd, req.arg >> 16); + return sd_r1; + + default: + return sd_invalid_state_for_cmd(sd, req); + } +} + static sd_rsp_type_t sd_cmd_SEND_RELATIVE_ADDR(SDState *sd, SDRequest req) { switch (sd->state) { @@ -2194,6 +2213,7 @@ static const SDProto sd_proto_emmc = { [0] = sd_cmd_GO_IDLE_STATE, [1] = emmc_cmd_SEND_OP_CMD, [2] = emmc_cmd_ALL_SEND_CID, + [3] = emmc_cmd_SEND_RELATIVE_ADDR, [5] = sd_cmd_illegal, [19] = sd_cmd_SEND_TUNING_BLOCK, [23] = sd_cmd_SET_BLOCK_COUNT,
Re: [PATCH v5 00/17] Add AST2700 support
On 6/4/24 07:44, Jamin Lin wrote: Changes from v1: The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC. Changes from v2: - replace is_aarch64 with is_bus64bit for sdmc patch review. - fix incorrect dram size for AST2700 Changes from v3: - Add AST2700 Evaluation board in ASPEED document - Add avocado test cases for AST2700 Evaluation board - Fix reviewers review issues and add reviewers suggestions - Implement INTC model GICINT 128 to GICINT136 for AST2700 Changes from v4: - support 64 bits dma dram address associated with review issues - support dma start length and 1 byte length unit associated with review issues - refactor intc model to fix serial console stuck issue and associated with review issues Changes from v5: - sdmc: incrementing the version of vmstate to 2. - smc: support different memory region ops for SMC flash region introduce a new "const MemoryRegionOps *" attribute in AspeedSMCClass and use it in aspeed_smc_flash_realize function. - intc: fix associated with review issues - dram size detect: change to use address space API and simplify with write transaction on the DRAM memory region of the SoC. - ast27x0_soc: update aspeed_soc_ast2700_gic function associated with review issues and rename to aspeed_soc_ast2700_gic_realize v5 looks good to me. Do you plan to send a MAINTAINERS file ? Thanks, C. Test Version: qemu commit: https://github.com/qemu/qemu/commit/74abb45dac6979e7ff76172b7f0a24e869405184 applied patch: https://patchew.org/QEMU/20240527124315.35356-1-...@redhat.com/ Test steps: 1. Download the latest openbmc image for AST2700 from AspeedTech-BMC/openbmc repository, https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.01 link: https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.01/ast2700-default-obmc.tar.gz 2. untar ast2700-default-obmc.tar.gz ``` tar -xf ast2700-default-obmc.tar.gz ``` 3. Run and the contents of scripts as following IMGDIR=ast2700-default UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin) UBOOT_DTB_ADDR=$((0x4 + ${UBOOT_SIZE})) qemu-system-aarch64 -M ast2700-evb -nographic\ -device loader,addr=0x4,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\ -device loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\ -device loader,addr=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\ -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\ -device loader,addr=0x43000,cpu-num=0\ -device loader,addr=0x43000,cpu-num=1\ -device loader,addr=0x43000,cpu-num=2\ -device loader,addr=0x43000,cpu-num=3\ -smp 4\ -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\ -serial mon:stdio\ -snapshot Jamin Lin (17): aspeed/wdt: Add AST2700 support aspeed/sli: Add AST2700 support aspeed/sdmc: remove redundant macros aspeed/sdmc: fix coding style aspeed/sdmc: Add AST2700 support aspeed/smc: correct device description aspeed/smc: support dma start length and 1 byte length unit aspeed/smc: support 64 bits dma dram address aspeed/smc: support different memory region ops for SMC flash region aspeed/smc: Add AST2700 support aspeed/scu: Add AST2700 support aspeed/intc: Add AST2700 support aspeed/soc: Add AST2700 support aspeed: Add an AST2700 eval board aspeed/soc: fix incorrect dram size for AST2700 test/avocado/machine_aspeed.py: Add AST2700 test case docs:aspeed: Add AST2700 Evaluation board docs/system/arm/aspeed.rst | 39 +- hw/arm/aspeed.c | 32 ++ hw/arm/aspeed_ast27x0.c | 648 +++ hw/arm/meson.build | 1 + hw/intc/aspeed_intc.c| 360 + hw/intc/meson.build | 1 + hw/intc/trace-events | 13 + hw/misc/aspeed_scu.c | 306 ++- hw/misc/aspeed_sdmc.c| 220 +-- hw/misc/aspeed_sli.c | 177 + hw/misc/meson.build | 3 +- hw/misc/trace-events | 11 + hw/ssi/aspeed_smc.c | 346 - hw/ssi/trace-events | 2 +- hw/watchdog/wdt_aspeed.c | 24 ++ include/hw/arm/aspeed_soc.h | 30 +- include/hw/intc/aspeed_intc.h| 44 +++ include/hw/misc/aspeed_scu.h | 47 ++- include/hw/misc/aspeed_sdmc.h| 5 +- include/hw/misc/aspeed_sli.h | 27 ++ include/hw/ssi/aspeed_smc.h | 2 + include/hw/watchdog/wdt_aspeed.h | 3 +- tests/avocado/machine_aspeed.py | 62 +++ 23 files changed, 2345 insertions(+), 58 deletions(-) create mode 100644 hw/arm/aspeed_ast27x0.c create mode 100644 hw/intc/aspeed_intc.c create mode 100644 hw/misc/aspeed_sli.c create mode 100644 include/hw/intc/aspeed_intc.h create mode 100644 include/hw/misc/aspeed_sli.h
Re: [PATCH v5 12/17] aspeed/intc: Add AST2700 support
On 6/4/24 07:44, Jamin Lin wrote: AST2700 interrupt controller(INTC) provides hardware interrupt interfaces to interrupt of processors PSP, SSP and TSP. In INTC, each interrupt of INT 128 to INT136 combines 32 interrupts. Introduce a new aspeed_intc class with instance_init and realize handlers. So far, this model only supports GICINT128 to GICINT136. It creates 9 GICINT or-gates to connect 32 interrupts sources from GICINT128 to GICINT136 as IRQ GPIO-OUTPUT pins. Then, this model registers IRQ handler with its IRQ GPIO-INPUT pins which connect to GICINT or-gates. And creates 9 GICINT IRQ GPIO-OUTPUT pins which connect to GIC device with GIC IRQ 128 to 136. If one interrupt source from GICINT128 to GICINT136 set irq, the OR-GATE irq callback function is called and set irq to INTC by OR-GATE GPIO-OUTPUT pins. Then, the INTC irq callback function is called and set irq to GIC by its GICINT IRQ GPIO-OUTPUT pins. Finally, the GIC irq callback function is called and set irq to CPUs and CPUs execute Interrupt Service Routine (ISR). Block diagram of GICINT132: GICINT132 ETH1+---+ +>+0 3| ETH2| 4| +>+1 5| ETH3| 6| +>+219| INTC GIC UART0 | 20|+--+ +>+721|| | +--+ UART1 | 22||orgate0 +> output_pin0+--->+GIC128| +>+823|| || | UART2 | 24||orgate1 +> output_pin1+--->+GIC129| +>+925|| || | UART3 | 26||orgate2 +> output_pin2+--->+GIC130| +->10 27|| || | UART5 | 28||orgate3 +> output_pin3+--->+GIC131| +>+11 29|| || | UART6 | +--->+orgate4 +> output_pin4+--->+GIC132| +>+12 30|| || | UART7 | 31||orgate5 +> output_pin5+--->+GIC133| +>+13 || || | UART8 | OR[0:31] ||orgate6 +> output_pin6+--->+GIC134| -->14 || || | UART9 | ||orgate7 +> output_pin7+--->+GIC135| ->+15 || || | UART10 | ||orgate8 +> output_pin8+--->+GIC136| ->+16 || | +--+ UART11 | |+--+ +>+17 | UART12 | | +->18 | | | | | | | +---+ Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/intc/aspeed_intc.c | 360 ++ hw/intc/meson.build | 1 + hw/intc/trace-events | 13 ++ include/hw/intc/aspeed_intc.h | 44 + 4 files changed, 418 insertions(+) create mode 100644 hw/intc/aspeed_intc.c create mode 100644 include/hw/intc/aspeed_intc.h diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c new file mode 100644 index 00..e232361791 --- /dev/null +++ b/hw/intc/aspeed_intc.c @@ -0,0 +1,360 @@ +/* + * ASPEED INTC Controller + * + * Copyright (C) 2024 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/intc/aspeed_intc.h" +#include "hw/irq.h" +#include "qemu/log.h" +#include "trace.h" +#include "hw/registerfields.h" +#include "qapi/error.h" + +/* INTC Registers */ +REG32(GICINT128_EN, 0x1000) +REG32(GICINT128_STATUS, 0x1004) +REG32(GICINT129_EN, 0x1100) +REG32(GICINT129_STATUS, 0x1104) +REG32(GICINT130_EN, 0x1200) +REG32(GICINT130_STATUS, 0x1204) +REG32(GICINT131_EN, 0x1300) +REG32(GICINT131_STATUS, 0x1304) +REG32(GICINT132_EN, 0x1400) +REG32(GICINT132_STATUS, 0x1404) +REG32(GICINT133_EN, 0x1500) +REG32(GICINT133_STATUS, 0x1504) +REG32(GICINT134_EN, 0x1600) +REG32(GICI
Re: [PATCH v5 13/17] aspeed/soc: Add AST2700 support
On 6/4/24 07:44, Jamin Lin wrote: Initial definitions for a simple machine using an AST2700 SOC (Cortex-a35 CPU). AST2700 SOC and its interrupt controller are too complex to handle in the common Aspeed SoC framework. We introduce a new ast2700 class with instance_init and realize handlers. AST2700 is a 64 bits quad core cpus and support 8 watchdog. Update maximum ASPEED_CPUS_NUM to 4 and ASPEED_WDTS_NUM to 8. In addition, update AspeedSocState to support scuio, sli, sliio and intc. Add TYPE_ASPEED27X0_SOC machine type. The SDMC controller is unlocked at SPL stage. At present, only supports to emulate booting start from u-boot stage. Set SDMC controller unlocked by default. In INTC, each interrupt of INT 128 to INT 136 combines 32 interrupts. It connect GICINT IRQ GPIO-OUTPUT pins to GIC device with irq 128 to 136. And, if a device irq is 128 to 136, its irq GPIO-OUTPUT pin is connected to GICINT or-gates instead of GIC device. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/arm/aspeed_ast27x0.c | 563 hw/arm/meson.build | 1 + include/hw/arm/aspeed_soc.h | 28 +- 3 files changed, 590 insertions(+), 2 deletions(-) create mode 100644 hw/arm/aspeed_ast27x0.c diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c new file mode 100644 index 00..29e75072c4 --- /dev/null +++ b/hw/arm/aspeed_ast27x0.c @@ -0,0 +1,563 @@ +/* + * ASPEED SoC 27x0 family + * + * Copyright (C) 2024 ASPEED Technology Inc. + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * Implementation extracted from the AST2600 and adapted for AST27x0. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/misc/unimp.h" +#include "hw/arm/aspeed_soc.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/i2c/aspeed_i2c.h" +#include "net/net.h" +#include "sysemu/sysemu.h" +#include "hw/intc/arm_gicv3.h" +#include "qapi/qmp/qlist.h" + +static const hwaddr aspeed_soc_ast2700_memmap[] = { +[ASPEED_DEV_SPI_BOOT] = 0x4, +[ASPEED_DEV_SRAM] = 0x1000, +[ASPEED_DEV_SDMC] = 0x12C0, +[ASPEED_DEV_SCU] = 0x12C02000, +[ASPEED_DEV_SCUIO] = 0x14C02000, +[ASPEED_DEV_UART0] = 0X14C33000, +[ASPEED_DEV_UART1] = 0X14C33100, +[ASPEED_DEV_UART2] = 0X14C33200, +[ASPEED_DEV_UART3] = 0X14C33300, +[ASPEED_DEV_UART4] = 0X12C1A000, +[ASPEED_DEV_UART5] = 0X14C33400, +[ASPEED_DEV_UART6] = 0X14C33500, +[ASPEED_DEV_UART7] = 0X14C33600, +[ASPEED_DEV_UART8] = 0X14C33700, +[ASPEED_DEV_UART9] = 0X14C33800, +[ASPEED_DEV_UART10]= 0X14C33900, +[ASPEED_DEV_UART11]= 0X14C33A00, +[ASPEED_DEV_UART12]= 0X14C33B00, +[ASPEED_DEV_WDT] = 0x14C37000, +[ASPEED_DEV_VUART] = 0X14C3, +[ASPEED_DEV_FMC] = 0x1400, +[ASPEED_DEV_SPI0] = 0x1401, +[ASPEED_DEV_SPI1] = 0x1402, +[ASPEED_DEV_SPI2] = 0x1403, +[ASPEED_DEV_SDRAM] = 0x4, +[ASPEED_DEV_MII1] = 0x1404, +[ASPEED_DEV_MII2] = 0x14040008, +[ASPEED_DEV_MII3] = 0x14040010, +[ASPEED_DEV_ETH1] = 0x1405, +[ASPEED_DEV_ETH2] = 0x1406, +[ASPEED_DEV_ETH3] = 0x1407, +[ASPEED_DEV_EMMC] = 0x1209, +[ASPEED_DEV_INTC] = 0x1210, +[ASPEED_DEV_SLI] = 0x12C17000, +[ASPEED_DEV_SLIIO] = 0x14C1E000, +[ASPEED_GIC_DIST] = 0x1220, +[ASPEED_GIC_REDIST]= 0x1228, +}; + +#define AST2700_MAX_IRQ 288 + +/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */ +static const int aspeed_soc_ast2700_irqmap[] = { +[ASPEED_DEV_UART0] = 132, +[ASPEED_DEV_UART1] = 132, +[ASPEED_DEV_UART2] = 132, +[ASPEED_DEV_UART3] = 132, +[ASPEED_DEV_UART4] = 8, +[ASPEED_DEV_UART5] = 132, +[ASPEED_DEV_UART6] = 132, +[ASPEED_DEV_UART7] = 132, +[ASPEED_DEV_UART8] = 132, +[ASPEED_DEV_UART9] = 132, +[ASPEED_DEV_UART10]= 132, +[ASPEED_DEV_UART11]= 132, +[ASPEED_DEV_UART12]= 132, +[ASPEED_DEV_FMC] = 131, +[ASPEED_DEV_SDMC] = 0, +[ASPEED_DEV_SCU] = 12, +[ASPEED_DEV_ADC] = 130, +[ASPEED_DEV_XDMA] = 5, +[ASPEED_DEV_EMMC] = 15, +[ASPEED_DEV_GPIO] = 11, +[ASPEED_DEV_GPIO_1_8V] = 130, +[ASPEED_DEV_RTC] = 13, +[ASPEED_DEV_TIMER1]= 16, +[ASPEED_DEV_TIMER2]= 17, +[ASPEED_DEV_TIMER3]= 18, +[ASPEED_DEV_TIMER4]= 19, +[ASPEED_DEV_TIMER5]= 20, +[ASPEED_DEV_TIMER6]= 21, +[ASPEED_DEV_TIMER7]
Re: [PATCH v5 15/17] aspeed/soc: fix incorrect dram size for AST2700
On 6/4/24 07:44, Jamin Lin wrote: AST2700 dram size calculation is not back compatible AST2600. According to the DDR capacity hardware behavior, if users write the data to the address which is beyond the ram size, it would write the data to the "address % ram_size". For example: a. sdram base address "0x4 " b. sdram size 1 GiB The available address range is from "0x4 " to "0x4 3FFF". If users write 0x12345678 to address "0x5 ", the value of DRAM address 0 (base address 0x4 ) will be 0x12345678. Add aspeed_soc_ast2700_dram_init to calculate the dram size and add memory I/O whose address range is from "max_ram_size - ram_size" to max_ram_size and its read/write handler to emulate DDR capacity hardware behavior. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/arm/aspeed_ast27x0.c | 87 - include/hw/arm/aspeed_soc.h | 2 + 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index 29e75072c4..b6876b4862 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -20,6 +20,7 @@ #include "sysemu/sysemu.h" #include "hw/intc/arm_gicv3.h" #include "qapi/qmp/qlist.h" +#include "qemu/log.h" static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_SPI_BOOT] = 0x4, @@ -191,6 +192,90 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev) return qdev_get_gpio_in(DEVICE(>gic), sc->irqmap[dev]); } +static uint64_t aspeed_ram_capacity_read(void *opaque, hwaddr addr, +unsigned int size) +{ +qemu_log_mask(LOG_GUEST_ERROR, + "%s: DRAM read out of ram size, addr:0x%" PRIx64 "\n", + __func__, addr); +return 0; +} + +static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data, +unsigned int size) +{ +AspeedSoCState *s = ASPEED_SOC(opaque); +ram_addr_t ram_size; +MemTxResult result; + +ram_size = object_property_get_uint(OBJECT(>sdmc), "ram-size", +_abort); + +/* + * Emulate ddr capacity hardware behavior. + * If writes the data to the address which is beyond the ram size, + * it would write the data to the "address % ram_size". + */ +result = address_space_write(>dram_as, addr % ram_size, + MEMTXATTRS_UNSPECIFIED, , 4); +if (result != MEMTX_OK) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: DRAM write failed, addr:0x%" HWADDR_PRIx + ", data :0x%" PRIx64 "\n", + __func__, addr % ram_size, data); +} +} + +static const MemoryRegionOps aspeed_ram_capacity_ops = { +.read = aspeed_ram_capacity_read, +.write = aspeed_ram_capacity_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 1, +.max_access_size = 8, +}, +}; + +/* + * SDMC should be realized first to get correct RAM size and max size + * values + */ +static bool aspeed_soc_ast2700_dram_init(DeviceState *dev, Error **errp) +{ +ram_addr_t ram_size, max_ram_size; +Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev); +AspeedSoCState *s = ASPEED_SOC(dev); +AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + +ram_size = object_property_get_uint(OBJECT(>sdmc), "ram-size", +_abort); +max_ram_size = object_property_get_uint(OBJECT(>sdmc), "max-ram-size", +_abort); + +memory_region_init(>dram_container, OBJECT(s), "ram-container", + ram_size); +memory_region_add_subregion(>dram_container, 0, s->dram_mr); +address_space_init(>dram_as, s->dram_mr, "dram"); + +/* + * Add a memory region beyond the RAM region to emulate + * ddr capacity hardware behavior. + */ +if (ram_size < max_ram_size) { +memory_region_init_io(>dram_empty, OBJECT(s), + _ram_capacity_ops, s, + "ram-empty", max_ram_size - ram_size); + +memory_region_add_subregion(s->memory, +sc->memmap[ASPEED_DEV_SDRAM] + ram_size, +>dram_empty); +} + +memory_region_add_subregion(s->memory, + sc->memmap[ASPEED_DEV_SDRAM], >dram_container); +return true; +} + static void aspeed_soc_ast2700_init(Object *obj) { Aspeed27x0SoCState *a = ASPEED27X0_SOC(obj);
Re: [PATCH v5 10/17] aspeed/smc: Add AST2700 support
On 6/4/24 07:44, Jamin Lin wrote: AST2700 fmc/spi controller's address decoding unit is 64KB and only bits [31:16] are used for decoding. Introduce seg_to_reg and reg_to_seg handlers for ast2700 fmc/spi controller. In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler. AST2700 is a 64 bits quad core CPUs(Cortex-a35). Introduce a new "aspeed_2700_smc_flash_ops" and set its valid "max_access_size" 8 for 64 bits data format access. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/ssi/aspeed_smc.c | 234 +++- 1 file changed, 233 insertions(+), 1 deletion(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 129d06690d..49205ab76d 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -185,7 +185,7 @@ * 0: 4 bytes * 0x1FC: 32M bytes * - * DMA length is from 1 byte to 32MB (AST2600, AST10x0) + * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700) * 0: 1 byte * 0x1FF: 32M bytes */ @@ -1938,6 +1938,234 @@ static const TypeInfo aspeed_1030_spi2_info = { .class_init = aspeed_1030_spi2_class_init, }; +/* + * The FMC Segment Registers of the AST2700 have a 64KB unit. + * Only bits [31:16] are used for decoding. + */ +#define AST2700_SEG_ADDR_MASK 0x + +static uint32_t aspeed_2700_smc_segment_to_reg(const AspeedSMCState *s, + const AspeedSegments *seg) +{ +uint32_t reg = 0; + +/* Disabled segments have a nil register */ +if (!seg->size) { +return 0; +} + +reg |= (seg->addr & AST2700_SEG_ADDR_MASK) >> 16; /* start offset */ +reg |= (seg->addr + seg->size - 1) & AST2700_SEG_ADDR_MASK; /* end offset */ +return reg; +} + +static void aspeed_2700_smc_reg_to_segment(const AspeedSMCState *s, + uint32_t reg, AspeedSegments *seg) +{ +uint32_t start_offset = (reg << 16) & AST2700_SEG_ADDR_MASK; +uint32_t end_offset = reg & AST2700_SEG_ADDR_MASK; +AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); + +if (reg) { +seg->addr = asc->flash_window_base + start_offset; +seg->size = end_offset + (64 * KiB) - start_offset; +} else { +seg->addr = asc->flash_window_base; +seg->size = 0; +} +} + +static const uint32_t aspeed_2700_fmc_resets[ASPEED_SMC_R_MAX] = { +[R_CONF] = (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0 | +CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1), +[R_CE_CTRL] = 0xaa00, +[R_CTRL0] = 0x406b0641, +[R_CTRL1] = 0x0400, +[R_CTRL2] = 0x0400, +[R_CTRL3] = 0x0400, +[R_SEG_ADDR0] = 0x0800, +[R_SEG_ADDR1] = 0x1800, +[R_SEG_ADDR2] = 0x, +[R_SEG_ADDR3] = 0x, +[R_DUMMY_DATA] = 0x0001, +[R_DMA_DRAM_ADDR_HIGH] = 0x, +[R_TIMINGS] = 0x007b, +}; + +static const MemoryRegionOps aspeed_2700_smc_flash_ops = { +.read = aspeed_smc_flash_read, +.write = aspeed_smc_flash_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 1, +.max_access_size = 8, +}, +}; + +static const AspeedSegments aspeed_2700_fmc_segments[] = { +{ 0x0, 128 * MiB }, /* start address is readonly */ +{ 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */ +{ 256 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */ +{ 0x0, 0 }, /* disabled */ +}; + +static void aspeed_2700_fmc_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +AspeedSMCClass *asc = ASPEED_SMC_CLASS(klass); + +dc->desc = "Aspeed 2700 FMC Controller"; +asc->r_conf= R_CONF; +asc->r_ce_ctrl = R_CE_CTRL; +asc->r_ctrl0 = R_CTRL0; +asc->r_timings = R_TIMINGS; +asc->nregs_timings = 3; +asc->conf_enable_w0= CONF_ENABLE_W0; +asc->cs_num_max= 3; +asc->segments = aspeed_2700_fmc_segments; +asc->segment_addr_mask = 0x; +asc->resets= aspeed_2700_fmc_resets; +asc->flash_window_base = 0x1; +asc->flash_window_size = 1 * GiB; +asc->features = ASPEED_SMC_FEATURE_DMA | + ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH; +asc->dma_flash_mask= 0x2FFC; +asc->dma_dram_mask = 0xFFFC; +asc->dma_start_length = 1; +asc->nregs = ASPEED_SMC_R_MAX; +asc->segment_to_reg= aspeed_2700_smc_segment_to_reg; +asc->reg_to_segment= aspeed_2700_smc_reg_to_segment; +asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; +asc->reg_ops = _2700_smc_flash_ops; +} + +static const TypeInfo aspeed_2
Re: [PATCH v5 09/17] aspeed/smc: support different memory region ops for SMC flash region
On 6/4/24 07:44, Jamin Lin wrote: It set "aspeed_smc_flash_ops" struct which containing read and write callbacks to be used when I/O is performed on the SMC flash region. And it set the valid max_access_size 4 by default for all ASPEED SMC models. However, the valid max_access_size 4 only support 32 bits CPUs. To support all ASPEED SMC model, introduce a new "const MemoryRegionOps *" attribute in AspeedSMCClass and use it in aspeed_smc_flash_realize function. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/ssi/aspeed_smc.c | 14 +- include/hw/ssi/aspeed_smc.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index df0c63469c..129d06690d 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -1316,7 +1316,7 @@ static void aspeed_smc_flash_realize(DeviceState *dev, Error **errp) * Use the default segment value to size the memory region. This * can be changed by FW at runtime. */ -memory_region_init_io(>mmio, OBJECT(s), _smc_flash_ops, +memory_region_init_io(>mmio, OBJECT(s), s->asc->reg_ops, s, name, s->asc->segments[s->cs].size); sysbus_init_mmio(SYS_BUS_DEVICE(dev), >mmio); } @@ -1391,6 +1391,7 @@ static void aspeed_2400_smc_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_smc_segment_to_reg; asc->reg_to_segment= aspeed_smc_reg_to_segment; asc->dma_ctrl = aspeed_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2400_smc_info = { @@ -1441,6 +1442,7 @@ static void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_smc_segment_to_reg; asc->reg_to_segment= aspeed_smc_reg_to_segment; asc->dma_ctrl = aspeed_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2400_fmc_info = { @@ -1480,6 +1482,7 @@ static void aspeed_2400_spi1_class_init(ObjectClass *klass, void *data) asc->reg_to_segment= aspeed_smc_reg_to_segment; asc->dma_ctrl = aspeed_smc_dma_ctrl; asc->addr_width= aspeed_2400_spi1_addr_width; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2400_spi1_info = { @@ -1525,6 +1528,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_smc_segment_to_reg; asc->reg_to_segment= aspeed_smc_reg_to_segment; asc->dma_ctrl = aspeed_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2500_fmc_info = { @@ -1560,6 +1564,7 @@ static void aspeed_2500_spi1_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_smc_segment_to_reg; asc->reg_to_segment= aspeed_smc_reg_to_segment; asc->dma_ctrl = aspeed_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2500_spi1_info = { @@ -1595,6 +1600,7 @@ static void aspeed_2500_spi2_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_smc_segment_to_reg; asc->reg_to_segment= aspeed_smc_reg_to_segment; asc->dma_ctrl = aspeed_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2500_spi2_info = { @@ -1682,6 +1688,7 @@ static void aspeed_2600_fmc_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_2600_smc_segment_to_reg; asc->reg_to_segment= aspeed_2600_smc_reg_to_segment; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2600_fmc_info = { @@ -1721,6 +1728,7 @@ static void aspeed_2600_spi1_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_2600_smc_segment_to_reg; asc->reg_to_segment= aspeed_2600_smc_reg_to_segment; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2600_spi1_info = { @@ -1761,6 +1769,7 @@ static void aspeed_2600_spi2_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_2600_smc_segment_to_reg; asc->reg_to_segment= aspeed_2600_smc_reg_to_segment; asc->dma_ctrl = aspeed_2600_smc_dma_ctrl; +asc->reg_ops = _smc_flash_ops; } static const TypeInfo aspeed_2600_spi2_info = { @@ -1843,6 +1852,7 @@ static void aspeed_1030_fmc_class_init(ObjectClass *klass, void *data) asc->segment_to_reg= aspeed_1030_smc_segment_to_reg; asc->reg_to_segme
Re: [PATCH v5 05/17] aspeed/sdmc: Add AST2700 support
On 6/4/24 07:44, Jamin Lin wrote: The SDRAM memory controller(DRAMC) controls the access to external DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY. The DRAM memory controller of AST2700 is not backward compatible to previous chips such AST2600, AST2500 and AST2400. Max memory is now 8GiB on the AST2700. Introduce new aspeed_2700_sdmc and class with read/write operation and reset handlers. Define DRAMC necessary protected registers and unprotected registers for AST2700 and increase the register set to 0x1000. Add unlocked property to change controller protected status. Incrementing the version of vmstate to 2. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/misc/aspeed_sdmc.c | 194 +- include/hw/misc/aspeed_sdmc.h | 5 +- 2 files changed, 195 insertions(+), 4 deletions(-) diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index 873d67c592..93e2e29ead 100644 --- a/hw/misc/aspeed_sdmc.c +++ b/hw/misc/aspeed_sdmc.c @@ -27,6 +27,7 @@ #define PROT_SOFTLOCKED0x00 #define PROT_KEY_UNLOCK 0xFC600309 +#define PROT_2700_KEY_UNLOCK 0x1688A8A8 #define PROT_KEY_HARDLOCK 0xDEADDEAD /* AST2600 */ /* Configuration Register */ @@ -54,6 +55,46 @@ #define R_DRAM_TIME (0x8c / 4) #define R_ECC_ERR_INJECT (0xb4 / 4) +/* AST2700 Register */ +#define R_2700_PROT (0x00 / 4) +#define R_INT_STATUS(0x04 / 4) +#define R_INT_CLEAR (0x08 / 4) +#define R_INT_MASK (0x0c / 4) +#define R_MAIN_CONF (0x10 / 4) +#define R_MAIN_CONTROL (0x14 / 4) +#define R_MAIN_STATUS (0x18 / 4) +#define R_ERR_STATUS(0x1c / 4) +#define R_ECC_FAIL_STATUS (0x78 / 4) +#define R_ECC_FAIL_ADDR (0x7c / 4) +#define R_ECC_TESTING_CONTROL (0x80 / 4) +#define R_PROT_REGION_LOCK_STATUS (0x94 / 4) +#define R_TEST_FAIL_ADDR(0xd4 / 4) +#define R_TEST_FAIL_D0 (0xd8 / 4) +#define R_TEST_FAIL_D1 (0xdc / 4) +#define R_TEST_FAIL_D2 (0xe0 / 4) +#define R_TEST_FAIL_D3 (0xe4 / 4) +#define R_DBG_STATUS(0xf4 / 4) +#define R_PHY_INTERFACE_STATUS (0xf8 / 4) +#define R_GRAPHIC_MEM_BASE_ADDR (0x10c / 4) +#define R_PORT0_INTERFACE_MONITOR0 (0x240 / 4) +#define R_PORT0_INTERFACE_MONITOR1 (0x244 / 4) +#define R_PORT0_INTERFACE_MONITOR2 (0x248 / 4) +#define R_PORT1_INTERFACE_MONITOR0 (0x2c0 / 4) +#define R_PORT1_INTERFACE_MONITOR1 (0x2c4 / 4) +#define R_PORT1_INTERFACE_MONITOR2 (0x2c8 / 4) +#define R_PORT2_INTERFACE_MONITOR0 (0x340 / 4) +#define R_PORT2_INTERFACE_MONITOR1 (0x344 / 4) +#define R_PORT2_INTERFACE_MONITOR2 (0x348 / 4) +#define R_PORT3_INTERFACE_MONITOR0 (0x3c0 / 4) +#define R_PORT3_INTERFACE_MONITOR1 (0x3c4 / 4) +#define R_PORT3_INTERFACE_MONITOR2 (0x3c8 / 4) +#define R_PORT4_INTERFACE_MONITOR0 (0x440 / 4) +#define R_PORT4_INTERFACE_MONITOR1 (0x444 / 4) +#define R_PORT4_INTERFACE_MONITOR2 (0x448 / 4) +#define R_PORT5_INTERFACE_MONITOR0 (0x4c0 / 4) +#define R_PORT5_INTERFACE_MONITOR1 (0x4c4 / 4) +#define R_PORT5_INTERFACE_MONITOR2 (0x4c8 / 4) + /* * Configuration register Ox4 (for Aspeed AST2400 SOC) * @@ -101,6 +142,19 @@ ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT |\ ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB)) +/* + * Main Configuration register Ox10 (for Aspeed AST2700 SOC and higher) + * + */ +#define ASPEED_SDMC_AST2700_RESERVED0x2082 /* 31:16, 13, 7, 1 */ +#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE (1 << 8) +#define ASPEED_SDMC_AST2700_ECC_ENABLE (1 << 6) +#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE(1 << 5) +#define ASPEED_SDMC_AST2700_DRAM_SIZE(x)((x & 0x7) << 2) + +#define ASPEED_SDMC_AST2700_READONLY_MASK \ + (ASPEED_SDMC_AST2700_RESERVED) + static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size) { AspeedSDMCState *s = ASPEED_SDMC(opaque); @@ -216,7 +270,7 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp) AspeedSDMCState *s = ASPEED_SDMC(dev); AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s); -assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */ +assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit); s->max_ram_size = asc->max_ram_size; memory_region_init_io(>iomem, OBJECT(s), _sdmc_ops, s, @@ -226,8 +280,8 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp) static const VMStateDescription vmstate_aspeed_sdmc = { .name = "aspeed.sdmc", -.version_id = 1, -.minimum_version_id = 1, +.version_id = 2, +.minimum_version_id = 2, .fields = (const VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, AspeedSDMCState, ASPEED_S
Re: [PATCH v6 18/19] intel_iommu: Implement [set|unset]_iommu_device() callbacks
On 6/3/24 13:02, Duan, Zhenzhong wrote: -Original Message- From: CLEMENT MATHIEU--DRIF Subject: Re: [PATCH v6 18/19] intel_iommu: Implement [set|unset]_iommu_device() callbacks On 03/06/2024 08:10, Zhenzhong Duan wrote: Caution: External email. Do not open attachments or click links, unless this email comes from a known sender and you know the content is safe. From: Yi Liu Implement [set|unset]_iommu_device() callbacks in Intel vIOMMU. In set call, a new structure VTDHostIOMMUDevice which holds a reference to HostIOMMUDevice is stored in hash table indexed by PCI BDF. Signed-off-by: Yi Liu Signed-off-by: Yi Sun Signed-off-by: Zhenzhong Duan --- hw/i386/intel_iommu_internal.h | 9 include/hw/i386/intel_iommu.h | 2 + hw/i386/intel_iommu.c | 76 ++ 3 files changed, 87 insertions(+) diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index f8cf99bddf..b800d62ca0 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -28,6 +28,7 @@ #ifndef HW_I386_INTEL_IOMMU_INTERNAL_H #define HW_I386_INTEL_IOMMU_INTERNAL_H #include "hw/i386/intel_iommu.h" +#include "sysemu/host_iommu_device.h" /* * Intel IOMMU register specification @@ -537,4 +538,12 @@ typedef struct VTDRootEntry VTDRootEntry; #define VTD_SL_IGN_COM 0xbff0ULL #define VTD_SL_TM (1ULL << 62) + +typedef struct VTDHostIOMMUDevice { +IntelIOMMUState *iommu_state; +PCIBus *bus; +uint8_t devfn; +HostIOMMUDevice *dev; +QLIST_ENTRY(VTDHostIOMMUDevice) next; +} VTDHostIOMMUDevice; #endif diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 7d694b0813..2bbde41e45 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -293,6 +293,8 @@ struct IntelIOMMUState { /* list of registered notifiers */ QLIST_HEAD(, VTDAddressSpace) vtd_as_with_notifiers; +GHashTable *vtd_host_iommu_dev; /* VTDHostIOMMUDevice */ + /* interrupt remapping */ bool intr_enabled; /* Whether guest enabled IR */ dma_addr_t intr_root; /* Interrupt remapping table pointer */ diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 519063c8f8..747c988bc4 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -237,6 +237,13 @@ static gboolean vtd_as_equal(gconstpointer v1, gconstpointer v2) (key1->pasid == key2->pasid); } +static gboolean vtd_as_idev_equal(gconstpointer v1, gconstpointer v2) +{ +const struct vtd_as_key *key1 = v1; +const struct vtd_as_key *key2 = v2; + +return (key1->bus == key2->bus) && (key1->devfn == key2->devfn); +} /* * Note that we use pointer to PCIBus as the key, so hashing/shifting * based on the pointer value is intended. Note that we deal with @@ -3812,6 +3819,70 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, return vtd_dev_as; } +static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn, + HostIOMMUDevice *hiod, Error **errp) +{ +IntelIOMMUState *s = opaque; +VTDHostIOMMUDevice *vtd_hdev; +struct vtd_as_key key = { +.bus = bus, +.devfn = devfn, +}; +struct vtd_as_key *new_key; + +assert(hiod); + +vtd_iommu_lock(s); + +vtd_hdev = g_hash_table_lookup(s->vtd_host_iommu_dev, ); + +if (vtd_hdev) { +error_setg(errp, "IOMMUFD device already exist"); +vtd_iommu_unlock(s); +return false; +} + +vtd_hdev = g_malloc0(sizeof(VTDHostIOMMUDevice)); +vtd_hdev->bus = bus; +vtd_hdev->devfn = (uint8_t)devfn; +vtd_hdev->iommu_state = s; +vtd_hdev->dev = hiod; + +new_key = g_malloc(sizeof(*new_key)); +new_key->bus = bus; +new_key->devfn = devfn; + +object_ref(hiod); +g_hash_table_insert(s->vtd_host_iommu_dev, new_key, vtd_hdev); + +vtd_iommu_unlock(s); + +return true; +} + +static void vtd_dev_unset_iommu_device(PCIBus *bus, void *opaque, int devfn) +{ +IntelIOMMUState *s = opaque; +VTDHostIOMMUDevice *vtd_hdev; +struct vtd_as_key key = { +.bus = bus, +.devfn = devfn, +}; + +vtd_iommu_lock(s); + +vtd_hdev = g_hash_table_lookup(s->vtd_host_iommu_dev, ); +if (!vtd_hdev) { +vtd_iommu_unlock(s); +return; +} + +g_hash_table_remove(s->vtd_host_iommu_dev, ); +object_unref(vtd_hdev->dev); Not sure but isn't that a potential use after free? Good catch! Will fix. Should be: object_unref(vtd_hdev->dev); g_hash_table_remove(s->vtd_host_iommu_dev, ); you could also implement a custom destroy hash function. Thanks, C. Thanks Zhenzhong + +vtd_iommu_unlock(s); +} + /* Unmap the whole range in the notifier's scope. */ static void vtd_address_space_unmap(VTDAddressSpace *as,
Re: [PATCH v6 05/19] backends/host_iommu_device: Introduce HostIOMMUDeviceCaps
On 6/3/24 08:10, Zhenzhong Duan wrote: HostIOMMUDeviceCaps's elements map to the host IOMMU's capabilities. Different platform IOMMU can support different elements. Currently only two elements, type and aw_bits, type hints the host platform IOMMU type, i.e., INTEL vtd, ARM smmu, etc; aw_bits hints host IOMMU address width. Introduce .get_cap() handler to check if HOST_IOMMU_DEVICE_CAP_XXX is supported. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan --- include/sysemu/host_iommu_device.h | 37 ++ 1 file changed, 37 insertions(+) diff --git a/include/sysemu/host_iommu_device.h b/include/sysemu/host_iommu_device.h index 2b58a94d62..d47d1034b1 100644 --- a/include/sysemu/host_iommu_device.h +++ b/include/sysemu/host_iommu_device.h @@ -15,11 +15,25 @@ #include "qom/object.h" #include "qapi/error.h" +/** + * struct HostIOMMUDeviceCaps - Define host IOMMU device capabilities. + * + * @type: host platform IOMMU type. + * + * @aw_bits: host IOMMU address width. 0xff if no limitation. Could we introduce a define for the special value 0xff ? This would answer Eric's question. Thanks, C. + */ +typedef struct HostIOMMUDeviceCaps { +uint32_t type; +uint8_t aw_bits; +} HostIOMMUDeviceCaps; + #define TYPE_HOST_IOMMU_DEVICE "host-iommu-device" OBJECT_DECLARE_TYPE(HostIOMMUDevice, HostIOMMUDeviceClass, HOST_IOMMU_DEVICE) struct HostIOMMUDevice { Object parent_obj; + +HostIOMMUDeviceCaps caps; }; /** @@ -47,5 +61,28 @@ struct HostIOMMUDeviceClass { * Returns: true on success, false on failure. */ bool (*realize)(HostIOMMUDevice *hiod, void *opaque, Error **errp); +/** + * @get_cap: check if a host IOMMU device capability is supported. + * + * Optional callback, if not implemented, hint not supporting query + * of @cap. + * + * @hiod: pointer to a host IOMMU device instance. + * + * @cap: capability to check. + * + * @errp: pass an Error out when fails to query capability. + * + * Returns: <0 on failure, 0 if a @cap is unsupported, or else + * 1 or some positive value for some special @cap, + * i.e., HOST_IOMMU_DEVICE_CAP_AW_BITS. + */ +int (*get_cap)(HostIOMMUDevice *hiod, int cap, Error **errp); }; + +/* + * Host IOMMU device capability list. + */ +#define HOST_IOMMU_DEVICE_CAP_IOMMU_TYPE0 +#define HOST_IOMMU_DEVICE_CAP_AW_BITS 1 #endif
Re: [PATCH v6 11/19] backends/iommufd: Implement HostIOMMUDeviceClass::get_cap() handler
On 6/3/24 13:32, Eric Auger wrote: On 6/3/24 08:10, Zhenzhong Duan wrote: Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan --- backends/iommufd.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/backends/iommufd.c b/backends/iommufd.c index c7e969d6f7..f2f7a762a0 100644 --- a/backends/iommufd.c +++ b/backends/iommufd.c @@ -230,6 +230,28 @@ bool iommufd_backend_get_device_info(IOMMUFDBackend *be, uint32_t devid, return true; } +static int hiod_iommufd_get_cap(HostIOMMUDevice *hiod, int cap, Error **errp) +{ +HostIOMMUDeviceCaps *caps = >caps; + +switch (cap) { +case HOST_IOMMU_DEVICE_CAP_IOMMU_TYPE: +return caps->type; +case HOST_IOMMU_DEVICE_CAP_AW_BITS: +return caps->aw_bits; +default: +error_setg(errp, "Not support get cap %x", cap); can't you add details about the faulting HostIOMMUDevice by tracing the devid for instance? yes. I would rephrase the error message into No support for capability 0x%x I was going to propose "Unsupported capability ..." Thanks, C. Eric +return -EINVAL; +} +} + +static void hiod_iommufd_class_init(ObjectClass *oc, void *data) +{ +HostIOMMUDeviceClass *hioc = HOST_IOMMU_DEVICE_CLASS(oc); + +hioc->get_cap = hiod_iommufd_get_cap; +}; + static const TypeInfo types[] = { { .name = TYPE_IOMMUFD_BACKEND, @@ -246,6 +268,7 @@ static const TypeInfo types[] = { }, { .name = TYPE_HOST_IOMMU_DEVICE_IOMMUFD, .parent = TYPE_HOST_IOMMU_DEVICE, +.class_init = hiod_iommufd_class_init, .abstract = true, } };
Re: [PATCH v6 01/19] backends: Introduce HostIOMMUDevice abstract
On 6/3/24 08:10, Zhenzhong Duan wrote: Introduce HostIOMMUDevice as an abstraction of host IOMMU device. Introduce .realize() to initialize HostIOMMUDevice further after instance init. Introduce a macro CONFIG_HOST_IOMMU_DEVICE to define the usage for VFIO, and VDPA in the future. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan --- MAINTAINERS| 2 ++ include/sysemu/host_iommu_device.h | 51 ++ backends/host_iommu_device.c | 30 ++ backends/Kconfig | 5 +++ backends/meson.build | 1 + 5 files changed, 89 insertions(+) create mode 100644 include/sysemu/host_iommu_device.h create mode 100644 backends/host_iommu_device.c diff --git a/MAINTAINERS b/MAINTAINERS index 448dc951c5..1cf2b25beb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2196,6 +2196,8 @@ M: Zhenzhong Duan S: Supported F: backends/iommufd.c F: include/sysemu/iommufd.h +F: backends/host_iommu_device.c +F: include/sysemu/host_iommu_device.h F: include/qemu/chardev_open.h F: util/chardev_open.c F: docs/devel/vfio-iommufd.rst diff --git a/include/sysemu/host_iommu_device.h b/include/sysemu/host_iommu_device.h new file mode 100644 index 00..2b58a94d62 --- /dev/null +++ b/include/sysemu/host_iommu_device.h @@ -0,0 +1,51 @@ +/* + * Host IOMMU device abstract declaration + * + * Copyright (C) 2024 Intel Corporation. + * + * Authors: Zhenzhong Duan + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef HOST_IOMMU_DEVICE_H +#define HOST_IOMMU_DEVICE_H + +#include "qom/object.h" +#include "qapi/error.h" + +#define TYPE_HOST_IOMMU_DEVICE "host-iommu-device" +OBJECT_DECLARE_TYPE(HostIOMMUDevice, HostIOMMUDeviceClass, HOST_IOMMU_DEVICE) + +struct HostIOMMUDevice { +Object parent_obj; +}; + +/** + * struct HostIOMMUDeviceClass - The base class for all host IOMMU devices. + * + * Different type of host devices (e.g., VFIO or VDPA device) or devices + * with different backend (e.g., VFIO legacy container or IOMMUFD backend) + * can have different sub-classes. + */ +struct HostIOMMUDeviceClass { +ObjectClass parent_class; + +/** + * @realize: initialize host IOMMU device instance further. + * + * Mandatory callback. + * + * @hiod: pointer to a host IOMMU device instance. + * + * @opaque: pointer to agent device of this host IOMMU device, + * i.e., for VFIO, pointer to VFIODevice + * + * @errp: pass an Error out when realize fails. + * + * Returns: true on success, false on failure. + */ +bool (*realize)(HostIOMMUDevice *hiod, void *opaque, Error **errp); +}; +#endif diff --git a/backends/host_iommu_device.c b/backends/host_iommu_device.c new file mode 100644 index 00..41f2fdce20 --- /dev/null +++ b/backends/host_iommu_device.c @@ -0,0 +1,30 @@ +/* + * Host IOMMU device abstract + * + * Copyright (C) 2024 Intel Corporation. + * + * Authors: Zhenzhong Duan + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "sysemu/host_iommu_device.h" + +OBJECT_DEFINE_ABSTRACT_TYPE(HostIOMMUDevice, +host_iommu_device, +HOST_IOMMU_DEVICE, +OBJECT) + +static void host_iommu_device_class_init(ObjectClass *oc, void *data) +{ +} + +static void host_iommu_device_init(Object *obj) +{ +} + +static void host_iommu_device_finalize(Object *obj) +{ +} diff --git a/backends/Kconfig b/backends/Kconfig index 2cb23f62fa..34ab29e994 100644 --- a/backends/Kconfig +++ b/backends/Kconfig @@ -3,3 +3,8 @@ source tpm/Kconfig config IOMMUFD bool depends on VFIO + +config HOST_IOMMU_DEVICE +bool +default y +depends on VFIO And you can drop HOST_IOMMU_DEVICE config diff --git a/backends/meson.build b/backends/meson.build index 8b2b111497..2e975d641e 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -25,6 +25,7 @@ if have_vhost_user endif system_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost.c')) system_ss.add(when: 'CONFIG_IOMMUFD', if_true: files('iommufd.c')) +system_ss.add(when: 'CONFIG_HOST_IOMMU_DEVICE', if_true: files('host_iommu_device.c')) and I would move host_iommu_device.c build under host_os == 'linux' Thanks, C. if have_vhost_user_crypto system_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost-user.c')) endif
Re: [SPAM] Re: [PATCH v4 09/16] aspeed/smc: Add AST2700 support
Thanks for your suggestion. How about these changes? 1. aspeed_smc.h struct AspeedSMCClass { const MemoryRegionOps *reg_ops; } 2. aspeed_smc.c a. create new memory region opts for ast2700 static const MemoryRegionOps aspeed_2700_smc_flash_ops = { .read = aspeed_smc_flash_read, .write = aspeed_smc_flash_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, .max_access_size = 8, }, }; b. set memory region opts in all model class init static void aspeed_2400_smc_class_init(ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2400_fmc_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2400_spi1_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2500_fmc_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2500_spi1_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2500_spi2_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2600_fmc_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2600_spi1_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2600_spi2_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_1030_fmc_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_1030_spi1_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_1030_spi2_class_init (ObjectClass *klass, void *data){ asc->reg_ops = _smc_flash_ops; } static void aspeed_2700_fmc_class_init(ObjectClass *klass, void *data) { asc->reg_ops = _2700_smc_flash_ops; } static void aspeed_2700_spi0_class_init (ObjectClass *klass, void *data) { asc->reg_ops = _2700_smc_flash_ops; } static void aspeed_2700_spi1_class_init (ObjectClass *klass, void *data) { asc->reg_ops = _2700_smc_flash_ops; } static void aspeed_2700_spi2_class_init (ObjectClass *klass, void *data) { asc->reg_ops = _2700_smc_flash_ops; } c. update realize to use memory region opts from class reg_opts static void aspeed_smc_flash_realize(DeviceState *dev, Error **errp) { memory_region_init_io(>mmio, OBJECT(s), s->asc->reg_ops, s, name, s->asc->segments[s->cs].size); } LGTM, Thanks, C.
Re: [SPAM] Re: [PATCH v4 09/16] aspeed/smc: Add AST2700 support
On 6/3/24 11:49, Jamin Lin wrote: Hi Cedric, From: Cédric Le Goater Subject: Re: [SPAM] Re: [PATCH v4 09/16] aspeed/smc: Add AST2700 support @@ -670,7 +670,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, - .max_access_size = 4, + .max_access_size = 8, Is this a bugfix? If so, please use a separate patch. Otherwise please mention why it is OK to widen access for AST2600 & AST10x0. According the design of SPI drivers, it uses this "memcpy_fromio" KERNEL API for SPI calibration. https://github.com/AspeedTech-BMC/linux/blob/1062a07420f9aed4ed7dc9deb 3429b8e7828f5cf/drivers/spi/spi-aspeed-smc.c#L1832 AST2700 is a 64 bits quad core cpus(Cortex-a35), so kernel API use 64 bits for data access. https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/a rm64/kernel/io.c#L25 I simply set the max_access_size to 8 for AST2700 support. AST2500, AST2600 and AST10x0 are all 32bits CPUS, that was why this max_access_size 8 did not impact these models. https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/a rm/kernel/io.c#L45 Yes. I think we are safe on that side. If you have any suggestion about this patch modification, please let me know. I am going to re-send v5 patch for AST2700 support. Please move this change in its own commit explaining the reason and add a TODO comment in the code. The aspeed_smc_flash_ops MemoryRegionOps should be copied in _realize() to set a different width for the AST2700 SoC. You could do that too. Thanks, C. I will do the following changes. Could you give me any suggestion? 1. add asc->max_access_size = 8 in aspeed_2700_fmc_class_init, aspeed_2700_spi0_class_init, aspeed_2700_spi1_class_init and aspeed_2700_spi2_class_init 2. Update aspeed_smc_flash_realize as below static void aspeed_smc_flash_realize(DeviceState *dev, Error **errp) { -- s->asc = ASPEED_SMC_GET_CLASS(s->controller) if (s->asc->max_access_size ==8) --> check max_access_size aspeed_smc_flash_ops.valid.max_access_size = s->asc->max_access --> update max_access_size You can not because aspeed_smc_flash_ops is a static const shared by all models Best option is to introduce a new 'const MemoryRegionOps*' attribute in AspeedSMCClass and use it in aspeed_smc_flash_realize(). Thanks, C.
Re: [SPAM] Re: [PATCH v4 09/16] aspeed/smc: Add AST2700 support
@@ -670,7 +670,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, - .max_access_size = 4, + .max_access_size = 8, Is this a bugfix? If so, please use a separate patch. Otherwise please mention why it is OK to widen access for AST2600 & AST10x0. According the design of SPI drivers, it uses this "memcpy_fromio" KERNEL API for SPI calibration. https://github.com/AspeedTech-BMC/linux/blob/1062a07420f9aed4ed7dc9deb3429b8e7828f5cf/drivers/spi/spi-aspeed-smc.c#L1832 AST2700 is a 64 bits quad core cpus(Cortex-a35), so kernel API use 64 bits for data access. https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/arm64/kernel/io.c#L25 I simply set the max_access_size to 8 for AST2700 support. AST2500, AST2600 and AST10x0 are all 32bits CPUS, that was why this max_access_size 8 did not impact these models. https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/arm/kernel/io.c#L45 Yes. I think we are safe on that side. If you have any suggestion about this patch modification, please let me know. I am going to re-send v5 patch for AST2700 support. Please move this change in its own commit explaining the reason and add a TODO comment in the code. The aspeed_smc_flash_ops MemoryRegionOps should be copied in _realize() to set a different width for the AST2700 SoC. You could do that too. Thanks, C.
Re: [PATCH v4 11/16] aspeed/intc: Add AST2700 support
+static void aspeed_2700_intc_class_init(ObjectClass *klass, void +*data) { +DeviceClass *dc = DEVICE_CLASS(klass); +AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); + +dc->desc = "ASPEED 2700 INTC Controller"; +aic->num_lines = 32; +aic->num_ints = 9; Use ASPEED_INTC_NR_INTS ? I am considering to support INTC model for future BMC SOCs. For example, if the num_ints has been changed to "18" in the future BMC Socs, users only need to update ASPEED_INTC_NR_INTS and Create a aspeed__intc_class_init to set its "aic->num_ints 18". That was why I set aic->num_ints 9 in aspeed_2700_intc_class_init. OK. This is minor. Thanks, C.
Re: [PATCH v4 12/16] aspeed/soc: Add AST2700 support
Hello Jamin, I refer to versal_create_apu_gic function, https://github.com/qemu/qemu/blob/master/hw/arm/xlnx-versal.c#L67 and updated aspeed_soc_ast2700_gic as following. If you have any concerned about the new changes, please let me know. Thanks-Jamin static bool aspeed_soc_ast2700_gic(DeviceState *dev, Error **errp) Please rename to aspeed_soc_ast2700_gic_realize() { Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev); AspeedSoCState *s = ASPEED_SOC(dev); AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); SysBusDevice *gicbusdev; DeviceState *gicdev; QList *redist_region_count; int i; object_initialize_child(OBJECT(a), "ast2700-gic", >gic, gicv3_class_name()); and object_initialize_child() can be called in aspeed_soc_ast2700_init(). gicbusdev = SYS_BUS_DEVICE(>gic); gicdev = DEVICE(>gic); qdev_prop_set_uint32(gicdev, "revision", 3); qdev_prop_set_uint32(gicdev, "num-cpu", sc->num_cpus); qdev_prop_set_uint32(gicdev, "num-irq", AST2700_MAX_IRQ); redist_region_count = qlist_new(); qlist_append_int(redist_region_count, sc->num_cpus); qdev_prop_set_array(gicdev, "redist-region-count", redist_region_count); if (!sysbus_realize(gicbusdev, errp)) { return false; } sysbus_mmio_map(gicbusdev, 0, sc->memmap[ASPEED_GIC_DIST]); sysbus_mmio_map(gicbusdev, 1, sc->memmap[ASPEED_GIC_REDIST]); for (i = 0; i < sc->num_cpus; i++) { DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); Could we avoid qemu_get_cpu() and use the cpu array of the SoC instead ? int NUM_IRQS = 256, ARCH_GIC_MAINT_IRQ = 9, VIRTUAL_PMU_IRQ = 7; int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; const int timer_irq[] = { [GTIMER_PHYS] = 14, [GTIMER_VIRT] = 11, [GTIMER_HYP] = 10, [GTIMER_SEC] = 13, }; int j; for (j = 0; j < ARRAY_SIZE(timer_irq); j++) { qdev_connect_gpio_out(cpudev, j, qdev_get_gpio_in(gicdev, ppibase + timer_irq[j])); } qemu_irq irq = qdev_get_gpio_in(gicdev, ppibase + ARCH_GIC_MAINT_IRQ); qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0, irq); qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, qdev_get_gpio_in(gicdev, ppibase + VIRTUAL_PMU_IRQ)); sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); sysbus_connect_irq(gicbusdev, i + sc->num_cpus, qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); sysbus_connect_irq(gicbusdev, i + 2 * sc->num_cpus, qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); sysbus_connect_irq(gicbusdev, i + 3 * sc->num_cpus, qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); } return true; } struct Aspeed27x0SoCState { AspeedSoCState parent; ARMCPU cpu[ASPEED_CPUS_NUM]; AspeedINTCState intc; GICv3State gic; }; #define TYPE_ASPEED27X0_SOC "aspeed27x0-soc" OBJECT_DECLARE_SIMPLE_TYPE(Aspeed27x0SoCState, ASPEED27X0_SOC) Thanks, C.
Re: [PATCH v4 14/16] aspeed/soc: fix incorrect dram size for AST2700
On 5/30/24 09:42, Jamin Lin wrote: Hi Cedric, From: Cédric Le Goater > Hello Jamin On 5/27/24 10:02, Jamin Lin wrote: AST2700 dram size calculation is not back compatible AST2600. According to the DDR capacity hardware behavior, if users write the data to address which is beyond the ram size, it would write the data to address 0. For example: a. sdram base address "0x4 " b. sdram size is 1 GiB The available address range is from "0x4 " to "0x4 4000". If users write 0xdeadbeef to address "0x6 ", the value of DRAM address 0 (base address 0x4 ) should be 0xdeadbeef. Add aspeed_soc_ast2700_dram_init to calculate the dram size and add memory I/O whose address range is from max_ram_size - ram_size to max_ram_size and its read/write handler to emulate DDR capacity hardware behavior. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed_ast27x0.c | 94 - include/hw/arm/aspeed_soc.h | 1 + 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index a3a03fc1ca..19380087fa 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -20,6 +20,7 @@ #include "sysemu/sysemu.h" #include "hw/intc/arm_gicv3.h" #include "qapi/qmp/qlist.h" +#include "qemu/log.h" static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_SPI_BOOT] = 0x4, @@ -191,6 +192,97 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev) return qdev_get_gpio_in(a->intc.gic, sc->irqmap[dev]); } +static uint64_t aspeed_ram_capacity_read(void *opaque, hwaddr addr, +unsigned int +size) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: read @%" PRIx64 " out of ram size\n", + __func__, addr); +return 0; +} + +static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data, +unsigned int size) { +AspeedSoCState *s = ASPEED_SOC(opaque); +uint32_t test_pattern = 0xdeadbeef; +bool invalid_pattern = true; +uint32_t *ram_ptr; +int sz; + +ram_ptr = memory_region_get_ram_ptr(s->dram_mr); + + /* +* Emulate ddr capacity hardware behavior. +* If writes the test_pattern to address which is beyond the ram size, +* it would write the test_pattern to address 0. +*/ +for (sz = 4; sz > 0 ; sz--) { +test_pattern = (test_pattern << 4) + sz; +if (data == test_pattern) { +ram_ptr[0] = test_pattern; +invalid_pattern = false; +break; +} +} + +if (invalid_pattern) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: write invalid pattern @%" PRIx64 + " to addr @%" HWADDR_PRIx "]\n", + __func__, data, addr); +} +} I would simplify with write transaction on the DRAM memory region of the SoC. For that, initialize a 'dram_as' on top of 'dram_mr' in aspeed_soc_ast2700_dram_init(): address_space_init(>dram_as, s->dram_mr, "dram"); Then, in aspeed_ram_capacity_write(), add : address_space_write(>dram_as, addr % ram_size, MEMTXATTRS_UNSPECIFIED, , size); and check returned error. It should be enough to detect the RAM size from FW. Thanks, C. Thanks for your suggestion and review. I changed to use address space APIs to write DRAM memory region(s->dram_mr). I have a question about aspeed_ram_capacity_write function implementation. Could you tell me which solution you prefer? Do you want to use solution 1? I prefer solution 1 because no assumption is made on what software does. It simply implements the wraparound HW does on RAM accesses. Thanks, C. Thanks-Jamin Solution 1: static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { AspeedSoCState *s = ASPEED_SOC(opaque); ram_addr_t ram_size; MemTxResult result; ram_size = object_property_get_uint(OBJECT(>sdmc), "ram-size", _abort); /* * Emulate ddr capacity hardware behavior. * If writes the data to the address which is beyond the ram size, * it would write the data to the "address % ram_size". */ result = address_space_write(>dram_as, addr % ram_size, MEMTXATTRS_UNSPECIFIED, , 4); if (result != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM write failed, addr:0x%" HWADDR_PRIx ", data :0x%" PRIx64 "\n&quo
Re: [RFC PATCH 08/10] ppc/pnv: Invert the design for big-core machine modelling
@@ -157,6 +157,14 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) pnv_cc->processor_id(chip, pc->hwid, 0, , ); +/* Only one DT node per (big) core */ +if (tir != 0) { +g_assert(pc->big_core); +g_assert(tir == 1); +g_assert(pc->hwid & 1); +return -1; return is -1 but it's not an error. right ? Not an error just a "no CPU node to insert". It's a bit ugly. Could return bool for yes/no and take a *offset maybe? or we could pass the pa_features array ? +if (machine->smp.threads > 8) { +error_report("Cannot support more than 8 threads/core " + "on a powernv9/10 machine"); +exit(1); +} +if (machine->smp.threads % 2 == 1) { is_power_of_2() It does have that check later in pnv_init(), but I wanted to be careful that we're dividing by 2 below I think it makes it more obvious (and big-core can't have 1 thread per big core). ok @@ -1099,6 +1157,8 @@ static void pnv_power9_init(MachineState *machine) static void pnv_power10_init(MachineState *machine) { +PnvMachineState *pnv = PNV_MACHINE(machine); +pnv->big_core_tbst_quirk = true; pnv_power9_init(machine); } @@ -1169,9 +1229,15 @@ static void pnv_processor_id_p9(PnvChip *chip, uint32_t core_id, uint32_t thread_id, uint32_t *pir, uint32_t *tir) { -if (chip->nr_threads == 8) { -*pir = (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) | - (thread_id >> 1); +PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); arg. We should avoid these qdev_get_machine() calls. Could big_core be a chip property instead ? We could, but per machine probably makes more sense. It's funny there seems to be no good way to get machine from CPU. Maybe we can just add a machine pointer in PnvChip? It would be easier/cleaner to propagate the machine settings to the chip unit and subunits. If I remember correctly, real HW has a scan init sequence doing something similar. I'l probably leave that for another series and try to convert most things. +static bool pnv_machine_get_hb(Object *obj, Error **errp) +{ +PnvMachineState *pnv = PNV_MACHINE(obj); + +return !!pnv->fw_load_addr; +} + +static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) +{ +PnvMachineState *pnv = PNV_MACHINE(obj); + +if (value) { +pnv->fw_load_addr = 0x800; +} +} we might want to get rid of the hostboot mode oneday. This was really experimental stuff. Okay sure, I don't use it. Although we may want to run the open source hostboot part of the firmware on QEMU one day, we can always add back some options for it. It's not invasive either. Let's keep it. It use to work with a trimdown Linux image. Thanks, C. We do have a PowerVM mode too which tweaks a few things, but that's no use for upstream. diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 059d372c8a..05195527a5 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c This change should come in another patch preferably Yeah this might have got into the wrong patch. Thanks, Nick
Re: [PATCH v4 02/11] ppc/pseries: Add Power11 cpu type
On 5/30/24 09:06, Harsh Prateek Bora wrote: On 5/28/24 12:35, Aditya Gupta wrote: Add sPAPR CPU Core definition for Power11 Cc: David Gibson (reviewer:sPAPR (pseries)) Cc: Harsh Prateek Bora (reviewer:sPAPR (pseries)) Cc: Cédric Le Goater Cc: Daniel Henrique Barboza Cc: Frédéric Barrat Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- docs/system/ppc/pseries.rst | 6 +++--- hw/ppc/spapr_cpu_core.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index a876d897b6e4..3277564b34c2 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -15,9 +15,9 @@ Supported devices = * Multi processor support for many Power processors generations: POWER7, - POWER7+, POWER8, POWER8NVL, POWER9, and Power10. Support for POWER5+ exists, - but its state is unknown. - * Interrupt Controller, XICS (POWER8) and XIVE (POWER9 and Power10) + POWER7+, POWER8, POWER8NVL, POWER9, Power10 and Power11. Support for POWER5+ + exists, but its state is unknown. + * Interrupt Controller, XICS (POWER8) and XIVE (POWER9, Power10, Power11) I think it would look more cleaner to rephrase as below: * Multi processor support for many Power processors generations: - POWER7, POWER7+ - POWER8, POWER8NVL - POWER9 - Power10 - Power11. - Support for POWER5+ exists, but its state is unknown. $ /usr/bin/qemu-system-ppc64 -version QEMU emulator version 8.1.3 (qemu-8.1.3-5.fc39) Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers With the correct kernel/userspace, it runs : # uname -a Linux buildroot 6.6.3 #1 SMP Fri Jan 5 00:00:45 CET 2024 ppc64 GNU/Linux # cat /proc/cpuinfo processor : 0 cpu : POWER5+ (gs) clock : 1000.00MHz revision: 2.1 (pvr 003b 0201) timebase: 51200 platform: pSeries model : IBM pSeries (emulated by qemu) machine : CHRP IBM pSeries (emulated by qemu) MMU : Hash Thanks, C. * Interrupt Controller - XICS (POWER8) - XIVE (Supported by below:) - POWER9 - Power10 - Power11 So, that every next platform just need to add one line for itself. With that, Reviewed-by: Harsh Prateek Bora Thanks Harsh * vPHB PCIe Host bridge. * vscsi and vnet devices, compatible with the same devices available on a PowerVM hypervisor with VIOS managing LPARs. diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index e7c9edd033c8..62416b7e0a7e 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -401,6 +401,7 @@ static const TypeInfo spapr_cpu_core_type_infos[] = { DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"), DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"), DEFINE_SPAPR_CPU_CORE_TYPE("power10_v2.0"), + DEFINE_SPAPR_CPU_CORE_TYPE("power11_v2.0"), #ifdef CONFIG_KVM DEFINE_SPAPR_CPU_CORE_TYPE("host"), #endif
Re: [PATCH v4 11/11] ppc/pnv: Update skiboot.lid to support Power11
On 5/30/24 08:41, Aditya Gupta wrote: Hello Cedric, On Tue, May 28, 2024 at 09:15:29AM GMT, Cédric Le Goater wrote: On 5/28/24 09:05, Aditya Gupta wrote: Skiboot/OPAL patches are in discussion upstream [1], with corresponding commits in github repository [2]. Update skiboot.lid, with binary built from 'upstream_power11' branch of skiboot repository with Power11 enablement patches [2]. --- This patch can be skipped for now, if need to wait for patches to be merged in open-power/skiboot. Have updated the skiboot.lid to aid in testing this patch series. When is the merge in skiboot planned ? QEMU 9.1 freeze is in ~2 months. I have asked, will let you know when I get the expected time. The typical flow would to be merge a new skiboot.lid with Power11 first, than this series. Thanks, C. [1]:https://lists.ozlabs.org/pipermail/skiboot/2024-April/018963.html [2]:https://github.com/maheshsal/skiboot. Cc: Cédric Le Goater Cc: Joel Stanley Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- pc-bios/skiboot.lid | Bin 2527328 -> 2527328 bytes Please don't resend. This is big ! Oh okay. Sure. Thanks, Aditya Gupta Thanks, C.
Re: [RFC PATCH 05/10] ppc/pnv: Extend chip_pir class method to TIR as well
On 5/30/24 08:38, Nicholas Piggin wrote: On Wed May 29, 2024 at 4:30 PM AEST, Cédric Le Goater wrote: On 5/29/24 02:24, Nicholas Piggin wrote: On Tue May 28, 2024 at 6:32 PM AEST, Harsh Prateek Bora wrote: On 5/26/24 17:56, Nicholas Piggin wrote: The chip_pir chip class method allows the platform to set the PIR processor identification register. Extend this to a more general ID function which also allows the TIR to be set. This is in preparation for "big core", which is a more complicated topology of cores and threads. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv_chip.h | 3 +- hw/ppc/pnv.c | 61 --- hw/ppc/pnv_core.c | 10 --- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h index 8589f3291e..679723926a 100644 --- a/include/hw/ppc/pnv_chip.h +++ b/include/hw/ppc/pnv_chip.h @@ -147,7 +147,8 @@ struct PnvChipClass { DeviceRealize parent_realize; -uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id); +void (*processor_id)(PnvChip *chip, uint32_t core_id, uint32_t thread_id, + uint32_t *pir, uint32_t *tir); Should it be named get_chip_core_thread_regs() ? Yeah, the name isn't great. It is getting the regs, but the regs are the "pervasive id" used as well... but maybe that's not too relevant here. What about we drop chip_ since we have the chip and no other methods use such prefix, then call it get_thread_pir_tir()? processor relates to chip and so, processor_id() is not great indeed. get_pir_tir() would be enough I think. What would be good though, since pnv is growing, is to start adding documentation to these common helpers. Okay we'll use that name. You mean just a comment them in the header? Might as well do that for new ones at least. Yes. All class handlers should have a minimal description. Thanks, C.
Re: [PATCH v7 1/9] vfio: Add Error** argument to .set_dirty_page_tracking() handler
On 5/29/24 08:26, Markus Armbruster wrote: I had a look at this before I realized it's already in. I'm sending this out not to demand any change, but only to point out an issue to be avoided in future work. Cédric Le Goater writes: We will use the Error object to improve error reporting in the .log_global*() handlers of VFIO. Add documentation while at it. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Avihai Horon Reviewed-by: Eric Auger Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-container-base.h | 18 -- hw/vfio/common.c | 4 ++-- hw/vfio/container-base.c | 4 ++-- hw/vfio/container.c | 6 +++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h index 3582d5f97a37877b2adfc0d0b06996c82403f8b7..326ceea52a2030eec9dad289a9845866c4a8c090 100644 --- a/include/hw/vfio/vfio-container-base.h +++ b/include/hw/vfio/vfio-container-base.h @@ -82,7 +82,7 @@ int vfio_container_add_section_window(VFIOContainerBase *bcontainer, void vfio_container_del_section_window(VFIOContainerBase *bcontainer, MemoryRegionSection *section); int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start); + bool start, Error **errp); int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, VFIOBitmap *vbmap, hwaddr iova, hwaddr size); @@ -121,9 +121,23 @@ struct VFIOIOMMUClass { int (*attach_device)(const char *name, VFIODevice *vbasedev, AddressSpace *as, Error **errp); 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); + bool start, Error **errp); Note for later: this is always called via vfio_container_set_dirty_page_tracking(). int (*query_dirty_bitmap)(const VFIOContainerBase *bcontainer, VFIOBitmap *vbmap, hwaddr iova, hwaddr size); diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 8f9cbdc0264044ce587877a7d19d14b28527291b..485e53916491f1164d29e739fb7106c0c77df737 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1076,7 +1076,7 @@ static bool vfio_listener_log_global_start(MemoryListener *listener, if (vfio_devices_all_device_dirty_tracking(bcontainer)) { ret = vfio_devices_dma_logging_start(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, true); +ret = vfio_container_set_dirty_page_tracking(bcontainer, true, NULL); } if (ret) { @@ -1096,7 +1096,7 @@ static void vfio_listener_log_global_stop(MemoryListener *listener) if (vfio_devices_all_device_dirty_tracking(bcontainer)) { vfio_devices_dma_logging_stop(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, false); +ret = vfio_container_set_dirty_page_tracking(bcontainer, false, NULL); } if (ret) { Note for later: all callers pass NULL to ignore the new Error. diff --git a/hw/vfio/container-base.c b/hw/vfio/container-base.c index 913ae49077c4f09b7b27517c1231cfbe4befb7fb..7c0764121d24b02b6c4e66e368d7dff78a6d65aa 100644 --- a/hw/vfio/container-base.c +++ b/hw/vfio/container-base.c @@ -53,14 +53,14 @@ void vfio_container_del_section_window(VFIOContainerBase *bcontainer, } int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start) + bool start, Error **errp) { if (!bcontainer->dirty_pages_supported) { return 0; } g_assert(bcontainer->ops->set_dirty_page_tracking); -return bcontainer->ops->set_dirty_page_tracking(bcontainer, start); +return bcontainer->ops->set_dirty_page_tracking(bcontainer, start, errp); } int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 77bdec276ec49cb9cd767c0de42ec801b4421572..c35221fbe7dc5453050f97cd186fc958e24f28f7 100644 ---
Re: [PATCH v4 14/16] aspeed/soc: fix incorrect dram size for AST2700
Hello Jamin On 5/27/24 10:02, Jamin Lin wrote: AST2700 dram size calculation is not back compatible AST2600. According to the DDR capacity hardware behavior, if users write the data to address which is beyond the ram size, it would write the data to address 0. For example: a. sdram base address "0x4 " b. sdram size is 1 GiB The available address range is from "0x4 " to "0x4 4000". If users write 0xdeadbeef to address "0x6 ", the value of DRAM address 0 (base address 0x4 ) should be 0xdeadbeef. Add aspeed_soc_ast2700_dram_init to calculate the dram size and add memory I/O whose address range is from max_ram_size - ram_size to max_ram_size and its read/write handler to emulate DDR capacity hardware behavior. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed_ast27x0.c | 94 - include/hw/arm/aspeed_soc.h | 1 + 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index a3a03fc1ca..19380087fa 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -20,6 +20,7 @@ #include "sysemu/sysemu.h" #include "hw/intc/arm_gicv3.h" #include "qapi/qmp/qlist.h" +#include "qemu/log.h" static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_SPI_BOOT] = 0x4, @@ -191,6 +192,97 @@ static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev) return qdev_get_gpio_in(a->intc.gic, sc->irqmap[dev]); } +static uint64_t aspeed_ram_capacity_read(void *opaque, hwaddr addr, +unsigned int size) +{ +qemu_log_mask(LOG_GUEST_ERROR, + "%s: read @%" PRIx64 " out of ram size\n", + __func__, addr); +return 0; +} + +static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data, +unsigned int size) +{ +AspeedSoCState *s = ASPEED_SOC(opaque); +uint32_t test_pattern = 0xdeadbeef; +bool invalid_pattern = true; +uint32_t *ram_ptr; +int sz; + +ram_ptr = memory_region_get_ram_ptr(s->dram_mr); + + /* +* Emulate ddr capacity hardware behavior. +* If writes the test_pattern to address which is beyond the ram size, +* it would write the test_pattern to address 0. +*/ +for (sz = 4; sz > 0 ; sz--) { +test_pattern = (test_pattern << 4) + sz; +if (data == test_pattern) { +ram_ptr[0] = test_pattern; +invalid_pattern = false; +break; +} +} + +if (invalid_pattern) { +qemu_log_mask(LOG_GUEST_ERROR, + "%s: write invalid pattern @%" PRIx64 + " to addr @%" HWADDR_PRIx "]\n", + __func__, data, addr); +} +} I would simplify with write transaction on the DRAM memory region of the SoC. For that, initialize a 'dram_as' on top of 'dram_mr' in aspeed_soc_ast2700_dram_init(): address_space_init(>dram_as, s->dram_mr, "dram"); Then, in aspeed_ram_capacity_write(), add : address_space_write(>dram_as, addr % ram_size, MEMTXATTRS_UNSPECIFIED, , size); and check returned error. It should be enough to detect the RAM size from FW. Thanks, C. +static const MemoryRegionOps aspeed_ram_capacity_ops = { +.read = aspeed_ram_capacity_read, +.write = aspeed_ram_capacity_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 1, +.max_access_size = 8, +}, +}; + +/* + * SDMC should be realized first to get correct RAM size and max size + * values + */ +static bool aspeed_soc_ast2700_dram_init(DeviceState *dev, Error **errp) +{ +ram_addr_t ram_size, max_ram_size; +Aspeed27x0SoCState *a = ASPEED27X0_SOC(dev); +AspeedSoCState *s = ASPEED_SOC(dev); +AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + +ram_size = object_property_get_uint(OBJECT(>sdmc), "ram-size", +_abort); +max_ram_size = object_property_get_uint(OBJECT(>sdmc), "max-ram-size", +_abort); + +memory_region_init(>dram_container, OBJECT(s), "ram-container", + ram_size); +memory_region_add_subregion(>dram_container, 0, s->dram_mr); + +/* + * Add a memory region beyond the RAM region to emulate + * ddr capacity hardware behavior. + */ +if (ram_size < max_ram_size) { +memory_region_init_io(>dram_empty, OBJECT(s), + _ram_capacity_ops, s, + "ram-empty", max_ram_size - ram_size); + +memory_region_add_subregion(s->memory, +sc->memmap[ASPEED_DEV_SDRAM] + ram_size, +>dram_empty); +} + +memory_region_add_subregion(s->memory, +
Re: [RFC PATCH 10/10] ppc/pnv: Add an LPAR per core machine option
On 5/26/24 14:26, Nicholas Piggin wrote: Recent POWER CPUs can operate in "LPAR per core" or "LPAR per thread" modes. In per-core mode, some SPRs and IPI doorbells are shared between threads in a core. In per-thread mode, supervisor and user state is not shared between threads. OpenPOWER systems use LPAR per thread mode as it is required for KVM. Enterprise systems use LPAR per core mode, as they partition the machine by core. Implement a lpar-per-core machine option for powernv machines. This is supported on POWER9 and POWER10. Signed-off-by: Nicholas Piggin LGTM, Reviewed-by: Cédric Le Goater Thanks, C. --- include/hw/ppc/pnv.h | 1 + include/hw/ppc/pnv_core.h | 1 + hw/ppc/pnv.c | 29 + hw/ppc/pnv_core.c | 8 target/ppc/cpu_init.c | 3 ++- 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index bec603f1a8..8f75c715d8 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -103,6 +103,7 @@ struct PnvMachineState { bool big_core; bool big_core_tbst_quirk; +bool lpar_per_core; }; PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id); diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 9599da15ea..e41b6347ea 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -57,6 +57,7 @@ struct PnvCore { /*< public >*/ PowerPCCPU **threads; bool big_core; +bool lpar_per_core; uint32_t pir; uint32_t hwid; uint64_t hrmor; diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 765142965f..0d830ad731 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1108,12 +1108,17 @@ static void pnv_init(MachineState *machine) static void pnv_power8_init(MachineState *machine) { +PnvMachineState *pnv = PNV_MACHINE(machine); + if (machine->smp.threads > 8) { error_report("Cannot support more than 8 threads/core " "on a powernv POWER8 machine"); exit(1); } +/* POWER8 is always lpar-per-core. */ +pnv->lpar_per_core = true; + pnv_init(machine); } @@ -2541,6 +2546,18 @@ static void pnv_machine_set_big_core(Object *obj, bool value, Error **errp) pnv->big_core = value; } +static bool pnv_machine_get_1lpar(Object *obj, Error **errp) +{ +PnvMachineState *pnv = PNV_MACHINE(obj); +return pnv->lpar_per_core; +} + +static void pnv_machine_set_1lpar(Object *obj, bool value, Error **errp) +{ +PnvMachineState *pnv = PNV_MACHINE(obj); +pnv->lpar_per_core = value; +} + static bool pnv_machine_get_hb(Object *obj, Error **errp) { PnvMachineState *pnv = PNV_MACHINE(obj); @@ -2614,6 +2631,12 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) pnv_machine_set_big_core); object_class_property_set_description(oc, "big-core", "Use big-core (aka fused-core) mode"); + +object_class_property_add_bool(oc, "lpar-per-core", + pnv_machine_get_1lpar, + pnv_machine_set_1lpar); +object_class_property_set_description(oc, "lpar-per-core", + "Use 1 LPAR per core mode"); } static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data) @@ -2660,6 +2683,12 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) pnv_machine_set_big_core); object_class_property_set_description(oc, "big-core", "Use big-core (aka fused-core) mode"); + +object_class_property_add_bool(oc, "lpar-per-core", + pnv_machine_get_1lpar, + pnv_machine_set_1lpar); +object_class_property_set_description(oc, "lpar-per-core", + "Use 1 LPAR per core mode"); } static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data) diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 835c35d90b..e510909db1 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -207,6 +207,9 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, val |= PPC_BIT(56 + i); } } +if (pc->lpar_per_core) { +val |= PPC_BIT(62); +} break; case PNV10_XSCOM_EC_CORE_THREAD_INFO: break; @@ -322,6 +325,11 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, env->core_index = core_hwid; } +if (pnv->lpar_per_core) { +pc->lpar_per_core = true; +cp
Re: [RFC PATCH 09/10] ppc/pnv: Implement POWER10 PC xscom registers for direct controls
On 5/26/24 14:26, Nicholas Piggin wrote: The PC unit in the processor core contains xscom registers that provide low level status and control of the CPU. This implements "direct controls" sufficient for OPAL (skiboot) firmware use, which is to stop threads and send them non-maskable IPIs in the form of SRESET interrupts. POWER10 is sufficiently different (particularly QME and special wakeup) from POWER9 that it is not trivial to implement by reusing the code. Signed-off-by: Nicholas Piggin --- include/hw/core/cpu.h | 8 include/hw/ppc/pnv.h | 2 + include/hw/ppc/pnv_core.h | 3 ++ hw/ppc/pnv.c | 7 +++- hw/ppc/pnv_core.c | 88 --- system/cpus.c | 10 + 6 files changed, 112 insertions(+), 6 deletions(-) diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index bb398e8237..52a8fc65cb 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -974,6 +974,14 @@ void cpu_reset_interrupt(CPUState *cpu, int mask); */ void cpu_exit(CPUState *cpu); +/** + * cpu_pause: + * @cpu: The CPU to pause. + * + * Resumes CPU, i.e. puts CPU into stopped state. + */ +void cpu_pause(CPUState *cpu); + /** * cpu_resume: * @cpu: The CPU to resume. diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 93ecb062b4..bec603f1a8 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -111,6 +111,8 @@ PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb); #define PNV_FDT_ADDR 0x0100 #define PNV_TIMEBASE_FREQ 51200ULL +void pnv_cpu_do_nmi(CPUState *cs); + /* * BMC helpers */ diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 39f8f33e6c..9599da15ea 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -109,6 +109,9 @@ OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD) struct PnvQuad { DeviceState parent_obj; +bool special_wakeup_done; +bool special_wakeup[4]; + uint32_t quad_id; MemoryRegion xscom_regs; MemoryRegion xscom_qme_regs; diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 5364c55bbb..765142965f 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -2700,12 +2700,17 @@ static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) } } +void pnv_cpu_do_nmi(CPUState *cs) +{ +async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); +} + static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) { CPUState *cs; CPU_FOREACH(cs) { -async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); +pnv_cpu_do_nmi(cs); } } What about ? https://lore.kernel.org/qemu-devel/20240424093048.180966-1-...@redhat.com/ Thanks, C. diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 10417d92ae..835c35d90b 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -184,16 +184,40 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = { */ #define PNV10_XSCOM_EC_CORE_THREAD_STATE0x412 +#define PNV10_XSCOM_EC_CORE_THREAD_INFO 0x413 +#define PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS 0x449 +#define PNV10_XSCOM_EC_CORE_RAS_STATUS 0x454 static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, unsigned int width) { +PnvCore *pc = PNV_CORE(opaque); +int nr_threads = CPU_CORE(pc)->nr_threads; +int i; uint32_t offset = addr >> 3; uint64_t val = 0; switch (offset) { case PNV10_XSCOM_EC_CORE_THREAD_STATE: -val = 0; +for (i = 0; i < nr_threads; i++) { +PowerPCCPU *cpu = pc->threads[i]; +CPUState *cs = CPU(cpu); + +if (cs->halted) { +val |= PPC_BIT(56 + i); +} +} +break; +case PNV10_XSCOM_EC_CORE_THREAD_INFO: +break; +case PNV10_XSCOM_EC_CORE_RAS_STATUS: +for (i = 0; i < nr_threads; i++) { +PowerPCCPU *cpu = pc->threads[i]; +CPUState *cs = CPU(cpu); +if (cs->stopped) { +val |= PPC_BIT(0 + 8*i) | PPC_BIT(1 + 8*i); +} +} break; default: qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, @@ -206,9 +230,45 @@ static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned int width) { +PnvCore *pc = PNV_CORE(opaque); +int nr_threads = CPU_CORE(pc)->nr_threads; +int i; uint32_t offset = addr >> 3; switch (offset) { +case PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS: +for (i = 0; i < nr_threads; i++) { +PowerPCCPU *cpu = pc->threads[i]; +CPUState *cs = CPU(cpu); + +if (val & PPC_BIT(7 + 8*i)) { /* stop */ +val &= ~PPC_BIT(7 + 8*i); +
Re: [RFC PATCH 08/10] ppc/pnv: Invert the design for big-core machine modelling
On 5/26/24 14:26, Nicholas Piggin wrote: POWER9 and POWER10 machines come in two variants, "big-core" and "small-core". Big core machines are SMT8 from the software point of view, but in the low level platform topology ("xscom registers and pervasive addressing"), these look more like a pair of small cores ganged together. Presently, the way this is modelled is to create an SMT8 PnvCore and add special cases to xscom and pervasive for big-core mode. This is becoming too complicated to manage as more of the machine is modelled. The better approach looks like the inverse, which is creating 2xPnvCore ganging them together to look like an SMT8 core in TCG. The TCG SMT code is quite simple to do that, and then the xscom and pervasive modelling does not need to differentiate big and small core modes for the most part. device-tree building does need a special case to only build one CPU node for each big-core because that's what the firmware expects. And so does a special case workaround in the ChipTOD model. A big-core machine option is added for powernv9 and 10 machines. That's another patch. It is difficult to follow all the changes. I think this patch needs further splitting. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv.h | 3 + include/hw/ppc/pnv_core.h| 8 ++ target/ppc/cpu.h | 4 +- hw/ppc/pnv.c | 183 --- hw/ppc/pnv_core.c| 20 +++- hw/ppc/spapr_cpu_core.c | 6 +- target/ppc/misc_helper.c | 6 +- target/ppc/timebase_helper.c | 9 ++ 8 files changed, 197 insertions(+), 42 deletions(-) diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 476b136146..93ecb062b4 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -100,6 +100,9 @@ struct PnvMachineState { PnvPnor *pnor; hwaddr fw_load_addr; + +bool big_core; +bool big_core_tbst_quirk; I think the quirk should be introduced in its own patch. }; PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id); diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 21297262c1..39f8f33e6c 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -27,6 +27,13 @@ /* ChipTOD and TimeBase State Machine */ struct pnv_tod_tbst { +/* + * POWER10 DD2.0 - big core TFMR drives the state machine on the even + * small core. Skiboot has a workaround that targets the even small core + * for CHIPTOD_TO_TB ops. + */ +bool big_core_quirk; + int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */ int tod_sent_to_tb; /* chiptod sent TOD to the core TB */ @@ -49,6 +56,7 @@ struct PnvCore { /*< public >*/ PowerPCCPU **threads; +bool big_core; uint32_t pir; uint32_t hwid; uint64_t hrmor; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 8fd6ade471..de15e38af8 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1248,6 +1248,7 @@ struct CPUArchState { int access_type; /* For SMT processors */ +int has_smt_siblings; int core_index; #if !defined(CONFIG_USER_ONLY) @@ -1276,7 +1277,6 @@ struct CPUArchState { uint32_t tlb_need_flush; /* Delayed flush needed */ #define TLB_NEED_LOCAL_FLUSH 0x1 #define TLB_NEED_GLOBAL_FLUSH 0x2 - #endif /* Other registers */ @@ -1407,7 +1407,7 @@ struct CPUArchState { }; #define PPC_CPU_HAS_CORE_SIBLINGS(cs) \ -(cs->nr_threads > 1) +(POWERPC_CPU(cs)->env.has_smt_siblings) #define PPC_CPU_HAS_LPAR_SIBLINGS(cs) \ ((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) && \ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 7d062ec16c..5364c55bbb 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -142,7 +142,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) CPUPPCState *env = >env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip); -g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); +uint32_t *servers_prop; int i; uint32_t pir, tir; uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), @@ -157,6 +157,14 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) pnv_cc->processor_id(chip, pc->hwid, 0, , ); +/* Only one DT node per (big) core */ +if (tir != 0) { +g_assert(pc->big_core); +g_assert(tir == 1); +g_assert(pc->hwid & 1); +return -1; return is -1 but it's not an error. right ? +} + nodename = g_strdup_printf("%s@%x", dc->fw_name, pir); offset = fdt_add_subnode(fdt, cpus_offset, nodename); _FDT(offset); @@ -236,12 +244,28 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) } /* Build interrupt servers properties */ -for (i = 0; i <
Re: [RFC PATCH 07/10] target/ppc: Add helpers to check for SMT sibling threads
On 5/26/24 14:26, Nicholas Piggin wrote: Add helpers for TCG code to determine if there are SMT siblings sharing per-core and per-lpar registers. This simplifies the callers and makes SMT register topology simpler to modify with later changes. Signed-off-by: Nicholas Piggin --- target/ppc/cpu.h | 7 +++ target/ppc/cpu_init.c| 2 +- target/ppc/excp_helper.c | 16 +++- target/ppc/misc_helper.c | 27 ++- target/ppc/timebase_helper.c | 20 +++- 5 files changed, 28 insertions(+), 44 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 9a89083932..8fd6ade471 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1406,6 +1406,13 @@ struct CPUArchState { uint64_t pmu_base_time; }; +#define PPC_CPU_HAS_CORE_SIBLINGS(cs) \ +(cs->nr_threads > 1) (cs)->nr_threads + +#define PPC_CPU_HAS_LPAR_SIBLINGS(cs) \ +((POWERPC_CPU(cs)->env.flags & POWERPC_FLAG_SMT_1LPAR) && \ + PPC_CPU_HAS_CORE_SIBLINGS(cs)) + I tend to prefer static inline when things get complex. The rest looks good. Thanks, C. #define _CORE_ID(cs)\ (POWERPC_CPU(cs)->env.core_index) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index ae483e20c4..e71ee008ed 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6975,7 +6975,7 @@ static void ppc_cpu_realize(DeviceState *dev, Error **errp) pcc->parent_realize(dev, errp); -if (env_cpu(env)->nr_threads > 1) { +if (PPC_CPU_HAS_CORE_SIBLINGS(cs)) { env->flags |= POWERPC_FLAG_SMT; } diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 0cd542675f..fd45da0f2b 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -3029,7 +3029,7 @@ void helper_book3s_msgsnd(CPUPPCState *env, target_ulong rb) brdcast = true; } -if (cs->nr_threads == 1 || !brdcast) { +if (!PPC_CPU_HAS_CORE_SIBLINGS(cs) || !brdcast) { ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1); return; } @@ -3067,21 +3067,19 @@ void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb) CPUState *cs = env_cpu(env); PowerPCCPU *cpu = env_archcpu(env); CPUState *ccs; -uint32_t nr_threads = cs->nr_threads; int ttir = rb & PPC_BITMASK(57, 63); helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP); -if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { -nr_threads = 1; /* msgsndp behaves as 1-thread in LPAR-per-thread mode*/ -} - -if (!dbell_type_server(rb) || ttir >= nr_threads) { +if (!dbell_type_server(rb)) { return; } -if (nr_threads == 1) { -ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1); +/* msgsndp behaves as 1-thread in LPAR-per-thread mode*/ +if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) { +if (ttir == 0) { +ppc_set_irq(cpu, PPC_INTERRUPT_DOORBELL, 1); +} return; } diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index 46ba3a5584..598c956cdd 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -49,9 +49,8 @@ void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn, { CPUState *cs = env_cpu(env); CPUState *ccs; -uint32_t nr_threads = cs->nr_threads; -if (nr_threads == 1) { +if (!PPC_CPU_HAS_CORE_SIBLINGS(cs)) { env->spr[sprn] = val; return; } @@ -196,7 +195,7 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val) return; } -if (cs->nr_threads == 1 || !(env->flags & POWERPC_FLAG_SMT_1LPAR)) { +if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) { env->spr[SPR_PTCR] = val; tlb_flush(cs); } else { @@ -243,16 +242,12 @@ target_ulong helper_load_dpdes(CPUPPCState *env) { CPUState *cs = env_cpu(env); CPUState *ccs; -uint32_t nr_threads = cs->nr_threads; target_ulong dpdes = 0; helper_hfscr_facility_check(env, HFSCR_MSGP, "load DPDES", HFSCR_IC_MSGP); -if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { -nr_threads = 1; /* DPDES behaves as 1-thread in LPAR-per-thread mode */ -} - -if (nr_threads == 1) { +/* DPDES behaves as 1-thread in LPAR-per-thread mode */ +if (!PPC_CPU_HAS_LPAR_SIBLINGS(cs)) { if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) { dpdes = 1; } @@ -279,21 +274,11 @@ void helper_store_dpdes(CPUPPCState *env, target_ulong val) PowerPCCPU *cpu = env_archcpu(env); CPUState *cs = env_cpu(env); CPUState *ccs; -uint32_t nr_threads = cs->nr_threads; helper_hfscr_facility_check(env, HFSCR_MSGP, "store DPDES", HFSCR_IC_MSGP); -if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { -nr_threads =
Re: [RFC PATCH 05/10] ppc/pnv: Extend chip_pir class method to TIR as well
On 5/29/24 02:24, Nicholas Piggin wrote: On Tue May 28, 2024 at 6:32 PM AEST, Harsh Prateek Bora wrote: On 5/26/24 17:56, Nicholas Piggin wrote: The chip_pir chip class method allows the platform to set the PIR processor identification register. Extend this to a more general ID function which also allows the TIR to be set. This is in preparation for "big core", which is a more complicated topology of cores and threads. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv_chip.h | 3 +- hw/ppc/pnv.c | 61 --- hw/ppc/pnv_core.c | 10 --- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/include/hw/ppc/pnv_chip.h b/include/hw/ppc/pnv_chip.h index 8589f3291e..679723926a 100644 --- a/include/hw/ppc/pnv_chip.h +++ b/include/hw/ppc/pnv_chip.h @@ -147,7 +147,8 @@ struct PnvChipClass { DeviceRealize parent_realize; -uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id); +void (*processor_id)(PnvChip *chip, uint32_t core_id, uint32_t thread_id, + uint32_t *pir, uint32_t *tir); Should it be named get_chip_core_thread_regs() ? Yeah, the name isn't great. It is getting the regs, but the regs are the "pervasive id" used as well... but maybe that's not too relevant here. What about we drop chip_ since we have the chip and no other methods use such prefix, then call it get_thread_pir_tir()? processor relates to chip and so, processor_id() is not great indeed. get_pir_tir() would be enough I think. What would be good though, since pnv is growing, is to start adding documentation to these common helpers. Thanks, C. @@ -155,7 +155,7 @@ static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) char *nodename; int cpus_offset = get_cpus_node(fdt); -pir = pnv_cc->chip_pir(chip, pc->hwid, 0); +pnv_cc->processor_id(chip, pc->hwid, 0, , ); As a generic helper API and potentially expandable, it should allow passing NULL for registers whose values are not really sought to avoid having to create un-necessary local variables by the caller. I'll do that. Thanks, Nick
Re: [PATCH v4 00/16] Add AST2700 support
On 5/28/24 12:02, Jamin Lin wrote: Hi Cedric, -Original Message- From: Cédric Le Goater Sent: Tuesday, May 28, 2024 5:56 PM To: Jamin Lin ; Peter Maydell ; Andrew Jeffery ; Joel Stanley ; Alistair Francis ; Cleber Rosa ; Philippe Mathieu-Daudé ; Wainer dos Santos Moschetta ; Beraldo Leal ; open list:ASPEED BMCs ; open list:All patches CC here Cc: Troy Lee ; Yunlin Tang Subject: Re: [PATCH v4 00/16] Add AST2700 support Jamin, I think you should add your self as a Reviewer to the ASPEED BMCs machine in the MAINTAINERS files. Would you agree ? Agree. Could you please add me, Troy and Steven in the MAINTAINERS files? steven_...@aspeedtech.com troy_...@aspeedtech.com jamin_...@aspeedtech.com You should send a patch updating the MAINTAINERS file with new names and those promoted should reply that they agree, or not. See https://qemu.readthedocs.io/en/v9.0.0/devel/maintainers.html for more info and the git history of MAINTAINERS also. Thanks, C.
Re: [PATCH v4 00/16] Add AST2700 support
Jamin, I think you should add your self as a Reviewer to the ASPEED BMCs machine in the MAINTAINERS files. Would you agree ? Thanks, C. On 5/27/24 10:02, Jamin Lin wrote: Changes from v1: The patch series supports WDT, SDMC, SMC, SCU, SLI and INTC for AST2700 SoC. Changes from v2: - replace is_aarch64 with is_bus64bit for sdmc patch review. - fix incorrect dram size for AST2700 Changes from v3: - Add AST2700 Evaluation board in ASPEED document - Add avocado test cases for AST2700 Evaluation board - Fix reviewers review issues and add reviewers suggestions - Implement INTC model GICINT 128 to GICINT136 for AST2700 Changes from v4: - support 64 bits dma dram address associated with review issues - support dma start length and 1 byte length unit associated with review issues - refactor intc model to fix serial console stuck issue and associated with review issues Test Version: https://github.com/qemu/qemu/commit/0c2a3807483b4ebe360cfa475dbfc9dfd2f6d16d Test steps: 1. Download the latest openbmc image for AST2700 from AspeedTech-BMC/openbmc repository, https://github.com/AspeedTech-BMC/openbmc/releases/tag/v09.01 link: https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.01/ast2700-default-obmc.tar.gz 2. untar ast2700-default-obmc.tar.gz ``` tar -xf ast2700-default-obmc.tar.gz ``` 3. Run and the contents of scripts as following IMGDIR=ast2700-default UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin) UBOOT_DTB_ADDR=$((0x4 + ${UBOOT_SIZE})) qemu-system-aarch64 -M ast2700-evb -nographic\ -device loader,addr=0x4,file=${IMGDIR}/u-boot-nodtb.bin,force-raw=on\ -device loader,addr=${UBOOT_DTB_ADDR},file=${IMGDIR}/u-boot.dtb,force-raw=on\ -device loader,addr=0x43000,file=${IMGDIR}/bl31.bin,force-raw=on\ -device loader,addr=0x43008,file=${IMGDIR}/optee/tee-raw.bin,force-raw=on\ -device loader,addr=0x43000,cpu-num=0\ -device loader,addr=0x43000,cpu-num=1\ -device loader,addr=0x43000,cpu-num=2\ -device loader,addr=0x43000,cpu-num=3\ -smp 4\ -drive file=${IMGDIR}/image-bmc,format=raw,if=mtd\ -serial mon:stdio\ -snapshot Jamin Lin (16): aspeed/wdt: Add AST2700 support aspeed/sli: Add AST2700 support aspeed/sdmc: remove redundant macros aspeed/sdmc: fix coding style aspeed/sdmc: Add AST2700 support aspeed/smc: correct device description aspeed/smc: support dma start length and 1 byte length unit aspeed/smc: support 64 bits dma dram address aspeed/smc: Add AST2700 support aspeed/scu: Add AST2700 support aspeed/intc: Add AST2700 support aspeed/soc: Add AST2700 support aspeed: Add an AST2700 eval board aspeed/soc: fix incorrect dram size for AST2700 test/avocado/machine_aspeed.py: Add AST2700 test case docs:aspeed: Add AST2700 Evaluation board docs/system/arm/aspeed.rst | 39 +- hw/arm/aspeed.c | 32 ++ hw/arm/aspeed_ast27x0.c | 655 +++ hw/arm/meson.build | 1 + hw/intc/aspeed_intc.c| 355 + hw/intc/meson.build | 1 + hw/intc/trace-events | 6 + hw/misc/aspeed_scu.c | 306 ++- hw/misc/aspeed_sdmc.c| 216 +- hw/misc/aspeed_sli.c | 177 + hw/misc/meson.build | 3 +- hw/misc/trace-events | 11 + hw/ssi/aspeed_smc.c | 321 ++- hw/ssi/trace-events | 2 +- hw/watchdog/wdt_aspeed.c | 24 ++ include/hw/arm/aspeed_soc.h | 27 +- include/hw/intc/aspeed_intc.h| 46 +++ include/hw/misc/aspeed_scu.h | 47 ++- include/hw/misc/aspeed_sdmc.h| 5 +- include/hw/misc/aspeed_sli.h | 27 ++ include/hw/ssi/aspeed_smc.h | 2 + include/hw/watchdog/wdt_aspeed.h | 3 +- tests/avocado/machine_aspeed.py | 62 +++ 23 files changed, 2312 insertions(+), 56 deletions(-) create mode 100644 hw/arm/aspeed_ast27x0.c create mode 100644 hw/intc/aspeed_intc.c create mode 100644 hw/misc/aspeed_sli.c create mode 100644 include/hw/intc/aspeed_intc.h create mode 100644 include/hw/misc/aspeed_sli.h
Re: [PATCH v4 05/16] aspeed/sdmc: Add AST2700 support
[ ... ] I don't think this is necessary to do so now. Possibly, increase the version number in the vmstate when resending a v5. If I understand your request, do you mean to change as following in this patch? static const VMStateDescription vmstate_aspeed_sdmc = { .name = "aspeed.sdmc", .version_id = 1, ---> Change 2 .minimum_version_id = 1, ---> Change 2 }; yes. Also, all Aspeed models should be addressed and that's beyond the scope of this series. And create a new patch series to update all vmstate version for all ASPEED models? That would be to remove migration support for Aspeed machines. For later. Let's address AST2700 first. Thanks, C.
Re: [PATCH v4 12/16] aspeed/soc: Add AST2700 support
On 5/27/24 10:02, Jamin Lin wrote: Initial definitions for a simple machine using an AST2700 SOC (Cortex-a35 CPU). AST2700 SOC and its interrupt controller are too complex to handle in the common Aspeed SoC framework. We introduce a new ast2700 class with instance_init and realize handlers. AST2700 is a 64 bits quad core cpus and support 8 watchdog. Update maximum ASPEED_CPUS_NUM to 4 and ASPEED_WDTS_NUM to 8. In addition, update AspeedSocState to support scuio, sli, sliio and intc. Add TYPE_ASPEED27X0_SOC machine type. The SDMC controller is unlocked at SPL stage. At present, only supports to emulate booting start from u-boot stage. Set SDMC controller unlocked by default. In INTC, each interrupt of INT 128 to INT 136 combines 32 interrupts. It connect GICINT IRQ GPIO-OUTPUT pins to GIC device with irq 128 to 136. And, if a device irq is 128 to 136, its irq GPIO-OUTPUT pin is connected to GICINT or-gates instead of GIC device. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed_ast27x0.c | 563 hw/arm/meson.build | 1 + include/hw/arm/aspeed_soc.h | 26 +- 3 files changed, 588 insertions(+), 2 deletions(-) create mode 100644 hw/arm/aspeed_ast27x0.c diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c new file mode 100644 index 00..a3a03fc1ca --- /dev/null +++ b/hw/arm/aspeed_ast27x0.c @@ -0,0 +1,563 @@ +/* + * ASPEED SoC 27x0 family + * + * Copyright (C) 2024 ASPEED Technology Inc. + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * Implementation extracted from the AST2600 and adapted for AST27x0. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/misc/unimp.h" +#include "hw/arm/aspeed_soc.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/i2c/aspeed_i2c.h" +#include "net/net.h" +#include "sysemu/sysemu.h" +#include "hw/intc/arm_gicv3.h" +#include "qapi/qmp/qlist.h" + +static const hwaddr aspeed_soc_ast2700_memmap[] = { +[ASPEED_DEV_SPI_BOOT] = 0x4, +[ASPEED_DEV_SRAM] = 0x1000, +[ASPEED_DEV_SDMC] = 0x12C0, +[ASPEED_DEV_SCU] = 0x12C02000, +[ASPEED_DEV_SCUIO] = 0x14C02000, +[ASPEED_DEV_UART0] = 0X14C33000, +[ASPEED_DEV_UART1] = 0X14C33100, +[ASPEED_DEV_UART2] = 0X14C33200, +[ASPEED_DEV_UART3] = 0X14C33300, +[ASPEED_DEV_UART4] = 0X12C1A000, +[ASPEED_DEV_UART5] = 0X14C33400, +[ASPEED_DEV_UART6] = 0X14C33500, +[ASPEED_DEV_UART7] = 0X14C33600, +[ASPEED_DEV_UART8] = 0X14C33700, +[ASPEED_DEV_UART9] = 0X14C33800, +[ASPEED_DEV_UART10]= 0X14C33900, +[ASPEED_DEV_UART11]= 0X14C33A00, +[ASPEED_DEV_UART12]= 0X14C33B00, +[ASPEED_DEV_WDT] = 0x14C37000, +[ASPEED_DEV_VUART] = 0X14C3, +[ASPEED_DEV_FMC] = 0x1400, +[ASPEED_DEV_SPI0] = 0x1401, +[ASPEED_DEV_SPI1] = 0x1402, +[ASPEED_DEV_SPI2] = 0x1403, +[ASPEED_DEV_SDRAM] = 0x4, +[ASPEED_DEV_MII1] = 0x1404, +[ASPEED_DEV_MII2] = 0x14040008, +[ASPEED_DEV_MII3] = 0x14040010, +[ASPEED_DEV_ETH1] = 0x1405, +[ASPEED_DEV_ETH2] = 0x1406, +[ASPEED_DEV_ETH3] = 0x1407, +[ASPEED_DEV_EMMC] = 0x1209, +[ASPEED_DEV_INTC] = 0x1210, +[ASPEED_DEV_SLI] = 0x12C17000, +[ASPEED_DEV_SLIIO] = 0x14C1E000, +[ASPEED_GIC_DIST] = 0x1220, +[ASPEED_GIC_REDIST]= 0x1228, +}; + +#define AST2700_MAX_IRQ 288 + +/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */ +static const int aspeed_soc_ast2700_irqmap[] = { +[ASPEED_DEV_UART0] = 132, +[ASPEED_DEV_UART1] = 132, +[ASPEED_DEV_UART2] = 132, +[ASPEED_DEV_UART3] = 132, +[ASPEED_DEV_UART4] = 8, +[ASPEED_DEV_UART5] = 132, +[ASPEED_DEV_UART6] = 132, +[ASPEED_DEV_UART7] = 132, +[ASPEED_DEV_UART8] = 132, +[ASPEED_DEV_UART9] = 132, +[ASPEED_DEV_UART10]= 132, +[ASPEED_DEV_UART11]= 132, +[ASPEED_DEV_UART12]= 132, +[ASPEED_DEV_FMC] = 131, +[ASPEED_DEV_SDMC] = 0, +[ASPEED_DEV_SCU] = 12, +[ASPEED_DEV_ADC] = 130, +[ASPEED_DEV_XDMA] = 5, +[ASPEED_DEV_EMMC] = 15, +[ASPEED_DEV_GPIO] = 11, +[ASPEED_DEV_GPIO_1_8V] = 130, +[ASPEED_DEV_RTC] = 13, +[ASPEED_DEV_TIMER1]= 16, +[ASPEED_DEV_TIMER2]= 17, +[ASPEED_DEV_TIMER3]= 18, +[ASPEED_DEV_TIMER4]= 19, +[ASPEED_DEV_TIMER5]= 20, +[ASPEED_DEV_TIMER6]= 21, +[ASPEED_DEV_TIMER7]= 22, +[ASPEED_DEV_TIMER8]= 23, +[ASPEED_DEV_WDT] = 131, +[ASPEED_DEV_PWM] = 131, +[ASPEED_DEV_LPC] = 128, +[ASPEED_DEV_IBT]
Re: [PATCH v4 11/16] aspeed/intc: Add AST2700 support
On 5/27/24 10:02, Jamin Lin wrote: AST2700 interrupt controller(INTC) provides hardware interrupt interfaces to interrupt of processors PSP, SSP and TSP. In INTC, each interrupt of INT 128 to INT136 combines 32 interrupts. Introduce a new aspeed_intc class with instance_init and realize handlers. So far, this model only supports GICINT128 to GICINT136. It creates 9 GICINT or-gates to connect 32 interrupts sources from GICINT128 to GICINT136 as IRQ GPIO-OUTPUT pins. Then, this model registers IRQ handler with its IRQ GPIO-INPUT pins which connect to GICINT or-gates. And creates 9 GICINT IRQ GPIO-OUTPUT pins which connect to GIC device with GIC IRQ 128 to 136. If one interrupt source from GICINT128 to GICINT136 set irq, the OR-GATE irq callback function is called and set irq to INTC by OR-GATE GPIO-OUTPUT pins. Then, the INTC irq callback function is called and set irq to GIC by its GICINT IRQ GPIO-OUTPUT pins. Finally, the GIC irq callback function is called and set irq to CPUs and CPUs execute Interrupt Service Routine (ISR). Block diagram of GICINT132: GICINT132 ETH1+---+ +>+0 3| ETH2| 4| +>+1 5| ETH3| 6| +>+219| INTC GIC UART0 | 20|+--+ +>+721|| | +--+ UART1 | 22||orgate0 +> output_pin0+--->+GIC128| +>+823|| || | UART2 | 24||orgate1 +> output_pin1+--->+GIC129| +>+925|| || | UART3 | 26||orgate2 +> output_pin2+--->+GIC130| +->10 27|| || | UART5 | 28||orgate3 +> output_pin3+--->+GIC131| +>+11 29|| || | UART6 | +--->+orgate4 +> output_pin4+--->+GIC132| +>+12 30|| || | UART7 | 31||orgate5 +> output_pin5+--->+GIC133| +>+13 || || | UART8 | OR[0:31] ||orgate6 +> output_pin6+--->+GIC134| -->14 || || | UART9 | ||orgate7 +> output_pin7+--->+GIC135| ->+15 || || | UART10 | ||orgate8 +> output_pin8+--->+GIC136| ->+16 || | +--+ UART11 | |+--+ +>+17 | UART12 | | +->18 | | | | | | | +---+ Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/intc/aspeed_intc.c | 355 ++ hw/intc/meson.build | 1 + hw/intc/trace-events | 6 + include/hw/intc/aspeed_intc.h | 46 + 4 files changed, 408 insertions(+) create mode 100644 hw/intc/aspeed_intc.c create mode 100644 include/hw/intc/aspeed_intc.h diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c new file mode 100644 index 00..cb6111d79c --- /dev/null +++ b/hw/intc/aspeed_intc.c @@ -0,0 +1,355 @@ +/* + * ASPEED INTC Controller + * + * Copyright (C) 2024 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/intc/aspeed_intc.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/intc/arm_gicv3.h" +#include "trace.h" +#include "hw/registerfields.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" + +/* INTC Registers */ +REG32(GICINT128_EN, 0x1000) +REG32(GICINT128_STATUS, 0x1004) +REG32(GICINT129_EN, 0x1100) +REG32(GICINT129_STATUS, 0x1104) +REG32(GICINT130_EN, 0x1200) +REG32(GICINT130_STATUS, 0x1204) +REG32(GICINT131_EN, 0x1300) +REG32(GICINT131_STATUS, 0x1304) +REG32(GICINT132_EN, 0x1400) +REG32(GICINT132_STATUS, 0x1404) +REG32(GICINT133_EN, 0x1500) +REG32(GICINT133_STATUS, 0x1504) +REG32(GICINT134_EN, 0x1600) +REG32(GICINT134_STATUS, 0x1604) +REG32(GICINT135_EN, 0x1700)
Re: [PATCH v4 12/16] aspeed/soc: Add AST2700 support
On 5/27/24 10:02, Jamin Lin wrote: Initial definitions for a simple machine using an AST2700 SOC (Cortex-a35 CPU). AST2700 SOC and its interrupt controller are too complex to handle in the common Aspeed SoC framework. We introduce a new ast2700 class with instance_init and realize handlers. AST2700 is a 64 bits quad core cpus and support 8 watchdog. Update maximum ASPEED_CPUS_NUM to 4 and ASPEED_WDTS_NUM to 8. In addition, update AspeedSocState to support scuio, sli, sliio and intc. Add TYPE_ASPEED27X0_SOC machine type. The SDMC controller is unlocked at SPL stage. At present, only supports to emulate booting start from u-boot stage. Set SDMC controller unlocked by default. In INTC, each interrupt of INT 128 to INT 136 combines 32 interrupts. It connect GICINT IRQ GPIO-OUTPUT pins to GIC device with irq 128 to 136. And, if a device irq is 128 to 136, its irq GPIO-OUTPUT pin is connected to GICINT or-gates instead of GIC device. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/arm/aspeed_ast27x0.c | 563 hw/arm/meson.build | 1 + include/hw/arm/aspeed_soc.h | 26 +- 3 files changed, 588 insertions(+), 2 deletions(-) create mode 100644 hw/arm/aspeed_ast27x0.c diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c new file mode 100644 index 00..a3a03fc1ca --- /dev/null +++ b/hw/arm/aspeed_ast27x0.c @@ -0,0 +1,563 @@ +/* + * ASPEED SoC 27x0 family + * + * Copyright (C) 2024 ASPEED Technology Inc. + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * Implementation extracted from the AST2600 and adapted for AST27x0. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/misc/unimp.h" +#include "hw/arm/aspeed_soc.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/i2c/aspeed_i2c.h" +#include "net/net.h" +#include "sysemu/sysemu.h" +#include "hw/intc/arm_gicv3.h" +#include "qapi/qmp/qlist.h" + +static const hwaddr aspeed_soc_ast2700_memmap[] = { +[ASPEED_DEV_SPI_BOOT] = 0x4, +[ASPEED_DEV_SRAM] = 0x1000, +[ASPEED_DEV_SDMC] = 0x12C0, +[ASPEED_DEV_SCU] = 0x12C02000, +[ASPEED_DEV_SCUIO] = 0x14C02000, +[ASPEED_DEV_UART0] = 0X14C33000, +[ASPEED_DEV_UART1] = 0X14C33100, +[ASPEED_DEV_UART2] = 0X14C33200, +[ASPEED_DEV_UART3] = 0X14C33300, +[ASPEED_DEV_UART4] = 0X12C1A000, +[ASPEED_DEV_UART5] = 0X14C33400, +[ASPEED_DEV_UART6] = 0X14C33500, +[ASPEED_DEV_UART7] = 0X14C33600, +[ASPEED_DEV_UART8] = 0X14C33700, +[ASPEED_DEV_UART9] = 0X14C33800, +[ASPEED_DEV_UART10]= 0X14C33900, +[ASPEED_DEV_UART11]= 0X14C33A00, +[ASPEED_DEV_UART12]= 0X14C33B00, +[ASPEED_DEV_WDT] = 0x14C37000, +[ASPEED_DEV_VUART] = 0X14C3, +[ASPEED_DEV_FMC] = 0x1400, +[ASPEED_DEV_SPI0] = 0x1401, +[ASPEED_DEV_SPI1] = 0x1402, +[ASPEED_DEV_SPI2] = 0x1403, +[ASPEED_DEV_SDRAM] = 0x4, +[ASPEED_DEV_MII1] = 0x1404, +[ASPEED_DEV_MII2] = 0x14040008, +[ASPEED_DEV_MII3] = 0x14040010, +[ASPEED_DEV_ETH1] = 0x1405, +[ASPEED_DEV_ETH2] = 0x1406, +[ASPEED_DEV_ETH3] = 0x1407, +[ASPEED_DEV_EMMC] = 0x1209, +[ASPEED_DEV_INTC] = 0x1210, +[ASPEED_DEV_SLI] = 0x12C17000, +[ASPEED_DEV_SLIIO] = 0x14C1E000, +[ASPEED_GIC_DIST] = 0x1220, +[ASPEED_GIC_REDIST]= 0x1228, +}; + +#define AST2700_MAX_IRQ 288 + +/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */ +static const int aspeed_soc_ast2700_irqmap[] = { +[ASPEED_DEV_UART0] = 132, +[ASPEED_DEV_UART1] = 132, +[ASPEED_DEV_UART2] = 132, +[ASPEED_DEV_UART3] = 132, +[ASPEED_DEV_UART4] = 8, +[ASPEED_DEV_UART5] = 132, +[ASPEED_DEV_UART6] = 132, +[ASPEED_DEV_UART7] = 132, +[ASPEED_DEV_UART8] = 132, +[ASPEED_DEV_UART9] = 132, +[ASPEED_DEV_UART10]= 132, +[ASPEED_DEV_UART11]= 132, +[ASPEED_DEV_UART12]= 132, +[ASPEED_DEV_FMC] = 131, +[ASPEED_DEV_SDMC] = 0, +[ASPEED_DEV_SCU] = 12, +[ASPEED_DEV_ADC] = 130, +[ASPEED_DEV_XDMA] = 5, +[ASPEED_DEV_EMMC] = 15, +[ASPEED_DEV_GPIO] = 11, +[ASPEED_DEV_GPIO_1_8V] = 130, +[ASPEED_DEV_RTC] = 13, +[ASPEED_DEV_TIMER1]= 16, +[ASPEED_DEV_TIMER2]= 17, +[ASPEED_DEV_TIMER3]= 18, +[ASPEED_DEV_TIMER4]= 19, +[ASPEED_DEV_TIMER5]= 20, +[ASPEED_DEV_TIMER6]= 21, +[ASPEED_DEV_TIMER7]= 22, +[ASPEED_DEV_TIMER8]= 23, +[ASPEED_DEV_WDT] = 131, +[ASPEED_DEV_PWM] = 131, +[ASPEED_DEV_LPC] = 128, +[ASPEED_DEV_IBT]
Re: [RFC PATCH 02/10] ppc/pnv: Move timebase state into PnvCore
On 5/28/24 08:28, Harsh Prateek Bora wrote: On 5/26/24 17:56, Nicholas Piggin wrote: The timebase state machine is per per-core state and can be driven by any thread in the core. It is currently implemented as a hack where the state is in a CPU structure and only thread 0's state is accessed by the chiptod, which limits programming the timebase side of the state machine to thread 0 of a core. Move the state out into PnvCore and share it among all threads. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv_core.h | 17 target/ppc/cpu.h | 20 -- hw/ppc/pnv_chiptod.c | 6 ++-- target/ppc/timebase_helper.c | 53 4 files changed, 49 insertions(+), 47 deletions(-) diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 30c1e5b1a3..f434c71547 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -25,6 +25,20 @@ #include "hw/ppc/pnv.h" #include "qom/object.h" +/* ChipTOD and TimeBase State Machine */ +struct pnv_tod_tbst { + int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */ + int tod_sent_to_tb; /* chiptod sent TOD to the core TB */ + + /* + * "Timers" for async TBST events are simulated by mfTFAC because TFAC + * is polled for such events. These are just used to ensure firmware + * performs the polling at least a few times. + */ + int tb_state_timer; + int tb_sync_pulse_timer; +}; + #define TYPE_PNV_CORE "powernv-cpu-core" OBJECT_DECLARE_TYPE(PnvCore, PnvCoreClass, PNV_CORE) @@ -38,6 +52,9 @@ struct PnvCore { uint32_t pir; uint32_t hwid; uint64_t hrmor; + + struct pnv_tod_tbst pnv_tod_tbst; + Now that it is part of struct PnvCore itself, we can drop pnv_ prefix and just call the member variable as tod_tbst ? yes and rename pnv_tod_tbst using CamelCase please. Thanks, C. PnvChip *chip; MemoryRegion xscom_regs; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 2015e603d4..1e86658da6 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1196,21 +1196,6 @@ DEXCR_ASPECT(SRAPD, 4) DEXCR_ASPECT(NPHIE, 5) DEXCR_ASPECT(PHIE, 6) -/*/ -/* PowerNV ChipTOD and TimeBase State Machine */ -struct pnv_tod_tbst { - int tb_ready_for_tod; /* core TB ready to receive TOD from chiptod */ - int tod_sent_to_tb; /* chiptod sent TOD to the core TB */ - - /* - * "Timers" for async TBST events are simulated by mfTFAC because TFAC - * is polled for such events. These are just used to ensure firmware - * performs the polling at least a few times. - */ - int tb_state_timer; - int tb_sync_pulse_timer; -}; - /*/ /* The whole PowerPC CPU context */ @@ -1292,11 +1277,6 @@ struct CPUArchState { #define TLB_NEED_LOCAL_FLUSH 0x1 #define TLB_NEED_GLOBAL_FLUSH 0x2 -#if defined(TARGET_PPC64) - /* PowerNV chiptod / timebase facility state. */ - /* Would be nice to put these into PnvCore */ - struct pnv_tod_tbst pnv_tod_tbst; -#endif #endif /* Other registers */ diff --git a/hw/ppc/pnv_chiptod.c b/hw/ppc/pnv_chiptod.c index 3831a72101..3eaddd66f0 100644 --- a/hw/ppc/pnv_chiptod.c +++ b/hw/ppc/pnv_chiptod.c @@ -365,7 +365,7 @@ static void pnv_chiptod_xscom_write(void *opaque, hwaddr addr, " TOD_MOVE_TOD_TO_TB_REG with no slave target\n"); } else { PowerPCCPU *cpu = chiptod->slave_pc_target->threads[0]; - CPUPPCState *env = >env; + PnvCore *pc = pnv_cpu_state(cpu)->core; /* * Moving TOD to TB will set the TB of all threads in a @@ -377,8 +377,8 @@ static void pnv_chiptod_xscom_write(void *opaque, hwaddr addr, * thread 0. */ - if (env->pnv_tod_tbst.tb_ready_for_tod) { - env->pnv_tod_tbst.tod_sent_to_tb = 1; + if (pc->pnv_tod_tbst.tb_ready_for_tod) { + pc->pnv_tod_tbst.tod_sent_to_tb = 1; } else { qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg" " TOD_MOVE_TOD_TO_TB_REG with TB not ready to" diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c index 39d397416e..788c498d63 100644 --- a/target/ppc/timebase_helper.c +++ b/target/ppc/timebase_helper.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "hw/ppc/ppc.h" +#include "hw/ppc/pnv_core.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "qemu/log.h" @@ -298,8 +299,17 @@ static void write_tfmr(CPUPPCState *env, target_ulong val) } } +static struct pnv_tod_tbst *cpu_get_tbst(PowerPCCPU *cpu) +{ + PnvCore *pc = pnv_cpu_state(cpu)->core; + + return >pnv_tod_tbst; +} + static void
Re: [RFC PATCH 04/10] ppc/pnv: specialise init for powernv8/9/10 machines
On 5/28/24 09:10, Harsh Prateek Bora wrote: Hi Nick, On 5/26/24 17:56, Nicholas Piggin wrote: This will allow different settings and checks for different machine types with later changes. Signed-off-by: Nicholas Piggin --- hw/ppc/pnv.c | 35 ++- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6e3a5ccdec..a706de2e36 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -976,11 +976,6 @@ static void pnv_init(MachineState *machine) pnv->num_chips = machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); - if (machine->smp.threads > 8) { - error_report("Cannot support more than 8 threads/core " - "on a powernv machine"); - exit(1); - } if (!is_power_of_2(machine->smp.threads)) { error_report("Cannot support %d threads/core on a powernv" "machine because it must be a power of 2", @@ -1076,6 +1071,33 @@ static void pnv_init(MachineState *machine) } } +static void pnv_power8_init(MachineState *machine) +{ + if (machine->smp.threads > 8) { + error_report("Cannot support more than 8 threads/core " + "on a powernv POWER8 machine"); We could use mc->desc for machine name above, so that .. + exit(1); + } with this patch, we can reuse p8 init for both p9 and p10 (and not just reuse p9 for p10 with hard coded string?). Good idea. You could add a 'max_smt' attribute to PnvMachineClass to limit POWER8 to one. Thanks, C. With that, Reviewed-by: Harsh Prateek Bora + + pnv_init(machine); +} + +static void pnv_power9_init(MachineState *machine) +{ + if (machine->smp.threads > 8) { + error_report("Cannot support more than 8 threads/core " + "on a powernv9/10 machine"); + exit(1); + } + + pnv_init(machine); +} + +static void pnv_power10_init(MachineState *machine) +{ + pnv_power9_init(machine); +} + /* * 0:21 Reserved - Read as zeros * 22:24 Chip ID @@ -2423,6 +2445,7 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) }; mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; + mc->init = pnv_power8_init; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); @@ -2449,6 +2472,7 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) }; mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; + mc->init = pnv_power9_init; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); @@ -2473,6 +2497,7 @@ static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data) { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, }; + mc->init = pnv_power10_init; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
Re: [PATCH v4 05/11] ppc/pnv: Add a Power11 Pnv11Chip, and a Power11 Machine
Hello Aditya On 5/28/24 09:05, Aditya Gupta wrote: Power11 core is same as Power10, use the existing functionalities to introduce a Power11 chip and machine, with Power10 chip as parent of Power11 chip, thus going through similar class_init paths This patch should come last, after all the POWER11 processor sub-unit models (HOMER, OCC, LPC) are implemented. Also the POWER11 chip model lacks an instance_init() handler initializing the chip children to the correct POWER11 types. AFAICT, power11-pnv-chip is still using power10 types. More below, Cc: Cédric Le Goater Cc: Frédéric Barrat Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- docs/system/ppc/powernv.rst | 9 +-- hw/ppc/pnv.c| 120 ++-- hw/ppc/pnv_core.c | 11 include/hw/ppc/pnv.h| 5 ++ include/hw/ppc/pnv_chip.h | 7 +++ include/hw/ppc/pnv_core.h | 1 + 6 files changed, 145 insertions(+), 8 deletions(-) diff --git a/docs/system/ppc/powernv.rst b/docs/system/ppc/powernv.rst index 09f39658587d..65606aa767aa 100644 --- a/docs/system/ppc/powernv.rst +++ b/docs/system/ppc/powernv.rst @@ -1,5 +1,5 @@ -PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``) -== +PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``, ``powernv11``) + PowerNV (as Non-Virtualized) is the "bare metal" platform using the OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can @@ -15,11 +15,12 @@ beyond the scope of what QEMU addresses today. Supported devices - - * Multi processor support for POWER8, POWER8NVL and POWER9. + * Multi processor support for POWER8, POWER8NVL, POWER9, Power10 and Power11. * XSCOM, serial communication sideband bus to configure chiplets. * Simple LPC Controller. * Processor Service Interface (PSI) Controller. - * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10). + * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10 & + Power11). * POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge. * Simple OCC is an on-chip micro-controller used for power management tasks. * iBT device to handle BMC communication, with the internal BMC simulator diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6e3a5ccdec76..f8270f4b123b 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -456,6 +456,33 @@ static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); } +static void pnv_chip_power11_dt_populate(PnvChip *chip, void *fdt) +{ +static const char compat[] = "ibm,power11-xscom\0ibm,xscom"; +int i; + +pnv_dt_xscom(chip, fdt, 0, + cpu_to_be64(PNV10_XSCOM_BASE(chip)), + cpu_to_be64(PNV10_XSCOM_SIZE), I wonder if we should not duplicate the PNV10 macros in PNV11. It's minor. + compat, sizeof(compat)); + +for (i = 0; i < chip->nr_cores; i++) { +PnvCore *pnv_core = chip->cores[i]; +int offset; + +offset = pnv_dt_core(chip, pnv_core, fdt); + +_FDT((fdt_setprop(fdt, offset, "ibm,pa-features", + pa_features_31, sizeof(pa_features_31; +} + +if (chip->ram_size) { +pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); +} + +pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); ditto +} + static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) { uint32_t io_base = d->ioport_id; @@ -1288,6 +1315,8 @@ static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, #define POWER10_CORE_MASK (0xffull) +#define POWER11_CORE_MASK (0xffull) + static void pnv_chip_power8_instance_init(Object *obj) { Pnv8Chip *chip8 = PNV8_CHIP(obj); @@ -1831,7 +1860,8 @@ static void pnv_chip_power10_instance_init(Object *obj) } } -static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) +static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp, Rename in pnv_chip_power1x_quad_realize may be ? same below. +const char *cpu_model) { PnvChip *chip = PNV_CHIP(chip10); int i; @@ -1841,9 +1871,10 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) for (i = 0; i < chip10->nr_quads; i++) { PnvQuad *eq = >quads[i]; +g_autofree char *type_name = PNV_QUAD_TYPE_NAME_DYN(cpu_model); and PNV_QUAD_TYPE_NAME_DYN becomes quite useless now. Thanks, C. pnv_chip_quad_realize_one(chip, eq, chip->cores[i
Re: [PATCH v4 11/11] ppc/pnv: Update skiboot.lid to support Power11
On 5/28/24 09:05, Aditya Gupta wrote: Skiboot/OPAL patches are in discussion upstream [1], with corresponding commits in github repository [2]. Update skiboot.lid, with binary built from 'upstream_power11' branch of skiboot repository with Power11 enablement patches [2]. --- This patch can be skipped for now, if need to wait for patches to be merged in open-power/skiboot. Have updated the skiboot.lid to aid in testing this patch series. When is the merge in skiboot planned ? QEMU 9.1 freeze is in ~2 months. [1]:https://lists.ozlabs.org/pipermail/skiboot/2024-April/018963.html [2]:https://github.com/maheshsal/skiboot. Cc: Cédric Le Goater Cc: Joel Stanley Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- pc-bios/skiboot.lid | Bin 2527328 -> 2527328 bytes Please don't resend. This is big ! Thanks, C.
Re: [SPAM] Re: [PATCH v4 09/16] aspeed/smc: Add AST2700 support
On 5/27/24 17:58, Philippe Mathieu-Daudé wrote: Hi, On 27/5/24 10:02, Jamin Lin wrote: AST2700 fmc/spi controller's address decoding unit is 64KB and only bits [31:16] are used for decoding. Introduce seg_to_reg and reg_to_seg handlers for ast2700 fmc/spi controller. In addition, adds ast2700 fmc, spi0, spi1, and spi2 class init handler. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/ssi/aspeed_smc.c | 222 +++- 1 file changed, 220 insertions(+), 2 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index df0c63469c..b4006c8339 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -185,7 +185,7 @@ * 0: 4 bytes * 0x1FC: 32M bytes * - * DMA length is from 1 byte to 32MB (AST2600, AST10x0) + * DMA length is from 1 byte to 32MB (AST2600, AST10x0 and AST2700) * 0: 1 byte * 0x1FF: 32M bytes */ @@ -670,7 +670,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = { .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, - .max_access_size = 4, + .max_access_size = 8, Is this a bugfix? If so, please use a separate patch. Otherwise please mention why it is OK to widen access for AST2600 & AST10x0. Ah I missed that. I wonder how we could set different access width tough on the model ? Should we allocate a MemoryRegionOps in the realize() handler and set the width depending on the SoC ? Thanks, C.
Re: [SPAM] Re: [PATCH v4 08/16] aspeed/smc: support 64 bits dma dram address
On 5/27/24 18:06, Philippe Mathieu-Daudé wrote: Hi Jamin, On 27/5/24 10:02, Jamin Lin wrote: AST2700 support the maximum dram size is 8GiB and has a "DMA DRAM Side Address High Part(0x7C)" register to support 64 bits dma dram address. Add helper routines functions to compute the dma dram address, new features and update trace-event to support 64 bits dram address. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin --- hw/ssi/aspeed_smc.c | 52 +++-- hw/ssi/trace-events | 2 +- include/hw/ssi/aspeed_smc.h | 1 + 3 files changed, 46 insertions(+), 9 deletions(-) +static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s) +{ + return s->regs[R_DMA_DRAM_ADDR] | + ((uint64_t) s->regs[R_DMA_DRAM_ADDR_HIGH] << 32); +} + static uint32_t aspeed_smc_dma_len(AspeedSMCState *s) { AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); @@ -903,24 +921,34 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) static void aspeed_smc_dma_rw(AspeedSMCState *s) { + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); + uint64_t dma_dram_offset; + uint64_t dma_dram_addr; MemTxResult result; uint32_t dma_len; uint32_t data; dma_len = aspeed_smc_dma_len(s); + dma_dram_addr = aspeed_smc_dma_dram_addr(s); + + if (aspeed_smc_has_dma64(asc)) { + dma_dram_offset = dma_dram_addr - s->dram_base; + } else { + dma_dram_offset = dma_dram_addr; Here s->dram_base is 0x0. Do we really need to check aspeed_smc_has_dma64? You are right, it could be done as your proposal below. However, we should add a comment regarding some values : R_DMA_DRAM_ADDR_HIGH and s->dram_base are only set on the AST2700 SoC and zero on other Aspeed SoCs. + } Maybe simplify improving aspeed_smc_dma_dram_addr() as: static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s) { return (s->regs[R_DMA_DRAM_ADDR] | ((uint64_t) s->regs[R_DMA_DRAM_ADDR_HIGH] << 32)) - s->dram_base; } Then no need for dma_dram_offset, dma_dram_addr is enough. we need both, dma_dram_offset for the transaction and dma_dram_addr to update the R_DMA_DRAM_ADDR_HIGH reg. A bit cumbersome, I agree. Thanks, C. trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ? "write" : "read", s->regs[R_DMA_FLASH_ADDR], - s->regs[R_DMA_DRAM_ADDR], + dma_dram_offset, dma_len); while (dma_len) { if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { - data = address_space_ldl_le(>dram_as, s->regs[R_DMA_DRAM_ADDR], + data = address_space_ldl_le(>dram_as, dma_dram_offset, MEMTXATTRS_UNSPECIFIED, ); if (result != MEMTX_OK) { - aspeed_smc_error("DRAM read failed @%08x", - s->regs[R_DMA_DRAM_ADDR]); + aspeed_smc_error("DRAM read failed @%" PRIx64, + dma_dram_offset); return; } @@ -940,11 +968,11 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s) return; } - address_space_stl_le(>dram_as, s->regs[R_DMA_DRAM_ADDR], + address_space_stl_le(>dram_as, dma_dram_offset, data, MEMTXATTRS_UNSPECIFIED, ); if (result != MEMTX_OK) { - aspeed_smc_error("DRAM write failed @%08x", - s->regs[R_DMA_DRAM_ADDR]); + aspeed_smc_error("DRAM write failed @%" PRIx64, + dma_dram_offset); return; } } @@ -953,8 +981,12 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s) * When the DMA is on-going, the DMA registers are updated * with the current working addresses and length. */ + dma_dram_offset += 4; + dma_dram_addr += 4; + + s->regs[R_DMA_DRAM_ADDR_HIGH] = dma_dram_addr >> 32; + s->regs[R_DMA_DRAM_ADDR] = dma_dram_addr & 0x; s->regs[R_DMA_FLASH_ADDR] += 4; - s->regs[R_DMA_DRAM_ADDR] += 4; dma_len -= 4; s->regs[R_DMA_LEN] = dma_len; s->regs[R_DMA_CHECKSUM] += data; @@ -1107,6 +1139,9 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, } else if (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN && aspeed_smc_dma_granted(s)) { s->regs[addr] = DMA_LENGTH(value); + } else if (aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) && + addr == R_DMA_DRAM_ADDR_HIGH) { + s->regs[addr] = DMA_DRAM_ADDR_HIGH(value); } else { qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", __func__, addr); @@ -1239,6 +1274,7 @@
Re: [PATCH v4 08/16] aspeed/smc: support 64 bits dma dram address
On 5/28/24 03:34, Jamin Lin wrote: Hi Cedric, On 5/27/24 10:02, Jamin Lin wrote: AST2700 support the maximum dram size is 8GiB and has a "DMA DRAM Side Address High Part(0x7C)" register to support 64 bits dma dram address. Add helper routines functions to compute the dma dram address, new features and update trace-event to support 64 bits dram address. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin I will move the addition of the "dram-base" property to another patch. See : https://patchew.org/QEMU/20240527124315.35356-1-...@redhat.com/ (Please review) Review done. If I need to resend v5 patch series, I will remove "dram-base property" from this patch. ok. Wait a bit before resending though. We are not done with v4 yet ! Thanks, C. Thanks for your help, Jamin Else, Reviewed-by: Cédric Le Goater Thanks, C. --- hw/ssi/aspeed_smc.c | 52 +++-- hw/ssi/trace-events | 2 +- include/hw/ssi/aspeed_smc.h | 1 + 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index ffb13a12e8..df0c63469c 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -132,6 +132,9 @@ #define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary 1: alternate */ #define FMC_WDT2_CTRL_EN BIT(0) +/* DMA DRAM Side Address High Part (AST2700) */ +#define R_DMA_DRAM_ADDR_HIGH (0x7c / 4) + /* DMA Control/Status Register */ #define R_DMA_CTRL(0x80 / 4) #define DMA_CTRL_REQUEST (1 << 31) @@ -187,6 +190,7 @@ * 0x1FF: 32M bytes */ #define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask) +#define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf) #define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask) #define DMA_LENGTH(val) ((val) & 0x01FF) @@ -207,6 +211,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[]; #define ASPEED_SMC_FEATURE_DMA 0x1 #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2 #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4 +#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08 static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc) { @@ -218,6 +223,11 @@ static inline bool aspeed_smc_has_wdt_control(const AspeedSMCClass *asc) return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL); } +static inline bool aspeed_smc_has_dma64(const AspeedSMCClass *asc) { +return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH); +} + #define aspeed_smc_error(fmt, ...) \ qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__) @@ -747,6 +757,8 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) || (aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) || (aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) || +(aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) && + addr == R_DMA_DRAM_ADDR_HIGH) || (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) || (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) || (addr >= R_SEG_ADDR0 && @@ -847,6 +859,12 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s) } } +static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s) { +return s->regs[R_DMA_DRAM_ADDR] | +((uint64_t) s->regs[R_DMA_DRAM_ADDR_HIGH] << 32); } + static uint32_t aspeed_smc_dma_len(AspeedSMCState *s) { AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); @@ -903,24 +921,34 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) static void aspeed_smc_dma_rw(AspeedSMCState *s) { +AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); +uint64_t dma_dram_offset; +uint64_t dma_dram_addr; MemTxResult result; uint32_t dma_len; uint32_t data; dma_len = aspeed_smc_dma_len(s); +dma_dram_addr = aspeed_smc_dma_dram_addr(s); + +if (aspeed_smc_has_dma64(asc)) { +dma_dram_offset = dma_dram_addr - s->dram_base; +} else { +dma_dram_offset = dma_dram_addr; +} trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ? "write" : "read", s->regs[R_DMA_FLASH_ADDR], -s->regs[R_DMA_DRAM_ADDR], +dma_dram_offset, dma_len); while (dma_len) { if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { -data = address_space_ldl_le(>dram_as, s->regs[R_DMA_DRAM_ADDR], +data = address_space_ldl_le(>dram_as, dma_dram_offset, MEMTXATTRS_UNSPECIFIED, );
Re: [PATCH v4 05/16] aspeed/sdmc: Add AST2700 support
On 5/28/24 03:26, Jamin Lin wrote: Hi Philippe, Cedric On 27/5/24 13:18, Cédric Le Goater wrote: On 5/27/24 12:24, Philippe Mathieu-Daudé wrote: Hi Jamin, On 27/5/24 10:02, Jamin Lin wrote: The SDRAM memory controller(DRAMC) controls the access to external DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY. The DRAM memory controller of AST2700 is not backward compatible to previous chips such AST2600, AST2500 and AST2400. Max memory is now 8GiB on the AST2700. Introduce new aspeed_2700_sdmc and class with read/write operation and reset handlers. Define DRAMC necessary protected registers and unprotected registers for AST2700 and increase the register set to 0x1000. Add unlocked property to change controller protected status. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/misc/aspeed_sdmc.c | 190 +- include/hw/misc/aspeed_sdmc.h | 5 +- 2 files changed, 193 insertions(+), 2 deletions(-) diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h index ec2d59a14f..61c979583a 100644 --- a/include/hw/misc/aspeed_sdmc.h +++ b/include/hw/misc/aspeed_sdmc.h @@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC) #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400" #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500" #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600" +#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700" /* * SDMC has 174 documented registers. In addition the u-boot device tree @@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC) * time, and the other is in the DDR-PHY IP which is used during DDR-PHY * training. */ -#define ASPEED_SDMC_NR_REGS (0x500 >> 2) +#define ASPEED_SDMC_NR_REGS (0x1000 >> 2) This change breaks the migration stream. Do you mean migration compat ? We never cared much about that for the Aspeed machines. So let's just remove the VMSTATE to reduce code burden? Otherwise incrementing the vmstate.version is enough. Regards, Phil. If you both okay, I will remove it. Do I need to create a new patch or just update in this patch? I don't think this is necessary to do so now. Possibly, increase the version number in the vmstate when resending a v5. Also, all Aspeed models should be addressed and that's beyond the scope of this series. Thanks, C.
Re: [RFC PATCH 01/10] ppc/pnv: Add pointer from PnvCPUState to PnvCore
On 5/26/24 14:26, Nicholas Piggin wrote: This helps move core state from CPU to core structures. Signed-off-by: Nicholas Piggin --- include/hw/ppc/pnv_core.h | 1 + hw/ppc/pnv_core.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index c6d62fd145..30c1e5b1a3 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -54,6 +54,7 @@ struct PnvCoreClass { #define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX typedef struct PnvCPUState { +PnvCore *core; Object *intc; } PnvCPUState; diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index f40ab721d6..7b0ea7812b 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -225,6 +225,7 @@ static const MemoryRegionOps pnv_core_power10_xscom_ops = { static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, int thread_index) { +PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); CPUPPCState *env = >env; int core_hwid; ppc_spr_t *pir = >spr_cb[SPR_PIR]; @@ -232,6 +233,8 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, Error *local_err = NULL; PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); +pnv_cpu->core = pc; I would do the assignment in pnv_core_realize() after cpu->machine_data is allocated. it's minor. Reviewed-by: Cédric Le Goater Thanks, C. if (!qdev_realize(DEVICE(cpu), NULL, errp)) { return; }
Re: [PATCH v3 05/11] ppc/pnv: Add a Power11 Pnv11Chip, and a Power11 Machine
On 5/27/24 09:10, Aditya Gupta wrote: Power11 core is same as Power10, use the existing functionalities to introduce a Power11 chip and machine, with Power10 chip as parent of Power11 chip, thus going through similar class_init paths Cc: Cédric Le Goater Cc: Frédéric Barrat Cc: Mahesh J Salgaonkar Cc: Madhavan Srinivasan Cc: Nicholas Piggin Signed-off-by: Aditya Gupta --- docs/system/ppc/powernv.rst | 9 +-- hw/ppc/pnv.c| 119 ++-- hw/ppc/pnv_core.c | 11 include/hw/ppc/pnv.h| 5 ++ include/hw/ppc/pnv_chip.h | 7 +++ include/hw/ppc/pnv_core.h | 1 + 6 files changed, 144 insertions(+), 8 deletions(-) diff --git a/docs/system/ppc/powernv.rst b/docs/system/ppc/powernv.rst index 09f39658587d..65606aa767aa 100644 --- a/docs/system/ppc/powernv.rst +++ b/docs/system/ppc/powernv.rst @@ -1,5 +1,5 @@ -PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``) -== +PowerNV family boards (``powernv8``, ``powernv9``, ``powernv10``, ``powernv11``) + PowerNV (as Non-Virtualized) is the "bare metal" platform using the OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can @@ -15,11 +15,12 @@ beyond the scope of what QEMU addresses today. Supported devices - - * Multi processor support for POWER8, POWER8NVL and POWER9. + * Multi processor support for POWER8, POWER8NVL, POWER9, Power10 and Power11. * XSCOM, serial communication sideband bus to configure chiplets. * Simple LPC Controller. * Processor Service Interface (PSI) Controller. - * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10). + * Interrupt Controller, XICS (POWER8) and XIVE (POWER9) and XIVE2 (Power10 & + Power11). * POWER8 PHB3 PCIe Host bridge and POWER9 PHB4 PCIe Host bridge. * Simple OCC is an on-chip micro-controller used for power management tasks. * iBT device to handle BMC communication, with the internal BMC simulator diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6e3a5ccdec76..939163f91784 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -456,6 +456,33 @@ static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); } +static void pnv_chip_power11_dt_populate(PnvChip *chip, void *fdt) +{ +static const char compat[] = "ibm,power11-xscom\0ibm,xscom"; +int i; + +pnv_dt_xscom(chip, fdt, 0, + cpu_to_be64(PNV10_XSCOM_BASE(chip)), + cpu_to_be64(PNV10_XSCOM_SIZE), + compat, sizeof(compat)); + +for (i = 0; i < chip->nr_cores; i++) { +PnvCore *pnv_core = chip->cores[i]; +int offset; + +offset = pnv_dt_core(chip, pnv_core, fdt); + +_FDT((fdt_setprop(fdt, offset, "ibm,pa-features", + pa_features_31, sizeof(pa_features_31; +} + +if (chip->ram_size) { +pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); +} + +pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); +} + static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) { uint32_t io_base = d->ioport_id; @@ -1288,6 +1315,8 @@ static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, #define POWER10_CORE_MASK (0xffull) +#define POWER11_CORE_MASK (0xffull) + static void pnv_chip_power8_instance_init(Object *obj) { Pnv8Chip *chip8 = PNV8_CHIP(obj); @@ -1831,7 +1860,8 @@ static void pnv_chip_power10_instance_init(Object *obj) } } -static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) +static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp, +const char *cpu_model) { PnvChip *chip = PNV_CHIP(chip10); int i; @@ -1843,7 +1873,7 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) PnvQuad *eq = >quads[i]; pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], - PNV_QUAD_TYPE_NAME("power10")); + PNV_QUAD_TYPE_NAME_DYN(cpu_model)); pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), >xscom_regs); @@ -1881,7 +1911,8 @@ static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) } } -static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) +static void pnv_chip_power10_common_realize(DeviceState *dev, Error **errp, +const char *cpu_model) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); PnvChip *chip = PNV_CHIP(dev); @@ -1898,7 +1929,7 @@ static
Re: [PATCH] vfio: container: Fix missing allocation of VFIOSpaprContainer
On 5/22/24 18:15, Shivaprasad G Bhat wrote: On 5/13/24 17:53, Cédric Le Goater wrote: Hello Shivaprasad, On 5/9/24 21:14, Shivaprasad G Bhat wrote: The commit 6ad359ec29 "(vfio/spapr: Move prereg_listener into spapr container)" began to use the newly introduced VFIOSpaprContainer structure. After several refactors, today the container_of(container, VFIOSpaprContainer, ABC) is used when VFIOSpaprContainer is actually not allocated. On PPC64 systems, this dereference is leading to corruption showing up as glibc malloc assertion during guest start when using vfio. Patch adds the missing allocation while also making the structure movement to vfio common header file. Fixes: 6ad359ec29 "(vfio/spapr: Move prereg_listener into spapr container)" Signed-off-by: Shivaprasad G Bhat --- hw/vfio/container.c | 6 -- hw/vfio/spapr.c | 6 -- include/hw/vfio/vfio-common.h | 6 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 77bdec276e..ecaf5786d9 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -539,6 +539,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, { VFIOContainer *container; VFIOContainerBase *bcontainer; + VFIOSpaprContainer *scontainer; We should do our best to avoid any direct use of ppc related attributes in the common VFIO code. This comment also applies to VFIO_SPAPR_TCE* which are still there because the clean up is not finished. So, this proposal will have to be reworked. Sure. The first step is to finish the QOMification of VFIOContainer, so that the VFIOContainer instance is created in vfio_connect_container() with : container = qdev_new(iommu_type_name); This requires the VFIOContainer to be a DeviceState object. The existing base class TYPE_VFIO_IOMMU is an InterfaceClass. I attempted VFIOContainer object declaration with TYPE_VFIO_IOMMU, like OBJECT_DECLARE_SIMPLE_TYPE(VFIOContainer, VFIO_IOMMU_LEGACY) This means reworking this part (and vfio_set_iommu()) : ... container = g_malloc0(sizeof(*container)); container->fd = fd; bcontainer = >bcontainer; if (!vfio_set_iommu(container, group->fd, space, errp)) { goto free_container_exit; } ... VFIOSpaprContainer can then implement its own .init_instance() handler to allocate/initialize attributes required by the pseries machines. With my above changes, I see the instance_init() is not supported for the InterfaceClass with the Yes. We need an Object, hence my remark on "QOMification of VFIOContainer". VFIOContainerBase needs to be reworked. Thanks, C. checks from below commit 422ca1432f7b44f2a9f3ad94a65d36927da021fa Author: Marc-André Lureau Date: Wed Sep 12 16:53:03 2018 +0400 qom/object: add some interface asserts Did you suggest me something else? Thank you, Shivaprasad While doing this, please try to reduce the use of ->iommu_type which is a design shortcut. I would like to completely remove it at some point. Thanks, C. int ret, fd; VFIOAddressSpace *space; @@ -611,7 +612,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, goto close_fd_exit; } - container = g_malloc0(sizeof(*container)); + scontainer = g_malloc0(sizeof(*scontainer)); + container = >container; container->fd = fd; bcontainer = >bcontainer; @@ -675,7 +677,7 @@ unregister_container_exit: vfio_cpr_unregister_container(bcontainer); free_container_exit: - g_free(container); + g_free(scontainer); close_fd_exit: close(fd); diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 0d949bb728..78d218b7e7 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -24,12 +24,6 @@ #include "qapi/error.h" #include "trace.h" -typedef struct VFIOSpaprContainer { - VFIOContainer container; - MemoryListener prereg_listener; - QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; -} VFIOSpaprContainer; - static bool vfio_prereg_listener_skipped_section(MemoryRegionSection *section) { if (memory_region_is_iommu(section->mr)) { diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..010fa68ac6 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -82,6 +82,12 @@ typedef struct VFIOContainer { QLIST_HEAD(, VFIOGroup) group_list; } VFIOContainer; +typedef struct VFIOSpaprContainer { + VFIOContainer container; + MemoryListener prereg_listener; + QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; +} VFIOSpaprContainer; + typedef struct VFIOHostDMAWindow { hwaddr min_iova; hwaddr max_iova;
Re: [PATCH v5 19/19] intel_iommu: Check compatibility with host IOMMU capabilities
On 5/8/24 11:03, Zhenzhong Duan wrote: If check fails, host device (either VFIO or VDPA device) is not compatible with current vIOMMU config and should not be passed to guest. Only aw_bits is checked for now, we don't care other capabilities before scalable modern mode is introduced. Signed-off-by: Yi Liu Signed-off-by: Zhenzhong Duan --- hw/i386/intel_iommu.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 747c988bc4..07bfd4f99e 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -20,6 +20,7 @@ */ #include "qemu/osdep.h" +#include CONFIG_DEVICES /* CONFIG_HOST_IOMMU_DEVICE */ #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "qapi/error.h" @@ -3819,6 +3820,26 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, return vtd_dev_as; } +static bool vtd_check_hdev(IntelIOMMUState *s, VTDHostIOMMUDevice *vtd_hdev, + Error **errp) +{ +#ifdef CONFIG_HOST_IOMMU_DEVICE +HostIOMMUDevice *hiod = vtd_hdev->dev; +int ret; + +/* Common checks */ +ret = host_iommu_device_get_cap(hiod, HOST_IOMMU_DEVICE_CAP_AW_BITS, errp); To avoid CONFIG_HOST_IOMMU_DEVICE, host_iommu_device_get_cap() could be open coded. +if (ret < 0) { +return false; +} +if (s->aw_bits > ret) { +error_setg(errp, "aw-bits %d > host aw-bits %d", s->aw_bits, ret); +return false; +} +#endif +return true; +} + static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn, HostIOMMUDevice *hiod, Error **errp) { @@ -3848,6 +3869,12 @@ static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn, vtd_hdev->iommu_state = s; vtd_hdev->dev = hiod; +if (!vtd_check_hdev(s, vtd_hdev, errp)) { +g_free(vtd_hdev); +vtd_iommu_unlock(s); +return false; +} This check could be first done before allocating vtd_hdev. Thanks, C. new_key = g_malloc(sizeof(*new_key)); new_key->bus = bus; new_key->devfn = devfn;
Re: [PATCH v5 01/19] backends: Introduce HostIOMMUDevice abstract
On 5/13/24 12:28, Duan, Zhenzhong wrote: Hi Cédric, -Original Message- From: Cédric Le Goater Subject: Re: [PATCH v5 01/19] backends: Introduce HostIOMMUDevice abstract Hello Zhenzhong, On 5/8/24 11:03, Zhenzhong Duan wrote: Introduce HostIOMMUDevice as an abstraction of host IOMMU device. Introduce .realize() to initialize HostIOMMUDevice further after instance init. Introduce a macro CONFIG_HOST_IOMMU_DEVICE to define the usage for VFIO, and VDPA in the future. This looks like a way to work around some other problem, like avoiding exposing Linux definitions on windows build. Yes, I have used this MACRO in patch19 to fix build failure on windows. Also need change HostIOMMUDeviceCaps::type to be uint32_t type. Routine host_iommu_device_get_cap() could be open coded in vtd_check_hdev() to avoid CONFIG_HOST_IOMMU_DEVICE. Thanks, C. Thanks, C. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan --- MAINTAINERS| 2 ++ include/sysemu/host_iommu_device.h | 51 ++ backends/host_iommu_device.c | 30 ++ backends/Kconfig | 5 +++ backends/meson.build | 1 + 5 files changed, 89 insertions(+) create mode 100644 include/sysemu/host_iommu_device.h create mode 100644 backends/host_iommu_device.c diff --git a/MAINTAINERS b/MAINTAINERS index 84391777db..5dab60bd04 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2191,6 +2191,8 @@ M: Zhenzhong Duan S: Supported F: backends/iommufd.c F: include/sysemu/iommufd.h +F: backends/host_iommu_device.c +F: include/sysemu/host_iommu_device.h F: include/qemu/chardev_open.h F: util/chardev_open.c F: docs/devel/vfio-iommufd.rst diff --git a/include/sysemu/host_iommu_device.h b/include/sysemu/host_iommu_device.h new file mode 100644 index 00..2b58a94d62 --- /dev/null +++ b/include/sysemu/host_iommu_device.h @@ -0,0 +1,51 @@ +/* + * Host IOMMU device abstract declaration + * + * Copyright (C) 2024 Intel Corporation. + * + * Authors: Zhenzhong Duan + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef HOST_IOMMU_DEVICE_H +#define HOST_IOMMU_DEVICE_H + +#include "qom/object.h" +#include "qapi/error.h" + +#define TYPE_HOST_IOMMU_DEVICE "host-iommu-device" +OBJECT_DECLARE_TYPE(HostIOMMUDevice, HostIOMMUDeviceClass, HOST_IOMMU_DEVICE) + +struct HostIOMMUDevice { +Object parent_obj; +}; + +/** + * struct HostIOMMUDeviceClass - The base class for all host IOMMU devices. + * + * Different type of host devices (e.g., VFIO or VDPA device) or devices + * with different backend (e.g., VFIO legacy container or IOMMUFD backend) + * can have different sub-classes. + */ +struct HostIOMMUDeviceClass { +ObjectClass parent_class; + +/** + * @realize: initialize host IOMMU device instance further. + * + * Mandatory callback. + * + * @hiod: pointer to a host IOMMU device instance. + * + * @opaque: pointer to agent device of this host IOMMU device, + * i.e., for VFIO, pointer to VFIODevice + * + * @errp: pass an Error out when realize fails. + * + * Returns: true on success, false on failure. + */ +bool (*realize)(HostIOMMUDevice *hiod, void *opaque, Error **errp); +}; +#endif diff --git a/backends/host_iommu_device.c b/backends/host_iommu_device.c new file mode 100644 index 00..41f2fdce20 --- /dev/null +++ b/backends/host_iommu_device.c @@ -0,0 +1,30 @@ +/* + * Host IOMMU device abstract + * + * Copyright (C) 2024 Intel Corporation. + * + * Authors: Zhenzhong Duan + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "sysemu/host_iommu_device.h" + +OBJECT_DEFINE_ABSTRACT_TYPE(HostIOMMUDevice, +host_iommu_device, +HOST_IOMMU_DEVICE, +OBJECT) + +static void host_iommu_device_class_init(ObjectClass *oc, void *data) +{ +} + +static void host_iommu_device_init(Object *obj) +{ +} + +static void host_iommu_device_finalize(Object *obj) +{ +} diff --git a/backends/Kconfig b/backends/Kconfig index 2cb23f62fa..34ab29e994 100644 --- a/backends/Kconfig +++ b/backends/Kconfig @@ -3,3 +3,8 @@ source tpm/Kconfig config IOMMUFD bool depends on VFIO + +config HOST_IOMMU_DEVICE +bool +default y +depends on VFIO diff --git a/backends/meson.build b/backends/meson.build index 8b2b111497..2e975d641e 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -25,6 +25,7 @@ if have_vhost_user endif system_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev- vhost.c')) system_ss.add(when: 'CONFIG_IOMMUFD', if_true: files('iommufd.c')) +syste
Re: [PATCH v4 07/16] aspeed/smc: support dma start length and 1 byte length unit
On 5/27/24 10:02, Jamin Lin wrote: DMA length is from 1 byte to 32MB for AST2600 and AST10x0 and DMA length is from 4 bytes to 32MB for AST2500. In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte data for AST2600 and AST10x0 and 4 bytes data for AST2500. To support all ASPEED SOCs, adds dma_start_length parameter to store the start length, add helper routines function to compute the dma length and update DMA_LENGTH mask to "1FF" to support dma 1 byte length unit for AST2600 and AST1030. Currently, only supports dma length 4 bytes aligned. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Thanks, C. --- hw/ssi/aspeed_smc.c | 43 ++--- include/hw/ssi/aspeed_smc.h | 1 + 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 8a8d77b480..ffb13a12e8 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -178,13 +178,17 @@ * DMA flash addresses should be 4 bytes aligned and the valid address * range is 0x2000 - 0x2FFF. * - * DMA length is from 4 bytes to 32MB + * DMA length is from 4 bytes to 32MB (AST2500) * 0: 4 bytes - * 0x7F: 32M bytes + * 0x1FC: 32M bytes + * + * DMA length is from 1 byte to 32MB (AST2600, AST10x0) + * 0: 1 byte + * 0x1FF: 32M bytes */ #define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask) #define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask) -#define DMA_LENGTH(val) ((val) & 0x01FC) +#define DMA_LENGTH(val) ((val) & 0x01FF) /* Flash opcodes. */ #define SPI_OP_READ 0x03/* Read data bytes (low frequency) */ @@ -843,6 +847,13 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s) } } +static uint32_t aspeed_smc_dma_len(AspeedSMCState *s) +{ +AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); + +return QEMU_ALIGN_UP(s->regs[R_DMA_LEN] + asc->dma_start_length, 4); +} + /* * Accumulate the result of the reads to provide a checksum that will * be used to validate the read timing settings. @@ -850,6 +861,7 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s) static void aspeed_smc_dma_checksum(AspeedSMCState *s) { MemTxResult result; +uint32_t dma_len; uint32_t data; if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { @@ -861,7 +873,9 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) aspeed_smc_dma_calibration(s); } -while (s->regs[R_DMA_LEN]) { +dma_len = aspeed_smc_dma_len(s); + +while (dma_len) { data = address_space_ldl_le(>flash_as, s->regs[R_DMA_FLASH_ADDR], MEMTXATTRS_UNSPECIFIED, ); if (result != MEMTX_OK) { @@ -877,7 +891,8 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) */ s->regs[R_DMA_CHECKSUM] += data; s->regs[R_DMA_FLASH_ADDR] += 4; -s->regs[R_DMA_LEN] -= 4; +dma_len -= 4; +s->regs[R_DMA_LEN] = dma_len; } if (s->inject_failure && aspeed_smc_inject_read_failure(s)) { @@ -889,14 +904,17 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) static void aspeed_smc_dma_rw(AspeedSMCState *s) { MemTxResult result; +uint32_t dma_len; uint32_t data; +dma_len = aspeed_smc_dma_len(s); + trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ? "write" : "read", s->regs[R_DMA_FLASH_ADDR], s->regs[R_DMA_DRAM_ADDR], -s->regs[R_DMA_LEN]); -while (s->regs[R_DMA_LEN]) { +dma_len); +while (dma_len) { if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { data = address_space_ldl_le(>dram_as, s->regs[R_DMA_DRAM_ADDR], MEMTXATTRS_UNSPECIFIED, ); @@ -937,7 +955,8 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s) */ s->regs[R_DMA_FLASH_ADDR] += 4; s->regs[R_DMA_DRAM_ADDR] += 4; -s->regs[R_DMA_LEN] -= 4; +dma_len -= 4; +s->regs[R_DMA_LEN] = dma_len; s->regs[R_DMA_CHECKSUM] += data; } } @@ -1381,6 +1400,7 @@ static void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data) asc->features = ASPEED_SMC_FEATURE_DMA; asc->dma_flash_mask= 0x0FFC; asc->dma_dram_mask = 0x1FFC; +asc->dma_start_length = 4; asc->nregs = ASPEED_SMC_R_MAX; asc->segment_to_reg= aspeed_smc_segment_to_reg; asc->reg_to_segment= aspeed_smc_reg_to_segment; @@ -1464,6 +1484,7 @@ static void aspeed_2500_fmc_class_init(ObjectC
Re: [PATCH v4 08/16] aspeed/smc: support 64 bits dma dram address
On 5/27/24 10:02, Jamin Lin wrote: AST2700 support the maximum dram size is 8GiB and has a "DMA DRAM Side Address High Part(0x7C)" register to support 64 bits dma dram address. Add helper routines functions to compute the dma dram address, new features and update trace-event to support 64 bits dram address. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin I will move the addition of the "dram-base" property to another patch. See : https://patchew.org/QEMU/20240527124315.35356-1-...@redhat.com/ (Please review) Else, Reviewed-by: Cédric Le Goater Thanks, C. --- hw/ssi/aspeed_smc.c | 52 +++-- hw/ssi/trace-events | 2 +- include/hw/ssi/aspeed_smc.h | 1 + 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index ffb13a12e8..df0c63469c 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -132,6 +132,9 @@ #define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: primary 1: alternate */ #define FMC_WDT2_CTRL_EN BIT(0) +/* DMA DRAM Side Address High Part (AST2700) */ +#define R_DMA_DRAM_ADDR_HIGH (0x7c / 4) + /* DMA Control/Status Register */ #define R_DMA_CTRL(0x80 / 4) #define DMA_CTRL_REQUEST (1 << 31) @@ -187,6 +190,7 @@ * 0x1FF: 32M bytes */ #define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask) +#define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf) #define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask) #define DMA_LENGTH(val) ((val) & 0x01FF) @@ -207,6 +211,7 @@ static const AspeedSegments aspeed_2500_spi2_segments[]; #define ASPEED_SMC_FEATURE_DMA 0x1 #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2 #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4 +#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08 static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc) { @@ -218,6 +223,11 @@ static inline bool aspeed_smc_has_wdt_control(const AspeedSMCClass *asc) return !!(asc->features & ASPEED_SMC_FEATURE_WDT_CONTROL); } +static inline bool aspeed_smc_has_dma64(const AspeedSMCClass *asc) +{ +return !!(asc->features & ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH); +} + #define aspeed_smc_error(fmt, ...) \ qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__) @@ -747,6 +757,8 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) || (aspeed_smc_has_dma(asc) && addr == R_DMA_FLASH_ADDR) || (aspeed_smc_has_dma(asc) && addr == R_DMA_DRAM_ADDR) || +(aspeed_smc_has_dma(asc) && aspeed_smc_has_dma64(asc) && + addr == R_DMA_DRAM_ADDR_HIGH) || (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) || (aspeed_smc_has_dma(asc) && addr == R_DMA_CHECKSUM) || (addr >= R_SEG_ADDR0 && @@ -847,6 +859,12 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s) } } +static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s) +{ +return s->regs[R_DMA_DRAM_ADDR] | +((uint64_t) s->regs[R_DMA_DRAM_ADDR_HIGH] << 32); +} + static uint32_t aspeed_smc_dma_len(AspeedSMCState *s) { AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); @@ -903,24 +921,34 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) static void aspeed_smc_dma_rw(AspeedSMCState *s) { +AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); +uint64_t dma_dram_offset; +uint64_t dma_dram_addr; MemTxResult result; uint32_t dma_len; uint32_t data; dma_len = aspeed_smc_dma_len(s); +dma_dram_addr = aspeed_smc_dma_dram_addr(s); + +if (aspeed_smc_has_dma64(asc)) { +dma_dram_offset = dma_dram_addr - s->dram_base; +} else { +dma_dram_offset = dma_dram_addr; +} trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ? "write" : "read", s->regs[R_DMA_FLASH_ADDR], -s->regs[R_DMA_DRAM_ADDR], +dma_dram_offset, dma_len); while (dma_len) { if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) { -data = address_space_ldl_le(>dram_as, s->regs[R_DMA_DRAM_ADDR], +data = address_space_ldl_le(>dram_as, dma_dram_offset, MEMTXATTRS_UNSPECIFIED, ); if (result != MEMTX_OK) { -aspeed_smc_error("DRAM read failed @%08x", - s->regs[R_DMA_DRAM_ADDR]); +aspeed_smc_error("DRAM read failed @%" PRIx64, +
[PATCH] aspeed/smc: Reintroduce "dram-base" property for AST2700
The Aspeed SMC device model use to have a 'sdram_base' property. It was removed by commit d177892d4a48 ("aspeed/smc: Remove unused "sdram-base" property") because previous changes simplified the DMA transaction model to use an offset in RAM and not the physical address. The AST2700 SoC has larger address space (64-bit) and a new register DMA DRAM Side Address High Part (0x7C) is introduced to deal with the high bits of the DMA address. To be able to compute the offset of the DMA transaction, as done on the other SoCs, we will need to know where the DRAM is mapped in the address space. Re-introduce a "dram-base" property to hold this value. Signed-off-by: Cédric Le Goater --- include/hw/ssi/aspeed_smc.h | 1 + hw/ssi/aspeed_smc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h index 8e1dda556b91..8791cc0ecb11 100644 --- a/include/hw/ssi/aspeed_smc.h +++ b/include/hw/ssi/aspeed_smc.h @@ -76,6 +76,7 @@ struct AspeedSMCState { AddressSpace flash_as; MemoryRegion *dram_mr; AddressSpace dram_as; +uint64_t dram_base; AspeedSMCFlash flashes[ASPEED_SMC_CS_MAX]; diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 6e1a84c19713..7075bc9d61b0 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -1220,6 +1220,7 @@ static const VMStateDescription vmstate_aspeed_smc = { static Property aspeed_smc_properties[] = { DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false), +DEFINE_PROP_UINT64("dram-base", AspeedSMCState, dram_base, 0), DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_END_OF_LIST(), -- 2.45.1
Re: [PATCH] hw/s390x: Remove unused macro VMSTATE_ADAPTER_ROUTES
On 5/27/24 14:13, Thomas Huth wrote: It's not used anywhere, so let's simply remove it. Signed-off-by: Thomas Huth Reviewed-by: Cédric Le Goater Thanks, C. --- include/hw/s390x/s390_flic.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index bcb081def5..382d9833f1 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -35,9 +35,6 @@ typedef struct AdapterRoutes { extern const VMStateDescription vmstate_adapter_routes; -#define VMSTATE_ADAPTER_ROUTES(_f, _s) \ -VMSTATE_STRUCT(_f, _s, 1, vmstate_adapter_routes, AdapterRoutes) - #define TYPE_S390_FLIC_COMMON "s390-flic" OBJECT_DECLARE_TYPE(S390FLICState, S390FLICStateClass, S390_FLIC_COMMON)
Re: [PATCH v4 05/16] aspeed/sdmc: Add AST2700 support
On 5/27/24 12:24, Philippe Mathieu-Daudé wrote: Hi Jamin, On 27/5/24 10:02, Jamin Lin wrote: The SDRAM memory controller(DRAMC) controls the access to external DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY. The DRAM memory controller of AST2700 is not backward compatible to previous chips such AST2600, AST2500 and AST2400. Max memory is now 8GiB on the AST2700. Introduce new aspeed_2700_sdmc and class with read/write operation and reset handlers. Define DRAMC necessary protected registers and unprotected registers for AST2700 and increase the register set to 0x1000. Add unlocked property to change controller protected status. Signed-off-by: Troy Lee Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater --- hw/misc/aspeed_sdmc.c | 190 +- include/hw/misc/aspeed_sdmc.h | 5 +- 2 files changed, 193 insertions(+), 2 deletions(-) diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h index ec2d59a14f..61c979583a 100644 --- a/include/hw/misc/aspeed_sdmc.h +++ b/include/hw/misc/aspeed_sdmc.h @@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC) #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400" #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500" #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600" +#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700" /* * SDMC has 174 documented registers. In addition the u-boot device tree @@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState, AspeedSDMCClass, ASPEED_SDMC) * time, and the other is in the DDR-PHY IP which is used during DDR-PHY * training. */ -#define ASPEED_SDMC_NR_REGS (0x500 >> 2) +#define ASPEED_SDMC_NR_REGS (0x1000 >> 2) This change breaks the migration stream. Do you mean migration compat ? We never cared much about that for the Aspeed machines. Thanks, C. struct AspeedSDMCState { /*< private >*/ @@ -41,6 +42,7 @@ struct AspeedSDMCState { uint32_t regs[ASPEED_SDMC_NR_REGS]; uint64_t ram_size; uint64_t max_ram_size; + bool unlocked; };
Re: [RFC PATCH 00/10] ppc/pnv: Better big-core model, lpar-per-core, PC unit
On 5/27/24 09:32, Nicholas Piggin wrote: On Mon May 27, 2024 at 4:25 PM AEST, Cédric Le Goater wrote: On 5/26/24 14:26, Nicholas Piggin wrote: Primary motivation for this series is to improve big-core support. Other things like SPR indirect, timebase state, PC xscom, are required for minimal big core support. I'm still not 100% happy with the big-core topology model after this. Maybe one day we add pnv big core and pnv small core structures. But I haven't look at the proposal yet, but indeed, we could introduce a new TYPE_PNV_CORE type for big cores only. Yeah. It's still tricky because big-core structure contains the CPUs if you are running in small core mode. So it would really have to be a PnvCPUCore and PnvPervasiveCore or something, where the former is either SMT4 and 1:1 with the latter or SMT8 and 1:2 depending on mode. And some of the "CPU" type operations in big core mode still need to operate on the small core. For now, the accessors and helpers seem to be not too bad. nothing is completely clean because big core mode still has certain small core restrictions. I think for now we take a bit of mostly abstracted ugliness in TCG code for the benefit of not spreading hacks through pervasive (xscom) core addressing. After this series, power9 and power10 get through skiboot/Linux boot s Have you tried SMT8 on powernv8 ? I remember seeing a hang if I am correct. I don't think POWER8 deserves much attention anymore, we could deprecate POWER8E and POWER8NVL. However, we should at least report an error if we know a setup is broken. Yeah it does have some problem. Maybe should just disable SMT unless someone finds time to work it out. The new _init routines would be a good place to do that. Thanks, C. Thanks, Nick
Re: [PATCH v3 08/16] aspeed/smc: support 64 bits dma dram address
Hello Jamin, [ ... ] See my aspeed-9.1 branch, I did some changes, mostly in the last patch. * aspeed_smc_dma_len() - can use QEMU_ALIGN_UP(). simpler. * aspeed_smc_dma_rw(): - dram_addr -> dma_dram_offset - There is no need to protect updates of the R_DMA_DRAM_ADDR_HIGH register with aspeed_smc_has_dma_dram_addr_high() since it is already protected with MMIO accesses. Skip the check and update always. * aspeed_smc_dma_dram_addr() - same as above. You can merge the changes in the respective patches if you agree. Still on the TODO list : - GIC review - aspeed/soc: fix incorrect dram size for AST2700 Thanks, C. I merged this commit into my code base and thanks for your kindly support. https://github.com/legoater/qemu/commit/d1bc2c776422a9d0d6af2b4414fae83fde1832ba About GIC settings, you can refer to our kernel DTS setting for detail. https://github.com/AspeedTech-BMC/linux/blob/aspeed-master-v6.6/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi#L143-L164 Could you please resend a v4 including all the changes we discussed ? Thanks, C.
Re: [PATCH 0/7] s390x/ccw: Error reporting cleanups
On 5/27/24 08:23, Thomas Huth wrote: On 22/05/2024 19.01, Cédric Le Goater wrote: Hello, The first patches of this series simply apply the practices described in the Rules section of the qapi/error.h file for routines taking an 'Error **' argument. The remaining patches are a fixup in the error path of vfio_ccw_realize() and some error reporting adjustements. Applies on top of this vfio PR : https://lore.kernel.org/qemu-devel/20240522095442.195243-1-...@redhat.com Thanks, C. Cédric Le Goater (6): hw/s390x/ccw: Make s390_ccw_get_dev_info() return a bool s390x/css: Make CCWDeviceClass::realize return bool hw/s390x/ccw: Remove local Error variable from s390_ccw_realize() s390x/css: Make S390CCWDeviceClass::realize return bool vfio/ccw: Use the 'Error **errp' argument of vfio_ccw_realize() vfio/{ap,ccw}: Use warn_report_err() for IRQ notifier registration errors Series Reviewed-by: Thomas Huth Applied to vfio-next. Thanks, C.
Re: [RFC PATCH 00/10] ppc/pnv: Better big-core model, lpar-per-core, PC unit
On 5/26/24 14:26, Nicholas Piggin wrote: Primary motivation for this series is to improve big-core support. Other things like SPR indirect, timebase state, PC xscom, are required for minimal big core support. I'm still not 100% happy with the big-core topology model after this. Maybe one day we add pnv big core and pnv small core structures. But I haven't look at the proposal yet, but indeed, we could introduce a new TYPE_PNV_CORE type for big cores only. nothing is completely clean because big core mode still has certain small core restrictions. I think for now we take a bit of mostly abstracted ugliness in TCG code for the benefit of not spreading hacks through pervasive (xscom) core addressing. After this series, power9 and power10 get through skiboot/Linux boot s Have you tried SMT8 on powernv8 ? I remember seeing a hang if I am correct. I don't think POWER8 deserves much attention anymore, we could deprecate POWER8E and POWER8NVL. However, we should at least report an error if we know a setup is broken. Thanks, C. Not all big core registers are modeled exactly (some are not shared between small core halves), but that mostly doesn't matter for OPAL and it can be improved later. Thanks, Nick Nicholas Piggin (10): ppc/pnv: Add pointer from PnvCPUState to PnvCore ppc/pnv: Move timebase state into PnvCore target/ppc: Improve SPR indirect registers ppc/pnv: specialise init for powernv8/9/10 machines ppc/pnv: Extend chip_pir class method to TIR as well ppc: Add a core_index to CPUPPCState for SMT vCPUs target/ppc: Add helpers to check for SMT sibling threads ppc/pnv: Invert the design for big-core machine modelling ppc/pnv: Implement POWER10 PC xscom registers for direct controls ppc/pnv: Add an LPAR per core machine option include/hw/core/cpu.h| 8 + include/hw/ppc/pnv.h | 6 + include/hw/ppc/pnv_chip.h| 3 +- include/hw/ppc/pnv_core.h| 31 target/ppc/cpu.h | 37 ++--- hw/ppc/pnv.c | 297 --- hw/ppc/pnv_chiptod.c | 6 +- hw/ppc/pnv_core.c| 129 +-- hw/ppc/spapr_cpu_core.c | 7 + system/cpus.c| 10 ++ target/ppc/cpu_init.c| 26 +-- target/ppc/excp_helper.c | 16 +- target/ppc/misc_helper.c | 98 ++-- target/ppc/timebase_helper.c | 82 +- 14 files changed, 548 insertions(+), 208 deletions(-)
Re: [PATCH 6/7] vfio/ccw: Fix the missed unrealize() call in error path
On 5/22/24 19:01, Cédric Le Goater wrote: From: Zhenzhong Duan When get name failed, we should call unrealize() so that vfio_ccw_realize() is self contained. Fixes: 909a6254eda ("vfio/ccw: Make vfio cdev pre-openable by passing a file handle") Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Thanks, C. --- hw/vfio/ccw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index a468fa2342b97e0ee36bd5fb8443025cc90a0453..36f2677a448c5e31523dcc3de7d973ec70e4a13c 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -588,7 +588,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) } if (!vfio_device_get_name(vbasedev, errp)) { -return; +goto out_unrealize; } if (!vfio_attach_device(cdev->mdevid, vbasedev, @@ -631,6 +631,7 @@ out_region_err: vfio_detach_device(vbasedev); out_attach_dev_err: g_free(vbasedev->name); +out_unrealize: if (cdc->unrealize) { cdc->unrealize(cdev); }
[PATCH 3/7] hw/s390x/ccw: Remove local Error variable from s390_ccw_realize()
Use the 'Error **errp' argument of s390_ccw_realize() instead and remove the error_propagate() call. Signed-off-by: Cédric Le Goater --- hw/s390x/s390-ccw.c | 13 + 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index 4b8ede701df90949720262b6fc1b65f4e505e34d..b3d14c61d732880a651edcf28a040ca723cb9f5b 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -115,13 +115,12 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) DeviceState *parent = DEVICE(ccw_dev); SubchDev *sch; int ret; -Error *err = NULL; -if (!s390_ccw_get_dev_info(cdev, sysfsdev, )) { -goto out_err_propagate; +if (!s390_ccw_get_dev_info(cdev, sysfsdev, errp)) { +return; } -sch = css_create_sch(ccw_dev->devno, ); +sch = css_create_sch(ccw_dev->devno, errp); if (!sch) { goto out_mdevid_free; } @@ -132,12 +131,12 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) ccw_dev->sch = sch; ret = css_sch_build_schib(sch, >hostid); if (ret) { -error_setg_errno(, -ret, "%s: Failed to build initial schib", +error_setg_errno(errp, -ret, "%s: Failed to build initial schib", __func__); goto out_err; } -if (!ck->realize(ccw_dev, )) { +if (!ck->realize(ccw_dev, errp)) { goto out_err; } @@ -151,8 +150,6 @@ out_err: g_free(sch); out_mdevid_free: g_free(cdev->mdevid); -out_err_propagate: -error_propagate(errp, err); } static void s390_ccw_unrealize(S390CCWDevice *cdev) -- 2.45.1
[PATCH 6/7] vfio/ccw: Fix the missed unrealize() call in error path
From: Zhenzhong Duan When get name failed, we should call unrealize() so that vfio_ccw_realize() is self contained. Fixes: 909a6254eda ("vfio/ccw: Make vfio cdev pre-openable by passing a file handle") Signed-off-by: Zhenzhong Duan --- hw/vfio/ccw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index a468fa2342b97e0ee36bd5fb8443025cc90a0453..36f2677a448c5e31523dcc3de7d973ec70e4a13c 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -588,7 +588,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) } if (!vfio_device_get_name(vbasedev, errp)) { -return; +goto out_unrealize; } if (!vfio_attach_device(cdev->mdevid, vbasedev, @@ -631,6 +631,7 @@ out_region_err: vfio_detach_device(vbasedev); out_attach_dev_err: g_free(vbasedev->name); +out_unrealize: if (cdc->unrealize) { cdc->unrealize(cdev); } -- 2.45.1
[PATCH 7/7] vfio/{ap, ccw}: Use warn_report_err() for IRQ notifier registration errors
vfio_ccw_register_irq_notifier() and vfio_ap_register_irq_notifier() errors are currently reported using error_report_err(). Since they are not considered as failing conditions, using warn_report_err() is more appropriate. Signed-off-by: Cédric Le Goater --- hw/vfio/ap.c | 2 +- hw/vfio/ccw.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c index c12531a7886a2fe87598be0861fba5923bd2c206..0c4354e3e70169ec072e16da0919936647d1d351 100644 --- a/hw/vfio/ap.c +++ b/hw/vfio/ap.c @@ -172,7 +172,7 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp) * Report this error, but do not make it a failing condition. * Lack of this IRQ in the host does not prevent normal operation. */ -error_report_err(err); +warn_report_err(err); } return; diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 36f2677a448c5e31523dcc3de7d973ec70e4a13c..1f8e1272c7555cd0a770481d1ae92988f6e2e62e 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -616,7 +616,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) * Report this error, but do not make it a failing condition. * Lack of this IRQ in the host does not prevent normal operation. */ -error_report_err(err); +warn_report_err(err); } return; -- 2.45.1
[PATCH 4/7] s390x/css: Make S390CCWDeviceClass::realize return bool
Since the realize() handler of S390CCWDeviceClass takes an 'Error **' argument, best practices suggest to return a bool. See the api/error.h Rules section. While at it, modify the call in vfio_ccw_realize(). Signed-off-by: Cédric Le Goater --- include/hw/s390x/s390-ccw.h | 2 +- hw/s390x/s390-ccw.c | 7 --- hw/vfio/ccw.c | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h index 2c807ee3a1ae8d85460fe65be8a62c64f212fe4b..2e0a70998132070996d6b0d083b8ddba5b9b87dc 100644 --- a/include/hw/s390x/s390-ccw.h +++ b/include/hw/s390x/s390-ccw.h @@ -31,7 +31,7 @@ struct S390CCWDevice { struct S390CCWDeviceClass { CCWDeviceClass parent_class; -void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp); +bool (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp); void (*unrealize)(S390CCWDevice *dev); IOInstEnding (*handle_request) (SubchDev *sch); int (*handle_halt) (SubchDev *sch); diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index b3d14c61d732880a651edcf28a040ca723cb9f5b..3c0975055089c3629dd76ce2e1484a4ef66d8d41 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -108,7 +108,7 @@ static bool s390_ccw_get_dev_info(S390CCWDevice *cdev, return true; } -static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) +static bool s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) { CcwDevice *ccw_dev = CCW_DEVICE(cdev); CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev); @@ -117,7 +117,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) int ret; if (!s390_ccw_get_dev_info(cdev, sysfsdev, errp)) { -return; +return false; } sch = css_create_sch(ccw_dev->devno, errp); @@ -142,7 +142,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, parent->hotplugged, 1); -return; +return true; out_err: css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL); @@ -150,6 +150,7 @@ out_err: g_free(sch); out_mdevid_free: g_free(cdev->mdevid); +return false; } static void s390_ccw_unrealize(S390CCWDevice *cdev) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 2600e62e37238779800dc2b3a0bd315d7633017b..9a8e052711fe2f7c067c52808b2af30d0ebfee0c 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -582,8 +582,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) /* Call the class init function for subchannel. */ if (cdc->realize) { -cdc->realize(cdev, vcdev->vdev.sysfsdev, ); -if (err) { +if (!cdc->realize(cdev, vcdev->vdev.sysfsdev, )) { goto out_err_propagate; } } -- 2.45.1
[PATCH 5/7] vfio/ccw: Use the 'Error **errp' argument of vfio_ccw_realize()
The local error variable is kept for vfio_ccw_register_irq_notifier() because it is not considered as a failing condition. We will change how error reporting is done in following changes. Remove the error_propagate() call. Cc: Zhenzhong Duan Signed-off-by: Cédric Le Goater --- hw/vfio/ccw.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 9a8e052711fe2f7c067c52808b2af30d0ebfee0c..a468fa2342b97e0ee36bd5fb8443025cc90a0453 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -582,8 +582,8 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) /* Call the class init function for subchannel. */ if (cdc->realize) { -if (!cdc->realize(cdev, vcdev->vdev.sysfsdev, )) { -goto out_err_propagate; +if (!cdc->realize(cdev, vcdev->vdev.sysfsdev, errp)) { +return; } } @@ -596,17 +596,17 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) goto out_attach_dev_err; } -if (!vfio_ccw_get_region(vcdev, )) { +if (!vfio_ccw_get_region(vcdev, errp)) { goto out_region_err; } -if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, )) { +if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, errp)) { goto out_io_notifier_err; } if (vcdev->crw_region) { if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, -)) { +errp)) { goto out_irq_notifier_err; } } @@ -634,8 +634,6 @@ out_attach_dev_err: if (cdc->unrealize) { cdc->unrealize(cdev); } -out_err_propagate: -error_propagate(errp, err); } static void vfio_ccw_unrealize(DeviceState *dev) -- 2.45.1
[PATCH 0/7] s390x/ccw: Error reporting cleanups
Hello, The first patches of this series simply apply the practices described in the Rules section of the qapi/error.h file for routines taking an 'Error **' argument. The remaining patches are a fixup in the error path of vfio_ccw_realize() and some error reporting adjustements. Applies on top of this vfio PR : https://lore.kernel.org/qemu-devel/20240522095442.195243-1-...@redhat.com Thanks, C. Cédric Le Goater (6): hw/s390x/ccw: Make s390_ccw_get_dev_info() return a bool s390x/css: Make CCWDeviceClass::realize return bool hw/s390x/ccw: Remove local Error variable from s390_ccw_realize() s390x/css: Make S390CCWDeviceClass::realize return bool vfio/ccw: Use the 'Error **errp' argument of vfio_ccw_realize() vfio/{ap,ccw}: Use warn_report_err() for IRQ notifier registration errors Zhenzhong Duan (1): vfio/ccw: Fix the missed unrealize() call in error path hw/s390x/ccw-device.h | 2 +- include/hw/s390x/s390-ccw.h | 2 +- hw/s390x/ccw-device.c | 3 ++- hw/s390x/s390-ccw.c | 29 + hw/vfio/ap.c| 2 +- hw/vfio/ccw.c | 18 -- 6 files changed, 26 insertions(+), 30 deletions(-) -- 2.45.1
[PATCH 1/7] hw/s390x/ccw: Make s390_ccw_get_dev_info() return a bool
Since s390_ccw_get_dev_info() takes an 'Error **' argument, best practices suggest to return a bool. See the qapi/error.h Rules section. While at it, modify the call in s390_ccw_realize(). Signed-off-by: Cédric Le Goater --- hw/s390x/s390-ccw.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index 5261e66724f1cc3157b9413b0d5fdf5289c92503..a06e91dfb318e3500324851488c56806fa46c08d 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -71,7 +71,7 @@ IOInstEnding s390_ccw_store(SubchDev *sch) return ret; } -static void s390_ccw_get_dev_info(S390CCWDevice *cdev, +static bool s390_ccw_get_dev_info(S390CCWDevice *cdev, char *sysfsdev, Error **errp) { @@ -84,12 +84,12 @@ static void s390_ccw_get_dev_info(S390CCWDevice *cdev, error_setg(errp, "No host device provided"); error_append_hint(errp, "Use -device vfio-ccw,sysfsdev=PATH_TO_DEVICE\n"); -return; +return false; } if (!realpath(sysfsdev, dev_path)) { error_setg_errno(errp, errno, "Host device '%s' not found", sysfsdev); -return; +return false; } cdev->mdevid = g_path_get_basename(dev_path); @@ -98,13 +98,14 @@ static void s390_ccw_get_dev_info(S390CCWDevice *cdev, tmp = g_path_get_basename(tmp_dir); if (sscanf(tmp, "%2x.%1x.%4x", , , ) != 3) { error_setg_errno(errp, errno, "Failed to read %s", tmp); -return; +return false; } cdev->hostid.cssid = cssid; cdev->hostid.ssid = ssid; cdev->hostid.devid = devid; cdev->hostid.valid = true; +return true; } static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) @@ -116,8 +117,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) int ret; Error *err = NULL; -s390_ccw_get_dev_info(cdev, sysfsdev, ); -if (err) { +if (!s390_ccw_get_dev_info(cdev, sysfsdev, )) { goto out_err_propagate; } -- 2.45.1
[PATCH 2/7] s390x/css: Make CCWDeviceClass::realize return bool
Since the realize() handler of CCWDeviceClass takes an 'Error **' argument, best practices suggest to return a bool. See the api/error.h Rules section. While at it, modify the call in s390_ccw_realize(). Signed-off-by: Cédric Le Goater --- hw/s390x/ccw-device.h | 2 +- hw/s390x/ccw-device.c | 3 ++- hw/s390x/s390-ccw.c | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h index 6dff95225df11c63f9b66975019026b215c8c448..5feeb0ee7a268b8709043b5bbc56b06e707a448d 100644 --- a/hw/s390x/ccw-device.h +++ b/hw/s390x/ccw-device.h @@ -36,7 +36,7 @@ extern const VMStateDescription vmstate_ccw_dev; struct CCWDeviceClass { DeviceClass parent_class; void (*unplug)(HotplugHandler *, DeviceState *, Error **); -void (*realize)(CcwDevice *, Error **); +bool (*realize)(CcwDevice *, Error **); void (*refill_ids)(CcwDevice *); }; diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c index fb8c1acc64d5002c861a4913f292d8346dbef192..a7d682e5af9ce90e7e2fad8c24b30e39328c7cf4 100644 --- a/hw/s390x/ccw-device.c +++ b/hw/s390x/ccw-device.c @@ -31,9 +31,10 @@ static void ccw_device_refill_ids(CcwDevice *dev) dev->subch_id.valid = true; } -static void ccw_device_realize(CcwDevice *dev, Error **errp) +static bool ccw_device_realize(CcwDevice *dev, Error **errp) { ccw_device_refill_ids(dev); +return true; } static Property ccw_device_properties[] = { diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index a06e91dfb318e3500324851488c56806fa46c08d..4b8ede701df90949720262b6fc1b65f4e505e34d 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -137,8 +137,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) goto out_err; } -ck->realize(ccw_dev, ); -if (err) { +if (!ck->realize(ccw_dev, )) { goto out_err; } -- 2.45.1
[PULL 30/47] vfio/display: Fix error path in call site of ramfb_setup()
From: Zhenzhong Duan vfio_display_dmabuf_init() and vfio_display_region_init() calls ramfb_setup() without checking its return value. So we may run into a situation that vfio_display_probe() succeed but errp is set. This is risky and may lead to assert failure in error_setv(). Cc: Gerd Hoffmann Fixes: b290659fc3d ("hw/vfio/display: add ramfb support") Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/display.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/hw/vfio/display.c b/hw/vfio/display.c index fe624a6c9b86e7204e2763ab62ef60903f19d350..d28b724102d5970cb2b9dc7464dc7575b6f441d9 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -361,6 +361,9 @@ static int vfio_display_dmabuf_init(VFIOPCIDevice *vdev, Error **errp) vdev); if (vdev->enable_ramfb) { vdev->dpy->ramfb = ramfb_setup(errp); +if (!vdev->dpy->ramfb) { +return -EINVAL; +} } vfio_display_edid_init(vdev); return 0; @@ -488,6 +491,9 @@ static int vfio_display_region_init(VFIOPCIDevice *vdev, Error **errp) vdev); if (vdev->enable_ramfb) { vdev->dpy->ramfb = ramfb_setup(errp); +if (!vdev->dpy->ramfb) { +return -EINVAL; +} } return 0; } -- 2.45.1
[PULL 24/47] vfio/container: Make vfio_connect_container() return bool
From: Zhenzhong Duan This is to follow the coding standand to return bool if 'Error **' is used to pass error. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/container.c | 18 +++--- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/vfio/container.c b/hw/vfio/container.c index f2e9560a1906c4151535260e3488ee80ca90e78b..802828ddff061fef25b8e4c997a68348d4be9892 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -536,8 +536,8 @@ static bool vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp) return true; } -static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - Error **errp) +static bool vfio_connect_container(VFIOGroup *group, AddressSpace *as, + Error **errp) { VFIOContainer *container; VFIOContainerBase *bcontainer; @@ -589,19 +589,18 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, error_report("vfio: error disconnecting group %d from" " container", group->groupid); } -return ret; +return false; } group->container = container; QLIST_INSERT_HEAD(>group_list, group, container_next); vfio_kvm_device_add_group(group); -return 0; +return true; } } fd = qemu_open_old("/dev/vfio/vfio", O_RDWR); if (fd < 0) { error_setg_errno(errp, errno, "failed to open /dev/vfio/vfio"); -ret = -errno; goto put_space_exit; } @@ -609,7 +608,6 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, if (ret != VFIO_API_VERSION) { error_setg(errp, "supported vfio version: %d, " "reported version: %d", VFIO_API_VERSION, ret); -ret = -EINVAL; goto close_fd_exit; } @@ -636,7 +634,6 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, assert(bcontainer->ops->setup); if (!bcontainer->ops->setup(bcontainer, errp)) { -ret = -EINVAL; goto enable_discards_exit; } @@ -652,7 +649,6 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, memory_listener_register(>listener, bcontainer->space->as); if (bcontainer->error) { -ret = -1; error_propagate_prepend(errp, bcontainer->error, "memory listener initialization failed: "); goto listener_release_exit; @@ -660,7 +656,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, bcontainer->initialized = true; -return 0; +return true; listener_release_exit: QLIST_REMOVE(group, container_next); QLIST_REMOVE(bcontainer, next); @@ -685,7 +681,7 @@ close_fd_exit: put_space_exit: vfio_put_address_space(space); -return ret; +return false; } static void vfio_disconnect_container(VFIOGroup *group) @@ -772,7 +768,7 @@ static VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp) group->groupid = groupid; QLIST_INIT(>device_list); -if (vfio_connect_container(group, as, errp)) { +if (!vfio_connect_container(group, as, errp)) { error_prepend(errp, "failed to setup container for group %d: ", groupid); goto close_fd_exit; -- 2.45.1
[PULL 45/47] vfio/pci-quirks: Make vfio_add_*_cap() return bool
From: Zhenzhong Duan This is to follow the coding standand in qapi/error.h to return bool for bool-valued functions. Include below functions: vfio_add_virt_caps() vfio_add_nv_gpudirect_cap() vfio_add_vmd_shadow_cap() Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/pci.h| 2 +- hw/vfio/pci-quirks.c | 42 +++--- hw/vfio/pci.c| 3 +-- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h index f1586810726584ecfc35ef685646faacabefbec0..bf67df2fbc09b3d0fd97d25dfaa5290ab33b03ea 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h @@ -212,7 +212,7 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr); void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr); void vfio_bar_quirk_finalize(VFIOPCIDevice *vdev, int nr); void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev); -int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp); +bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp); void vfio_quirk_reset(VFIOPCIDevice *vdev); VFIOQuirk *vfio_quirk_alloc(int nr_mem); void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr); diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c index ca27917159785f760f688c8db0a9ac492080d74b..39dae72497e0315eeb580dbcd5255c58bc38c8ed 100644 --- a/hw/vfio/pci-quirks.c +++ b/hw/vfio/pci-quirks.c @@ -1536,7 +1536,7 @@ static bool is_valid_std_cap_offset(uint8_t pos) pos <= (PCI_CFG_SPACE_SIZE - PCI_CAP_SIZEOF)); } -static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) +static bool vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) { ERRP_GUARD(); PCIDevice *pdev = >pdev; @@ -1545,18 +1545,18 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) uint8_t tmp; if (vdev->nv_gpudirect_clique == 0xFF) { -return 0; +return true; } if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID)) { error_setg(errp, "NVIDIA GPUDirect Clique ID: invalid device vendor"); -return -EINVAL; +return false; } if (pci_get_byte(pdev->config + PCI_CLASS_DEVICE + 1) != PCI_BASE_CLASS_DISPLAY) { error_setg(errp, "NVIDIA GPUDirect Clique ID: unsupported PCI class"); -return -EINVAL; +return false; } /* @@ -1572,7 +1572,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) vdev->config_offset + PCI_CAPABILITY_LIST); if (ret != 1 || !is_valid_std_cap_offset(tmp)) { error_setg(errp, "NVIDIA GPUDirect Clique ID: error getting cap list"); -return -EINVAL; +return false; } do { @@ -1590,13 +1590,13 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) pos = 0xD4; } else { error_setg(errp, "NVIDIA GPUDirect Clique ID: invalid config space"); -return -EINVAL; +return false; } ret = pci_add_capability(pdev, PCI_CAP_ID_VNDR, pos, 8, errp); if (ret < 0) { error_prepend(errp, "Failed to add NVIDIA GPUDirect cap: "); -return ret; +return false; } memset(vdev->emulated_config_bits + pos, 0xFF, 8); @@ -1608,7 +1608,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) pci_set_byte(pdev->config + pos++, vdev->nv_gpudirect_clique << 3); pci_set_byte(pdev->config + pos, 0); -return 0; +return true; } /* @@ -1629,7 +1629,7 @@ static int vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp) */ #define VMD_SHADOW_CAP_VER 1 #define VMD_SHADOW_CAP_LEN 24 -static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp) +static bool vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp) { ERRP_GUARD(); uint8_t membar_phys[16]; @@ -1639,7 +1639,7 @@ static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp) vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x467F) || vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x4C3D) || vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, 0x9A0B))) { -return 0; +return true; } ret = pread(vdev->vbasedev.fd, membar_phys, 16, @@ -1647,14 +1647,14 @@ static int vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp) if (ret != 16) { error_report("VMD %s cannot read MEMBARs (%d)", vdev->vbasedev.name, ret); -return -EFAULT; +return false; } ret = pci_add_capability(>pdev, PCI_CAP_ID_VNDR, pos, VMD_SHADOW_CAP_LEN, errp); if (ret < 0) { error_prepend(errp, "Failed to add VMD MEMBAR Shadow cap: "); -return ret; +return false; } memset(v
[PULL 46/47] vfio: Use g_autofree in all call site of vfio_get_region_info()
From: Zhenzhong Duan There are some exceptions when pointer to vfio_region_info is reused. In that case, the pointed memory is freed manually. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/helpers.c | 7 ++- hw/vfio/igd.c | 5 ++--- hw/vfio/pci.c | 13 +++-- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 4b079dc383683a71d1d96507a0fb66a4bc3ba923..27ea26aa48f67e6518f871ac651ab8d2703cc611 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -343,7 +343,7 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *region, int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, int index, const char *name) { -struct vfio_region_info *info; +g_autofree struct vfio_region_info *info = NULL; int ret; ret = vfio_get_region_info(vbasedev, index, ); @@ -376,8 +376,6 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, } } -g_free(info); - trace_vfio_region_setup(vbasedev->name, index, name, region->flags, region->fd_offset, region->size); return 0; @@ -594,14 +592,13 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) { -struct vfio_region_info *info = NULL; +g_autofree struct vfio_region_info *info = NULL; bool ret = false; if (!vfio_get_region_info(vbasedev, region, )) { if (vfio_get_region_info_cap(info, cap_type)) { ret = true; } -g_free(info); } return ret; diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c index 402fc5ce1da966fda1340f328e0611cb1a2a0635..1e79202f2bd136b0bafd4f08c2f1407e467e0d65 100644 --- a/hw/vfio/igd.c +++ b/hw/vfio/igd.c @@ -367,8 +367,8 @@ static const MemoryRegionOps vfio_igd_index_quirk = { void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) { -struct vfio_region_info *rom = NULL, *opregion = NULL, -*host = NULL, *lpc = NULL; +g_autofree struct vfio_region_info *rom = NULL; +struct vfio_region_info *opregion = NULL, *host = NULL, *lpc = NULL; VFIOQuirk *quirk; VFIOIGDQuirk *igd; PCIDevice *lpc_bridge; @@ -609,7 +609,6 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb); out: -g_free(rom); g_free(opregion); g_free(host); g_free(lpc); diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 35ad9b582f6b99510a812edab5c2855c697a1da2..74a79bdf61f9aeb4860d532b6c076dd3491dd0ab 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -879,7 +879,7 @@ static void vfio_update_msi(VFIOPCIDevice *vdev) static void vfio_pci_load_rom(VFIOPCIDevice *vdev) { -struct vfio_region_info *reg_info; +g_autofree struct vfio_region_info *reg_info = NULL; uint64_t size; off_t off = 0; ssize_t bytes; @@ -897,8 +897,6 @@ static void vfio_pci_load_rom(VFIOPCIDevice *vdev) vdev->rom_size = size = reg_info->size; vdev->rom_offset = reg_info->offset; -g_free(reg_info); - if (!vdev->rom_size) { vdev->rom_read_failed = true; error_report("vfio-pci: Cannot read device rom at " @@ -2668,7 +2666,7 @@ static VFIODeviceOps vfio_pci_ops = { bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) { VFIODevice *vbasedev = >vbasedev; -struct vfio_region_info *reg_info; +g_autofree struct vfio_region_info *reg_info = NULL; int ret; ret = vfio_get_region_info(vbasedev, VFIO_PCI_VGA_REGION_INDEX, _info); @@ -2685,7 +2683,6 @@ bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) error_setg(errp, "unexpected VGA info, flags 0x%lx, size 0x%lx", (unsigned long)reg_info->flags, (unsigned long)reg_info->size); -g_free(reg_info); return false; } @@ -2694,8 +2691,6 @@ bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) vdev->vga->fd_offset = reg_info->offset; vdev->vga->fd = vdev->vbasedev.fd; -g_free(reg_info); - vdev->vga->region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE; vdev->vga->region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM; QLIST_INIT(>vga->region[QEMU_PCI_VGA_MEM].quirks); @@ -2736,7 +2731,7 @@ bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) static bool vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) { VFIODevice *vbasedev = >vbasedev; -struct vfio_region_info *reg_info; +g_autofree struct vfio_region_info *reg_info = NULL; struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) }; int i, ret = -1; @@ -27
[PULL 16/47] vfio/migration: Emit VFIO migration QAPI event
From: Avihai Horon Emit VFIO migration QAPI event when a VFIO device changes its migration state. This can be used by management applications to get updates on the current state of the VFIO device for their own purposes. A new per VFIO device capability, "migration-events", is added so events can be enabled only for the required devices. It is disabled by default. Signed-off-by: Avihai Horon Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-common.h | 1 + hw/vfio/migration.c | 59 +-- hw/vfio/pci.c | 2 ++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b6ac24953667bc5f72f28480a6bf0f4722069cb9..878e34a12874f63fcb8bbc8dc8ca3d2dfa84fdb4 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -115,6 +115,7 @@ typedef struct VFIODevice { bool no_mmap; bool ram_block_discard_allowed; OnOffAuto enable_migration; +bool migration_events; VFIODeviceOps *ops; unsigned int num_irqs; unsigned int num_regions; diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index c4403a38ddb5e7e09fbcde0ad4132653ecaf0d24..af579b868d7caa726fde1eeb73c832ebc3136a7a 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -24,6 +24,7 @@ #include "migration/register.h" #include "migration/blocker.h" #include "qapi/error.h" +#include "qapi/qapi-events-vfio.h" #include "exec/ramlist.h" #include "exec/ram_addr.h" #include "pci.h" @@ -80,6 +81,58 @@ static const char *mig_state_to_str(enum vfio_device_mig_state state) } } +static VfioMigrationState +mig_state_to_qapi_state(enum vfio_device_mig_state state) +{ +switch (state) { +case VFIO_DEVICE_STATE_STOP: +return QAPI_VFIO_MIGRATION_STATE_STOP; +case VFIO_DEVICE_STATE_RUNNING: +return QAPI_VFIO_MIGRATION_STATE_RUNNING; +case VFIO_DEVICE_STATE_STOP_COPY: +return QAPI_VFIO_MIGRATION_STATE_STOP_COPY; +case VFIO_DEVICE_STATE_RESUMING: +return QAPI_VFIO_MIGRATION_STATE_RESUMING; +case VFIO_DEVICE_STATE_RUNNING_P2P: +return QAPI_VFIO_MIGRATION_STATE_RUNNING_P2P; +case VFIO_DEVICE_STATE_PRE_COPY: +return QAPI_VFIO_MIGRATION_STATE_PRE_COPY; +case VFIO_DEVICE_STATE_PRE_COPY_P2P: +return QAPI_VFIO_MIGRATION_STATE_PRE_COPY_P2P; +default: +g_assert_not_reached(); +} +} + +static void vfio_migration_send_event(VFIODevice *vbasedev) +{ +VFIOMigration *migration = vbasedev->migration; +DeviceState *dev = vbasedev->dev; +g_autofree char *qom_path = NULL; +Object *obj; + +if (!vbasedev->migration_events) { +return; +} + +g_assert(vbasedev->ops->vfio_get_object); +obj = vbasedev->ops->vfio_get_object(vbasedev); +g_assert(obj); +qom_path = object_get_canonical_path(obj); + +qapi_event_send_vfio_migration( +dev->id, qom_path, mig_state_to_qapi_state(migration->device_state)); +} + +static void vfio_migration_set_device_state(VFIODevice *vbasedev, +enum vfio_device_mig_state state) +{ +VFIOMigration *migration = vbasedev->migration; + +migration->device_state = state; +vfio_migration_send_event(vbasedev); +} + static int vfio_migration_set_state(VFIODevice *vbasedev, enum vfio_device_mig_state new_state, enum vfio_device_mig_state recover_state, @@ -131,12 +184,12 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, goto reset_device; } -migration->device_state = recover_state; +vfio_migration_set_device_state(vbasedev, recover_state); return ret; } -migration->device_state = new_state; +vfio_migration_set_device_state(vbasedev, new_state); if (mig_state->data_fd != -1) { if (migration->data_fd != -1) { /* @@ -162,7 +215,7 @@ reset_device: strerror(errno)); } -migration->device_state = VFIO_DEVICE_STATE_RUNNING; +vfio_migration_set_device_state(vbasedev, VFIO_DEVICE_STATE_RUNNING); return ret; } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 4789d43c0f9cc7ef94b73adc815377f7222d8c57..b5d1d398b120076c85cdd92d61793393f65e8554 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -3388,6 +3388,8 @@ static Property vfio_pci_dev_properties[] = { VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT, false), DEFINE_PROP_ON_OFF_AUTO("enable-migration", VFIOPCIDevice, vbasedev.enable_migration, ON_OFF_AUTO_AUTO), +DEFINE_PROP_BOOL("migration-events", VFIOPCIDevice, + vbasedev.migration_
[PULL 21/47] vfio: Make VFIOIOMMUClass::attach_device() and its wrapper return bool
From: Zhenzhong Duan Make VFIOIOMMUClass::attach_device() and its wrapper function vfio_attach_device() return bool. This is to follow the coding standand to return bool if 'Error **' is used to pass error. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-common.h | 4 ++-- include/hw/vfio/vfio-container-base.h | 4 ++-- hw/vfio/ap.c | 6 ++ hw/vfio/ccw.c | 6 ++ hw/vfio/common.c | 4 ++-- hw/vfio/container.c | 14 +++--- hw/vfio/iommufd.c | 11 +-- hw/vfio/pci.c | 5 ++--- hw/vfio/platform.c| 7 +++ 9 files changed, 27 insertions(+), 34 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 878e34a12874f63fcb8bbc8dc8ca3d2dfa84fdb4..e85817e65e65317d08bc2b17b738449198784796 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -222,8 +222,8 @@ void vfio_region_exit(VFIORegion *region); void vfio_region_finalize(VFIORegion *region); void vfio_reset_handler(void *opaque); struct vfio_device_info *vfio_get_device_info(int fd); -int vfio_attach_device(char *name, VFIODevice *vbasedev, - AddressSpace *as, Error **errp); +bool vfio_attach_device(char *name, VFIODevice *vbasedev, +AddressSpace *as, Error **errp); void vfio_detach_device(VFIODevice *vbasedev); int vfio_kvm_device_add_fd(int fd, Error **errp); diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h index b04057ad1aff73d974ecec718d0fe45f7a930b59..44927ca8c3583246145defe043ac34da604d39bf 100644 --- a/include/hw/vfio/vfio-container-base.h +++ b/include/hw/vfio/vfio-container-base.h @@ -117,8 +117,8 @@ struct VFIOIOMMUClass { int (*dma_unmap)(const VFIOContainerBase *bcontainer, hwaddr iova, ram_addr_t size, IOMMUTLBEntry *iotlb); -int (*attach_device)(const char *name, VFIODevice *vbasedev, - AddressSpace *as, Error **errp); +bool (*attach_device)(const char *name, VFIODevice *vbasedev, + AddressSpace *as, Error **errp); void (*detach_device)(VFIODevice *vbasedev); /* migration feature */ diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c index 8bb024e2fde4a1d72346dee4b662d762374326b9..ba653ef70f08ebdf482009baafc62eb33ebda9a8 100644 --- a/hw/vfio/ap.c +++ b/hw/vfio/ap.c @@ -154,7 +154,6 @@ static void vfio_ap_unregister_irq_notifier(VFIOAPDevice *vapdev, static void vfio_ap_realize(DeviceState *dev, Error **errp) { ERRP_GUARD(); -int ret; Error *err = NULL; VFIOAPDevice *vapdev = VFIO_AP_DEVICE(dev); VFIODevice *vbasedev = >vdev; @@ -163,9 +162,8 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp) return; } -ret = vfio_attach_device(vbasedev->name, vbasedev, - _space_memory, errp); -if (ret) { +if (!vfio_attach_device(vbasedev->name, vbasedev, +_space_memory, errp)) { goto error; } diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 1c630f6e9abe93ae0c2b5615d4409669f096c8c9..89bb98016764e65cf826183d7a38c59d429f6eeb 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -579,7 +579,6 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); VFIODevice *vbasedev = >vdev; Error *err = NULL; -int ret; /* Call the class init function for subchannel. */ if (cdc->realize) { @@ -593,9 +592,8 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) return; } -ret = vfio_attach_device(cdev->mdevid, vbasedev, - _space_memory, errp); -if (ret) { +if (!vfio_attach_device(cdev->mdevid, vbasedev, +_space_memory, errp)) { goto out_attach_dev_err; } diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 1fbd10801d35079341a833fa68a43de2b758cde0..c04a259ffd7cfcfba480335bea1ddff787f47bdc 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1523,8 +1523,8 @@ retry: return info; } -int vfio_attach_device(char *name, VFIODevice *vbasedev, - AddressSpace *as, Error **errp) +bool vfio_attach_device(char *name, VFIODevice *vbasedev, +AddressSpace *as, Error **errp) { const VFIOIOMMUClass *ops = VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_LEGACY)); diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 9534120d4ac835bb58e37667dad8d39205404c08..e7c416774791d506cc7c4696fb6a6d94dc809c8e 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -910,8 +910,8 @@ static in
[PULL 22/47] vfio: Make VFIOIOMMUClass::setup() return bool
From: Zhenzhong Duan This is to follow the coding standand to return bool if 'Error **' is used to pass error. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-container-base.h | 2 +- hw/vfio/container.c | 10 +- hw/vfio/spapr.c | 12 +--- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h index 44927ca8c3583246145defe043ac34da604d39bf..202e23cb6b800983b036bf3808c0ec38b1c363d0 100644 --- a/include/hw/vfio/vfio-container-base.h +++ b/include/hw/vfio/vfio-container-base.h @@ -110,7 +110,7 @@ struct VFIOIOMMUClass { InterfaceClass parent_class; /* basic feature */ -int (*setup)(VFIOContainerBase *bcontainer, Error **errp); +bool (*setup)(VFIOContainerBase *bcontainer, Error **errp); int (*dma_map)(const VFIOContainerBase *bcontainer, hwaddr iova, ram_addr_t size, void *vaddr, bool readonly); diff --git a/hw/vfio/container.c b/hw/vfio/container.c index e7c416774791d506cc7c4696fb6a6d94dc809c8e..f2e9560a1906c4151535260e3488ee80ca90e78b 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -507,7 +507,7 @@ static void vfio_get_iommu_info_migration(VFIOContainer *container, } } -static int vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp) +static bool vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp) { VFIOContainer *container = container_of(bcontainer, VFIOContainer, bcontainer); @@ -517,7 +517,7 @@ static int vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp) ret = vfio_get_iommu_info(container, ); if (ret) { error_setg_errno(errp, -ret, "Failed to get VFIO IOMMU info"); -return ret; +return false; } if (info->flags & VFIO_IOMMU_INFO_PGSIZES) { @@ -533,7 +533,7 @@ static int vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp) vfio_get_info_iova_range(info, bcontainer); vfio_get_iommu_info_migration(container, info); -return 0; +return true; } static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, @@ -635,8 +635,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, assert(bcontainer->ops->setup); -ret = bcontainer->ops->setup(bcontainer, errp); -if (ret) { +if (!bcontainer->ops->setup(bcontainer, errp)) { +ret = -EINVAL; goto enable_discards_exit; } diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 0d949bb728212534a7e2296e491aa8d95f45945d..148b257c9ca6a0f957115f8060ddb50e377dfcb8 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -458,8 +458,8 @@ static void vfio_spapr_container_release(VFIOContainerBase *bcontainer) } } -static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer, - Error **errp) +static bool vfio_spapr_container_setup(VFIOContainerBase *bcontainer, + Error **errp) { VFIOContainer *container = container_of(bcontainer, VFIOContainer, bcontainer); @@ -480,7 +480,7 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer, ret = ioctl(fd, VFIO_IOMMU_ENABLE); if (ret) { error_setg_errno(errp, errno, "failed to enable container"); -return -errno; +return false; } } else { scontainer->prereg_listener = vfio_prereg_listener; @@ -488,7 +488,6 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer, memory_listener_register(>prereg_listener, _space_memory); if (bcontainer->error) { -ret = -1; error_propagate_prepend(errp, bcontainer->error, "RAM memory listener initialization failed: "); goto listener_unregister_exit; @@ -500,7 +499,6 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer, if (ret) { error_setg_errno(errp, errno, "VFIO_IOMMU_SPAPR_TCE_GET_INFO failed"); -ret = -errno; goto listener_unregister_exit; } @@ -527,13 +525,13 @@ static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer, 0x1000); } -return 0; +return true; listener_unregister_exit: if (v2) { memory_listener_unregister(>prereg_listener); } -return ret; +return false; } static void vfio_iommu_spapr_class_init(ObjectClass *klass, void *data) -- 2.45.1
[PULL 27/47] vfio/iommufd: Make iommufd_cdev_*() return bool
From: Zhenzhong Duan This is to follow the coding standand to return bool if 'Error **' is used to pass error. The changed functions include: iommufd_cdev_kvm_device_add iommufd_cdev_connect_and_bind iommufd_cdev_attach_ioas_hwpt iommufd_cdev_detach_ioas_hwpt iommufd_cdev_attach_container iommufd_cdev_get_info_iova_range After the change, all functions in hw/vfio/iommufd.c follows the standand. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/iommufd.c | 88 +-- 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index 4c6992fca11969bc8fe26c11e902e2521d6bff7a..84c86b970e756d34b202d5b18ae51c30c730e092 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -49,9 +49,9 @@ static int iommufd_cdev_unmap(const VFIOContainerBase *bcontainer, container->ioas_id, iova, size); } -static int iommufd_cdev_kvm_device_add(VFIODevice *vbasedev, Error **errp) +static bool iommufd_cdev_kvm_device_add(VFIODevice *vbasedev, Error **errp) { -return vfio_kvm_device_add_fd(vbasedev->fd, errp); +return !vfio_kvm_device_add_fd(vbasedev->fd, errp); } static void iommufd_cdev_kvm_device_del(VFIODevice *vbasedev) @@ -63,18 +63,16 @@ static void iommufd_cdev_kvm_device_del(VFIODevice *vbasedev) } } -static int iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp) +static bool iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp) { IOMMUFDBackend *iommufd = vbasedev->iommufd; struct vfio_device_bind_iommufd bind = { .argsz = sizeof(bind), .flags = 0, }; -int ret; -ret = iommufd_backend_connect(iommufd, errp); -if (ret) { -return ret; +if (iommufd_backend_connect(iommufd, errp)) { +return false; } /* @@ -82,15 +80,13 @@ static int iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp) * in KVM. Especially for some emulated devices, it requires * to have kvm information in the device open. */ -ret = iommufd_cdev_kvm_device_add(vbasedev, errp); -if (ret) { +if (!iommufd_cdev_kvm_device_add(vbasedev, errp)) { goto err_kvm_device_add; } /* Bind device to iommufd */ bind.iommufd = iommufd->fd; -ret = ioctl(vbasedev->fd, VFIO_DEVICE_BIND_IOMMUFD, ); -if (ret) { +if (ioctl(vbasedev->fd, VFIO_DEVICE_BIND_IOMMUFD, )) { error_setg_errno(errp, errno, "error bind device fd=%d to iommufd=%d", vbasedev->fd, bind.iommufd); goto err_bind; @@ -99,12 +95,12 @@ static int iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp) vbasedev->devid = bind.out_devid; trace_iommufd_cdev_connect_and_bind(bind.iommufd, vbasedev->name, vbasedev->fd, vbasedev->devid); -return ret; +return true; err_bind: iommufd_cdev_kvm_device_del(vbasedev); err_kvm_device_add: iommufd_backend_disconnect(iommufd); -return ret; +return false; } static void iommufd_cdev_unbind_and_disconnect(VFIODevice *vbasedev) @@ -176,10 +172,10 @@ out: return ret; } -static int iommufd_cdev_attach_ioas_hwpt(VFIODevice *vbasedev, uint32_t id, +static bool iommufd_cdev_attach_ioas_hwpt(VFIODevice *vbasedev, uint32_t id, Error **errp) { -int ret, iommufd = vbasedev->iommufd->fd; +int iommufd = vbasedev->iommufd->fd; struct vfio_device_attach_iommufd_pt attach_data = { .argsz = sizeof(attach_data), .flags = 0, @@ -187,38 +183,38 @@ static int iommufd_cdev_attach_ioas_hwpt(VFIODevice *vbasedev, uint32_t id, }; /* Attach device to an IOAS or hwpt within iommufd */ -ret = ioctl(vbasedev->fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, _data); -if (ret) { +if (ioctl(vbasedev->fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, _data)) { error_setg_errno(errp, errno, "[iommufd=%d] error attach %s (%d) to id=%d", iommufd, vbasedev->name, vbasedev->fd, id); -} else { -trace_iommufd_cdev_attach_ioas_hwpt(iommufd, vbasedev->name, -vbasedev->fd, id); +return false; } -return ret; + +trace_iommufd_cdev_attach_ioas_hwpt(iommufd, vbasedev->name, +vbasedev->fd, id); +return true; } -static int iommufd_cdev_detach_ioas_hwpt(VFIODevice *vbasedev, Error **errp) +static bool iommufd_cdev_detach_ioas_hwpt(VFIODevice *vbasedev, Error **errp) { -int ret, iommufd = vbasedev->iommufd->fd; +int iommufd = vbasedev->iommufd->fd; struct vfio_device_detach_iommufd_pt detach_data
[PULL 29/47] backends/iommufd: Make iommufd_backend_*() return bool
From: Zhenzhong Duan This is to follow the coding standand to return bool if 'Error **' is used to pass error. The changed functions include: iommufd_backend_connect iommufd_backend_alloc_ioas By this chance, simplify the functions a bit by avoiding duplicate recordings, e.g., log through either error interface or trace, not both. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/sysemu/iommufd.h | 6 +++--- backends/iommufd.c | 29 + hw/vfio/iommufd.c| 5 ++--- backends/trace-events| 4 ++-- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/include/sysemu/iommufd.h b/include/sysemu/iommufd.h index 9af27ebd6ccb78ca8e16aa3c62629aab9f7f31e4..293bfbe967215381532b8267227dde61fa9157b7 100644 --- a/include/sysemu/iommufd.h +++ b/include/sysemu/iommufd.h @@ -23,11 +23,11 @@ struct IOMMUFDBackend { /*< public >*/ }; -int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp); +bool iommufd_backend_connect(IOMMUFDBackend *be, Error **errp); void iommufd_backend_disconnect(IOMMUFDBackend *be); -int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id, - Error **errp); +bool iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id, +Error **errp); void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id); int iommufd_backend_map_dma(IOMMUFDBackend *be, uint32_t ioas_id, hwaddr iova, ram_addr_t size, void *vaddr, bool readonly); diff --git a/backends/iommufd.c b/backends/iommufd.c index 76a0204852f73466a9f31492a08d89d468bff7c0..c506afbdac4beddb7dac88f74f10544f7a083e58 100644 --- a/backends/iommufd.c +++ b/backends/iommufd.c @@ -72,24 +72,22 @@ static void iommufd_backend_class_init(ObjectClass *oc, void *data) object_class_property_add_str(oc, "fd", NULL, iommufd_backend_set_fd); } -int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp) +bool iommufd_backend_connect(IOMMUFDBackend *be, Error **errp) { -int fd, ret = 0; +int fd; if (be->owned && !be->users) { fd = qemu_open_old("/dev/iommu", O_RDWR); if (fd < 0) { error_setg_errno(errp, errno, "/dev/iommu opening failed"); -ret = fd; -goto out; +return false; } be->fd = fd; } be->users++; -out: -trace_iommufd_backend_connect(be->fd, be->owned, - be->users, ret); -return ret; + +trace_iommufd_backend_connect(be->fd, be->owned, be->users); +return true; } void iommufd_backend_disconnect(IOMMUFDBackend *be) @@ -106,25 +104,24 @@ out: trace_iommufd_backend_disconnect(be->fd, be->users); } -int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id, - Error **errp) +bool iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id, +Error **errp) { -int ret, fd = be->fd; +int fd = be->fd; struct iommu_ioas_alloc alloc_data = { .size = sizeof(alloc_data), .flags = 0, }; -ret = ioctl(fd, IOMMU_IOAS_ALLOC, _data); -if (ret) { +if (ioctl(fd, IOMMU_IOAS_ALLOC, _data)) { error_setg_errno(errp, errno, "Failed to allocate ioas"); -return ret; +return false; } *ioas_id = alloc_data.out_ioas_id; -trace_iommufd_backend_alloc_ioas(fd, *ioas_id, ret); +trace_iommufd_backend_alloc_ioas(fd, *ioas_id); -return ret; +return true; } void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id) diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index 6a446b16dcd64838dc9ebb6150cd5ed85ec6fef3..554f9a6292454f51015ab3a56df3fab6a482ccb7 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -71,7 +71,7 @@ static bool iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp) .flags = 0, }; -if (iommufd_backend_connect(iommufd, errp)) { +if (!iommufd_backend_connect(iommufd, errp)) { return false; } @@ -346,8 +346,7 @@ static bool iommufd_cdev_attach(const char *name, VFIODevice *vbasedev, } /* Need to allocate a new dedicated container */ -ret = iommufd_backend_alloc_ioas(vbasedev->iommufd, _id, errp); -if (ret < 0) { +if (!iommufd_backend_alloc_ioas(vbasedev->iommufd, _id, errp)) { goto err_alloc_ioas; } diff --git a/backends/trace-events b/backends/trace-events index d45c6e31a67ed66d94787f60eb08a525cf6ff68b..211e6f374adcef25be0409ce3e42cbed6f31b744 100644 --- a/backends/trace-events +++ b/backends/trace-events @@ -7,11 +7,11 @@ dbus_vmstate_loading(const char *id) "id: %s" dbus_vmstate_saving(const char *id) "
[PULL 13/47] vfio/ccw: Make vfio_ccw_register_irq_notifier() return a bool
Since vfio_ccw_register_irq_notifier() takes an 'Error **' argument, best practices suggest to return a bool. See the qapi/error.h Rules section. Reviewed-by: Markus Armbruster Reviewed-by: Eric Farman Signed-off-by: Cédric Le Goater --- hw/vfio/ccw.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 6764388bc47a970329fce2233626ccb8178e0165..1c630f6e9abe93ae0c2b5615d4409669f096c8c9 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -379,7 +379,7 @@ read_err: css_inject_io_interrupt(sch); } -static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, +static bool vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, unsigned int irq, Error **errp) { @@ -405,13 +405,13 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, break; default: error_setg(errp, "vfio: Unsupported device irq(%d)", irq); -return; +return false; } if (vdev->num_irqs < irq + 1) { error_setg(errp, "vfio: IRQ %u not available (number of irqs %u)", irq, vdev->num_irqs); -return; +return false; } argsz = sizeof(*irq_info); @@ -421,14 +421,14 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, irq_info) < 0 || irq_info->count < 1) { error_setg_errno(errp, errno, "vfio: Error getting irq info"); -return; +return false; } if (event_notifier_init(notifier, 0)) { error_setg_errno(errp, errno, "vfio: Unable to init event notifier for irq (%d)", irq); -return; +return false; } fd = event_notifier_get_fd(notifier); @@ -439,6 +439,8 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, qemu_set_fd_handler(fd, NULL, NULL, vcdev); event_notifier_cleanup(notifier); } + +return true; } static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, @@ -602,20 +604,18 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) goto out_region_err; } -vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, ); -if (err) { +if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, )) { goto out_io_notifier_err; } if (vcdev->crw_region) { -vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, ); -if (err) { +if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, +)) { goto out_irq_notifier_err; } } -vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX, ); -if (err) { +if (!vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX, )) { /* * Report this error, but do not make it a failing condition. * Lack of this IRQ in the host does not prevent normal operation. -- 2.45.1
[PULL 47/47] vfio/igd: Use g_autofree in vfio_probe_igd_bar4_quirk()
From: Zhenzhong Duan Pointer opregion, host and lpc are allocated and freed in vfio_probe_igd_bar4_quirk(). Use g_autofree to automatically free them. Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/igd.c | 27 --- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c index 1e79202f2bd136b0bafd4f08c2f1407e467e0d65..d320d032a7f3b19df0d055178f6fefe4bdfd8668 100644 --- a/hw/vfio/igd.c +++ b/hw/vfio/igd.c @@ -368,7 +368,9 @@ static const MemoryRegionOps vfio_igd_index_quirk = { void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) { g_autofree struct vfio_region_info *rom = NULL; -struct vfio_region_info *opregion = NULL, *host = NULL, *lpc = NULL; +g_autofree struct vfio_region_info *opregion = NULL; +g_autofree struct vfio_region_info *host = NULL; +g_autofree struct vfio_region_info *lpc = NULL; VFIOQuirk *quirk; VFIOIGDQuirk *igd; PCIDevice *lpc_bridge; @@ -426,7 +428,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) if ((ret || !rom->size) && !vdev->pdev.romfile) { error_report("IGD device %s has no ROM, legacy mode disabled", vdev->vbasedev.name); -goto out; +return; } /* @@ -437,7 +439,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) error_report("IGD device %s hotplugged, ROM disabled, " "legacy mode disabled", vdev->vbasedev.name); vdev->rom_read_failed = true; -goto out; +return; } /* @@ -450,7 +452,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) if (ret) { error_report("IGD device %s does not support OpRegion access," "legacy mode disabled", vdev->vbasedev.name); -goto out; +return; } ret = vfio_get_dev_region_info(>vbasedev, @@ -459,7 +461,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) if (ret) { error_report("IGD device %s does not support host bridge access," "legacy mode disabled", vdev->vbasedev.name); -goto out; +return; } ret = vfio_get_dev_region_info(>vbasedev, @@ -468,7 +470,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) if (ret) { error_report("IGD device %s does not support LPC bridge access," "legacy mode disabled", vdev->vbasedev.name); -goto out; +return; } gmch = vfio_pci_read_config(>pdev, IGD_GMCH, 4); @@ -482,7 +484,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name); error_report("IGD device %s failed to enable VGA access, " "legacy mode disabled", vdev->vbasedev.name); -goto out; +return; } /* Create our LPC/ISA bridge */ @@ -490,7 +492,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) if (ret) { error_report("IGD device %s failed to create LPC bridge, " "legacy mode disabled", vdev->vbasedev.name); -goto out; +return; } /* Stuff some host values into the VM PCI host bridge */ @@ -498,14 +500,14 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) if (ret) { error_report("IGD device %s failed to modify host bridge, " "legacy mode disabled", vdev->vbasedev.name); -goto out; +return; } /* Setup OpRegion access */ if (!vfio_pci_igd_opregion_init(vdev, opregion, )) { error_append_hint(, "IGD legacy mode disabled\n"); error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name); -goto out; +return; } /* Setup our quirk to munge GTT addresses to the VM allocated buffer */ @@ -607,9 +609,4 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) } trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb); - -out: -g_free(opregion); -g_free(host); -g_free(lpc); } -- 2.45.1
[PULL 03/47] migration: Extend migration_file_set_error() with Error* argument
Use it to update the current error of the migration stream if available and if not, simply print out the error. Next changes will update with an error to report. Reviewed-by: Avihai Horon Acked-by: Fabiano Rosas Reviewed-by: Eric Auger Signed-off-by: Cédric Le Goater --- include/migration/misc.h | 2 +- hw/vfio/common.c | 4 ++-- hw/vfio/migration.c | 4 ++-- migration/migration.c| 6 -- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/migration/misc.h b/include/migration/misc.h index bf7339cc1e6430226127fb6a878d06b458170858..bfadc5613bac614a316e5aed7da95d8c7845cf42 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -97,7 +97,7 @@ void migration_add_notifier_mode(NotifierWithReturn *notify, void migration_remove_notifier(NotifierWithReturn *notify); bool migration_is_running(void); -void migration_file_set_error(int err); +void migration_file_set_error(int ret, Error *err); /* True if incoming migration entered POSTCOPY_INCOMING_DISCARD */ bool migration_in_incoming_postcopy(void); diff --git a/hw/vfio/common.c b/hw/vfio/common.c index b5102f54a6474a50c6366e8fbce23812d55e384e..2c97de6c730d963d961bf81c0831326c0e25afa7 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -147,10 +147,10 @@ bool vfio_viommu_preset(VFIODevice *vbasedev) return vbasedev->bcontainer->space->as != _space_memory; } -static void vfio_set_migration_error(int err) +static void vfio_set_migration_error(int ret) { if (migration_is_setup_or_active()) { -migration_file_set_error(err); +migration_file_set_error(ret, NULL); } } diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 06ae40969b6c19037e190008e14f28be646278cd..bf2fd0759ba6e4fb103cc5c1a43edb180a3d0de4 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -726,7 +726,7 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running, * Migration should be aborted in this case, but vm_state_notify() * currently does not support reporting failures. */ -migration_file_set_error(ret); +migration_file_set_error(ret, NULL); } trace_vfio_vmstate_change_prepare(vbasedev->name, running, @@ -756,7 +756,7 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state) * Migration should be aborted in this case, but vm_state_notify() * currently does not support reporting failures. */ -migration_file_set_error(ret); +migration_file_set_error(ret, NULL); } trace_vfio_vmstate_change(vbasedev->name, running, RunState_str(state), diff --git a/migration/migration.c b/migration/migration.c index e88b24f1e6cbe82dad3f890c00e264d2ab6ad355..70d66a441bf04761decf91dbe57ce52c57fde58f 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2994,13 +2994,15 @@ static MigThrError postcopy_pause(MigrationState *s) } } -void migration_file_set_error(int err) +void migration_file_set_error(int ret, Error *err) { MigrationState *s = current_migration; WITH_QEMU_LOCK_GUARD(>qemu_file_lock) { if (s->to_dst_file) { -qemu_file_set_error(s->to_dst_file, err); +qemu_file_set_error_obj(s->to_dst_file, ret, err); +} else if (err) { +error_report_err(err); } } } -- 2.45.1
[PULL 01/47] vfio: Add Error** argument to .set_dirty_page_tracking() handler
We will use the Error object to improve error reporting in the .log_global*() handlers of VFIO. Add documentation while at it. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Avihai Horon Reviewed-by: Eric Auger Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-container-base.h | 18 -- hw/vfio/common.c | 4 ++-- hw/vfio/container-base.c | 4 ++-- hw/vfio/container.c | 6 +++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h index 3582d5f97a37877b2adfc0d0b06996c82403f8b7..326ceea52a2030eec9dad289a9845866c4a8c090 100644 --- a/include/hw/vfio/vfio-container-base.h +++ b/include/hw/vfio/vfio-container-base.h @@ -82,7 +82,7 @@ int vfio_container_add_section_window(VFIOContainerBase *bcontainer, void vfio_container_del_section_window(VFIOContainerBase *bcontainer, MemoryRegionSection *section); int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start); + bool start, Error **errp); int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, VFIOBitmap *vbmap, hwaddr iova, hwaddr size); @@ -121,9 +121,23 @@ struct VFIOIOMMUClass { int (*attach_device)(const char *name, VFIODevice *vbasedev, AddressSpace *as, Error **errp); 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); + bool start, Error **errp); int (*query_dirty_bitmap)(const VFIOContainerBase *bcontainer, VFIOBitmap *vbmap, hwaddr iova, hwaddr size); diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 8f9cbdc0264044ce587877a7d19d14b28527291b..485e53916491f1164d29e739fb7106c0c77df737 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1076,7 +1076,7 @@ static bool vfio_listener_log_global_start(MemoryListener *listener, if (vfio_devices_all_device_dirty_tracking(bcontainer)) { ret = vfio_devices_dma_logging_start(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, true); +ret = vfio_container_set_dirty_page_tracking(bcontainer, true, NULL); } if (ret) { @@ -1096,7 +1096,7 @@ static void vfio_listener_log_global_stop(MemoryListener *listener) if (vfio_devices_all_device_dirty_tracking(bcontainer)) { vfio_devices_dma_logging_stop(bcontainer); } else { -ret = vfio_container_set_dirty_page_tracking(bcontainer, false); +ret = vfio_container_set_dirty_page_tracking(bcontainer, false, NULL); } if (ret) { diff --git a/hw/vfio/container-base.c b/hw/vfio/container-base.c index 913ae49077c4f09b7b27517c1231cfbe4befb7fb..7c0764121d24b02b6c4e66e368d7dff78a6d65aa 100644 --- a/hw/vfio/container-base.c +++ b/hw/vfio/container-base.c @@ -53,14 +53,14 @@ void vfio_container_del_section_window(VFIOContainerBase *bcontainer, } int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, - bool start) + bool start, Error **errp) { if (!bcontainer->dirty_pages_supported) { return 0; } g_assert(bcontainer->ops->set_dirty_page_tracking); -return bcontainer->ops->set_dirty_page_tracking(bcontainer, start); +return bcontainer->ops->set_dirty_page_tracking(bcontainer, start, errp); } int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 77bdec276ec49cb9cd767c0de42ec801b4421572..c35221fbe7dc5453050f97cd186fc958e24f28f7 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -209,7 +209,7 @@ static int vfio_legacy_dma_map(const VFIOContainerBase *bcontainer, hwaddr iova, static int vfio_legacy_set_dirty_page_tracking(const VFIOContainerBase *bcontainer, -bool start) +bool start, Error **errp) { const VFIOContainer *container = container_of(bcon
[PULL 18/47] vfio/migration: Enhance VFIO migration state tracing
From: Avihai Horon Move trace_vfio_migration_set_state() to the top of the function, add recover_state to it, and add a new trace event to vfio_migration_set_device_state(). This improves tracing of device state changes as state changes are now also logged when vfio_migration_set_state() fails (covering recover state and device reset transitions) and in no-op state transitions to the same state. Suggested-by: Cédric Le Goater Signed-off-by: Avihai Horon Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/migration.c | 8 ++-- hw/vfio/trace-events | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 56edffaf6251e28e39ef32991394697abb1b9e55..34d4be2ce1b13626a8690d4787366ee41a9ebe1e 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -129,6 +129,9 @@ static void vfio_migration_set_device_state(VFIODevice *vbasedev, { VFIOMigration *migration = vbasedev->migration; +trace_vfio_migration_set_device_state(vbasedev->name, + mig_state_to_str(state)); + migration->device_state = state; vfio_migration_send_event(vbasedev); } @@ -150,6 +153,9 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, g_strdup_printf("%s: Failed setting device state to %s.", vbasedev->name, mig_state_to_str(new_state)); +trace_vfio_migration_set_state(vbasedev->name, mig_state_to_str(new_state), + mig_state_to_str(recover_state)); + if (new_state == migration->device_state) { return 0; } @@ -209,8 +215,6 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, migration->data_fd = mig_state->data_fd; } -trace_vfio_migration_set_state(vbasedev->name, mig_state_to_str(new_state)); - return 0; reset_device: diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index f0474b244bf04d044e8327c88bf49aef349afcca..64161bf6f44cffd73851a90b70694120a5fb2a82 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -152,7 +152,8 @@ vfio_load_device_config_state(const char *name) " (%s)" vfio_load_state(const char *name, uint64_t data) " (%s) data 0x%"PRIx64 vfio_load_state_device_data(const char *name, uint64_t data_size, int ret) " (%s) size 0x%"PRIx64" ret %d" vfio_migration_realize(const char *name) " (%s)" -vfio_migration_set_state(const char *name, const char *state) " (%s) state %s" +vfio_migration_set_device_state(const char *name, const char *state) " (%s) state %s" +vfio_migration_set_state(const char *name, const char *new_state, const char *recover_state) " (%s) new state %s, recover state %s" vfio_migration_state_notifier(const char *name, int state) " (%s) state %d" vfio_save_block(const char *name, int data_size) " (%s) data_size %d" vfio_save_cleanup(const char *name) " (%s)" -- 2.45.1
[PULL 05/47] vfio/migration: Add Error** argument to .vfio_save_config() handler
Use vmstate_save_state_with_err() to improve error reporting in the callers and store a reported error under the migration stream. Add documentation while at it. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Eric Auger Reviewed-by: Avihai Horon Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-common.h | 25 - hw/vfio/migration.c | 25 ++--- hw/vfio/pci.c | 5 +++-- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index d66e27db02a4db8329204f88d02a204eedf1caa1..3ff633ad3b395e953a55683f5f0308bca50af3dd 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -133,7 +133,30 @@ struct VFIODeviceOps { int (*vfio_hot_reset_multi)(VFIODevice *vdev); void (*vfio_eoi)(VFIODevice *vdev); Object *(*vfio_get_object)(VFIODevice *vdev); -void (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f); + +/** + * @vfio_save_config + * + * Save device config state + * + * @vdev: #VFIODevice for which to save the config + * @f: #QEMUFile where to send the data + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns zero to indicate success and negative for error + */ +int (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f, Error **errp); + +/** + * @vfio_load_config + * + * Load device config state + * + * @vdev: #VFIODevice for which to load the config + * @f: #QEMUFile where to get the data + * + * Returns zero to indicate success and negative for error + */ int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f); }; diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 43fed0dbdbe3415ae2dd68fbe45b302b85a80fa4..5d91364f3bbc34060d84b4b4b1823eadbc7b12bf 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -193,21 +193,30 @@ static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev, return ret; } -static int vfio_save_device_config_state(QEMUFile *f, void *opaque) +static int vfio_save_device_config_state(QEMUFile *f, void *opaque, + Error **errp) { VFIODevice *vbasedev = opaque; +int ret; qemu_put_be64(f, VFIO_MIG_FLAG_DEV_CONFIG_STATE); if (vbasedev->ops && vbasedev->ops->vfio_save_config) { -vbasedev->ops->vfio_save_config(vbasedev, f); +ret = vbasedev->ops->vfio_save_config(vbasedev, f, errp); +if (ret) { +return ret; +} } qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); trace_vfio_save_device_config_state(vbasedev->name); -return qemu_file_get_error(f); +ret = qemu_file_get_error(f); +if (ret < 0) { +error_setg_errno(errp, -ret, "Failed to save state"); +} +return ret; } static int vfio_load_device_config_state(QEMUFile *f, void *opaque) @@ -592,13 +601,15 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) static void vfio_save_state(QEMUFile *f, void *opaque) { VFIODevice *vbasedev = opaque; +Error *local_err = NULL; int ret; -ret = vfio_save_device_config_state(f, opaque); +ret = vfio_save_device_config_state(f, opaque, _err); if (ret) { -error_report("%s: Failed to save device config space", - vbasedev->name); -qemu_file_set_error(f, ret); +error_prepend(_err, + "vfio: Failed to save device config space of %s - ", + vbasedev->name); +qemu_file_set_error_obj(f, ret, local_err); } } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 64780d1b793345c8e8996fe6b7987059ce831c11..fc6e54e871508bb0e2a3ac9079a195c086531f21 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2586,11 +2586,12 @@ static const VMStateDescription vmstate_vfio_pci_config = { } }; -static void vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f) +static int vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f, Error **errp) { VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); -vmstate_save_state(f, _vfio_pci_config, vdev, NULL); +return vmstate_save_state_with_err(f, _vfio_pci_config, vdev, NULL, + errp); } static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f) -- 2.45.1
[PULL 33/47] vfio/helpers: Make vfio_set_irq_signaling() return bool
From: Zhenzhong Duan This is to follow the coding standand in qapi/error.h to return bool for bool-valued functions. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-common.h | 4 ++-- hw/vfio/ap.c | 8 +++ hw/vfio/ccw.c | 8 +++ hw/vfio/helpers.c | 18 ++-- hw/vfio/pci.c | 40 ++- hw/vfio/platform.c| 18 +++- 6 files changed, 46 insertions(+), 50 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b7bb4f5304addcdb03c971f27f99e5350ad0940a..b712799caffdc950b593a87d569d7f5281976e2f 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -207,8 +207,8 @@ void vfio_spapr_container_deinit(VFIOContainer *container); void vfio_disable_irqindex(VFIODevice *vbasedev, int index); void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index); void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index); -int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, - int action, int fd, Error **errp); +bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, +int action, int fd, Error **errp); void vfio_region_write(void *opaque, hwaddr addr, uint64_t data, unsigned size); uint64_t vfio_region_read(void *opaque, diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c index ba653ef70f08ebdf482009baafc62eb33ebda9a8..d8a9615feec065e98f53831912087d9878fdff9c 100644 --- a/hw/vfio/ap.c +++ b/hw/vfio/ap.c @@ -117,8 +117,8 @@ static bool vfio_ap_register_irq_notifier(VFIOAPDevice *vapdev, fd = event_notifier_get_fd(notifier); qemu_set_fd_handler(fd, fd_read, NULL, vapdev); -if (vfio_set_irq_signaling(vdev, irq, 0, VFIO_IRQ_SET_ACTION_TRIGGER, fd, - errp)) { +if (!vfio_set_irq_signaling(vdev, irq, 0, VFIO_IRQ_SET_ACTION_TRIGGER, fd, +errp)) { qemu_set_fd_handler(fd, NULL, NULL, vapdev); event_notifier_cleanup(notifier); } @@ -141,8 +141,8 @@ static void vfio_ap_unregister_irq_notifier(VFIOAPDevice *vapdev, return; } -if (vfio_set_irq_signaling(>vdev, irq, 0, - VFIO_IRQ_SET_ACTION_TRIGGER, -1, )) { +if (!vfio_set_irq_signaling(>vdev, irq, 0, +VFIO_IRQ_SET_ACTION_TRIGGER, -1, )) { warn_reportf_err(err, VFIO_MSG_PREFIX, vapdev->vdev.name); } diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 89bb98016764e65cf826183d7a38c59d429f6eeb..1f578a3c75d975e12bbac52b3683e6fd193801cb 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -434,8 +434,8 @@ static bool vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, fd = event_notifier_get_fd(notifier); qemu_set_fd_handler(fd, fd_read, NULL, vcdev); -if (vfio_set_irq_signaling(vdev, irq, 0, - VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) { +if (!vfio_set_irq_signaling(vdev, irq, 0, +VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) { qemu_set_fd_handler(fd, NULL, NULL, vcdev); event_notifier_cleanup(notifier); } @@ -464,8 +464,8 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, return; } -if (vfio_set_irq_signaling(>vdev, irq, 0, - VFIO_IRQ_SET_ACTION_TRIGGER, -1, )) { +if (!vfio_set_irq_signaling(>vdev, irq, 0, +VFIO_IRQ_SET_ACTION_TRIGGER, -1, )) { warn_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); } diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 1f3bdd9bf059beec186d87ba4772f2f6e34bc7d4..9edbc966884de12e7248af8d50d87f26c8cd2764 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -107,12 +107,12 @@ static const char *index_to_str(VFIODevice *vbasedev, int index) } } -int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, - int action, int fd, Error **errp) +bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, +int action, int fd, Error **errp) { ERRP_GUARD(); g_autofree struct vfio_irq_set *irq_set = NULL; -int argsz, ret = 0; +int argsz; const char *name; int32_t *pfd; @@ -127,15 +127,11 @@ int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, pfd = (int32_t *)_set->data; *pfd = fd; -if (ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { -ret = -errno; +if (!ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { +return true; } -if (!ret) { -return 0; -} - -error_setg_errno(errp,
[PULL 26/47] vfio/container: Make vfio_get_device() return bool
From: Zhenzhong Duan This is to follow the coding standand to return bool if 'Error **' is used to pass error. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/container.c | 16 +++- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/hw/vfio/container.c b/hw/vfio/container.c index e330b2897423b97fee467884f4237669ceff4756..53649e397cab94f8a2b61e6d66f21d635556e04e 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -802,8 +802,8 @@ static void vfio_put_group(VFIOGroup *group) g_free(group); } -static int vfio_get_device(VFIOGroup *group, const char *name, - VFIODevice *vbasedev, Error **errp) +static bool vfio_get_device(VFIOGroup *group, const char *name, +VFIODevice *vbasedev, Error **errp) { g_autofree struct vfio_device_info *info = NULL; int fd; @@ -815,14 +815,14 @@ static int vfio_get_device(VFIOGroup *group, const char *name, error_append_hint(errp, "Verify all devices in group %d are bound to vfio- " "or pci-stub and not already in use\n", group->groupid); -return fd; +return false; } info = vfio_get_device_info(fd); if (!info) { error_setg_errno(errp, errno, "error getting device info"); close(fd); -return -1; +return false; } /* @@ -837,7 +837,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, error_setg(errp, "Inconsistent setting of support for discarding " "RAM (e.g., balloon) within group"); close(fd); -return -1; +return false; } if (!group->ram_block_discard_allowed) { @@ -858,7 +858,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, vbasedev->reset_works = !!(info->flags & VFIO_DEVICE_FLAGS_RESET); -return 0; +return true; } static void vfio_put_base_device(VFIODevice *vbasedev) @@ -911,7 +911,6 @@ static bool vfio_legacy_attach_device(const char *name, VFIODevice *vbasedev, VFIODevice *vbasedev_iter; VFIOGroup *group; VFIOContainerBase *bcontainer; -int ret; if (groupid < 0) { return false; @@ -931,8 +930,7 @@ static bool vfio_legacy_attach_device(const char *name, VFIODevice *vbasedev, return false; } } -ret = vfio_get_device(group, name, vbasedev, errp); -if (ret) { +if (!vfio_get_device(group, name, vbasedev, errp)) { vfio_put_group(group); return false; } -- 2.45.1
[PULL 40/47] vfio/pci: Make vfio_intx_enable() return bool
From: Zhenzhong Duan This is to follow the coding standand in qapi/error.h to return bool for bool-valued functions. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/pci.c | 19 --- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 46d3c618596d95266543e9a0ebc65c04d9a7cc5d..7f35cb8a29176840412652afe5ab31cd52a1bf06 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -261,7 +261,7 @@ static void vfio_irqchip_change(Notifier *notify, void *data) vfio_intx_update(vdev, >intx.route); } -static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) +static bool vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) { uint8_t pin = vfio_pci_read_config(>pdev, PCI_INTERRUPT_PIN, 1); Error *err = NULL; @@ -270,7 +270,7 @@ static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) if (!pin) { -return 0; +return true; } vfio_disable_interrupts(vdev); @@ -292,7 +292,7 @@ static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) ret = event_notifier_init(>intx.interrupt, 0); if (ret) { error_setg_errno(errp, -ret, "event_notifier_init failed"); -return ret; +return false; } fd = event_notifier_get_fd(>intx.interrupt); qemu_set_fd_handler(fd, vfio_intx_interrupt, NULL, vdev); @@ -301,7 +301,7 @@ static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) { qemu_set_fd_handler(fd, NULL, NULL, vdev); event_notifier_cleanup(>intx.interrupt); -return -errno; +return false; } if (!vfio_intx_enable_kvm(vdev, )) { @@ -311,7 +311,7 @@ static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) vdev->interrupt = VFIO_INT_INTx; trace_vfio_intx_enable(vdev->vbasedev.name); -return 0; +return true; } static void vfio_intx_disable(VFIOPCIDevice *vdev) @@ -836,8 +836,7 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev) vfio_disable_irqindex(>vbasedev, VFIO_PCI_MSIX_IRQ_INDEX); vfio_msi_disable_common(vdev); -vfio_intx_enable(vdev, ); -if (err) { +if (!vfio_intx_enable(vdev, )) { error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name); } @@ -2450,8 +2449,7 @@ void vfio_pci_post_reset(VFIOPCIDevice *vdev) Error *err = NULL; int nr; -vfio_intx_enable(vdev, ); -if (err) { +if (!vfio_intx_enable(vdev, )) { error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name); } @@ -3194,8 +3192,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) vfio_intx_routing_notifier); vdev->irqchip_change_notifier.notify = vfio_irqchip_change; kvm_irqchip_add_change_notifier(>irqchip_change_notifier); -ret = vfio_intx_enable(vdev, errp); -if (ret) { +if (!vfio_intx_enable(vdev, errp)) { goto out_deregister; } } -- 2.45.1
[PULL 20/47] vfio/pci: Use g_autofree in iommufd_cdev_get_info_iova_range()
From: Zhenzhong Duan Local pointer info is freed before return from iommufd_cdev_get_info_iova_range(). Use 'g_autofree' to avoid the g_free() calls. Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/iommufd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index 8827ffe636e2aba1551ba794bf666a7a214590b7..c6441279728fcede1dde2a099c076ad04c464a1f 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -258,7 +258,7 @@ static int iommufd_cdev_get_info_iova_range(VFIOIOMMUFDContainer *container, uint32_t ioas_id, Error **errp) { VFIOContainerBase *bcontainer = >bcontainer; -struct iommu_ioas_iova_ranges *info; +g_autofree struct iommu_ioas_iova_ranges *info = NULL; struct iommu_iova_range *iova_ranges; int ret, sz, fd = container->be->fd; @@ -291,12 +291,10 @@ static int iommufd_cdev_get_info_iova_range(VFIOIOMMUFDContainer *container, } bcontainer->pgsizes = info->out_iova_alignment; -g_free(info); return 0; error: ret = -errno; -g_free(info); error_setg_errno(errp, errno, "Cannot get IOVA ranges"); return ret; } -- 2.45.1
[PULL 19/47] vfio/pci: Use g_autofree in vfio_realize
From: Zhenzhong Duan Local pointer name is allocated before vfio_attach_device() call and freed after the call. Same for tmp when calling realpath(). Use 'g_autofree' to avoid the g_free() calls. Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/pci.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index b5d1d398b120076c85cdd92d61793393f65e8554..84f7bff664fd7595b75cce1f6974068144f0d42d 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2972,12 +2972,13 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) ERRP_GUARD(); VFIOPCIDevice *vdev = VFIO_PCI(pdev); VFIODevice *vbasedev = >vbasedev; -char *tmp, *subsys; +char *subsys; Error *err = NULL; int i, ret; bool is_mdev; char uuid[UUID_STR_LEN]; -char *name; +g_autofree char *name = NULL; +g_autofree char *tmp = NULL; if (vbasedev->fd < 0 && !vbasedev->sysfsdev) { if (!(~vdev->host.domain || ~vdev->host.bus || @@ -3008,7 +3009,6 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) */ tmp = g_strdup_printf("%s/subsystem", vbasedev->sysfsdev); subsys = realpath(tmp, NULL); -g_free(tmp); is_mdev = subsys && (strcmp(subsys, "/sys/bus/mdev") == 0); free(subsys); @@ -3029,7 +3029,6 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) ret = vfio_attach_device(name, vbasedev, pci_device_iommu_address_space(pdev), errp); -g_free(name); if (ret) { goto error; } -- 2.45.1
[PULL 34/47] vfio/helpers: Make vfio_device_get_name() return bool
From: Zhenzhong Duan This is to follow the coding standand in qapi/error.h to return bool for bool-valued functions. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-common.h | 2 +- hw/vfio/ap.c | 2 +- hw/vfio/ccw.c | 2 +- hw/vfio/helpers.c | 8 hw/vfio/pci.c | 2 +- hw/vfio/platform.c| 5 ++--- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b712799caffdc950b593a87d569d7f5281976e2f..4cb1ab8645dcdf604f3c2bb29328668fd5eb7284 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -279,7 +279,7 @@ int vfio_get_dirty_bitmap(const VFIOContainerBase *bcontainer, uint64_t iova, uint64_t size, ram_addr_t ram_addr, Error **errp); /* Returns 0 on success, or a negative errno. */ -int vfio_device_get_name(VFIODevice *vbasedev, Error **errp); +bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp); void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp); void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, DeviceState *dev, bool ram_discard); diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c index d8a9615feec065e98f53831912087d9878fdff9c..c12531a7886a2fe87598be0861fba5923bd2c206 100644 --- a/hw/vfio/ap.c +++ b/hw/vfio/ap.c @@ -158,7 +158,7 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp) VFIOAPDevice *vapdev = VFIO_AP_DEVICE(dev); VFIODevice *vbasedev = >vdev; -if (vfio_device_get_name(vbasedev, errp) < 0) { +if (!vfio_device_get_name(vbasedev, errp)) { return; } diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 1f578a3c75d975e12bbac52b3683e6fd193801cb..8850ca17c84632d278e27819cd52e104ed436d6c 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -588,7 +588,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) } } -if (vfio_device_get_name(vbasedev, errp) < 0) { +if (!vfio_device_get_name(vbasedev, errp)) { return; } diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 9edbc966884de12e7248af8d50d87f26c8cd2764..4b079dc383683a71d1d96507a0fb66a4bc3ba923 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -607,7 +607,7 @@ bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) return ret; } -int vfio_device_get_name(VFIODevice *vbasedev, Error **errp) +bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp) { ERRP_GUARD(); struct stat st; @@ -616,7 +616,7 @@ int vfio_device_get_name(VFIODevice *vbasedev, Error **errp) if (stat(vbasedev->sysfsdev, ) < 0) { error_setg_errno(errp, errno, "no such host device"); error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev); -return -errno; +return false; } /* User may specify a name, e.g: VFIO platform device */ if (!vbasedev->name) { @@ -625,7 +625,7 @@ int vfio_device_get_name(VFIODevice *vbasedev, Error **errp) } else { if (!vbasedev->iommufd) { error_setg(errp, "Use FD passing only with iommufd backend"); -return -EINVAL; +return false; } /* * Give a name with fd so any function printing out vbasedev->name @@ -636,7 +636,7 @@ int vfio_device_get_name(VFIODevice *vbasedev, Error **errp) } } -return 0; +return true; } void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 358da4497b8ab9b58b4f36252d1857279efbe521..aad012c34885ff2a5a39039777962236b41b 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2999,7 +2999,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) vdev->host.slot, vdev->host.function); } -if (vfio_device_get_name(vbasedev, errp) < 0) { +if (!vfio_device_get_name(vbasedev, errp)) { return; } diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c index 3233ca86918a22b69265b83a1a9dec8b6b59380f..e1a32863d919fe09a743f5fb108f9787984d4378 100644 --- a/hw/vfio/platform.c +++ b/hw/vfio/platform.c @@ -545,9 +545,8 @@ static int vfio_base_device_init(VFIODevice *vbasedev, Error **errp) vbasedev->name); } -ret = vfio_device_get_name(vbasedev, errp); -if (ret) { -return ret; +if (!vfio_device_get_name(vbasedev, errp)) { +return -EINVAL; } if (!vfio_attach_device(vbasedev->name, vbasedev, -- 2.45.1
[PULL 32/47] vfio/helpers: Use g_autofree in vfio_set_irq_signaling()
From: Zhenzhong Duan Local pointer irq_set is freed before return from vfio_set_irq_signaling(). Use 'g_autofree' to avoid the g_free() calls. Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/helpers.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 47b4096c05ee8915c42b763fa18754c425aa00f6..1f3bdd9bf059beec186d87ba4772f2f6e34bc7d4 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -111,7 +111,7 @@ int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, int action, int fd, Error **errp) { ERRP_GUARD(); -struct vfio_irq_set *irq_set; +g_autofree struct vfio_irq_set *irq_set = NULL; int argsz, ret = 0; const char *name; int32_t *pfd; @@ -130,7 +130,6 @@ int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, if (ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { ret = -errno; } -g_free(irq_set); if (!ret) { return 0; -- 2.45.1
[PULL 43/47] vfio/pci: Use g_autofree for vfio_region_info pointer
From: Zhenzhong Duan Pointer opregion is freed after vfio_pci_igd_opregion_init(). Use 'g_autofree' to avoid the g_free() calls. Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- hw/vfio/pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index c3323912dd773e80ad2dbbefc5d833e8a33cd147..8379d2284a20bed0c0bd24e46bbb39e321dc9767 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -3143,7 +3143,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) if (!vdev->igd_opregion && vdev->features & VFIO_FEATURE_ENABLE_IGD_OPREGION) { -struct vfio_region_info *opregion; +g_autofree struct vfio_region_info *opregion = NULL; if (vdev->pdev.qdev.hotplugged) { error_setg(errp, @@ -3162,7 +3162,6 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) } ret = vfio_pci_igd_opregion_init(vdev, opregion, errp); -g_free(opregion); if (ret) { goto out_teardown; } -- 2.45.1
[PULL 23/47] vfio: Make VFIOIOMMUClass::add_window() and its wrapper return bool
From: Zhenzhong Duan Make VFIOIOMMUClass::add_window() and its wrapper function vfio_container_add_section_window() return bool. This is to follow the coding standand to return bool if 'Error **' is used to pass error. Suggested-by: Cédric Le Goater Signed-off-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater Signed-off-by: Cédric Le Goater --- include/hw/vfio/vfio-container-base.h | 12 ++-- hw/vfio/common.c | 2 +- hw/vfio/container-base.c | 8 hw/vfio/spapr.c | 16 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h index 202e23cb6b800983b036bf3808c0ec38b1c363d0..2776481fc97ef5720b10a4e3b3e6deaa075ece75 100644 --- a/include/hw/vfio/vfio-container-base.h +++ b/include/hw/vfio/vfio-container-base.h @@ -76,9 +76,9 @@ int vfio_container_dma_map(VFIOContainerBase *bcontainer, int vfio_container_dma_unmap(VFIOContainerBase *bcontainer, hwaddr iova, ram_addr_t size, IOMMUTLBEntry *iotlb); -int vfio_container_add_section_window(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, - Error **errp); +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, @@ -156,9 +156,9 @@ struct VFIOIOMMUClass { int (*pci_hot_reset)(VFIODevice *vbasedev, bool single); /* SPAPR specific */ -int (*add_window)(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, - Error **errp); +bool (*add_window)(VFIOContainerBase *bcontainer, + MemoryRegionSection *section, + Error **errp); void (*del_window)(VFIOContainerBase *bcontainer, MemoryRegionSection *section); void (*release)(VFIOContainerBase *bcontainer); diff --git a/hw/vfio/common.c b/hw/vfio/common.c index c04a259ffd7cfcfba480335bea1ddff787f47bdc..f9619a1dfbc689b10d70a60ce21b9b018f32391f 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -588,7 +588,7 @@ static void vfio_listener_region_add(MemoryListener *listener, return; } -if (vfio_container_add_section_window(bcontainer, section, )) { +if (!vfio_container_add_section_window(bcontainer, section, )) { goto fail; } diff --git a/hw/vfio/container-base.c b/hw/vfio/container-base.c index 26f4bb464a720c9895b35c7c9e01c84d6322c3c9..760d9d0622b2e847ecb3368c88df772efb06043f 100644 --- a/hw/vfio/container-base.c +++ b/hw/vfio/container-base.c @@ -31,12 +31,12 @@ int vfio_container_dma_unmap(VFIOContainerBase *bcontainer, return bcontainer->ops->dma_unmap(bcontainer, iova, size, iotlb); } -int vfio_container_add_section_window(VFIOContainerBase *bcontainer, - MemoryRegionSection *section, - Error **errp) +bool vfio_container_add_section_window(VFIOContainerBase *bcontainer, + MemoryRegionSection *section, + Error **errp) { if (!bcontainer->ops->add_window) { -return 0; +return true; } return bcontainer->ops->add_window(bcontainer, section, errp); diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 148b257c9ca6a0f957115f8060ddb50e377dfcb8..47b040f1bcca7dd0b5cf052d941b43541e98a3c5 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -323,7 +323,7 @@ static int vfio_spapr_create_window(VFIOContainer *container, return 0; } -static int +static bool vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer, MemoryRegionSection *section, Error **errp) @@ -351,13 +351,13 @@ vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer, error_setg(errp, "Container %p can't map guest IOVA region" " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, container, iova, end); -return -EINVAL; +return false; } -return 0; +return true; } if (container->iommu_type != VFIO_SPAPR_TCE_v2_IOMMU) { -return 0; +return true; } /* For now intersections are not allowed, we may relax this later */ @@ -373,14 +373,14 @@ vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer,