projects/linux·commit d076a8d3

Merge tag 'iommu-updates-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux

d076a8d3 · Linus Torvalds <[email protected]> · 2026-06-17 12:24:50 -07:00

Pull iommu updates from Joerg Roedel:
 "Core Code:

   - Fix dma-iommu scatterlist length handling in the P2PDMA path

   - Extend the generic IOMMU page-table code with detailed gather
     support for more precise invalidations

   - Add pending-gather tracking to generic page-table invalidation
     handling

   - Add support for smaller virtual address sizes in the generic AMDv1
     page-table format, including KUnit coverage

   - Fix page-size bitmap calculation for smaller VA configurations

   - Rework Arm io-pgtable allocation/freeing to consistently use the
     iommu-pages API and address-conversion helpers

   - Add PCI ATS infrastructure for devices that require ATS, including
     always-on ATS handling for pre-CXL devices

  AMD IOMMU:

   - Fix several IOTLB invalidation details, including PDE handling,
     flush-all behavior, and command address encoding

   - Honor IVINFO[VASIZE] when deriving address limits

   - Fix premature loop termination in init_iommu_one()

   - Add Hygon family 18h model 4h IOAPIC support

   - Clean up legacy-mode handling, stale comments, dead IVMD
     exclusion-range code, and unused address-size macros

  Arm SMMU / Arm SMMU v3:

   - SMMUv2:
      - Device-tree binding updates for Qualcomm Hawi, Nord and Shikra
        SoCs
      - Constrain the clocks which can be specified for recent Qualcomm
        SoCs
      - Fix broken compatible string for Qualcomm prefetcher
        configuration an add new entry for the Glymur MDSS
      - Ensure SMMU is powered-up when writing context bank for Adreno
        client

   - SMMUv3:
      - Fix off-by-one in queue allocation retry loop
      - Enable hardware update of access/dirty bits from the SMMU
      - Re-jig command construction to use separate inline helpers for
        each command type

  Intel VT-d:

   - Add the PCI segment number to DMA fault messages

   - Improve support for non-PRI mode SVA

   - Ensure atomicity during context entry teardown

   - Fix RB-tree corruption in the probe error path

  RISC-V IOMMU:

   - Add NAPOT range invalidation support

   - Use detailed gather information for invalidation decisions

   - Compute the best stride for single invalidations

   - Advertise Svpbmt support to the generic page-table code

   - Add capability definitions and clean up command macro encoding

  VeriSilicon IOMMU:

   - Add a new VeriSilicon IOMMU driver

   - Add devicetree binding documentation and MAINTAINERS coverage

   - Add the RK3588 VeriSilicon IOMMU node

   - Apply small cleanups and warning fixes in the new driver

  Rockchip IOMMU:

   - Disable the fetch DTE time limit

  Apple DART:

   - Correct a stale CONFIG_PCIE_APPLE macro name in a comment"

* tag 'iommu-updates-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux: (66 commits)
  iommu/dma-iommu: Fix wrong scatterlist length assignment in P2PDMA path
  iommu/amd: Control INVALIDATE_IOMMU_PAGES PDE from the gather
  iommu/amd: Make CMD_INV_IOMMU_ALL_PAGES_ADDRESS match the spec
  iommu/amd: Have amd_iommu_domain_flush_pages() use last
  iommu/amd: Pass last in through to build_inv_address()
  iommu/amd: Simplify build_inv_address()
  iommu/apple-dart: correct CONFIG_PCIE_APPLE macro name in comment
  iommu/vt-d: Fix RB-tree corruption in probe error path
  iommu/vt-d: Improve IOMMU fault information
  iommu/vt-d: Remove typo from pasid_pte_config_nested()
  iommu/vt-d: Clear Present bit before tearing down scalable-mode context entry
  iommu/vt-d: Avoid WARNING in sva unbind path
  dt-bindings: arm-smmu: Correct and add constraints for Hawi, Shikra and Kaanapali
  dt-bindings: arm-smmu: Add compatible for Qualcomm Nord SoC
  iommu/amd: Don't split flush for amd_iommu_domain_flush_all()
  iommu/rockchip: disable fetch dte time limit
  iommu/arm-smmu-v3: Allow ATS to be always on
  PCI: Allow ATS to be always on for pre-CXL devices
  PCI: Add pci_ats_required() for CXL.cache capable devices
  iommu/vsi: Use list_for_each_entry()
  ...
