* [PATCH 2/4] lib: sbi: Move PMP encoding into a new file
2026-03-10 0:49 [PATCH 1/4] platform: generic: Tenstorrent Atlantis support Nicholas Piggin
@ 2026-03-10 0:49 ` Nicholas Piggin
2026-04-01 12:50 ` Joel Stanley
2026-03-10 0:49 ` [PATCH 3/4] lib: sbi: Add hart_ prefix to PMP functions Nicholas Piggin
2026-03-10 0:49 ` [PATCH 4/4] platform: generic: tenstorrent: Add RISC-V IOMMU support Nicholas Piggin
2 siblings, 1 reply; 7+ messages in thread
From: Nicholas Piggin @ 2026-03-10 0:49 UTC (permalink / raw)
To: opensbi; +Cc: Nicholas Piggin
The Tenstorrent RISC-V IOMMU PMP MMRs use the same encoding as PMP CSRs.
In preparation to support it, move the non hart-specific PMP operations
into their own file where they will also be used to build the IOMMU
PMPs.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
include/sbi/riscv_asm.h | 2 +-
include/sbi/sbi_pmp.h | 24 +++++++
lib/sbi/objects.mk | 1 +
lib/sbi/riscv_asm.c | 156 ++++++++++++----------------------------
lib/sbi/sbi_pmp.c | 91 +++++++++++++++++++++++
5 files changed, 164 insertions(+), 110 deletions(-)
create mode 100644 include/sbi/sbi_pmp.h
create mode 100644 lib/sbi/sbi_pmp.c
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
index 0cf3fc37..b97e1880 100644
--- a/include/sbi/riscv_asm.h
+++ b/include/sbi/riscv_asm.h
@@ -213,7 +213,7 @@ void misa_string(int xlen, char *out, unsigned int out_sz);
int pmp_disable(unsigned int n);
/* Check if the matching field is set */
-int is_pmp_entry_mapped(unsigned long entry);
+int is_pmp_entry_mapped(unsigned int entry);
int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len);
diff --git a/include/sbi/sbi_pmp.h b/include/sbi/sbi_pmp.h
new file mode 100644
index 00000000..66664bb0
--- /dev/null
+++ b/include/sbi/sbi_pmp.h
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SBI_PMP_H__
+#define __SBI_PMP_H__
+
+#include <sbi/sbi_types.h>
+
+struct pmp {
+ u8 cfg;
+ u64 addr;
+};
+typedef struct pmp pmp_t;
+
+bool pmp_enabled(pmp_t *pmp);
+
+int pmp_create(pmp_t *pmp, unsigned long prot, unsigned long addr,
+ unsigned long log2len);
+int pmp_decode(pmp_t *pmp, unsigned long *prot, unsigned long *addr,
+ unsigned long *log2len);
+
+#endif
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 07d13229..0e29a277 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -87,6 +87,7 @@ libsbi-objs-y += sbi_init.o
libsbi-objs-y += sbi_ipi.o
libsbi-objs-y += sbi_irqchip.o
libsbi-objs-y += sbi_platform.o
+libsbi-objs-y += sbi_pmp.o
libsbi-objs-y += sbi_pmu.o
libsbi-objs-y += sbi_dbtr.o
libsbi-objs-y += sbi_mpxy.o
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index 3e44320f..c11abb1a 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -12,6 +12,7 @@
#include <sbi/sbi_error.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_console.h>
+#include <sbi/sbi_pmp.h>
/* determine CPU extension, return non-zero support */
int misa_extension_imp(char ext)
@@ -272,24 +273,9 @@ void csr_write_num(int csr_num, unsigned long val)
#undef switchcase_csr_write
}
-static unsigned long ctz(unsigned long x)
+int hart_pmp_read(unsigned int n, pmp_t *pmp)
{
- unsigned long ret = 0;
-
- if (x == 0)
- return 8 * sizeof(x);
-
- while (!(x & 1UL)) {
- ret++;
- x = x >> 1;
- }
-
- return ret;
-}
-
-int pmp_disable(unsigned int n)
-{
- int pmpcfg_csr, pmpcfg_shift;
+ int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
unsigned long cfgmask, pmpcfg;
if (n >= PMP_COUNT)
@@ -304,44 +290,24 @@ int pmp_disable(unsigned int n)
#else
# error "Unexpected __riscv_xlen"
#endif
+ pmpaddr_csr = CSR_PMPADDR0 + n;
+ pmp->addr = csr_read_num(pmpaddr_csr);
- /* Clear the address matching bits to disable the pmp entry */
- cfgmask = ~(0xffUL << pmpcfg_shift);
- pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask);
-
- csr_write_num(pmpcfg_csr, pmpcfg);
+ cfgmask = (0xffUL << pmpcfg_shift);
+ pmpcfg = csr_read_num(pmpcfg_csr) & cfgmask;
+ pmp->cfg = pmpcfg >> pmpcfg_shift;
return SBI_OK;
}
-int is_pmp_entry_mapped(unsigned long entry)
-{
- unsigned long prot;
- unsigned long addr;
- unsigned long log2len;
-
- if (pmp_get(entry, &prot, &addr, &log2len) != 0)
- return false;
-
- /* If address matching bits are non-zero, the entry is enable */
- if (prot & PMP_A)
- return true;
-
- return false;
-}
-
-int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
- unsigned long log2len)
+int hart_pmp_write(unsigned int n, pmp_t *pmp)
{
int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
unsigned long cfgmask, pmpcfg;
- unsigned long addrmask, pmpaddr;
- /* check parameters */
- if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
+ if (n >= PMP_COUNT)
return SBI_EINVAL;
- /* calculate PMP register and offset */
#if __riscv_xlen == 32
pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
pmpcfg_shift = (n & 3) << 3;
@@ -353,82 +319,54 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
#endif
pmpaddr_csr = CSR_PMPADDR0 + n;
- /* encode PMP config */
- prot &= ~PMP_A;
- prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
cfgmask = ~(0xffUL << pmpcfg_shift);
pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask);
- pmpcfg |= ((prot << pmpcfg_shift) & ~cfgmask);
-
- /* encode PMP address */
- if (log2len == PMP_SHIFT) {
- pmpaddr = (addr >> PMP_SHIFT);
- } else {
- if (log2len == __riscv_xlen) {
- pmpaddr = -1UL;
- } else {
- addrmask = (1UL << (log2len - PMP_SHIFT)) - 1;
- pmpaddr = ((addr >> PMP_SHIFT) & ~addrmask);
- pmpaddr |= (addrmask >> 1);
- }
- }
+ pmpcfg |= (unsigned long)pmp->cfg << pmpcfg_shift;
- /* write csrs */
- csr_write_num(pmpaddr_csr, pmpaddr);
+ csr_write_num(pmpaddr_csr, pmp->addr);
csr_write_num(pmpcfg_csr, pmpcfg);
- return 0;
+ return SBI_OK;
}
-int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
- unsigned long *log2len)
+int pmp_disable(unsigned int n)
{
- int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
- unsigned long cfgmask, pmpcfg, prot;
- unsigned long t1, addr, len;
+ struct pmp pmp = { .cfg = 0, .addr = 0 };
+ return hart_pmp_write(n, &pmp);
+}
- /* check parameters */
- if (n >= PMP_COUNT || !prot_out || !addr_out || !log2len)
- return SBI_EINVAL;
- *prot_out = *addr_out = *log2len = 0;
+int is_pmp_entry_mapped(unsigned int entry)
+{
+ pmp_t pmp;
- /* calculate PMP register and offset */
-#if __riscv_xlen == 32
- pmpcfg_csr = CSR_PMPCFG0 + (n >> 2);
- pmpcfg_shift = (n & 3) << 3;
-#elif __riscv_xlen == 64
- pmpcfg_csr = (CSR_PMPCFG0 + (n >> 2)) & ~1;
- pmpcfg_shift = (n & 7) << 3;
-#else
-# error "Unexpected __riscv_xlen"
-#endif
- pmpaddr_csr = CSR_PMPADDR0 + n;
+ if (hart_pmp_read(entry, &pmp))
+ return pmp_enabled(&pmp);
- /* decode PMP config */
- cfgmask = (0xffUL << pmpcfg_shift);
- pmpcfg = csr_read_num(pmpcfg_csr) & cfgmask;
- prot = pmpcfg >> pmpcfg_shift;
-
- /* decode PMP address */
- if ((prot & PMP_A) == PMP_A_NAPOT) {
- addr = csr_read_num(pmpaddr_csr);
- if (addr == -1UL) {
- addr = 0;
- len = __riscv_xlen;
- } else {
- t1 = ctz(~addr);
- addr = (addr & ~((1UL << t1) - 1)) << PMP_SHIFT;
- len = (t1 + PMP_SHIFT + 1);
- }
- } else {
- addr = csr_read_num(pmpaddr_csr) << PMP_SHIFT;
- len = PMP_SHIFT;
- }
+ return false;
+}
+
+int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
+ unsigned long log2len)
+{
+ pmp_t pmp;
+ int rc;
+
+ rc = pmp_create(&pmp, prot, addr, log2len);
+ if (rc)
+ return rc;
+
+ return hart_pmp_write(n, &pmp);
+}
+
+int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
+ unsigned long *log2len)
+{
+ pmp_t pmp;
+ int rc;
- /* return details */
- *prot_out = prot;
- *addr_out = addr;
- *log2len = len;
+ rc = hart_pmp_read(n, &pmp);
+ if (rc)
+ return rc;
- return 0;
+ return pmp_decode(&pmp, prot_out, addr_out, log2len);
}
diff --git a/lib/sbi/sbi_pmp.c b/lib/sbi/sbi_pmp.c
new file mode 100644
index 00000000..22132d81
--- /dev/null
+++ b/lib/sbi/sbi_pmp.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_pmp.h>
+
+bool pmp_enabled(pmp_t *pmp)
+{
+ return pmp->cfg & PMP_A;
+}
+
+int pmp_create(pmp_t *pmp, unsigned long prot, unsigned long addr,
+ unsigned long log2len)
+{
+ unsigned long addrmask, pmpaddr;
+
+ /* check parameters */
+ if (log2len > __riscv_xlen || log2len < PMP_SHIFT)
+ return SBI_EINVAL;
+
+ /* encode PMP config */
+ prot &= ~PMP_A;
+ prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
+
+ /* encode PMP address */
+ if (log2len == PMP_SHIFT) {
+ pmpaddr = (addr >> PMP_SHIFT);
+ } else {
+ if (log2len == __riscv_xlen) {
+ pmpaddr = -1UL;
+ } else {
+ addrmask = (1UL << (log2len - PMP_SHIFT)) - 1;
+ pmpaddr = ((addr >> PMP_SHIFT) & ~addrmask);
+ pmpaddr |= (addrmask >> 1);
+ }
+ }
+
+ pmp->cfg = prot;
+ pmp->addr = pmpaddr;
+
+ return SBI_OK;
+}
+
+static unsigned long cto(unsigned long x)
+{
+ unsigned long ret = 0;
+
+ while (x & 1UL) {
+ ret++;
+ x = x >> 1;
+ }
+
+ return ret;
+}
+
+int pmp_decode(pmp_t *pmp, unsigned long *prot_out, unsigned long *addr_out,
+ unsigned long *log2len)
+{
+ /* check parameters */
+ if (!pmp || !prot_out || !addr_out || !log2len)
+ return SBI_EINVAL;
+
+ if (!pmp_enabled(pmp))
+ return SBI_EINVAL;
+
+ /* decode PMP address */
+ if ((pmp->cfg & PMP_A) == PMP_A_NAPOT) {
+ if (pmp->addr == -1UL) {
+ *addr_out = 0;
+ *log2len = __riscv_xlen + 3;
+ } else {
+ unsigned long mask = ~((1UL << cto(pmp->addr)) - 1);
+ *addr_out = (pmp->addr & mask) << PMP_SHIFT;
+ *log2len = (cto(pmp->addr) + PMP_SHIFT + 1);
+ }
+ } else {
+ *addr_out = pmp->addr << PMP_SHIFT;
+ *log2len = PMP_SHIFT;
+ }
+
+ return SBI_OK;
+}
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 2/4] lib: sbi: Move PMP encoding into a new file
2026-03-10 0:49 ` [PATCH 2/4] lib: sbi: Move PMP encoding into a new file Nicholas Piggin
@ 2026-04-01 12:50 ` Joel Stanley
0 siblings, 0 replies; 7+ messages in thread
From: Joel Stanley @ 2026-04-01 12:50 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: opensbi
On Tue, 10 Mar 2026 at 11:19, Nicholas Piggin <npiggin@gmail.com> wrote:
>
> The Tenstorrent RISC-V IOMMU PMP MMRs use the same encoding as PMP CSRs.
> In preparation to support it, move the non hart-specific PMP operations
> into their own file where they will also be used to build the IOMMU
> PMPs.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> --- a/lib/sbi/riscv_asm.c
> +++ b/lib/sbi/riscv_asm.c
> +int is_pmp_entry_mapped(unsigned int entry)
> +{
> + pmp_t pmp;
> + if (hart_pmp_read(entry, &pmp))
> + return pmp_enabled(&pmp);
The diff is a bit all over the place so I may have confused myself.
The patch keeps is_pmp_entry_mapped but changes the body from
if (pmp_get(entry, &prot, &addr, &log2len) != 0)
return false;
to
if (hart_pmp_read(entry, &pmp))
return pmp_enabled(&pmp);
but hart_pmp_read returns SBI_OK (0) on success. So we should keep the !=0?
> +int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
> + unsigned long *log2len)
> +{
> + pmp_t pmp;
> + int rc;
>
> - /* return details */
> - *prot_out = prot;
It looks like prot_out is no longer written to after your patch. This
hunk never made it into the new pmp_decode:
/* decode PMP config */
cfgmask = (0xffUL << pmpcfg_shift);
pmpcfg = csr_read_num(pmpcfg_csr) & cfgmask;
prot = pmpcfg >> pmpcfg_shift;
> --- /dev/null
> +++ b/lib/sbi/sbi_pmp.c
> @@ -0,0 +1,91 @@
> +int pmp_create(pmp_t *pmp, unsigned long prot, unsigned long addr,
> + unsigned long log2len)
> +{
> + unsigned long addrmask, pmpaddr;
> +
> + /* check parameters */
> + if (log2len > __riscv_xlen || log2len < PMP_SHIFT)
> + return SBI_EINVAL;
Here we check that log2len <=__riscv_xlen, but in pmp_decode below we
set log2len = __riscv_xlen + 3. Is that just how it works, or should
pmp_decode be able to decode what pmp_create does?
> +
> + /* encode PMP config */
> + prot &= ~PMP_A;
> + prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;
> +
> + /* encode PMP address */
> + if (log2len == PMP_SHIFT) {
> + pmpaddr = (addr >> PMP_SHIFT);
> + } else {
> + if (log2len == __riscv_xlen) {
> + pmpaddr = -1UL;
> + } else {
> + addrmask = (1UL << (log2len - PMP_SHIFT)) - 1;
> + pmpaddr = ((addr >> PMP_SHIFT) & ~addrmask);
> + pmpaddr |= (addrmask >> 1);
> + }
> + }
> +
> + pmp->cfg = prot;
> + pmp->addr = pmpaddr;
> +
> + return SBI_OK;
> +}
> +
> +int pmp_decode(pmp_t *pmp, unsigned long *prot_out, unsigned long *addr_out,
> + unsigned long *log2len)
> +{
> + /* check parameters */
> + if (!pmp || !prot_out || !addr_out || !log2len)
> + return SBI_EINVAL;
> +
> + if (!pmp_enabled(pmp))
> + return SBI_EINVAL;
> +
> + /* decode PMP address */
> + if ((pmp->cfg & PMP_A) == PMP_A_NAPOT) {
> + if (pmp->addr == -1UL) {
> + *addr_out = 0;
> + *log2len = __riscv_xlen + 3;
> + } else {
> + unsigned long mask = ~((1UL << cto(pmp->addr)) - 1);
> + *addr_out = (pmp->addr & mask) << PMP_SHIFT;
> + *log2len = (cto(pmp->addr) + PMP_SHIFT + 1);
> + }
> + } else {
> + *addr_out = pmp->addr << PMP_SHIFT;
> + *log2len = PMP_SHIFT;
> + }
> +
> + return SBI_OK;
> +}
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/4] lib: sbi: Add hart_ prefix to PMP functions
2026-03-10 0:49 [PATCH 1/4] platform: generic: Tenstorrent Atlantis support Nicholas Piggin
2026-03-10 0:49 ` [PATCH 2/4] lib: sbi: Move PMP encoding into a new file Nicholas Piggin
@ 2026-03-10 0:49 ` Nicholas Piggin
2026-04-01 12:50 ` Joel Stanley
2026-03-10 0:49 ` [PATCH 4/4] platform: generic: tenstorrent: Add RISC-V IOMMU support Nicholas Piggin
2 siblings, 1 reply; 7+ messages in thread
From: Nicholas Piggin @ 2026-03-10 0:49 UTC (permalink / raw)
To: opensbi; +Cc: Nicholas Piggin
Give PMP functions that deal with HART CSRs a hart_ prefix, to help
distinguish from general PMP encoding functions that will be shared by
the Tenstorrent IOMMU.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
include/sbi/riscv_asm.h | 8 +++----
lib/sbi/riscv_asm.c | 10 ++++-----
lib/sbi/sbi_hart_pmp.c | 14 ++++++-------
platform/generic/eswin/eic770x.c | 36 ++++++++++++++++----------------
4 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
index b97e1880..14bc35e5 100644
--- a/include/sbi/riscv_asm.h
+++ b/include/sbi/riscv_asm.h
@@ -210,15 +210,15 @@ int misa_xlen(void);
void misa_string(int xlen, char *out, unsigned int out_sz);
/* Disable pmp entry at a given index */
-int pmp_disable(unsigned int n);
+int hart_pmp_disable(unsigned int n);
/* Check if the matching field is set */
-int is_pmp_entry_mapped(unsigned int entry);
+int hart_is_pmp_enabled(unsigned int n);
-int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
+int hart_pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len);
-int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
+int hart_pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
unsigned long *log2len);
#endif /* !__ASSEMBLER__ */
diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c
index c11abb1a..03c8e4d7 100644
--- a/lib/sbi/riscv_asm.c
+++ b/lib/sbi/riscv_asm.c
@@ -329,23 +329,23 @@ int hart_pmp_write(unsigned int n, pmp_t *pmp)
return SBI_OK;
}
-int pmp_disable(unsigned int n)
+int hart_pmp_disable(unsigned int n)
{
struct pmp pmp = { .cfg = 0, .addr = 0 };
return hart_pmp_write(n, &pmp);
}
-int is_pmp_entry_mapped(unsigned int entry)
+int hart_is_pmp_enabled(unsigned int n)
{
pmp_t pmp;
- if (hart_pmp_read(entry, &pmp))
+ if (hart_pmp_read(n, &pmp))
return pmp_enabled(&pmp);
return false;
}
-int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
+int hart_pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
unsigned long log2len)
{
pmp_t pmp;
@@ -358,7 +358,7 @@ int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
return hart_pmp_write(n, &pmp);
}
-int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
+int hart_pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
unsigned long *log2len)
{
pmp_t pmp;
diff --git a/lib/sbi/sbi_hart_pmp.c b/lib/sbi/sbi_hart_pmp.c
index 02a3b3c4..0aa4752f 100644
--- a/lib/sbi/sbi_hart_pmp.c
+++ b/lib/sbi/sbi_hart_pmp.c
@@ -100,7 +100,7 @@ static void sbi_hart_smepmp_set(struct sbi_scratch *scratch,
sbi_platform_pmp_set(sbi_platform_ptr(scratch),
pmp_idx, reg->flags, pmp_flags,
reg->base, reg->order);
- pmp_set(pmp_idx, pmp_flags, reg->base, reg->order);
+ hart_pmp_set(pmp_idx, pmp_flags, reg->base, reg->order);
} else {
sbi_printf("Can not configure pmp for domain %s because"
" memory region address 0x%lx or size 0x%lx "
@@ -139,7 +139,7 @@ static int sbi_hart_smepmp_configure(struct sbi_scratch *scratch)
csr_set(CSR_MSECCFG, MSECCFG_RLB);
/* Disable the reserved entry */
- pmp_disable(SBI_SMEPMP_RESV_ENTRY);
+ hart_pmp_disable(SBI_SMEPMP_RESV_ENTRY);
/* Program M-only regions when MML is not set. */
pmp_idx = 0;
@@ -224,7 +224,7 @@ static int sbi_hart_smepmp_map_range(struct sbi_scratch *scratch,
unsigned int pmp_flags = (PMP_W | PMP_X);
unsigned long order, base = 0;
- if (is_pmp_entry_mapped(SBI_SMEPMP_RESV_ENTRY))
+ if (hart_is_pmp_enabled(SBI_SMEPMP_RESV_ENTRY))
return SBI_ENOSPC;
for (order = MAX(sbi_hart_pmp_log2gran(scratch), log2roundup(size));
@@ -244,7 +244,7 @@ static int sbi_hart_smepmp_map_range(struct sbi_scratch *scratch,
sbi_platform_pmp_set(sbi_platform_ptr(scratch), SBI_SMEPMP_RESV_ENTRY,
SBI_DOMAIN_MEMREGION_SHARED_SURW_MRW,
pmp_flags, base, order);
- pmp_set(SBI_SMEPMP_RESV_ENTRY, pmp_flags, base, order);
+ hart_pmp_set(SBI_SMEPMP_RESV_ENTRY, pmp_flags, base, order);
return SBI_OK;
}
@@ -253,7 +253,7 @@ static int sbi_hart_smepmp_unmap_range(struct sbi_scratch *scratch,
unsigned long addr, unsigned long size)
{
sbi_platform_pmp_disable(sbi_platform_ptr(scratch), SBI_SMEPMP_RESV_ENTRY);
- return pmp_disable(SBI_SMEPMP_RESV_ENTRY);
+ return hart_pmp_disable(SBI_SMEPMP_RESV_ENTRY);
}
static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch)
@@ -281,7 +281,7 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch)
sbi_platform_pmp_set(sbi_platform_ptr(scratch),
pmp_idx, reg->flags, pmp_flags,
reg->base, reg->order);
- pmp_set(pmp_idx++, pmp_flags, reg->base, reg->order);
+ hart_pmp_set(pmp_idx++, pmp_flags, reg->base, reg->order);
} else {
sbi_printf("Can not configure pmp for domain %s because"
" memory region address 0x%lx or size 0x%lx "
@@ -307,7 +307,7 @@ static void sbi_hart_pmp_unconfigure(struct sbi_scratch *scratch)
continue;
sbi_platform_pmp_disable(sbi_platform_ptr(scratch), i);
- pmp_disable(i);
+ hart_pmp_disable(i);
}
}
diff --git a/platform/generic/eswin/eic770x.c b/platform/generic/eswin/eic770x.c
index 7330df9f..dfca0c41 100644
--- a/platform/generic/eswin/eic770x.c
+++ b/platform/generic/eswin/eic770x.c
@@ -254,21 +254,21 @@ static int eswin_eic7700_final_init(bool cold_boot)
__func__);
return SBI_EFAIL;
}
- pmp_set(pmp_idx++, sbi_domain_get_oldpmp_flags(reg),
- reg->base, reg->order);
+ hart_pmp_set(pmp_idx++, sbi_domain_get_oldpmp_flags(reg),
+ reg->base, reg->order);
}
- pmp_set(PMP_RESERVED_A, PMP_L, EIC770X_L3_ZERO_REMOTE,
- log2roundup(EIC770X_L3_ZERO_SIZE));
+ hart_pmp_set(PMP_RESERVED_A, PMP_L, EIC770X_L3_ZERO_REMOTE,
+ log2roundup(EIC770X_L3_ZERO_SIZE));
/**
* Enable P550 internal + System Port, so OpenSBI can access
* CLINT/PLIC/UART. Might be overwritten in pmp_configure.
*/
- pmp_set(PMP_FREE_A_START + PMP_FREE_A_COUNT - 1, 0, 0,
- log2roundup(EIC770X_MEMPORT_BASE));
+ hart_pmp_set(PMP_FREE_A_START + PMP_FREE_A_COUNT - 1, 0, 0,
+ log2roundup(EIC770X_MEMPORT_BASE));
- pmp_set(PMP_RESERVED_B, PMP_L, 0,
- log2roundup(EIC770X_MEMPORT_LIMIT));
+ hart_pmp_set(PMP_RESERVED_B, PMP_L, 0,
+ log2roundup(EIC770X_MEMPORT_LIMIT));
/**
* These must come after the setup of PMP, as we are about to
* enable speculation and HW prefetcher bits
@@ -321,13 +321,13 @@ static int eswin_eic7700_pmp_configure(struct sbi_scratch *scratch)
if (pmp_idx >= pmp_max)
goto no_more_pmp;
- pmp_set(pmp_idx++, sbi_domain_get_oldpmp_flags(reg),
- reg->base, reg->order);
+ hart_pmp_set(pmp_idx++, sbi_domain_get_oldpmp_flags(reg),
+ reg->base, reg->order);
prev = reg;
}
/* Disable the rest */
while (pmp_idx < pmp_max)
- pmp_disable(pmp_idx++);
+ hart_pmp_disable(pmp_idx++);
/* Process the second free range B [7-7] */
pmp_idx = PMP_FREE_B_START,
@@ -340,12 +340,12 @@ static int eswin_eic7700_pmp_configure(struct sbi_scratch *scratch)
if (pmp_idx >= pmp_max)
goto no_more_pmp;
- pmp_set(pmp_idx++, sbi_domain_get_oldpmp_flags(reg),
- reg->base, reg->order);
+ hart_pmp_set(pmp_idx++, sbi_domain_get_oldpmp_flags(reg),
+ reg->base, reg->order);
}
/* Disable the rest */
while (pmp_idx < pmp_max)
- pmp_disable(pmp_idx++);
+ hart_pmp_disable(pmp_idx++);
sbi_hart_pmp_fence();
return 0;
@@ -357,14 +357,14 @@ no_more_pmp:
static void eswin_eic7700_pmp_unconfigure(struct sbi_scratch *scratch)
{
/* Enable P550 internal + System Port */
- pmp_set(PMP_FREE_A_START + PMP_FREE_A_COUNT - 1, 0, 0,
- log2roundup(EIC770X_MEMPORT_BASE));
+ hart_pmp_set(PMP_FREE_A_START + PMP_FREE_A_COUNT - 1, 0, 0,
+ log2roundup(EIC770X_MEMPORT_BASE));
for (unsigned int i = 0; i < PMP_FREE_A_COUNT - 1; i++)
- pmp_disable(i + PMP_FREE_A_START);
+ hart_pmp_disable(i + PMP_FREE_A_START);
for (unsigned int i = 0; i < PMP_FREE_B_COUNT; i++)
- pmp_disable(i + PMP_FREE_B_START);
+ hart_pmp_disable(i + PMP_FREE_B_START);
}
static struct sbi_hart_protection eswin_eic7700_pmp_protection = {
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 3/4] lib: sbi: Add hart_ prefix to PMP functions
2026-03-10 0:49 ` [PATCH 3/4] lib: sbi: Add hart_ prefix to PMP functions Nicholas Piggin
@ 2026-04-01 12:50 ` Joel Stanley
0 siblings, 0 replies; 7+ messages in thread
From: Joel Stanley @ 2026-04-01 12:50 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: opensbi
On Tue, 10 Mar 2026 at 11:19, Nicholas Piggin <npiggin@gmail.com> wrote:
>
> Give PMP functions that deal with HART CSRs a hart_ prefix, to help
> distinguish from general PMP encoding functions that will be shared by
> the Tenstorrent IOMMU.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> include/sbi/riscv_asm.h | 8 +++----
> lib/sbi/riscv_asm.c | 10 ++++-----
> lib/sbi/sbi_hart_pmp.c | 14 ++++++-------
Some changes have been made to master since you sent your patch. This
fixup is required for sbi_hart_pmp.c :
--- a/lib/sbi/sbi_hart_pmp.c
+++ b/lib/sbi/sbi_hart_pmp.c
@@ -206,7 +206,7 @@ static int sbi_hart_smepmp_configure(struct
sbi_scratch *scratch)
}
/* Disable remaining PMP entries */
for(; pmp_idx < pmp_count; pmp_idx++)
- pmp_disable(pmp_idx);
+ hart_pmp_disable(pmp_idx);
/*
* All entries are programmed.
@@ -291,7 +291,7 @@ static int sbi_hart_oldpmp_configure(struct
sbi_scratch *scratch)
}
/* Disable remaining PMP entries */
for(; pmp_idx < pmp_count; pmp_idx++)
- pmp_disable(pmp_idx);
+ hart_pmp_disable(pmp_idx);
sbi_hart_pmp_fence();
return 0;
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/4] platform: generic: tenstorrent: Add RISC-V IOMMU support
2026-03-10 0:49 [PATCH 1/4] platform: generic: Tenstorrent Atlantis support Nicholas Piggin
2026-03-10 0:49 ` [PATCH 2/4] lib: sbi: Move PMP encoding into a new file Nicholas Piggin
2026-03-10 0:49 ` [PATCH 3/4] lib: sbi: Add hart_ prefix to PMP functions Nicholas Piggin
@ 2026-03-10 0:49 ` Nicholas Piggin
2026-04-01 12:51 ` Joel Stanley
2 siblings, 1 reply; 7+ messages in thread
From: Nicholas Piggin @ 2026-03-10 0:49 UTC (permalink / raw)
To: opensbi; +Cc: Nicholas Piggin
Add support for the Tenstorrent RISC-V IOMMU, and enable it for the
Atlantis platform. The IOMMU must have PMA and PMP registers set up.
These are implemented as MMRs with the same format as the corresponding
HART CSRs, making it possible to reuse much existing PMP code. PMAs are
copied from HART CSRs directly because those are set up by a prior boot
stage.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
platform/generic/Kconfig | 1 +
platform/generic/include/tenstorrent/iommu.h | 12 +
platform/generic/tenstorrent/Kconfig | 3 +
platform/generic/tenstorrent/atlantis.c | 18 ++
platform/generic/tenstorrent/iommu.c | 245 +++++++++++++++++++
platform/generic/tenstorrent/objects.mk | 1 +
platform/generic/tenstorrent/pma.c | 3 +-
7 files changed, 282 insertions(+), 1 deletion(-)
create mode 100644 platform/generic/include/tenstorrent/iommu.h
create mode 100644 platform/generic/tenstorrent/iommu.c
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 7de5e5a6..ba2cfa38 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -88,6 +88,7 @@ config PLATFORM_STARFIVE_JH7110
config PLATFORM_TENSTORRENT_ATLANTIS
bool "Tenstorrent Atlantis support"
select CPU_TENSTORRENT_ASCALON
+ select CPU_TENSTORRENT_IOMMU
default n
config PLATFORM_THEAD
diff --git a/platform/generic/include/tenstorrent/iommu.h b/platform/generic/include/tenstorrent/iommu.h
new file mode 100644
index 00000000..45231dfa
--- /dev/null
+++ b/platform/generic/include/tenstorrent/iommu.h
@@ -0,0 +1,12 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __TENSTORRENT_IOMMU_H__
+#define __TENSTORRENT_IOMMU_H__
+
+int tt_iommu_configure(unsigned long iommu_m_regs);
+int tt_iommu_fdt_configure(const void *fdt);
+
+#endif
diff --git a/platform/generic/tenstorrent/Kconfig b/platform/generic/tenstorrent/Kconfig
index 76c7fb32..5c524b33 100644
--- a/platform/generic/tenstorrent/Kconfig
+++ b/platform/generic/tenstorrent/Kconfig
@@ -3,3 +3,6 @@
config CPU_TENSTORRENT_ASCALON
bool
+
+config CPU_TENSTORRENT_IOMMU
+ bool
diff --git a/platform/generic/tenstorrent/atlantis.c b/platform/generic/tenstorrent/atlantis.c
index 4c312f7e..59bbd0eb 100644
--- a/platform/generic/tenstorrent/atlantis.c
+++ b/platform/generic/tenstorrent/atlantis.c
@@ -12,12 +12,30 @@
#include <tenstorrent/ascalon.h>
#include <tenstorrent/pma.h>
+#include <tenstorrent/iommu.h>
static int tt_atlantis_final_init(bool cold_boot)
{
if (cold_boot) {
+ int rc;
+
/* Boot firmware sets HART PMAs. Read and verify them. */
tt_ascalon_discover_pmas_from_boot_hart();
+
+ /*
+ * IOMMU must be configured at platform final_init time, to get
+ * the right PMP settings, see init_coldboot() comment. IOMMU
+ * is also configured with PMAs discovered from the boot HART,
+ * above.
+ */
+ rc = tt_iommu_fdt_configure(fdt_get_address());
+ if (rc) {
+ if (rc == SBI_ENOTSUPP)
+ sbi_printf("Tenstorrent Atlantis: No IOMMU "
+ "in device tree, continuing.\n");
+ else
+ return rc;
+ }
} else {
/* Verify nonboot HARTs have PMAs matching boot HART */
tt_ascalon_verify_pmas_nonboot_hart();
diff --git a/platform/generic/tenstorrent/iommu.c b/platform/generic/tenstorrent/iommu.c
new file mode 100644
index 00000000..acc31c09
--- /dev/null
+++ b/platform/generic/tenstorrent/iommu.c
@@ -0,0 +1,245 @@
+/*
+ * SPDX-FileCopyrightText: (c) 2025-2026 Tenstorrent USA, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_string.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_pmp.h>
+#include <libfdt.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+
+#include <tenstorrent/iommu.h>
+#include <tenstorrent/pma.h>
+
+/* PMA/PMP register offsets */
+#define RISCV_IOMMU_REG_PMA_CFG 0x1000
+#define RISCV_IOMMU_REG_PMP_CFG 0x2000
+#define RISCV_IOMMU_REG_PMP_ADDR 0x2040
+#define RISCV_IOMMU_REG_MACHINE_SIZE 0x3000 /* Minimum size of MMRs used */
+
+static int iommu_pmp_write(void *iommu, unsigned int n, pmp_t *pmp)
+{
+ void *pmpcfg_reg, *pmpaddr_reg;
+ u64 pmpcfg;
+ unsigned int pmpcfg_shift;
+
+ if (n >= PMP_COUNT)
+ return SBI_EINVAL;
+
+ pmpaddr_reg = iommu + RISCV_IOMMU_REG_PMP_ADDR + n * 8;
+ writeq(pmp->addr, pmpaddr_reg);
+
+ pmpcfg_reg = iommu + RISCV_IOMMU_REG_PMP_CFG + (n / 8) * 8;
+ pmpcfg_shift = (n % 8) * 8;
+ pmpcfg = readq(pmpcfg_reg);
+ pmpcfg &= ~((u64)0xff << pmpcfg_shift);
+ pmpcfg |= (u64)pmp->cfg << pmpcfg_shift;
+ writeq(pmpcfg, pmpcfg_reg);
+
+ return SBI_OK;
+}
+
+static int iommu_pmp_disable(void *iommu, unsigned int n)
+{
+ struct pmp pmp = { .cfg = 0, .addr = 0 };
+
+ return iommu_pmp_write(iommu, n, &pmp);
+}
+
+static int iommu_pmp_set(void *iommu, unsigned int n,
+ unsigned long prot, unsigned long addr, unsigned long log2len)
+{
+ pmp_t pmp;
+ int rc;
+
+ rc = pmp_create(&pmp, prot, addr, log2len);
+ if (rc)
+ return rc;
+
+ return iommu_pmp_write(iommu, n, &pmp);
+}
+
+/* This matches sbi_hart_oldpmp_configure. IOMMU does not support Smepmp */
+static int iommu_pmp_configure(void *iommu, unsigned int pmp_count,
+ unsigned int pmp_log2gran, unsigned long pmp_addr_max)
+{
+ struct sbi_domain_memregion *reg;
+ struct sbi_domain *dom;
+ unsigned int pmp_idx, pmp_flags;
+
+ /* For now, attach IOMMUs to root domain */
+ dom = &root;
+
+ /* Disable all PMPs */
+ for (int i = 0; i < pmp_count; i++)
+ iommu_pmp_disable(iommu, i);
+
+ pmp_idx = 0;
+ sbi_domain_for_each_memregion(dom, reg) {
+ if (pmp_count <= pmp_idx)
+ break;
+
+ pmp_flags = 0;
+
+ /*
+ * If permissions are to be enforced for all modes on
+ * this region, the lock bit should be set.
+ */
+ if (reg->flags & SBI_DOMAIN_MEMREGION_ENF_PERMISSIONS)
+ pmp_flags |= PMP_L;
+
+ if (reg->flags & SBI_DOMAIN_MEMREGION_SU_READABLE)
+ pmp_flags |= PMP_R;
+ if (reg->flags & SBI_DOMAIN_MEMREGION_SU_WRITABLE)
+ pmp_flags |= PMP_W;
+ if (reg->flags & SBI_DOMAIN_MEMREGION_SU_EXECUTABLE)
+ pmp_flags |= PMP_X;
+
+ if (reg->order < pmp_log2gran || (reg->base >> PMP_SHIFT) >= pmp_addr_max) {
+ sbi_printf("Can not configure pmp for domain %s because"
+ " memory region address 0x%lx or size 0x%lx "
+ "is not in range.\n", dom->name, reg->base,
+ reg->order);
+ continue;
+ }
+
+ iommu_pmp_set(iommu, pmp_idx, pmp_flags, reg->base, reg->order);
+ pmp_idx++;
+ }
+
+ return 0;
+}
+
+static int iommu_pma_write(void *iommu, unsigned int n, u64 pma)
+{
+ void *pmacfg_reg;
+
+ if (n >= TT_MAX_PMAS)
+ return SBI_EINVAL;
+
+ pmacfg_reg = iommu + RISCV_IOMMU_REG_PMA_CFG + n*8;
+
+ writeq(pma, pmacfg_reg);
+
+ if (readq(pmacfg_reg) != pma)
+ return SBI_ENOTSUPP;
+
+ return SBI_OK;
+}
+
+static int iommu_pma_configure(void *iommu)
+{
+ for (int i = 0; i < TT_MAX_PMAS; i++) {
+ int rc = iommu_pma_write(iommu, i, tt_pma_get(i));
+ if (rc) {
+ sbi_printf("IOMMU: Error setting unimplemented PMA%02u\n", i);
+ return rc;
+ }
+ }
+
+ return SBI_OK;
+}
+
+static void tt_iommu_detect_pmp(void *iommu, unsigned int *pmp_count,
+ unsigned int *pmp_log2gran,
+ unsigned long *pmp_addr_max)
+{
+ unsigned long pmp_addr_bits;
+ void *pmpaddr_reg;
+ u64 val;
+ unsigned int i;
+
+ pmpaddr_reg = iommu + RISCV_IOMMU_REG_PMP_ADDR + 0 * 8;
+ writeq(PMP_ADDR_MASK, pmpaddr_reg);
+ val = readq(pmpaddr_reg);
+ *pmp_log2gran = sbi_ffs(val) + 2;
+ pmp_addr_bits = sbi_fls(val);
+
+ *pmp_addr_max = (1UL << pmp_addr_bits) | ((1UL << pmp_addr_bits) - 1);
+
+ for (i = 0; i < PMP_COUNT; i++) {
+ pmpaddr_reg = iommu + RISCV_IOMMU_REG_PMP_ADDR + i * 8;
+ writeq(val, pmpaddr_reg);
+ val = readq(pmpaddr_reg);
+ if (!val)
+ break;
+ writeq(0, pmpaddr_reg);
+ }
+ *pmp_count = i;
+}
+
+int tt_iommu_configure(unsigned long iommu_m_regs)
+{
+ unsigned int pmp_count;
+ unsigned int pmp_log2gran;
+ unsigned long pmp_addr_max;
+ int rc;
+
+ rc = iommu_pma_configure((void *)iommu_m_regs);
+ if (rc) {
+ sbi_printf("IOMMU: Failed to set PMAs\n");
+ return rc;
+ }
+
+ tt_iommu_detect_pmp((void *)iommu_m_regs, &pmp_count,
+ &pmp_log2gran, &pmp_addr_max);
+ sbi_dprintf("IOMMU: detected %u PMPs %u log2gran 0x%016lx addr max\n",
+ pmp_count, pmp_log2gran, pmp_addr_max);
+
+ rc = iommu_pmp_configure((void *)iommu_m_regs, pmp_count,
+ pmp_log2gran, pmp_addr_max);
+ if (rc) {
+ sbi_printf("IOMMU: Failed to set PMPs\n");
+ return rc;
+ }
+
+ return SBI_OK;
+}
+
+int tt_iommu_fdt_configure(const void *fdt)
+{
+ const char *compatible = "tenstorrent,riscv-iommu";
+ bool found_dt = false;
+ int offset = -1;
+
+ for (;;) {
+ uint64_t addr, size;
+ int rc;
+
+ offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ if (offset < 0)
+ break;
+
+ rc = fdt_get_node_addr_size_by_name(fdt, offset, "machine",
+ &addr, &size);
+ if (rc < 0 || !size) {
+ sbi_printf("tenstorrent,riscv-iommu did not find "
+ "machine regs\n");
+ continue;
+ }
+
+ if (size < RISCV_IOMMU_REG_MACHINE_SIZE) {
+ sbi_printf("tenstorrent,riscv-iommu@0x%016lx "
+ " machine regs region too small\n", addr);
+ continue;
+ }
+
+ sbi_dprintf("tenstorrent,riscv-iommu found machine regs "
+ "0x%016lx-0x%016lx\n", addr, addr + size - 1);
+
+ rc = tt_iommu_configure(addr);
+ if (rc)
+ sbi_printf("tenstorrent,riscv-iommu@0x%016lx "
+ "init failed\n", addr);
+ }
+
+ if (!found_dt)
+ return SBI_ENOTSUPP;
+
+ return SBI_OK;
+}
diff --git a/platform/generic/tenstorrent/objects.mk b/platform/generic/tenstorrent/objects.mk
index 1e4aeb2d..0bf9c69b 100644
--- a/platform/generic/tenstorrent/objects.mk
+++ b/platform/generic/tenstorrent/objects.mk
@@ -5,6 +5,7 @@
platform-objs-y += tenstorrent/pma.o
platform-objs-$(CONFIG_CPU_TENSTORRENT_ASCALON) += tenstorrent/ascalon.o
+platform-objs-$(CONFIG_CPU_TENSTORRENT_IOMMU) += tenstorrent/iommu.o
carray-platform_override_modules-$(CONFIG_PLATFORM_TENSTORRENT_ATLANTIS) += tenstorrent_atlantis
platform-objs-$(CONFIG_PLATFORM_TENSTORRENT_ATLANTIS) += tenstorrent/atlantis.o
diff --git a/platform/generic/tenstorrent/pma.c b/platform/generic/tenstorrent/pma.c
index daf60192..1556707c 100644
--- a/platform/generic/tenstorrent/pma.c
+++ b/platform/generic/tenstorrent/pma.c
@@ -13,7 +13,8 @@
/*
* All PMAs in the system should be the same (after boot). The init code
- * must have set PMAs for all HARTs.
+ * must have set PMAs for all HARTs. IOMMU init programs IOMMU PMAs to
+ * match the HARTs.
*/
/*
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 4/4] platform: generic: tenstorrent: Add RISC-V IOMMU support
2026-03-10 0:49 ` [PATCH 4/4] platform: generic: tenstorrent: Add RISC-V IOMMU support Nicholas Piggin
@ 2026-04-01 12:51 ` Joel Stanley
0 siblings, 0 replies; 7+ messages in thread
From: Joel Stanley @ 2026-04-01 12:51 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: opensbi
On Tue, 10 Mar 2026 at 11:19, Nicholas Piggin <npiggin@gmail.com> wrote:
> --- /dev/null
> +++ b/platform/generic/tenstorrent/iommu.c
> +int tt_iommu_fdt_configure(const void *fdt)
> +{
> + const char *compatible = "tenstorrent,riscv-iommu";
> + bool found_dt = false;
> + int offset = -1;
> +
> + for (;;) {
> + uint64_t addr, size;
> + int rc;
> +
> + offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
> + if (offset < 0)
> + break;
> +
> + rc = fdt_get_node_addr_size_by_name(fdt, offset, "machine",
> + &addr, &size);
> + if (rc < 0 || !size) {
> + sbi_printf("tenstorrent,riscv-iommu did not find "
> + "machine regs\n");
> + continue;
> + }
> +
> + if (size < RISCV_IOMMU_REG_MACHINE_SIZE) {
> + sbi_printf("tenstorrent,riscv-iommu@0x%016lx "
> + " machine regs region too small\n", addr);
> + continue;
> + }
should this set found_dt = true here?
> +
> + sbi_dprintf("tenstorrent,riscv-iommu found machine regs "
> + "0x%016lx-0x%016lx\n", addr, addr + size - 1);
> +
> + rc = tt_iommu_configure(addr);
> + if (rc)
> + sbi_printf("tenstorrent,riscv-iommu@0x%016lx "
> + "init failed\n", addr);
> + }
> +
> + if (!found_dt)
> + return SBI_ENOTSUPP;
because found_dt never gets modified.
> +
> + return SBI_OK;
> +}
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 7+ messages in thread