2022-07-26 20:36:48

by Sam Protsenko

[permalink] [raw]
Subject: [PATCH 0/2] iommu/exynos: Add fault handling on SysMMU v7

Exynos IOMMU driver implements fault handling for SysMMU v1..v5. But the
abstraction currently used is not suited for SysMMU v7, as it has quite
different fault related register set.

This patch series reworks the mentioned fault handling abstraction and
adds fault handling support for SysMMU v7.

Sam Protsenko (2):
iommu/exynos: Abstract getting the fault info
iommu/exynos: Implement fault handling on SysMMU v7

drivers/iommu/exynos-iommu.c | 208 ++++++++++++++++++++++++-----------
1 file changed, 143 insertions(+), 65 deletions(-)

--
2.30.2


2022-07-26 20:56:46

by Sam Protsenko

[permalink] [raw]
Subject: [PATCH 2/2] iommu/exynos: Implement fault handling on SysMMU v7

SysMMU v7 has a bit different registers for getting the fault info:
- there is one single register (MMU_FAULT_VA) to get the fault address
- fault access type (R/W) can be read from MMU_FAULT_TRANS_INFO
register now
- interrupt status register has different bits w.r.t. previous SysMMU
versions
- VM and non-VM layouts have different register addresses

Add correct fault handling implementation for SysMMU v7, according to
all mentioned differences. Only VID #0 (default) is handled, as VM
domains support is not implemented yet.

Signed-off-by: Sam Protsenko <[email protected]>
---
drivers/iommu/exynos-iommu.c | 48 +++++++++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 766d409e084a..ac47c796741b 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -217,6 +217,13 @@ static const char * const sysmmu_v5_fault_names[] = {
"SECURITY PROTECTION"
};

+static const char * const sysmmu_v7_fault_names[] = {
+ "PTW",
+ "PAGE",
+ "ACCESS PROTECTION",
+ "RESERVED"
+};
+
/*
* This structure is attached to dev->iommu->priv of the master device
* on device add, contains a list of SYSMMU controllers defined by device tree,
@@ -260,6 +267,8 @@ struct sysmmu_variant {
u32 flush_end; /* end address of range invalidation */
u32 int_status; /* interrupt status information */
u32 int_clear; /* clear the interrupt */
+ u32 fault_va; /* IOVA address that caused fault */
+ u32 fault_info; /* fault transaction info */

int (*get_fault_info)(struct sysmmu_drvdata *data, unsigned int itype,
struct sysmmu_fault *fault);
@@ -337,6 +346,19 @@ static int exynos_sysmmu_v5_get_fault_info(struct sysmmu_drvdata *data,
return 0;
}

+static int exynos_sysmmu_v7_get_fault_info(struct sysmmu_drvdata *data,
+ unsigned int itype,
+ struct sysmmu_fault *fault)
+{
+ u32 info = readl(SYSMMU_REG(data, fault_info));
+
+ fault->addr = readl(SYSMMU_REG(data, fault_va));
+ fault->name = sysmmu_v7_fault_names[itype % 4];
+ fault->type = (info & BIT(20)) ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ;
+
+ return 0;
+}
+
/* SysMMU v1..v3 */
static const struct sysmmu_variant sysmmu_v1_variant = {
.flush_all = 0x0c,
@@ -348,7 +370,7 @@ static const struct sysmmu_variant sysmmu_v1_variant = {
.get_fault_info = exynos_sysmmu_v1_get_fault_info,
};

-/* SysMMU v5 and v7 (non-VM capable) */
+/* SysMMU v5 */
static const struct sysmmu_variant sysmmu_v5_variant = {
.pt_base = 0x0c,
.flush_all = 0x10,
@@ -362,7 +384,23 @@ static const struct sysmmu_variant sysmmu_v5_variant = {
.get_fault_info = exynos_sysmmu_v5_get_fault_info,
};

-/* SysMMU v7: VM capable register set */
+/* SysMMU v7: non-VM capable register layout */
+static const struct sysmmu_variant sysmmu_v7_variant = {
+ .pt_base = 0x0c,
+ .flush_all = 0x10,
+ .flush_entry = 0x14,
+ .flush_range = 0x18,
+ .flush_start = 0x20,
+ .flush_end = 0x24,
+ .int_status = 0x60,
+ .int_clear = 0x64,
+ .fault_va = 0x70,
+ .fault_info = 0x78,
+
+ .get_fault_info = exynos_sysmmu_v7_get_fault_info,
+};
+
+/* SysMMU v7: VM capable register layout */
static const struct sysmmu_variant sysmmu_v7_vm_variant = {
.pt_base = 0x800c,
.flush_all = 0x8010,
@@ -372,8 +410,10 @@ static const struct sysmmu_variant sysmmu_v7_vm_variant = {
.flush_end = 0x8024,
.int_status = 0x60,
.int_clear = 0x64,
+ .fault_va = 0x1000,
+ .fault_info = 0x1004,

- .get_fault_info = exynos_sysmmu_v5_get_fault_info,
+ .get_fault_info = exynos_sysmmu_v7_get_fault_info,
};

static struct exynos_iommu_domain *to_exynos_domain(struct iommu_domain *dom)
@@ -496,7 +536,7 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data)
if (data->has_vcr)
data->variant = &sysmmu_v7_vm_variant;
else
- data->variant = &sysmmu_v5_variant;
+ data->variant = &sysmmu_v7_variant;
}

__sysmmu_disable_clocks(data);
--
2.30.2

2022-08-08 17:36:01

by Sam Protsenko

[permalink] [raw]
Subject: Re: [PATCH 0/2] iommu/exynos: Add fault handling on SysMMU v7

On Tue, 26 Jul 2022 at 23:07, Sam Protsenko <[email protected]> wrote:
>
> Exynos IOMMU driver implements fault handling for SysMMU v1..v5. But the
> abstraction currently used is not suited for SysMMU v7, as it has quite
> different fault related register set.
>
> This patch series reworks the mentioned fault handling abstraction and
> adds fault handling support for SysMMU v7.
>
> Sam Protsenko (2):
> iommu/exynos: Abstract getting the fault info
> iommu/exynos: Implement fault handling on SysMMU v7
>
> drivers/iommu/exynos-iommu.c | 208 ++++++++++++++++++++++++-----------
> 1 file changed, 143 insertions(+), 65 deletions(-)
>
> --
> 2.30.2
>

Hi Marek,

Can you please review and test this series? I only have my E850 (which
has VM-capable SysMMU register layout). So it would be nice to check
if it works fine with non-VM SysMMU v7 and older versions.

Thanks!

2023-01-25 11:05:13

by Joerg Roedel

[permalink] [raw]
Subject: Re: [PATCH 0/2] iommu/exynos: Add fault handling on SysMMU v7

On Tue, Jul 26, 2022 at 11:07:37PM +0300, Sam Protsenko wrote:
> Sam Protsenko (2):
> iommu/exynos: Abstract getting the fault info
> iommu/exynos: Implement fault handling on SysMMU v7

Applied, thanks.