Commit
d076a8d3b9b36563fdd029ef33c79f713445970e
Parents
4cc14386 · dd8a3c6c

Merge commit. Changes below are compared with the first parent: 4cc14386.

Changes

42 files changed · +2055 −766

FileStatusAddDelContent
Documentation/devicetree/bindings/iommu/arm,smmu.yamlmodified+43−1View file
Documentation/devicetree/bindings/iommu/verisilicon,iommu.yamladded+71−0View file
MAINTAINERSmodified+8−0View file
arch/arm64/boot/dts/rockchip/rk3588-base.dtsimodified+11−0View file
drivers/iommu/Kconfigmodified+11−0View file
drivers/iommu/Makefilemodified+1−0View file
drivers/iommu/amd/amd_iommu.hmodified+3−3View file
drivers/iommu/amd/amd_iommu_types.hmodified+8−21View file
drivers/iommu/amd/init.cmodified+27−36View file
drivers/iommu/amd/iommu.cmodified+84−97View file
drivers/iommu/amd/pasid.cmodified+1−1View file
drivers/iommu/apple-dart.cmodified+1−1View file
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.cmodified+12−12View file
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.cmodified+10−0View file
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.cmodified+245−313View file
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.hmodified+159−90View file
drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.cmodified+8−8View file
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.cmodified+12−1View file
drivers/iommu/dma-iommu.cmodified+1−1View file
drivers/iommu/generic_pt/fmt/amdv1.hmodified+1−0View file
drivers/iommu/generic_pt/fmt/iommu_riscv64.cmodified+3−1View file
drivers/iommu/generic_pt/fmt/riscv.hmodified+10−1View file
drivers/iommu/generic_pt/iommu_pt.hmodified+76−34View file
drivers/iommu/generic_pt/kunit_generic_pt.hmodified+7−3View file
drivers/iommu/generic_pt/kunit_iommu_pt.hmodified+3−2View file
drivers/iommu/intel/dmar.cmodified+6−3View file
drivers/iommu/intel/iommu.cmodified+5−1View file
drivers/iommu/intel/iommu.hmodified+11−0View file
drivers/iommu/intel/pasid.cmodified+9−7View file
drivers/iommu/intel/svm.cmodified+4−8View file
drivers/iommu/io-pgtable-arm.cmodified+61−27View file
drivers/iommu/riscv/iommu-bits.hmodified+74−49View file
drivers/iommu/riscv/iommu.cmodified+124−38View file
drivers/iommu/rockchip-iommu.cmodified+8−0View file
drivers/iommu/vsi-iommu.cadded+791−0View file
drivers/pci/ats.cmodified+47−0View file
drivers/pci/pci.hmodified+9−0View file
drivers/pci/quirks.cmodified+42−0View file
include/linux/generic_pt/common.hmodified+9−0View file
include/linux/iommu.hmodified+35−7View file
include/linux/pci-ats.hmodified+3−0View file
include/uapi/linux/pci_regs.hmodified+1−0View file

Only the first 600 diff lines are shown. Download the complete patch.

Documentation/devicetree/bindings/iommu/arm,smmu.yaml

