Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions Documentation/devicetree/bindings/iommu/riscv,iommu.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iommu/riscv,iommu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: RISC-V IOMMU Architecture Implementation

maintainers:
- Tomasz Jeznach <tjeznach@rivosinc.com>

description: |
The RISC-V IOMMU provides memory address translation and isolation for
input and output devices, supporting per-device translation context,
shared process address spaces including the ATS and PRI components of
the PCIe specification, two stage address translation and MSI remapping.
It supports identical translation table format to the RISC-V address
translation tables with page level access and protection attributes.
Hardware uses in-memory command and fault reporting queues with wired
interrupt or MSI notifications.

Visit https://github.com/riscv-non-isa/riscv-iommu for more details.

For information on assigning RISC-V IOMMU to its peripheral devices,
see generic IOMMU bindings.

properties:
# For PCIe IOMMU hardware compatible property should contain the vendor
# and device ID according to the PCI Bus Binding specification.
# Since PCI provides built-in identification methods, compatible is not
# actually required. For non-PCIe hardware implementations 'riscv,iommu'
# should be specified along with 'reg' property providing MMIO location.
compatible:
oneOf:
- items:
- enum:
- qemu,riscv-iommu
- const: riscv,iommu
- items:
- enum:
- pci1efd,edf1
- const: riscv,pci-iommu

reg:
maxItems: 1
description:
For non-PCI devices this represents base address and size of for the
IOMMU memory mapped registers interface.
For PCI IOMMU hardware implementation this should represent an address
of the IOMMU, as defined in the PCI Bus Binding reference.

'#iommu-cells':
const: 1
description:
The single cell describes the requester id emitted by a master to the
IOMMU.

interrupts:
minItems: 1
maxItems: 4
description:
Wired interrupt vectors available for RISC-V IOMMU to notify the
RISC-V HARTS. The cause to interrupt vector is software defined
using IVEC IOMMU register.

msi-parent: true

power-domains:
maxItems: 1

required:
- compatible
- reg
- '#iommu-cells'

additionalProperties: false

examples:
- |+
/* Example 1 (IOMMU device with wired interrupts) */
#include <dt-bindings/interrupt-controller/irq.h>

iommu1: iommu@1bccd000 {
compatible = "qemu,riscv-iommu", "riscv,iommu";
reg = <0x1bccd000 0x1000>;
interrupt-parent = <&aplic_smode>;
interrupts = <32 IRQ_TYPE_LEVEL_HIGH>,
<33 IRQ_TYPE_LEVEL_HIGH>,
<34 IRQ_TYPE_LEVEL_HIGH>,
<35 IRQ_TYPE_LEVEL_HIGH>;
#iommu-cells = <1>;
};

/* Device with two IOMMU device IDs, 0 and 7 */
master1 {
iommus = <&iommu1 0>, <&iommu1 7>;
};

- |+
/* Example 2 (IOMMU device with shared wired interrupt) */
#include <dt-bindings/interrupt-controller/irq.h>

iommu2: iommu@1bccd000 {
compatible = "qemu,riscv-iommu", "riscv,iommu";
reg = <0x1bccd000 0x1000>;
interrupt-parent = <&aplic_smode>;
interrupts = <32 IRQ_TYPE_LEVEL_HIGH>;
#iommu-cells = <1>;
};

- |+
/* Example 3 (IOMMU device with MSIs) */
iommu3: iommu@1bcdd000 {
compatible = "qemu,riscv-iommu", "riscv,iommu";
reg = <0x1bccd000 0x1000>;
msi-parent = <&imsics_smode>;
#iommu-cells = <1>;
};

- |+
/* Example 4 (IOMMU PCIe device with MSIs) */
bus {
#address-cells = <2>;
#size-cells = <2>;

pcie@30000000 {
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
reg = <0x0 0x30000000 0x0 0x1000000>;
ranges = <0x02000000 0x0 0x41000000 0x0 0x41000000 0x0 0x0f000000>;

/*
* The IOMMU manages all functions in this PCI domain except
* itself. Omit BDF 00:01.0.
*/
iommu-map = <0x0 &iommu0 0x0 0x8>,
<0x9 &iommu0 0x9 0xfff7>;

/* The IOMMU programming interface uses slot 00:01.0 */
iommu0: iommu@1,0 {
compatible = "pci1efd,edf1", "riscv,pci-iommu";
reg = <0x800 0 0 0 0>;
#iommu-cells = <1>;
};
};
};
9 changes: 9 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -18449,6 +18449,15 @@ F: arch/riscv/
N: riscv
K: riscv

RISC-V IOMMU
M: Tomasz Jeznach <tjeznach@rivosinc.com>
L: iommu@lists.linux.dev
L: linux-riscv@lists.infradead.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux.git
F: Documentation/devicetree/bindings/iommu/riscv,iommu.yaml
F: drivers/iommu/riscv/

