qemu/hw-arm-smmuv3-Forward-cache-invalidate-commands-via-.patch

230 lines
7.4 KiB
Diff
Raw Permalink Normal View History

QEMU update to version 8.2.0-30: - Revert "linux-user: Print tid not pid with strace" - gpex-acpi: Remove duplicate DSM #5 - smmuv3: Use default bus for arm-smmuv3-accel - smmuv3: Change arm-smmuv3-nested name to arm-smmuv3-accel - smmu-common: Return sysmem address space only for vfio-pci - smmuv3: realize get_pasid_cap and set ssidsize with pasid - vfio: Synthesize vPASID capability to VM - backend/iommufd: Report PASID capability - pci: Get pasid capability from vIOMMU - smmuv3: Add support for page fault handling - kvm: Translate MSI doorbell address only if it is valid - hw/arm/smmuv3: Enable sva/stall IDR features - iommufd.h: Updated to openeuler olk-6.6 kernel - tests/data/acpi/virt: Update IORT acpi table - hw/arm/virt-acpi-build: Add IORT RMR regions to handle MSI nested binding - tests/qtest: Allow IORT acpi table to change - hw/arm/virt-acpi-build: Build IORT with multiple SMMU nodes - hw/arm/smmuv3: Associate a pci bus with a SMMUv3 Nested device - hw/arm/smmuv3: Add initial support for SMMUv3 Nested device - hw/arm/virt: Add an SMMU_IO_LEN macro - hw/pci-host/gpex: [needs kernel fix] Allow to generate preserve boot config DSM #5 - tests/data/acpi: Update DSDT acpi tables - acpi/gpex: Fix PCI Express Slot Information function 0 returned value - tests/qtest: Allow DSDT acpi tables to change - hw/arm/smmuv3: Forward cache invalidate commands via iommufd - hw/arm/smmu-common: Replace smmu_iommu_mr with smmu_find_sdev - hw/arm/smmuv3: Add missing STE invalidation - hw/arm/smmuv3: Add smmu_dev_install_nested_ste() for CFGI_STE - hw/arm/smmuv3: Check idr registers for STE_S1CDMAX and STE_S1STALLD - hw/arm/smmuv3: Read host SMMU device info - hw/arm/smmuv3: Ignore IOMMU_NOTIFIER_MAP for nested-smmuv3 - hw/arm/smmu-common: Return sysmem if stage-1 is bypassed - hw/arm/smmu-common: Add iommufd helpers - hw/arm/smmu-common: Add set/unset_iommu_device callback - hw/arm/smmu-common: Extract smmu_get_sbus and smmu_get_sdev helpers - hw/arm/smmu-common: Bypass emulated IOTLB for a nested SMMU - hw/arm/smmu-common: Add a nested flag to SMMUState - backends/iommufd: Introduce iommufd_viommu_invalidate_cache - backends/iommufd: Introduce iommufd_vdev_alloc - backends/iommufd: Introduce iommufd_backend_alloc_viommu - vfio/iommufd: Implement [at|de]tach_hwpt handlers - vfio/iommufd: Implement HostIOMMUDeviceClass::realize_late() handler - HostIOMMUDevice: Introduce realize_late callback - vfio/iommufd: Add properties and handlers to TYPE_HOST_IOMMU_DEVICE_IOMMUFD - backends/iommufd: Add helpers for invalidating user-managed HWPT - Update iommufd.h header for vSVA - vfio/common: Allow disabling device dirty page tracking - vfio/migration: Don't block migration device dirty tracking is unsupported - vfio/iommufd: Implement VFIOIOMMUClass::query_dirty_bitmap support - vfio/iommufd: Implement VFIOIOMMUClass::set_dirty_tracking support - vfio/iommufd: Probe and request hwpt dirty tracking capability - vfio/{iommufd, container}: Invoke HostIOMMUDevice::realize() during attach_device() - vfio/iommufd: Add hw_caps field to HostIOMMUDeviceCaps - vfio/{iommufd,container}: Remove caps::aw_bits - HostIOMMUDevice: Store the VFIO/VDPA agent - vfio/iommufd: Introduce auto domain creation - vfio/ccw: Don't initialize HOST_IOMMU_DEVICE with mdev - vfio/ap: Don't initialize HOST_IOMMU_DEVICE with mdev - vfio/iommufd: Return errno in iommufd_cdev_attach_ioas_hwpt() - backends/iommufd: Extend iommufd_backend_get_device_info() to fetch HW capabilities - vfio/iommufd: Don't initialize nor set a HOST_IOMMU_DEVICE with mdev - vfio/pci: Extract mdev check into an helper - intel_iommu: Check compatibility with host IOMMU capabilities - intel_iommu: Implement [set|unset]_iommu_device() callbacks - intel_iommu: Extract out vtd_cap_init() to initialize cap/ecap - vfio/pci: Pass HostIOMMUDevice to vIOMMU - hw/pci: Introduce pci_device_[set|unset]_iommu_device() - hw/pci: Introduce helper function pci_device_get_iommu_bus_devfn() - vfio: Create host IOMMU device instance - backends/iommufd: Implement HostIOMMUDeviceClass::get_cap() handler - vfio/container: Implement HostIOMMUDeviceClass::get_cap() handler - vfio/iommufd: Implement HostIOMMUDeviceClass::realize() handler - backends/iommufd: Introduce helper function iommufd_backend_get_device_info() - vfio/container: Implement HostIOMMUDeviceClass::realize() handler - range: Introduce range_get_last_bit() - backends/iommufd: Introduce TYPE_HOST_IOMMU_DEVICE_IOMMUFD[_VFIO] devices - vfio/container: Introduce TYPE_HOST_IOMMU_DEVICE_LEGACY_VFIO device - backends/host_iommu_device: Introduce HostIOMMUDeviceCaps - backends: Introduce HostIOMMUDevice abstract - vfio/iommufd: Remove CONFIG_IOMMUFD usage - vfio/spapr: Extend VFIOIOMMUOps with a release handler - vfio/spapr: Only compile sPAPR IOMMU support when needed - vfio/iommufd: Introduce a VFIOIOMMU iommufd QOM interface - vfio/spapr: Introduce a sPAPR VFIOIOMMU QOM interface - vfio/container: Intoduce a new VFIOIOMMUClass::setup handler - vfio/container: Introduce a VFIOIOMMU legacy QOM interface - vfio/container: Introduce a VFIOIOMMU QOM interface - vfio/container: Initialize VFIOIOMMUOps under vfio_init_container() - vfio/container: Introduce vfio_legacy_setup() for further cleanups - docs/devel: Add VFIO iommufd backend documentation - vfio: Introduce a helper function to initialize VFIODevice - vfio/ccw: Move VFIODevice initializations in vfio_ccw_instance_init - vfio/ap: Move VFIODevice initializations in vfio_ap_instance_init - vfio/platform: Move VFIODevice initializations in vfio_platform_instance_init - vfio/pci: Move VFIODevice initializations in vfio_instance_init - hw/i386: Activate IOMMUFD for q35 machines - kconfig: Activate IOMMUFD for s390x machines - hw/arm: Activate IOMMUFD for virt machines - vfio: Make VFIOContainerBase poiner parameter const in VFIOIOMMUOps callbacks - vfio/ccw: Make vfio cdev pre-openable by passing a file handle - vfio/ccw: Allow the selection of a given iommu backend - vfio/ap: Make vfio cdev pre-openable by passing a file handle - vfio/ap: Allow the selection of a given iommu backend - vfio/platform: Make vfio cdev pre-openable by passing a file handle - vfio/platform: Allow the selection of a given iommu backend - vfio/pci: Make vfio cdev pre-openable by passing a file handle - vfio/pci: Allow the selection of a given iommu backend - vfio/iommufd: Enable pci hot reset through iommufd cdev interface - vfio/pci: Introduce a vfio pci hot reset interface - vfio/pci: Extract out a helper vfio_pci_get_pci_hot_reset_info - vfio/iommufd: Add support for iova_ranges and pgsizes - vfio/iommufd: Relax assert check for iommufd backend - vfio/iommufd: Implement the iommufd backend - vfio/common: return early if space isn't empty - util/char_dev: Add open_cdev() - backends/iommufd: Introduce the iommufd object - vfio/spapr: Move hostwin_list into spapr container - vfio/spapr: Move prereg_listener into spapr container - vfio/spapr: switch to spapr IOMMU BE add/del_section_window - vfio/spapr: Introduce spapr backend and target interface - vfio/container: Implement attach/detach_device - vfio/container: Move iova_ranges to base container - vfio/container: Move dirty_pgsizes and max_dirty_bitmap_size to base container - vfio/container: Move listener to base container - vfio/container: Move vrdl_list to base container - vfio/container: Move pgsizes and dma_max_mappings to base container - vfio/container: Convert functions to base container - vfio/container: Move per container device list in base container - vfio/container: Switch to IOMMU BE set_dirty_page_tracking/query_dirty_bitmap API - vfio/container: Move space field to base container - vfio/common: Move giommu_list in base container - vfio/common: Introduce vfio_container_init/destroy helper - vfio/container: Switch to dma_map|unmap API - vfio/container: Introduce a empty VFIOIOMMUOps - vfio: Introduce base object for VFIOContainer and targeted interface - cryptodev: Fix error handling in cryptodev_lkcf_execute_task() - hw/xen: Fix xen_bus_realize() error handling - hw/misc/aspeed_hace: Fix buffer overflow in has_padding function - target/s390x: Fix a typo in s390_cpu_class_init() - hw/sd/sdhci: free irq on exit - hw/ufs: free irq on exit - hw/pci-host/designware: Fix ATU_UPPER_TARGET register access - target/i386: Make invtsc migratable when user sets tsc-khz explicitly - target/i386: Construct CPUID 2 as stateful iff times > 1 - target/i386: Enable fdp-excptn-only and zero-fcs-fds - target/i386: Don't construct a all-zero entry for CPUID[0xD 0x3f] - i386/cpuid: Remove subleaf constraint on CPUID leaf 1F - target/i386: pass X86CPU to x86_cpu_get_supported_feature_word - target/i386: Raise the highest index value used for any VMCS encoding - target/i386: Add VMX control bits for nested FRED support - target/i386: Delete duplicated macro definition CR4_FRED_MASK - target/i386: Add get/set/migrate support for FRED MSRs - target/i386: enumerate VMX nested-exception support - vmxcap: add support for VMX FRED controls - target/i386: mark CR4.FRED not reserved - target/i386: add support for FRED in CPUID enumeration - target/i386: fix feature dependency for WAITPKG - target/i386: Add more features enumerated by CPUID.7.2.EDX - net: fix build when libbpf is disabled, but libxdp is enabled - hw/nvme: fix invalid endian conversion - hw/nvme: fix invalid check on mcl - backends/cryptodev: Do not ignore throttle/backends Errors - backends/cryptodev: Do not abort for invalid session ID - virtcca: add kvm isolation when get tmi version. - qga: Don't daemonize before channel is initialized - qga: Add log to guest-fsfreeze-thaw command - backends: VirtCCA: cvm_gpa_start supports both 1GB and 3GB - BUGFIX: Enforce isolation for virtcca_shared_hugepage - arm: VirtCCA: qemu CoDA support UEFI boot - arm: VirtCCA: Compatibility with older versions of TMM and the kernel - arm: VirtCCA: qemu uefi boot support kae - arm: VirtCCA: CVM support UEFI boot Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com> (cherry picked from commit 85fd7a435d8203dde56fedc4c8f500e41faf132c)
2025-04-22 14:34:58 +08:00
From b331acc42fa54ca93496c32d92cdf5397927bff1 Mon Sep 17 00:00:00 2001
From: Nicolin Chen <nicolinc@nvidia.com>
Date: Fri, 21 Apr 2023 15:18:56 -0700
Subject: [PATCH] hw/arm/smmuv3: Forward cache invalidate commands via iommufd
Inroduce an SMMUCommandBatch and some helpers to batch the commands.
Rewind the q->cons accordingly when it fails to execute a batch/command.
Currently separate TLBI commands and device cache commands to avoid some
errata on certain version of SMMUs. Later it should check IIDR register
to detect if underlying SMMU hw has such an erratum.
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
hw/arm/smmuv3-internal.h | 13 +++++
hw/arm/smmuv3.c | 113 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 125 insertions(+), 1 deletion(-)
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index 163459d450..a411fd4048 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -226,6 +226,19 @@ static inline bool smmuv3_gerror_irq_enabled(SMMUv3State *s)
#define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> (q)->log2size)
#define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> (q)->log2size)
+#define Q_IDX(llq, p) ((p) & ((1 << (llq)->max_n_shift) - 1))
+
+static inline int smmuv3_q_ncmds(SMMUQueue *q)
+{
+ uint32_t prod = Q_PROD(q);
+ uint32_t cons = Q_CONS(q);
+
+ if (Q_PROD_WRAP(q) == Q_CONS_WRAP(q))
+ return prod - cons;
+ else
+ return WRAP_MASK(q) - cons + prod;
+}
+
static inline bool smmuv3_q_full(SMMUQueue *q)
{
return ((q->cons ^ q->prod) & WRAP_INDEX_MASK(q)) == WRAP_MASK(q);
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index b2ffe2d40b..b860c8385f 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -1357,16 +1357,85 @@ static void smmuv3_invalidate_nested_ste(SMMUSIDRange *sid_range)
}
}
+/**
+ * SMMUCommandBatch - batch of commands to issue for nested SMMU invalidation
+ * @cmds: Pointer to list of commands
+ * @cons: Pointer to list of CONS corresponding to the commands
+ * @ncmds: Total ncmds in the batch
+ * @dev_cache: Issue to a device cache
+ */
+typedef struct SMMUCommandBatch {
+ Cmd *cmds;
+ uint32_t *cons;
+ uint32_t ncmds;
+ bool dev_cache;
+} SMMUCommandBatch;
+
+/* Update batch->ncmds to the number of execute cmds */
+static int smmuv3_issue_cmd_batch(SMMUState *bs, SMMUCommandBatch *batch)
+{
+ uint32_t total = batch->ncmds;
+ int ret;
+
+ ret = smmu_viommu_invalidate_cache(bs->viommu->core,
+ IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3,
+ sizeof(Cmd), &batch->ncmds, batch->cmds);
+ if (total != batch->ncmds) {
+ error_report("%s failed: ret=%d, total=%d, done=%d",
+ __func__, ret, total, batch->ncmds);
+ return ret;
+ }
+
+ batch->ncmds = 0;
+ batch->dev_cache = false;
+ return ret;
+}
+
+static int smmuv3_batch_cmds(SMMUState *bs, SMMUCommandBatch *batch,
+ Cmd *cmd, uint32_t *cons, bool dev_cache)
+{
+ int ret;
+
+ if (!bs->nested || !bs->viommu) {
+ return 0;
+ }
+
+ /*
+ * Currently separate dev_cache and hwpt for safety, which might not be
+ * necessary if underlying HW SMMU does not have the errata.
+ *
+ * TODO check IIDR register values read from hw_info.
+ */
+ if (batch->ncmds && (dev_cache != batch->dev_cache)) {
+ ret = smmuv3_issue_cmd_batch(bs, batch);
+ if (ret) {
+ *cons = batch->cons[batch->ncmds];
+ return ret;
+ }
+ }
+ batch->dev_cache = dev_cache;
+ batch->cmds[batch->ncmds] = *cmd;
+ batch->cons[batch->ncmds++] = *cons;
+ return 0;
+}
+
static int smmuv3_cmdq_consume(SMMUv3State *s)
{
SMMUState *bs = ARM_SMMU(s);
SMMUCmdError cmd_error = SMMU_CERROR_NONE;
SMMUQueue *q = &s->cmdq;
SMMUCommandType type = 0;
+ SMMUCommandBatch batch = {};
+ uint32_t ncmds = 0;
if (!smmuv3_cmdq_enabled(s)) {
return 0;
}
+
+ ncmds = smmuv3_q_ncmds(q);
+ batch.cmds = g_new0(Cmd, ncmds);
+ batch.cons = g_new0(uint32_t, ncmds);
+
/*
* some commands depend on register values, typically CR0. In case those
* register values change while handling the command, spec says it
@@ -1463,6 +1532,13 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
trace_smmuv3_cmdq_cfgi_cd(sid);
smmuv3_flush_config(sdev);
+
+ if (sdev->s1_hwpt) {
+ if (smmuv3_batch_cmds(sdev->smmu, &batch, &cmd, &q->cons, true)) {
+ cmd_error = SMMU_CERROR_ILL;
+ break;
+ }
+ }
break;
}
case SMMU_CMD_TLBI_NH_ASID:
@@ -1477,6 +1553,10 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
trace_smmuv3_cmdq_tlbi_nh_asid(asid);
smmu_inv_notifiers_all(&s->smmu_state);
smmu_iotlb_inv_asid(bs, asid);
+ if (smmuv3_batch_cmds(bs, &batch, &cmd, &q->cons, false)) {
+ cmd_error = SMMU_CERROR_ILL;
+ break;
+ }
break;
}
case SMMU_CMD_TLBI_NH_ALL:
@@ -1489,6 +1569,11 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
trace_smmuv3_cmdq_tlbi_nh();
smmu_inv_notifiers_all(&s->smmu_state);
smmu_iotlb_inv_all(bs);
+
+ if (smmuv3_batch_cmds(bs, &batch, &cmd, &q->cons, false)) {
+ cmd_error = SMMU_CERROR_ILL;
+ break;
+ }
break;
case SMMU_CMD_TLBI_NH_VAA:
case SMMU_CMD_TLBI_NH_VA:
@@ -1497,7 +1582,24 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
break;
}
smmuv3_range_inval(bs, &cmd);
+
+ if (smmuv3_batch_cmds(bs, &batch, &cmd, &q->cons, false)) {
+ cmd_error = SMMU_CERROR_ILL;
+ break;
+ }
break;
+ case SMMU_CMD_ATC_INV:
+ {
+ SMMUDevice *sdev = smmu_find_sdev(bs, CMD_SID(&cmd));
+
+ if (sdev->s1_hwpt) {
+ if (smmuv3_batch_cmds(sdev->smmu, &batch, &cmd, &q->cons, true)) {
+ cmd_error = SMMU_CERROR_ILL;
+ break;
+ }
+ }
+ break;
+ }
case SMMU_CMD_TLBI_S12_VMALL:
{
uint16_t vmid = CMD_VMID(&cmd);
@@ -1529,7 +1631,6 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
case SMMU_CMD_TLBI_EL2_ASID:
case SMMU_CMD_TLBI_EL2_VA:
case SMMU_CMD_TLBI_EL2_VAA:
- case SMMU_CMD_ATC_INV:
case SMMU_CMD_PRI_RESP:
case SMMU_CMD_RESUME:
case SMMU_CMD_STALL_TERM:
@@ -1554,12 +1655,22 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
*/
queue_cons_incr(q);
}
+ qemu_mutex_lock(&s->mutex);
+ if (!cmd_error && batch.ncmds && bs->viommu) {
+ if (smmuv3_issue_cmd_batch(bs, &batch)) {
+ q->cons = batch.cons[batch.ncmds];
+ cmd_error = SMMU_CERROR_ILL;
+ }
+ }
+ qemu_mutex_unlock(&s->mutex);
if (cmd_error) {
trace_smmuv3_cmdq_consume_error(smmu_cmd_string(type), cmd_error);
smmu_write_cmdq_err(s, cmd_error);
smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_CMDQ_ERR_MASK);
}
+ g_free(batch.cmds);
+ g_free(batch.cons);
trace_smmuv3_cmdq_consume_out(Q_PROD(q), Q_CONS(q),
Q_PROD_WRAP(q), Q_CONS_WRAP(q));
--
2.41.0.windows.1