View file
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index 06fb5c8..a701dec 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -37,8 +37,10 @@ properties:
- enum:
- qcom,eliza-smmu-500
- qcom,glymur-smmu-500
+ - qcom,hawi-smmu-500
- qcom,kaanapali-smmu-500
- qcom,milos-smmu-500
+ - qcom,nord-smmu-500
- qcom,qcm2290-smmu-500
- qcom,qcs615-smmu-500
- qcom,qcs8300-smmu-500
@@ -55,6 +57,7 @@ properties:
- qcom,sdx55-smmu-500
- qcom,sdx65-smmu-500
- qcom,sdx75-smmu-500
+ - qcom,shikra-smmu-500
- qcom,sm6115-smmu-500
- qcom,sm6125-smmu-500
- qcom,sm6350-smmu-500
@@ -566,7 +569,11 @@ allOf:
properties:
compatible:
items:
- - const: qcom,sm8750-smmu-500
+ - enum:
+ - qcom,glymur-smmu-500
+ - qcom,hawi-smmu-500
+ - qcom,kaanapali-smmu-500
+ - qcom,sm8750-smmu-500
- const: qcom,adreno-smmu
- const: qcom,smmu-500
- const: arm,mmu-500
@@ -595,6 +602,7 @@ allOf:
- qcom,sdm845-smmu-500
- qcom,sdx55-smmu-500
- qcom,sdx65-smmu-500
+ - qcom,sdx75-smmu-500
- qcom,sm6350-smmu-500
- qcom,sm6375-smmu-500
then:
@@ -602,6 +610,40 @@ allOf:
clock-names: false
clocks: false
+ # Disallow clocks for all other platforms where specific compatible is used
+ # with different fallbacks and only one combination has no clocks
+ - if:
+ properties:
+ compatible:
+ items:
+ - enum:
+ - qcom,eliza-smmu-500
+ - qcom,glymur-smmu-500
+ - qcom,hawi-smmu-500
+ - qcom,kaanapali-smmu-500
+ - qcom,milos-smmu-500
+ - qcom,nord-smmu-500
+ - qcom,qcs615-smmu-500
+ - qcom,qcs8300-smmu-500
+ - qcom,sa8775p-smmu-500
+ - qcom,shikra-smmu-500
+ - qcom,sm6115-smmu-500
+ - qcom,sm6125-smmu-500
+ - qcom,sm8150-smmu-500
+ - qcom,sm8250-smmu-500
+ - qcom,sm8350-smmu-500
+ - qcom,sm8450-smmu-500
+ - qcom,sm8550-smmu-500
+ - qcom,sm8650-smmu-500
+ - qcom,sm8750-smmu-500
+ - qcom,x1e80100-smmu-500
+ - const: qcom,smmu-500
+ - const: arm,mmu-500
+ then:
+ properties:
+ clock-names: false
+ clocks: false
+
- if:
properties:
compatible:

Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml

View file
diff --git a/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml b/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
new file mode 100644
index 0000000..d3ce9e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iommu/verisilicon,iommu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Verisilicon IOMMU
+
+maintainers:
+ - Benjamin Gaignard <[email protected]>
+
+description: |+
+ A Versilicon iommu translates io virtual addresses to physical addresses for
+ its associated video decoder.
+
+properties:
+ compatible:
+ items:
+ - const: rockchip,rk3588-av1-iommu
+ - const: verisilicon,iommu-1.2
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Core clock
+ - description: Interface clock
+
+ clock-names:
+ items:
+ - const: core
+ - const: iface
+
+ "#iommu-cells":
+ const: 0
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - "#iommu-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/rockchip,rk3588-cru.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ iommu@fdca0000 {
+ compatible = "rockchip,rk3588-av1-iommu","verisilicon,iommu-1.2";
+ reg = <0x0 0xfdca0000 0x0 0x600>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
+ clock-names = "core", "iface";
+ #iommu-cells = <0>;
+ };
+ };

MAINTAINERS

View file
diff --git a/MAINTAINERS b/MAINTAINERS
index ab2dbef..e67d929 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28093,6 +28093,14 @@ F: drivers/media/v4l2-core/v4l2-isp.c
F: include/media/v4l2-isp.h
F: include/uapi/linux/media/v4l2-isp.h
+VERISILICON IOMMU DRIVER
+M: Benjamin Gaignard <[email protected]>
+S: Maintained
+F: Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
+F: drivers/iommu/vsi-iommu.c
+F: include/linux/vsi-iommu.h
+
VF610 NAND DRIVER
M: Stefan Agner <[email protected]>

arch/arm64/boot/dts/rockchip/rk3588-base.dtsi