RISC-V MICROCHIP FPGA SUPPORT
M: Conor Dooley <conor.dooley@microchip.com>
M: Daire McNamara <daire.mcnamara@microchip.com>
Expand Down
1 change: 1 addition & 0 deletions drivers/iommu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ config MSM_IOMMU
source "drivers/iommu/amd/Kconfig"
source "drivers/iommu/intel/Kconfig"
source "drivers/iommu/iommufd/Kconfig"
source "drivers/iommu/riscv/Kconfig"

config IRQ_REMAP
bool "Support for Interrupt Remapping"
Expand Down
1 change: 1 addition & 0 deletions drivers/iommu/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += amd/ intel/ arm/ iommufd/
obj-y += amd/ intel/ arm/ iommufd/ riscv/
obj-$(CONFIG_IOMMU_API) += iommu.o
obj-$(CONFIG_IOMMU_API) += iommu-traces.o
obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
Expand Down
3 changes: 2 additions & 1 deletion drivers/iommu/apple-dart.c
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,8 @@ static void apple_dart_domain_free(struct iommu_domain *domain)
kfree(dart_domain);
}

static int apple_dart_of_xlate(struct device *dev, struct of_phandle_args *args)
static int apple_dart_of_xlate(struct device *dev,
const struct of_phandle_args *args)
{
struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
struct platform_device *iommu_pdev = of_find_device_by_node(args->np);
Expand Down
3 changes: 2 additions & 1 deletion drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -2760,7 +2760,8 @@ static int arm_smmu_enable_nesting(struct iommu_domain *domain)
return ret;
}

static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
static int arm_smmu_of_xlate(struct device *dev,
const struct of_phandle_args *args)
{
return iommu_fwspec_add_ids(dev, args->args, 1);
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/iommu/arm/arm-smmu/arm-smmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,8 @@ static int arm_smmu_set_pgtable_quirks(struct iommu_domain *domain,
return ret;
}

static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
static int arm_smmu_of_xlate(struct device *dev,
const struct of_phandle_args *args)
{
u32 mask, fwid = 0;

Expand Down
3 changes: 2 additions & 1 deletion drivers/iommu/arm/arm-smmu/qcom_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,8 @@ static struct iommu_device *qcom_iommu_probe_device(struct device *dev)
return &qcom_iommu->iommu;
}

static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
static int qcom_iommu_of_xlate(struct device *dev,
const struct of_phandle_args *args)
{
struct qcom_iommu_dev *qcom_iommu;
struct platform_device *iommu_pdev;
Expand Down
2 changes: 1 addition & 1 deletion drivers/iommu/exynos-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,7 +1429,7 @@ static void exynos_iommu_release_device(struct device *dev)
}

static int exynos_iommu_of_xlate(struct device *dev,
struct of_phandle_args *spec)
const struct of_phandle_args *spec)
{
struct platform_device *sysmmu = of_find_device_by_node(spec->np);
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
Expand Down
16 changes: 9 additions & 7 deletions drivers/iommu/intel/dmar.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include "iommu.h"
#include "../irq_remapping.h"
#include "../iommu-pages.h"
#include "perf.h"
#include "trace.h"
#include "perfmon.h"
Expand Down Expand Up @@ -1185,7 +1186,7 @@ static void free_iommu(struct intel_iommu *iommu)
}

if (iommu->qi) {
free_page((unsigned long)iommu->qi->desc);
iommu_free_page(iommu->qi->desc);
kfree(iommu->qi->desc_status);
kfree(iommu->qi);
}
Expand Down Expand Up @@ -1737,7 +1738,8 @@ static void __dmar_enable_qi(struct intel_iommu *iommu)
int dmar_enable_qi(struct intel_iommu *iommu)
{
struct q_inval *qi;
struct page *desc_page;
void *desc;
int order;

if (!ecap_qis(iommu->ecap))
return -ENOENT;
Expand All @@ -1758,19 +1760,19 @@ int dmar_enable_qi(struct intel_iommu *iommu)
* Need two pages to accommodate 256 descriptors of 256 bits each
* if the remapping hardware supports scalable mode translation.
*/
desc_page = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO,
!!ecap_smts(iommu->ecap));
if (!desc_page) {
order = ecap_smts(iommu->ecap) ? 1 : 0;
desc = iommu_alloc_pages_node(iommu->node, GFP_ATOMIC, order);
if (!desc) {
kfree(qi);
iommu->qi = NULL;
return -ENOMEM;
}

qi->desc = page_address(desc_page);
qi->desc = desc;

qi->desc_status = kcalloc(QI_LENGTH, sizeof(int), GFP_ATOMIC);
if (!qi->desc_status) {
free_page((unsigned long) qi->desc);
iommu_free_page(qi->desc);
kfree(qi);
iommu->qi = NULL;
return -ENOMEM;
Expand Down
Loading
Loading