View file
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index a22da66..fc1fdbf 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -1472,6 +1472,17 @@
clock-names = "aclk", "hclk";
power-domains = <&power RK3588_PD_AV1>;
resets = <&cru SRST_A_AV1>, <&cru SRST_P_AV1>, <&cru SRST_A_AV1_BIU>, <&cru SRST_P_AV1_BIU>;
+ iommus = <&av1d_mmu>;
+ };
+
+ av1d_mmu: iommu@fdca0000 {
+ compatible = "rockchip,rk3588-av1-iommu", "verisilicon,iommu-1.2";
+ reg = <0x0 0xfdca0000 0x0 0x600>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
+ clock-names = "core", "iface";
+ #iommu-cells = <0>;
+ power-domains = <&power RK3588_PD_AV1>;
};
vicap: video-capture@fdce0000 {

drivers/iommu/Kconfig

View file
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f86262b..18d3d68 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -384,6 +384,17 @@ config SPRD_IOMMU
Say Y here if you want to use the multimedia devices listed above.
+config VSI_IOMMU
+ tristate "Verisilicon IOMMU Support"
+ depends on (ARCH_ROCKCHIP && ARM64) || COMPILE_TEST
+ select IOMMU_API
+ help
+ Support for IOMMUs used by Verisilicon sub-systems like video
+ decoders or encoder hardware blocks.
+
+ Say Y here if you want to use this IOMMU in front of these
+ hardware blocks.
+
config IOMMU_DEBUG_PAGEALLOC
bool "Debug IOMMU mappings against page allocations"
depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION

drivers/iommu/Makefile

View file
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 0275821..887af35 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -36,4 +36,5 @@ obj-$(CONFIG_IOMMU_SVA) += iommu-sva.o
obj-$(CONFIG_IOMMU_IOPF) += io-pgfault.o
obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o
obj-$(CONFIG_APPLE_DART) += apple-dart.o
+obj-$(CONFIG_VSI_IOMMU) += vsi-iommu.o
obj-$(CONFIG_IOMMU_DEBUG_PAGEALLOC) += iommu-debug-pagealloc.o

drivers/iommu/amd/amd_iommu.h

View file
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 834d8fa..a2fe804 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -44,7 +44,7 @@ int amd_iommu_enable_faulting(unsigned int cpu);
extern int amd_iommu_guest_ir;
extern enum protection_domain_mode amd_iommu_pgtable;
extern int amd_iommu_gpt_level;
-extern u8 amd_iommu_hpt_level;
+extern u8 amd_iommu_hpt_vasize;
extern unsigned long amd_iommu_pgsize_bitmap;
extern bool amd_iommu_hatdis;
@@ -91,9 +91,9 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag);
*/
void amd_iommu_flush_all_caches(struct amd_iommu *iommu);
void amd_iommu_domain_flush_pages(struct protection_domain *domain,
- u64 address, size_t size);
+ u64 address, u64 last, u32 flags);
void amd_iommu_dev_flush_pasid_pages(struct iommu_dev_data *dev_data,
- ioasid_t pasid, u64 address, size_t size);
+ ioasid_t pasid, u64 address, u64 last);
#ifdef CONFIG_IRQ_REMAP
int amd_iommu_create_irq_domain(struct amd_iommu *iommu);

drivers/iommu/amd/amd_iommu_types.h

View file
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index f9f7180..3c292fd 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -51,10 +51,6 @@
#define MMIO_GET_BUS(x) (((x) & MMIO_RANGE_BUS_MASK) >> MMIO_RANGE_BUS_SHIFT)
#define MMIO_MSI_NUM(x) ((x) & 0x1f)
-/* Flag masks for the AMD IOMMU exclusion range */
-#define MMIO_EXCL_ENABLE_MASK 0x01ULL
-#define MMIO_EXCL_ALLOW_MASK 0x02ULL
-
/* Used offsets into the MMIO space */
#define MMIO_DEV_TABLE_OFFSET 0x0000
#define MMIO_CMD_BUF_OFFSET 0x0008
@@ -221,7 +217,7 @@
#define PPR_STATUS_MASK 0xf
#define PPR_STATUS_SHIFT 12
-#define CMD_INV_IOMMU_ALL_PAGES_ADDRESS 0x7fffffffffffffffULL
+#define CMD_INV_IOMMU_ALL_PAGES_ADDRESS 0x7ffffffffffff000ULL
/* macros and definitions for device table entries */
#define DEV_ENTRY_VALID 0x00
@@ -231,7 +227,6 @@
#define DEV_ENTRY_IR 0x3d
#define DEV_ENTRY_IW 0x3e
#define DEV_ENTRY_NO_PAGE_FAULT 0x62
-#define DEV_ENTRY_EX 0x67
#define DEV_ENTRY_SYSMGT1 0x68
#define DEV_ENTRY_SYSMGT2 0x69
#define DTE_DATA1_SYSMGT_MASK GENMASK_ULL(41, 40)
@@ -305,9 +300,6 @@
#define GA_GUEST_NR 0x1
-#define IOMMU_IN_ADDR_BIT_SIZE 52
-#define IOMMU_OUT_ADDR_BIT_SIZE 52
-
/*
* This bitmap is used to advertise the page sizes our hardware support
* to the IOMMU core, which will then use this information to split
@@ -389,8 +381,6 @@
#define IOMMU_PROT_IR 0x01
#define IOMMU_PROT_IW 0x02
-#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE (1 << 2)
-
/* IOMMU capabilities */
#define IOMMU_CAP_IOTLB 24
#define IOMMU_CAP_NPCACHE 26
@@ -400,6 +390,7 @@
#define IOMMU_IVINFO_OFFSET 36
#define IOMMU_IVINFO_EFRSUP BIT(0)
#define IOMMU_IVINFO_DMA_REMAP BIT(1)
+#define IOMMU_IVINFO_VASIZE GENMASK_ULL(21, 15)
/* IOMMU Feature Reporting Field (for IVHD type 10h */
#define IOMMU_FEAT_GASUP_SHIFT 6
@@ -685,11 +676,6 @@ struct amd_iommu {
/* pci domain of this IOMMU */
struct amd_iommu_pci_seg *pci_seg;
- /* start of exclusion range of that IOMMU */
- u64 exclusion_start;
- /* length of exclusion range of that IOMMU */
- u64 exclusion_length;
-
/* command buffer virtual address */
u8 *cmd_buf;
u32 cmd_buf_head;
@@ -948,12 +934,13 @@ static inline int get_hpet_devid(int id)
}
enum amd_iommu_intr_mode_type {
- AMD_IOMMU_GUEST_IR_LEGACY,
-
- /* This mode is not visible to users. It is used when
- * we cannot fully enable vAPIC and fallback to only support
- * legacy interrupt remapping via 128-bit IRTE.
+ /*
+ * The legacy format mode is not visible to users to prevent the user
+ * from crashing x2APIC systems, which for all intents and purposes
+ * require 128-bit IRTEs. The legacy format will be forced as needed
+ * when hardware doesn't support 128-bit IRTEs.
*/
+ AMD_IOMMU_GUEST_IR_LEGACY,
AMD_IOMMU_GUEST_IR_LEGACY_GA,
AMD_IOMMU_GUEST_IR_VAPIC,
};

drivers/iommu/amd/init.c

View file
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 3bdb380..e93bcb5 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -155,8 +155,8 @@ bool amd_iommu_dump;
bool amd_iommu_irq_remap __read_mostly;
enum protection_domain_mode amd_iommu_pgtable = PD_MODE_V1;
-/* Host page table level */
-u8 amd_iommu_hpt_level;
+/* Virtual address size */
+u8 amd_iommu_hpt_vasize;
/* Guest page table level */
int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;
@@ -355,28 +355,6 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
*
****************************************************************************/
-/*
- * This function set the exclusion range in the IOMMU. DMA accesses to the
- * exclusion range are passed through untranslated
- */
-static void iommu_set_exclusion_range(struct amd_iommu *iommu)
-{
- u64 start = iommu->exclusion_start & PAGE_MASK;
- u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
- u64 entry;
-
- if (!iommu->exclusion_start)
- return;
-
- entry = start | MMIO_EXCL_ENABLE_MASK;
- memcpy_toio(iommu->mmio_base + MMIO_EXCL_BASE_OFFSET,
- &entry, sizeof(entry));
-
- entry = limit;
- memcpy_toio(iommu->mmio_base + MMIO_EXCL_LIMIT_OFFSET,
- &entry, sizeof(entry));
-}
-
static void iommu_set_cwwb_range(struct amd_iommu *iommu)
{
u64 start = iommu_virt_to_phys((void *)iommu->cmd_sem);
@@ -972,8 +950,8 @@ static int iommu_init_ga_log(struct amd_iommu *iommu)
{
int nid = iommu->dev ? dev_to_node(&iommu->dev->dev) : NUMA_NO_NODE;
- if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
- return 0;
+ if (WARN_ON_ONCE(!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)))
+ return -EINVAL;
iommu->ga_log = iommu_alloc_pages_node_sz(nid, GFP_KERNEL, GA_LOG_SIZE);
if (!iommu->ga_log)
@@ -1939,12 +1917,11 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h,
/* XT and GAM require GA mode. */
if ((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0) {
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
- break;
+ } else {
+ if (h->efr_reg & BIT(IOMMU_EFR_XTSUP_SHIFT))
+ amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
}
- if (h->efr_reg & BIT(IOMMU_EFR_XTSUP_SHIFT))
- amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
-
if (h->efr_attr & BIT(IOMMU_IVHD_ATTR_HATDIS_SHIFT)) {
pr_warn_once("Host Address Translation is not supported.\n");
amd_iommu_hatdis = true;
@@ -2905,7 +2882,6 @@ static void early_enable_iommu(struct amd_iommu *iommu)
iommu_init_flags(iommu);
iommu_set_device_table(iommu);
iommu_enable_command_buffer(iommu);
- iommu_set_exclusion_range(iommu);
iommu_enable_gt(iommu);
iommu_enable_ga(iommu);
iommu_enable_xt(iommu);
@@ -3022,8 +2998,10 @@ static void enable_iommus_vapic(void)
return;
}
- if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) &&
- !check_feature(FEATURE_GAM_VAPIC)) {
+ if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
+ return;
+
+ if (!check_feature(FEATURE_GAM_VAPIC)) {
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA;
return;
}
@@ -3110,6 +3088,9 @@ static void __init free_iommu_resources(void)
/* SB IOAPIC is always on this device in AMD systems */
#define IOAPIC_SB_DEVID ((0x00 << 8) | PCI_DEVFN(0x14, 0))
+/* SB IOAPIC for Hygon family 18h model 4h is on the device 0xb */
+#define IOAPIC_SB_DEVID_FAM18H_M4H ((0x00 << 8) | PCI_DEVFN(0xb, 0))
+
static bool __init check_ioapic_information(void)
{
const char *fw_bug = FW_BUG;
@@ -3135,7 +3116,12 @@ static bool __init check_ioapic_information(void)
pr_err("%s: IOAPIC[%d] not in IVRS table\n",
fw_bug, id);
ret = false;
- } else if (devid == IOAPIC_SB_DEVID) {
+ } else if (devid == IOAPIC_SB_DEVID ||
+ (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON &&
+ boot_cpu_data.x86 == 0x18 &&
+ boot_cpu_data.x86_model >= 0x4 &&
+ boot_cpu_data.x86_model <= 0xf &&
+ devid == IOAPIC_SB_DEVID_FAM18H_M4H)) {
has_sb_ioapic = true;
ret = true;
}
@@ -3202,7 +3188,7 @@ static int __init early_amd_iommu_init(void)
struct acpi_table_header *ivrs_base;
int ret;
acpi_status status;
- u8 efr_hats;
+ u8 efr_hats, max_vasize;
if (!amd_iommu_detected)
return -ENODEV;
@@ -3232,6 +3218,10 @@ static int __init early_amd_iommu_init(void)
ivinfo_init(ivrs_base);
+ max_vasize = FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo);
+ if (!max_vasize)
+ max_vasize = 64;
+
amd_iommu_target_ivhd_type = get_highest_supported_ivhd_type(ivrs_base);
DUMP_printk("Using IVHD type %#x\n", amd_iommu_target_ivhd_type);
@@ -3254,7 +3244,8 @@ static int __init early_amd_iommu_init(void)
* efr[HATS] bits specify the maximum host translation level
* supported, with LEVEL 4 being initial max level.
*/
- amd_iommu_hpt_level = efr_hats + PAGE_MODE_4_LEVEL;
+ amd_iommu_hpt_vasize = min_t(unsigned int, max_vasize,
+ (efr_hats + PAGE_MODE_4_LEVEL - 1) * 9 + 21);
} else {
pr_warn_once(FW_BUG "Disable host address translation due to invalid translation level (%#x).\n",
efr_hats);

drivers/iommu/amd/iommu.c

View file
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 57dc8fa..563f9c2 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1270,69 +1270,63 @@ static void build_inv_dte(struct iommu_cmd *cmd, u16 devid)
* Builds an invalidation address which is suitable for one page or multiple
* pages. Sets the size bit (S) as needed is more than one page is flushed.
*/
-static inline u64 build_inv_address(u64 address, size_t size)
+static inline u64 build_inv_address(u64 address, u64 last)
{
- u64 pages, end, msb_diff;
+ unsigned int sz_lg2;
- pages = iommu_num_pages(address, size, PAGE_SIZE);
-
- if (pages == 1)
- return address & PAGE_MASK;
-
- end = address + size - 1;
+ address &= GENMASK_U64(63, 12);
+ sz_lg2 = fls64(address ^ last);
+ if (sz_lg2 <= 12)
+ return address;
/*
- * msb_diff would hold the index of the most significant bit that
- * flipped between the start and end.
+ * Encode sz_lg2 according to Table 14: Example Page Size Encodings
+ *
+ * See "Note *":
+ * Address bits 51:32 can be used to encode page sizes greater
+ * that 4 Gbytes.
+ * Which we take to mean that the highest page size has bit
+ * [51]=0, [50:12]=1
+ * and that coding happens when sz_lg2 is 52. Fall back to full
+ * invalidation if the size is too big.
+ *
*/
- msb_diff = fls64(end ^ address) - 1;
+ if (unlikely(sz_lg2 > 52))
+ return CMD_INV_IOMMU_ALL_PAGES_ADDRESS |
+ CMD_INV_IOMMU_PAGES_SIZE_MASK;
/*
- * Bits 63:52 are sign extended. If for some reason bit 51 is different
- * between the start and the end, invalidate everything.
+ * The sz_lg2 calculation with fls() ensures that:
+ * address & BIT(sz_lg2 - 1) == 0
+ * Therefore only the 1's need to be added. 8KB requires no 1's
*/
- if (unlikely(msb_diff > 51)) {
- address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
- } else {
- /*
- * The msb-bit must be clear on the address. Just set all the
- * lower bits.
- */
- address |= (1ull << msb_diff) - 1;
- }
-
- /* Clear bits 11:0 */
- address &= PAGE_MASK;
-
- /* Set the size bit - we flush more than one 4kb page */
+ if (sz_lg2 > 13)
+ address |= GENMASK_U64(sz_lg2 - 2, 12);
return address | CMD_INV_IOMMU_PAGES_SIZE_MASK;
}
static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
- size_t size, u16 domid,
- ioasid_t pasid, bool gn)
+ u64 last, u16 domid, ioasid_t pasid,
+ u32 flags)
{
- u64 inv_address = build_inv_address(address, size);
+ u64 inv_address = build_inv_address(address, last);
memset(cmd, 0, sizeof(*cmd));
cmd->data[1] |= domid;
cmd->data[2] = lower_32_bits(inv_address);
cmd->data[3] = upper_32_bits(inv_address);
- /* PDE bit - we want to flush everything, not only the PTEs */
- cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
- if (gn) {
+ cmd->data[2] |= flags;
+ if (flags & CMD_INV_IOMMU_PAGES_GN_MASK)
cmd->data[0] |= pasid;
- cmd->data[2] |= CMD_INV_IOMMU_PAGES_GN_MASK;
- }
CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
}
static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep,
- u64 address, size_t size,
+ u64 address, u64 last,
ioasid_t pasid, bool gn)
{
- u64 inv_address = build_inv_address(address, size);
+ u64 inv_address = build_inv_address(address, last);
memset(cmd, 0, sizeof(*cmd));

This diff is incomplete. Download the complete patch.

drivers/iommu/amd/pasid.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/apple-dart.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/dma-iommu.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/generic_pt/fmt/amdv1.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/generic_pt/fmt/iommu_riscv64.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/generic_pt/fmt/riscv.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/generic_pt/iommu_pt.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/generic_pt/kunit_generic_pt.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/generic_pt/kunit_iommu_pt.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/intel/dmar.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/intel/iommu.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/intel/iommu.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/intel/pasid.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/intel/svm.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/io-pgtable-arm.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/riscv/iommu-bits.h

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/riscv/iommu.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/rockchip-iommu.c

View file

This diff is incomplete. Download the complete patch.

drivers/iommu/vsi-iommu.c

View file

This diff is incomplete. Download the complete patch.

drivers/pci/ats.c

View file

This diff is incomplete. Download the complete patch.

drivers/pci/pci.h

View file

This diff is incomplete. Download the complete patch.

drivers/pci/quirks.c

View file

This diff is incomplete. Download the complete patch.

include/linux/generic_pt/common.h

View file

This diff is incomplete. Download the complete patch.

include/linux/iommu.h

View file

This diff is incomplete. Download the complete patch.

include/linux/pci-ats.h

View file

This diff is incomplete. Download the complete patch.

include/uapi/linux/pci_regs.h

View file

This diff is incomplete. Download the complete patch.