* [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table
@ 2025-06-17 13:58 Anshul Dalal
2025-06-17 13:58 ` [PATCH v3 2/2] mach-k3: add dynamic mmu fixups for SPL stage Anshul Dalal
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Anshul Dalal @ 2025-06-17 13:58 UTC (permalink / raw)
To: u-boot
Cc: Anshul Dalal, vigneshr, trini, afd, m-chawdhry, n-francis, b-liu,
nm, bb, u-kumar1
In u-boot we only provide a single MMU table for all k3 platforms,
this does not scale for devices with reserved memory outside the range
0x9e780000 - 0xa0000000 (eg j722s[1]) or for devices with < 2GiB of
memory (eg am62-SIP with 512MiB of RAM).
To properly configure the MMU on various k3 platforms, the
reserved-memory regions need to be queried at runtime from the
device-tree and the MMU table should be updated accordingly.
This patch adds the required fixups to the MMU table (during proper
U-boot stage) by marking the reserved regions as non cacheable and
keeping the remaining area as cacheable.
For the A-core SPL, the 128MiB region starting from SPL_TEXT_BASE
is marked as cacheable i.e 0x80080000 to 0x88080000.
The 128MiB size is chosen to allow for future use cases such as falcon
boot from the A-Core SPL which would require loading kernel image from
the SPL stage. This change also ensures the reserved memory regions that
all exist past 0x88080000 are non cacheable preventing speculative
accesses to those addresses.
[1]:
https://git.ti.com/cgit/ti-u-boot/ti-u-boot/tree/arch/arm/mach-k3/arm64/arm64-mmu.c?h=ti-u-boot-2025.01-next#n54
Signed-off-by: Anshul Dalal <anshuld@ti.com>
---
Changes for v3:
- Remove unused memory regions in SPL's map
- Add runtime addition of MMU entry for the framebuffer in SPL
- Refactor k3_mem_map_init to use standard u-boot APIs
- Unmap reserved-memory regions instead of keeping them uncached
v2: https://lore.kernel.org/u-boot/20250610160833.1705534-1-anshuld@ti.com/
Changes in v2:
- Removed dependency to:
https://lore.kernel.org/u-boot/20250522150941.563959-1-anshuld@ti.com/
v1: https://lore.kernel.org/u-boot/20250602120054.1466951-1-anshuld@ti.com/
---
arch/arm/mach-k3/arm64/arm64-mmu.c | 191 +++++++++++++++++++++++--
arch/arm/mach-k3/include/mach/k3-ddr.h | 9 ++
board/ti/common/k3-ddr.c | 10 ++
3 files changed, 197 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-k3/arm64/arm64-mmu.c b/arch/arm/mach-k3/arm64/arm64-mmu.c
index 0e07b1b7ce0..4db5f43b89d 100644
--- a/arch/arm/mach-k3/arm64/arm64-mmu.c
+++ b/arch/arm/mach-k3/arm64/arm64-mmu.c
@@ -11,9 +11,16 @@
#include <asm/system.h>
#include <asm/armv8/mmu.h>
+#include <mach/k3-ddr.h>
+#include <sort.h>
-struct mm_region k3_mem_map[] = {
+#include "../common_fdt.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mm_region k3_mem_map[K3_MMU_REGIONS_COUNT] = {
{
+ /* Peripherals */
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x80000000UL,
@@ -21,30 +28,27 @@ struct mm_region k3_mem_map[] = {
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
- .virt = 0x80000000UL,
- .phys = 0x80000000UL,
- .size = 0x1e780000UL,
- .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
- PTE_BLOCK_INNER_SHARE
- }, {
- .virt = 0xa0000000UL,
- .phys = 0xa0000000UL,
- .size = 0x60000000UL,
- .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
- PTE_BLOCK_INNER_SHARE
- }, {
+ /* Higher DDR banks */
.virt = 0x880000000UL,
.phys = 0x880000000UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
+ /* Flash peripherals */
.virt = 0x500000000UL,
.phys = 0x500000000UL,
.size = 0x380000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ /* Map SPL load region and the next 128MiB as cacheable */
+ .virt = CONFIG_SPL_TEXT_BASE,
+ .phys = CONFIG_SPL_TEXT_BASE,
+ .size = SZ_128M,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
}, {
/* List terminator */
0,
@@ -52,3 +56,164 @@ struct mm_region k3_mem_map[] = {
};
struct mm_region *mem_map = k3_mem_map;
+
+static int dt_reserved_cmp(const void *a, const void *b)
+{
+ const struct fdt_resource *val_a = a, *val_b = b;
+
+ return (val_a->start - val_b->start);
+}
+
+int k3_mem_map_init(void)
+{
+ fdt_addr_t mem_base;
+ fdt_size_t mem_size;
+ struct fdt_resource dt_reserved[K3_MMU_REGIONS_COUNT],
+ coalesced[K3_MMU_REGIONS_COUNT];
+ int k3_map_idx = -EINVAL, ret, nodeoffset, subnode;
+ void *blob = (void *)gd->fdt_blob;
+ unsigned int carveout_len, i, j;
+
+ ret = fdt_fixup_reserved(blob, "tfa", CONFIG_K3_ATF_LOAD_ADDR, 0x80000);
+ if (ret) {
+ pr_err("%s: Failed to fixup reserved node for tfa [%d]\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = fdt_fixup_reserved(blob, "optee", CONFIG_K3_OPTEE_LOAD_ADDR,
+ 0x1800000);
+ if (ret) {
+ pr_err("%s: Failed to fixup reserved node for optee [%d]\n",
+ __func__, ret);
+ return ret;
+ }
+
+ nodeoffset = fdt_subnode_offset(blob, 0, "memory");
+ if (nodeoffset < 0) {
+ pr_err("%s: Failed to get memory data: %s\n", __func__,
+ fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+
+ mem_base = fdtdec_get_addr_size(blob, nodeoffset, "reg", &mem_size);
+ if (mem_base != CFG_SYS_SDRAM_BASE)
+ return -EINVAL;
+
+ for (i = 0; i < K3_MMU_REGIONS_COUNT; i++) {
+ if (k3_mem_map[i].virt == CONFIG_SPL_TEXT_BASE) {
+ k3_map_idx = i;
+ break;
+ }
+ }
+
+ if (k3_map_idx == -EINVAL) {
+ pr_err("%s: Failed to find DDR region in MMU memory map\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ i = 0;
+ nodeoffset = fdt_subnode_offset(blob, 0, "reserved-memory");
+ fdt_for_each_subnode(subnode, blob, nodeoffset) {
+ const char *name;
+ fdt_addr_t addr, end_addr;
+ fdt_size_t size;
+
+ if (i >= K3_MMU_REGIONS_COUNT) {
+ /*
+ * This is a recoverable error if the regions can be
+ * coalesced, the required logic can be implemented once
+ * requirement arises.
+ */
+ pr_err("%s: Not enough space in MMU map for carveouts\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ name = fdt_get_name(blob, subnode, NULL);
+ addr = fdtdec_get_addr_size(blob, subnode, "reg", &size);
+
+ if (addr == FDT_ADDR_T_NONE)
+ continue;
+
+ if (!fdtdec_get_bool(blob, subnode, "no-map"))
+ continue;
+
+ if (addr >= mem_base + mem_size)
+ continue;
+
+ end_addr = addr + size;
+
+ if (end_addr <= mem_base)
+ continue;
+
+ debug("Added memory carveout at 0x%llx, size: 0x%llx for '%s'\n",
+ addr, size, name);
+
+ addr = max(addr, mem_base);
+ end_addr = min(end_addr, mem_base + mem_size);
+ size = end_addr - addr;
+ dt_reserved[i].start = addr;
+ dt_reserved[i].end = end_addr;
+ i++;
+ }
+ carveout_len = i;
+
+ if (!carveout_len)
+ return 0;
+
+ /* sort carveout regions by address required for creating carveouts */
+ qsort(dt_reserved, carveout_len, sizeof(dt_reserved[0]),
+ dt_reserved_cmp);
+
+ /* coalesce regions */
+ struct fdt_resource coalescing_temp = dt_reserved[0];
+
+ j = 0;
+ for (i = 1; i < carveout_len; i++) {
+ struct fdt_resource current = dt_reserved[i];
+
+ if (coalescing_temp.end >= current.start) {
+ coalescing_temp.end = current.end;
+ continue;
+ }
+ coalesced[j] = coalescing_temp;
+ coalescing_temp = current;
+ j++;
+ }
+
+ coalesced[j] = coalescing_temp;
+ carveout_len = j + 1;
+
+ if (coalesced[0].start != mem_base) {
+ k3_mem_map[k3_map_idx].virt = mem_base;
+ k3_mem_map[k3_map_idx].phys = mem_base;
+ k3_mem_map[k3_map_idx].size = coalesced[0].start - mem_base;
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+ }
+
+ for (i = 1; i < carveout_len; i++) {
+ k3_mem_map[k3_map_idx].virt = coalesced[i - 1].end;
+ k3_mem_map[k3_map_idx].phys = coalesced[i - 1].end;
+ k3_mem_map[k3_map_idx].size =
+ coalesced[i].start - coalesced[i - 1].end;
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+ }
+
+ k3_mem_map[k3_map_idx].virt = coalesced[carveout_len - 1].end;
+ k3_mem_map[k3_map_idx].phys = coalesced[carveout_len - 1].end;
+ k3_mem_map[k3_map_idx].size =
+ mem_base + mem_size - coalesced[carveout_len - 1].end;
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+
+ k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
+
+ return 0;
+}
diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
index 39e6725bb9b..0b164ebf5e6 100644
--- a/arch/arm/mach-k3/include/mach/k3-ddr.h
+++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
@@ -8,10 +8,19 @@
#include <spl.h>
+/* Number of mappable regions in the MMU page table */
+#define K3_MMU_REGIONS_COUNT 32
+
int dram_init(void);
int dram_init_banksize(void);
void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
void fixup_memory_node(struct spl_image_info *spl_image);
+/*
+ * Modifies the MMU memory map based on DDR size and reserved-memory
+ * nodes in DT
+ */
+int k3_mem_map_init(void);
+
#endif /* _K3_DDR_H_ */
diff --git a/board/ti/common/k3-ddr.c b/board/ti/common/k3-ddr.c
index a8425da8de5..ee882f62109 100644
--- a/board/ti/common/k3-ddr.c
+++ b/board/ti/common/k3-ddr.c
@@ -7,6 +7,7 @@
#include <dm/uclass.h>
#include <k3-ddrss.h>
#include <spl.h>
+#include <mach/k3-ddr.h>
#include "k3-ddr.h"
@@ -14,6 +15,15 @@ int dram_init(void)
{
s32 ret;
+ if (IS_ENABLED(CONFIG_ARM64) && xpl_phase() != PHASE_SPL) {
+ ret = k3_mem_map_init();
+ if (ret) {
+ printf("%s: Error fixing up MMU memory map: %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
ret = fdtdec_setup_mem_size_base_lowest();
if (ret)
printf("Error setting up mem size and base. %d\n", ret);
--
2.49.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 2/2] mach-k3: add dynamic mmu fixups for SPL stage
2025-06-17 13:58 [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Anshul Dalal
@ 2025-06-17 13:58 ` Anshul Dalal
2025-06-18 10:26 ` [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Kumar, Udit
2025-06-18 12:48 ` Anshul Dalal
2 siblings, 0 replies; 6+ messages in thread
From: Anshul Dalal @ 2025-06-17 13:58 UTC (permalink / raw)
To: u-boot
Cc: Anshul Dalal, vigneshr, trini, afd, m-chawdhry, n-francis, b-liu,
nm, bb, u-kumar1
On platforms with spl splash support i.e CONFIG_VIDEO=y, the top of DDR
is reserved for the framebuffer.
The size for the framebuffer is computed at runtime by video_reserve.
During the MMU configuration an entry corresponding to the framebuffer
should be dynamically created to properly map the required space for the
framebuffer.
Therefore this patch adds k3_spl_mem_map_init which adds the required
MMU entry by querying the gd after the framebuffer size has been
computed in spl_reserve_video_from_ram_top.
For non VIDEO=y platforms, the added k3_spl_mem_map_init function gets
optimized out of the final binary so overall, the spl size is not
impacted[1].
[1]: Tested on clang 19.1.7 and gcc 15.1.1
Signed-off-by: Anshul Dalal <anshuld@ti.com>
---
arch/arm/mach-k3/arm64/arm64-mmu.c | 44 ++++++++++++++++++++++++++
arch/arm/mach-k3/common.c | 13 ++++++--
arch/arm/mach-k3/include/mach/k3-ddr.h | 3 ++
3 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-k3/arm64/arm64-mmu.c b/arch/arm/mach-k3/arm64/arm64-mmu.c
index 4db5f43b89d..7680e9f1654 100644
--- a/arch/arm/mach-k3/arm64/arm64-mmu.c
+++ b/arch/arm/mach-k3/arm64/arm64-mmu.c
@@ -49,6 +49,10 @@ struct mm_region k3_mem_map[K3_MMU_REGIONS_COUNT] = {
.size = SZ_128M,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
+ }, {
+ /* Framebuffer reserved, size set at runtime */
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
}, {
/* List terminator */
0,
@@ -57,6 +61,46 @@ struct mm_region k3_mem_map[K3_MMU_REGIONS_COUNT] = {
struct mm_region *mem_map = k3_mem_map;
+int k3_spl_mem_map_init(void)
+{
+ unsigned int i;
+ int k3_map_idx = -EINVAL;
+
+ for (i = 0; i < K3_MMU_REGIONS_COUNT; i++) {
+ if (k3_mem_map[i].virt == 0 && k3_mem_map[i].phys == 0 &&
+ k3_mem_map[i].size == 0) {
+ k3_map_idx = i;
+ break;
+ }
+ }
+
+ if (k3_map_idx == -EINVAL) {
+ pr_err("%s: Failed to find fixup region in MMU memory map\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (k3_map_idx >= K3_MMU_REGIONS_COUNT - 1) {
+ pr_err("%s: Not enough space in MMU map for the added entry\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ if (CONFIG_IS_ENABLED(VIDEO)) {
+ k3_mem_map[k3_map_idx].virt = gd_video_bottom();
+ k3_mem_map[k3_map_idx].phys = gd_video_bottom();
+ k3_mem_map[k3_map_idx].size =
+ gd_video_top() - gd_video_bottom();
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+ }
+
+ k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
+
+ return 0;
+}
+
static int dt_reserved_cmp(const void *a, const void *b)
{
const struct fdt_resource *val_a = a, *val_b = b;
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index fc230f180d0..198ab4e85fe 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -15,6 +15,7 @@
#include <asm/global_data.h>
#include <linux/printk.h>
#include "common.h"
+#include "mach/k3-ddr.h"
#include <dm.h>
#include <remoteproc.h>
#include <asm/cache.h>
@@ -224,9 +225,6 @@ void spl_enable_cache(void)
dram_init();
- /* reserve TLB table */
- gd->arch.tlb_size = PGTABLE_SIZE;
-
gd->ram_top += get_effective_memsize();
gd->relocaddr = gd->ram_top;
@@ -234,6 +232,15 @@ void spl_enable_cache(void)
if (ret)
panic("Failed to reserve framebuffer memory (%d)\n", ret);
+ if (IS_ENABLED(CONFIG_ARM64)) {
+ ret = k3_spl_mem_map_init();
+ if (ret)
+ panic("Failed to perform MMU fixups: %d\n", ret);
+ }
+
+ /* reserve TLB table */
+ gd->arch.tlb_size = PGTABLE_SIZE;
+
gd->arch.tlb_addr = gd->relocaddr - gd->arch.tlb_size;
gd->arch.tlb_addr &= ~(0x10000 - 1);
debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
index 0b164ebf5e6..375a1a85945 100644
--- a/arch/arm/mach-k3/include/mach/k3-ddr.h
+++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
@@ -17,6 +17,9 @@ int dram_init_banksize(void);
void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
void fixup_memory_node(struct spl_image_info *spl_image);
+/* Performs MMU memory map fixups at SPL stage */
+int k3_spl_mem_map_init(void);
+
/*
* Modifies the MMU memory map based on DDR size and reserved-memory
* nodes in DT
--
2.49.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table
2025-06-17 13:58 [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Anshul Dalal
2025-06-17 13:58 ` [PATCH v3 2/2] mach-k3: add dynamic mmu fixups for SPL stage Anshul Dalal
@ 2025-06-18 10:26 ` Kumar, Udit
2025-06-18 11:52 ` Anshul Dalal
2025-06-18 12:48 ` Anshul Dalal
2 siblings, 1 reply; 6+ messages in thread
From: Kumar, Udit @ 2025-06-18 10:26 UTC (permalink / raw)
To: Anshul Dalal, u-boot
Cc: vigneshr, trini, afd, m-chawdhry, n-francis, b-liu, nm, bb
On 6/17/2025 7:28 PM, Anshul Dalal wrote:
> In u-boot we only provide a single MMU table for all k3 platforms,
> this does not scale for devices with reserved memory outside the range
> 0x9e780000 - 0xa0000000 (eg j722s[1]) or for devices with < 2GiB of
> memory (eg am62-SIP with 512MiB of RAM).
please avoid giving reference to internal HACKs
> To properly configure the MMU on various k3 platforms, the
> reserved-memory regions need to be queried at runtime from the
> device-tree and the MMU table should be updated accordingly.
>
> This patch adds the required fixups to the MMU table (during proper
> U-boot stage) by marking the reserved regions as non cacheable and
> keeping the remaining area as cacheable.
>
> For the A-core SPL, the 128MiB region starting from SPL_TEXT_BASE
> is marked as cacheable i.e 0x80080000 to 0x88080000.
>
> The 128MiB size is chosen to allow for future use cases such as falcon
> boot from the A-Core SPL which would require loading kernel image from
> the SPL stage. This change also ensures the reserved memory regions that
> all exist past 0x88080000 are non cacheable preventing speculative
> accesses to those addresses.
>
> [1]:
> https://git.ti.com/cgit/ti-u-boot/ti-u-boot/tree/arch/arm/mach-k3/arm64/arm64-mmu.c?h=ti-u-boot-2025.01-next#n54
>
> Signed-off-by: Anshul Dalal <anshuld@ti.com>
> ---
> Changes for v3:
> - Remove unused memory regions in SPL's map
> - Add runtime addition of MMU entry for the framebuffer in SPL
> - Refactor k3_mem_map_init to use standard u-boot APIs
> - Unmap reserved-memory regions instead of keeping them uncached
> v2: https://lore.kernel.org/u-boot/20250610160833.1705534-1-anshuld@ti.com/
>
> Changes in v2:
> - Removed dependency to:
> https://lore.kernel.org/u-boot/20250522150941.563959-1-anshuld@ti.com/
>
> v1: https://lore.kernel.org/u-boot/20250602120054.1466951-1-anshuld@ti.com/
> ---
> arch/arm/mach-k3/arm64/arm64-mmu.c | 191 +++++++++++++++++++++++--
> arch/arm/mach-k3/include/mach/k3-ddr.h | 9 ++
> board/ti/common/k3-ddr.c | 10 ++
> 3 files changed, 197 insertions(+), 13 deletions(-)
>
> diff --git a/arch/arm/mach-k3/arm64/arm64-mmu.c b/arch/arm/mach-k3/arm64/arm64-mmu.c
> index 0e07b1b7ce0..4db5f43b89d 100644
> --- a/arch/arm/mach-k3/arm64/arm64-mmu.c
> +++ b/arch/arm/mach-k3/arm64/arm64-mmu.c
> @@ -11,9 +11,16 @@
>
> #include <asm/system.h>
> #include <asm/armv8/mmu.h>
> +#include <mach/k3-ddr.h>
> +#include <sort.h>
>
> -struct mm_region k3_mem_map[] = {
> +#include "../common_fdt.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct mm_region k3_mem_map[K3_MMU_REGIONS_COUNT] = {
> {
> + /* Peripherals */
> .virt = 0x0UL,
> .phys = 0x0UL,
> .size = 0x80000000UL,
> @@ -21,30 +28,27 @@ struct mm_region k3_mem_map[] = {
> PTE_BLOCK_NON_SHARE |
> PTE_BLOCK_PXN | PTE_BLOCK_UXN
> }, {
> - .virt = 0x80000000UL,
> - .phys = 0x80000000UL,
> - .size = 0x1e780000UL,
> - .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> - PTE_BLOCK_INNER_SHARE
> - }, {
> - .virt = 0xa0000000UL,
> - .phys = 0xa0000000UL,
> - .size = 0x60000000UL,
> - .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> - PTE_BLOCK_INNER_SHARE
> - }, {
> + /* Higher DDR banks */
> .virt = 0x880000000UL,
> .phys = 0x880000000UL,
> .size = 0x80000000UL,
> .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> PTE_BLOCK_INNER_SHARE
> }, {
> + /* Flash peripherals */
> .virt = 0x500000000UL,
> .phys = 0x500000000UL,
> .size = 0x380000000UL,
> .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
> PTE_BLOCK_NON_SHARE |
> PTE_BLOCK_PXN | PTE_BLOCK_UXN
> + }, {
> + /* Map SPL load region and the next 128MiB as cacheable */
> + .virt = CONFIG_SPL_TEXT_BASE,
> + .phys = CONFIG_SPL_TEXT_BASE,
> + .size = SZ_128M,
> + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> + PTE_BLOCK_INNER_SHARE
> }, {
> /* List terminator */
> 0,
> @@ -52,3 +56,164 @@ struct mm_region k3_mem_map[] = {
> };
>
> struct mm_region *mem_map = k3_mem_map;
> +
> +static int dt_reserved_cmp(const void *a, const void *b)
> +{
> + const struct fdt_resource *val_a = a, *val_b = b;
> +
> + return (val_a->start - val_b->start);
> +}
> +
> +int k3_mem_map_init(void)
> +{
> + fdt_addr_t mem_base;
> + fdt_size_t mem_size;
> + struct fdt_resource dt_reserved[K3_MMU_REGIONS_COUNT],
> + coalesced[K3_MMU_REGIONS_COUNT];
> + int k3_map_idx = -EINVAL, ret, nodeoffset, subnode;
> + void *blob = (void *)gd->fdt_blob;
> + unsigned int carveout_len, i, j;
> +
> + ret = fdt_fixup_reserved(blob, "tfa", CONFIG_K3_ATF_LOAD_ADDR, 0x80000);
> + if (ret) {
> + pr_err("%s: Failed to fixup reserved node for tfa [%d]\n",
> + __func__, ret);
> + return ret;
> + }
am62l3_fdt.c , needs more size.
fdt_fixup_reserved(blob, "tfa", CONFIG_K3_ATF_LOAD_ADDR, 0x200000)
> +
> + ret = fdt_fixup_reserved(blob, "optee", CONFIG_K3_OPTEE_LOAD_ADDR,
> + 0x1800000);
> + if (ret) {
> + pr_err("%s: Failed to fixup reserved node for optee [%d]\n",
> + __func__, ret);
> + return ret;
> + }
> +
> + nodeoffset = fdt_subnode_offset(blob, 0, "memory");
> + if (nodeoffset < 0) {
> + pr_err("%s: Failed to get memory data: %s\n", __func__,
> + fdt_strerror(nodeoffset));
> + return nodeoffset;
> + }
> +
> + mem_base = fdtdec_get_addr_size(blob, nodeoffset, "reg", &mem_size);
> + if (mem_base != CFG_SYS_SDRAM_BASE)
> + return -EINVAL;
> +
> + for (i = 0; i < K3_MMU_REGIONS_COUNT; i++) {
> + if (k3_mem_map[i].virt == CONFIG_SPL_TEXT_BASE) {
> + k3_map_idx = i;
> + break;
> + }
> + }
you can fix this entry at offset 0, instead of looping all over
> +
> + if (k3_map_idx == -EINVAL) {
> + pr_err("%s: Failed to find DDR region in MMU memory map\n",
> + __func__);
> + return -EINVAL;
> + }
> +
> + i = 0;
> + nodeoffset = fdt_subnode_offset(blob, 0, "reserved-memory");
> + fdt_for_each_subnode(subnode, blob, nodeoffset) {
> + const char *name;
> + fdt_addr_t addr, end_addr;
> + fdt_size_t size;
> +
> + if (i >= K3_MMU_REGIONS_COUNT) {
> + /*
> + * This is a recoverable error if the regions can be
> + * coalesced, the required logic can be implemented once
> + * requirement arises.
> + */
> + pr_err("%s: Not enough space in MMU map for carveouts\n",
> + __func__);
> + return -ENOMEM;
> + }
> +
> + name = fdt_get_name(blob, subnode, NULL);
> + addr = fdtdec_get_addr_size(blob, subnode, "reg", &size);
> +
> + if (addr == FDT_ADDR_T_NONE)
> + continue;
> +
> + if (!fdtdec_get_bool(blob, subnode, "no-map"))
> + continue;
> +
> + if (addr >= mem_base + mem_size)
> + continue;
> +
> + end_addr = addr + size;
> +
> + if (end_addr <= mem_base)
> + continue;
> +
> + debug("Added memory carveout at 0x%llx, size: 0x%llx for '%s'\n",
> + addr, size, name);
> +
> + addr = max(addr, mem_base);
> + end_addr = min(end_addr, mem_base + mem_size);
> + size = end_addr - addr;
> + dt_reserved[i].start = addr;
> + dt_reserved[i].end = end_addr;
> + i++;
> + }
> + carveout_len = i;
> +
> + if (!carveout_len)
> + return 0;
> +
> + /* sort carveout regions by address required for creating carveouts */
> + qsort(dt_reserved, carveout_len, sizeof(dt_reserved[0]),
> + dt_reserved_cmp);
> +
> + /* coalesce regions */
> + struct fdt_resource coalescing_temp = dt_reserved[0];
> +
> + j = 0;
> + for (i = 1; i < carveout_len; i++) {
> + struct fdt_resource current = dt_reserved[i];
> +
> + if (coalescing_temp.end >= current.start) {
> + coalescing_temp.end = current.end;
> + continue;
> + }
> + coalesced[j] = coalescing_temp;
> + coalescing_temp = current;
> + j++;
> + }
> +
> + coalesced[j] = coalescing_temp;
> + carveout_len = j + 1;
> +
> + if (coalesced[0].start != mem_base) {
> + k3_mem_map[k3_map_idx].virt = mem_base;
> + k3_mem_map[k3_map_idx].phys = mem_base;
> + k3_mem_map[k3_map_idx].size = coalesced[0].start - mem_base;
> + k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> + PTE_BLOCK_INNER_SHARE;
> + k3_map_idx++;
> + }
> +
> + for (i = 1; i < carveout_len; i++) {
> + k3_mem_map[k3_map_idx].virt = coalesced[i - 1].end;
> + k3_mem_map[k3_map_idx].phys = coalesced[i - 1].end;
> + k3_mem_map[k3_map_idx].size =
> + coalesced[i].start - coalesced[i - 1].end;
> + k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> + PTE_BLOCK_INNER_SHARE;
> + k3_map_idx++;
> + }
> +
> + k3_mem_map[k3_map_idx].virt = coalesced[carveout_len - 1].end;
> + k3_mem_map[k3_map_idx].phys = coalesced[carveout_len - 1].end;
> + k3_mem_map[k3_map_idx].size =
> + mem_base + mem_size - coalesced[carveout_len - 1].end;
> + k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> + PTE_BLOCK_INNER_SHARE;
> + k3_map_idx++;
> +
> + k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
I assume you are looping over reserved -memory and adding to map..
what if , we need some reserved memory as non-cached.
> +
> + return 0;
> +}
> diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
> index 39e6725bb9b..0b164ebf5e6 100644
> --- a/arch/arm/mach-k3/include/mach/k3-ddr.h
> +++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
> @@ -8,10 +8,19 @@
>
> #include <spl.h>
>
> +/* Number of mappable regions in the MMU page table */
> +#define K3_MMU_REGIONS_COUNT 32
> +
why 32 ?
> int dram_init(void);
> int dram_init_banksize(void);
>
> void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
> void fixup_memory_node(struct spl_image_info *spl_image);
>
> +/*
> + * Modifies the MMU memory map based on DDR size and reserved-memory
> + * nodes in DT
> + */
> +int k3_mem_map_init(void);
> +
> #endif /* _K3_DDR_H_ */
> diff --git a/board/ti/common/k3-ddr.c b/board/ti/common/k3-ddr.c
> index a8425da8de5..ee882f62109 100644
> --- a/board/ti/common/k3-ddr.c
> +++ b/board/ti/common/k3-ddr.c
> @@ -7,6 +7,7 @@
> #include <dm/uclass.h>
> #include <k3-ddrss.h>
> #include <spl.h>
> +#include <mach/k3-ddr.h>
>
> #include "k3-ddr.h"
>
> @@ -14,6 +15,15 @@ int dram_init(void)
> {
> s32 ret;
>
> + if (IS_ENABLED(CONFIG_ARM64) && xpl_phase() != PHASE_SPL) {
> + ret = k3_mem_map_init();
> + if (ret) {
> + printf("%s: Error fixing up MMU memory map: %d\n",
> + __func__, ret);
> + return ret;
If can not set MMU table, then should be Hang , no ?
> + }
> + }
> +
> ret = fdtdec_setup_mem_size_base_lowest();
> if (ret)
> printf("Error setting up mem size and base. %d\n", ret);
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table
2025-06-18 10:26 ` [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Kumar, Udit
@ 2025-06-18 11:52 ` Anshul Dalal
2025-06-18 13:51 ` Kumar, Udit
0 siblings, 1 reply; 6+ messages in thread
From: Anshul Dalal @ 2025-06-18 11:52 UTC (permalink / raw)
To: Kumar, Udit, u-boot
Cc: vigneshr, trini, afd, m-chawdhry, n-francis, b-liu, nm, bb
On Wed Jun 18, 2025 at 3:56 PM IST, Udit Kumar wrote:
>
> On 6/17/2025 7:28 PM, Anshul Dalal wrote:
>> In u-boot we only provide a single MMU table for all k3 platforms,
>> this does not scale for devices with reserved memory outside the range
>> 0x9e780000 - 0xa0000000 (eg j722s[1]) or for devices with < 2GiB of
>> memory (eg am62-SIP with 512MiB of RAM).
>
> please avoid giving reference to internal HACKs
>
Got it :)
>> To properly configure the MMU on various k3 platforms, the
>> reserved-memory regions need to be queried at runtime from the
>> device-tree and the MMU table should be updated accordingly.
>>
>> This patch adds the required fixups to the MMU table (during proper
>> U-boot stage) by marking the reserved regions as non cacheable and
>> keeping the remaining area as cacheable.
>>
>> For the A-core SPL, the 128MiB region starting from SPL_TEXT_BASE
>> is marked as cacheable i.e 0x80080000 to 0x88080000.
>>
>> The 128MiB size is chosen to allow for future use cases such as falcon
>> boot from the A-Core SPL which would require loading kernel image from
>> the SPL stage. This change also ensures the reserved memory regions that
>> all exist past 0x88080000 are non cacheable preventing speculative
>> accesses to those addresses.
>>
>> [1]:
>> https://git.ti.com/cgit/ti-u-boot/ti-u-boot/tree/arch/arm/mach-k3/arm64/arm64-mmu.c?h=ti-u-boot-2025.01-next#n54
>>
>> Signed-off-by: Anshul Dalal <anshuld@ti.com>
>> ---
>> Changes for v3:
>> - Remove unused memory regions in SPL's map
>> - Add runtime addition of MMU entry for the framebuffer in SPL
>> - Refactor k3_mem_map_init to use standard u-boot APIs
>> - Unmap reserved-memory regions instead of keeping them uncached
>> v2: https://lore.kernel.org/u-boot/20250610160833.1705534-1-anshuld@ti.com/
>>
>> Changes in v2:
>> - Removed dependency to:
>> https://lore.kernel.org/u-boot/20250522150941.563959-1-anshuld@ti.com/
>>
>> v1: https://lore.kernel.org/u-boot/20250602120054.1466951-1-anshuld@ti.com/
>> ---
>> arch/arm/mach-k3/arm64/arm64-mmu.c | 191 +++++++++++++++++++++++--
>> arch/arm/mach-k3/include/mach/k3-ddr.h | 9 ++
>> board/ti/common/k3-ddr.c | 10 ++
>> 3 files changed, 197 insertions(+), 13 deletions(-)
>>
[snip]
>> +int k3_mem_map_init(void)
>> +{
>> + fdt_addr_t mem_base;
>> + fdt_size_t mem_size;
>> + struct fdt_resource dt_reserved[K3_MMU_REGIONS_COUNT],
>> + coalesced[K3_MMU_REGIONS_COUNT];
>> + int k3_map_idx = -EINVAL, ret, nodeoffset, subnode;
>> + void *blob = (void *)gd->fdt_blob;
>> + unsigned int carveout_len, i, j;
>> +
>> + ret = fdt_fixup_reserved(blob, "tfa", CONFIG_K3_ATF_LOAD_ADDR, 0x80000);
>> + if (ret) {
>> + pr_err("%s: Failed to fixup reserved node for tfa [%d]\n",
>> + __func__, ret);
>> + return ret;
>> + }
>
> am62l3_fdt.c , needs more size.
>
> fdt_fixup_reserved(blob, "tfa", CONFIG_K3_ATF_LOAD_ADDR, 0x200000)
>
>
The fdt_fixup_reserved actually handles these contingencies, if a
matching reserved region already exists it ignores the size we provided
and uses the size form the dt instead.
>> +
>> + ret = fdt_fixup_reserved(blob, "optee", CONFIG_K3_OPTEE_LOAD_ADDR,
>> + 0x1800000);
>> + if (ret) {
>> + pr_err("%s: Failed to fixup reserved node for optee [%d]\n",
>> + __func__, ret);
>> + return ret;
>> + }
>> +
>> + nodeoffset = fdt_subnode_offset(blob, 0, "memory");
>> + if (nodeoffset < 0) {
>> + pr_err("%s: Failed to get memory data: %s\n", __func__,
>> + fdt_strerror(nodeoffset));
>> + return nodeoffset;
>> + }
>> +
>> + mem_base = fdtdec_get_addr_size(blob, nodeoffset, "reg", &mem_size);
>> + if (mem_base != CFG_SYS_SDRAM_BASE)
>> + return -EINVAL;
>> +
>> + for (i = 0; i < K3_MMU_REGIONS_COUNT; i++) {
>> + if (k3_mem_map[i].virt == CONFIG_SPL_TEXT_BASE) {
>> + k3_map_idx = i;
>> + break;
>> + }
>> + }
>
> you can fix this entry at offset 0, instead of looping all over
>
>
We have to have some static nodes in the DT as well for peripherals,
flash etc. All the nodes that are added as part of this fixup append to
the table so as to not interfere with the already defined MMU entries.
If we move this entry to 0, appending to the table would overwrite the
existing entries that we do want.
>> +
>> + if (k3_map_idx == -EINVAL) {
>> + pr_err("%s: Failed to find DDR region in MMU memory map\n",
>> + __func__);
>> + return -EINVAL;
>> + }
>> +
>> + i = 0;
[snip]
>> + k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
>> + PTE_BLOCK_INNER_SHARE;
>> + k3_map_idx++;
>> +
>> + k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
>
> I assume you are looping over reserved -memory and adding to map..
>
> what if , we need some reserved memory as non-cached.
>
>
Yes, here I loop over all the reserved regions and add the carveouts to
the map after coalescing. So far the reserved regions are kept unmapped
but that causes issues with remoteproc, I'll fix that in the next
revision by marking them as non-cacheable instead.
>> +
>> + return 0;
>> +}
>> diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
>> index 39e6725bb9b..0b164ebf5e6 100644
>> --- a/arch/arm/mach-k3/include/mach/k3-ddr.h
>> +++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
>> @@ -8,10 +8,19 @@
>>
>> #include <spl.h>
>>
>> +/* Number of mappable regions in the MMU page table */
>> +#define K3_MMU_REGIONS_COUNT 32
>> +
> why 32 ?
I just took it as a worst case scenario with assuming > 10
reserved-memory nodes with no coalescing and two entries per node (one
for the carveout and another for the non-cached entry as per above).
The table size is 1KiB at the moment and I think it's a reasonable
compromise.
>> int dram_init(void);
>> int dram_init_banksize(void);
>>
>> void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
>> void fixup_memory_node(struct spl_image_info *spl_image);
>>
>> +/*
>> + * Modifies the MMU memory map based on DDR size and reserved-memory
>> + * nodes in DT
>> + */
>> +int k3_mem_map_init(void);
>> +
>> #endif /* _K3_DDR_H_ */
>> diff --git a/board/ti/common/k3-ddr.c b/board/ti/common/k3-ddr.c
>> index a8425da8de5..ee882f62109 100644
>> --- a/board/ti/common/k3-ddr.c
>> +++ b/board/ti/common/k3-ddr.c
>> @@ -7,6 +7,7 @@
>> #include <dm/uclass.h>
>> #include <k3-ddrss.h>
>> #include <spl.h>
>> +#include <mach/k3-ddr.h>
>>
>> #include "k3-ddr.h"
>>
>> @@ -14,6 +15,15 @@ int dram_init(void)
>> {
>> s32 ret;
>>
>> + if (IS_ENABLED(CONFIG_ARM64) && xpl_phase() != PHASE_SPL) {
>> + ret = k3_mem_map_init();
>
>> + if (ret) {
>> + printf("%s: Error fixing up MMU memory map: %d\n",
>> + __func__, ret);
>> + return ret;
> If can not set MMU table, then should be Hang , no ?
That I have deferred to the caller which is initcall in our case which
will hang the board if dram_init fails.
>> + }
>> + }
>> +
>> ret = fdtdec_setup_mem_size_base_lowest();
>> if (ret)
>> printf("Error setting up mem size and base. %d\n", ret);
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table
2025-06-18 11:52 ` Anshul Dalal
@ 2025-06-18 13:51 ` Kumar, Udit
0 siblings, 0 replies; 6+ messages in thread
From: Kumar, Udit @ 2025-06-18 13:51 UTC (permalink / raw)
To: Anshul Dalal, u-boot
Cc: vigneshr, trini, afd, m-chawdhry, n-francis, b-liu, nm, bb
On 6/18/2025 5:22 PM, Anshul Dalal wrote:
> On Wed Jun 18, 2025 at 3:56 PM IST, Udit Kumar wrote:
>> On 6/17/2025 7:28 PM, Anshul Dalal wrote:
>>> In u-boot we only provide a single MMU table for all k3 platforms,
>>> this does not scale for devices with reserved memory outside the range
>>> 0x9e780000 - 0xa0000000 (eg j722s[1]) or for devices with < 2GiB of
>>> memory (eg am62-SIP with 512MiB of RAM).
>> please avoid giving reference to internal HACKs
>>
> Got it :)
>
>>> To properly configure the MMU on various k3 platforms, the
>>> reserved-memory regions need to be queried at runtime from the
>>> device-tree and the MMU table should be updated accordingly.
>>>
>>> This patch adds the required fixups to the MMU table (during proper
>>> U-boot stage) by marking the reserved regions as non cacheable and
>>> keeping the remaining area as cacheable.
>>>
>>> For the A-core SPL, the 128MiB region starting from SPL_TEXT_BASE
>>> is marked as cacheable i.e 0x80080000 to 0x88080000.
>>>
>>> The 128MiB size is chosen to allow for future use cases such as falcon
>>> boot from the A-Core SPL which would require loading kernel image from
>>> the SPL stage. This change also ensures the reserved memory regions that
>>> all exist past 0x88080000 are non cacheable preventing speculative
>>> accesses to those addresses.
>>>
>>> [1]:
>>> https://git.ti.com/cgit/ti-u-boot/ti-u-boot/tree/arch/arm/mach-k3/arm64/arm64-mmu.c?h=ti-u-boot-2025.01-next#n54
>>>
>>> Signed-off-by: Anshul Dalal <anshuld@ti.com>
>>> ---
>>> Changes for v3:
>>> - Remove unused memory regions in SPL's map
>>> - Add runtime addition of MMU entry for the framebuffer in SPL
>>> - Refactor k3_mem_map_init to use standard u-boot APIs
>>> - Unmap reserved-memory regions instead of keeping them uncached
>>> v2: https://lore.kernel.org/u-boot/20250610160833.1705534-1-anshuld@ti.com/
>>>
>>> Changes in v2:
>>> - Removed dependency to:
>>> https://lore.kernel.org/u-boot/20250522150941.563959-1-anshuld@ti.com/
>>>
>>> v1: https://lore.kernel.org/u-boot/20250602120054.1466951-1-anshuld@ti.com/
>>> ---
>>> arch/arm/mach-k3/arm64/arm64-mmu.c | 191 +++++++++++++++++++++++--
>>> arch/arm/mach-k3/include/mach/k3-ddr.h | 9 ++
>>> board/ti/common/k3-ddr.c | 10 ++
>>> 3 files changed, 197 insertions(+), 13 deletions(-)
>>>
> [snip]
>
>>> +int k3_mem_map_init(void)
>>> +{
>>> + fdt_addr_t mem_base;
>>> + fdt_size_t mem_size;
>>> + struct fdt_resource dt_reserved[K3_MMU_REGIONS_COUNT],
>>> + coalesced[K3_MMU_REGIONS_COUNT];
>>> + int k3_map_idx = -EINVAL, ret, nodeoffset, subnode;
>>> + void *blob = (void *)gd->fdt_blob;
>>> + unsigned int carveout_len, i, j;
>>> +
>>> + ret = fdt_fixup_reserved(blob, "tfa", CONFIG_K3_ATF_LOAD_ADDR, 0x80000);
>>> + if (ret) {
>>> + pr_err("%s: Failed to fixup reserved node for tfa [%d]\n",
>>> + __func__, ret);
>>> + return ret;
>>> + }
>> [..]+
>> + k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
>> I assume you are looping over reserved -memory and adding to map..
>>
>> what if , we need some reserved memory as non-cached.
>>
>>
> Yes, here I loop over all the reserved regions and add the carveouts to
> the map after coalescing. So far the reserved regions are kept unmapped
> but that causes issues with remoteproc, I'll fix that in the next
> revision by marking them as non-cacheable instead.
you should check wrt device capability, If device is coherent then it
can be as is
If device is non-coherent (we observed in J722s, still to confirm this)
then node should be
non-cacheable
>
>>> +
>>> + return 0;
>>> +}
>>> diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
>>> index 39e6725bb9b..0b164ebf5e6 100644
>>> --- a/arch/arm/mach-k3/include/mach/k3-ddr.h
>>> +++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
>>> @@ -8,10 +8,19 @@
>>>
>>> #include <spl.h>
>>>
>>> +/* Number of mappable regions in the MMU page table */
>>> +#define K3_MMU_REGIONS_COUNT 32
>>> +
>> why 32 ?
> I just took it as a worst case scenario with assuming > 10
> reserved-memory nodes with no coalescing and two entries per node (one
> for the carveout and another for the non-cached entry as per above).
> The table size is 1KiB at the moment and I think it's a reasonable
> compromise.
>
>>> int dram_init(void);
>>> int dram_init_banksize(void);
>>>
>>> void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
>>> void fixup_memory_node(struct spl_image_info *spl_image);
>>>
>>> +/*
>>> + * Modifies the MMU memory map based on DDR size and reserved-memory
>>> + * nodes in DT
>>> + */
>>> +int k3_mem_map_init(void);
>>> +
>>> #endif /* _K3_DDR_H_ */
>>> diff --git a/board/ti/common/k3-ddr.c b/board/ti/common/k3-ddr.c
>>> index a8425da8de5..ee882f62109 100644
>>> --- a/board/ti/common/k3-ddr.c
>>> +++ b/board/ti/common/k3-ddr.c
>>> @@ -7,6 +7,7 @@
>>> #include <dm/uclass.h>
>>> #include <k3-ddrss.h>
>>> #include <spl.h>
>>> +#include <mach/k3-ddr.h>
>>>
>>> #include "k3-ddr.h"
>>>
>>> @@ -14,6 +15,15 @@ int dram_init(void)
>>> {
>>> s32 ret;
>>>
>>> + if (IS_ENABLED(CONFIG_ARM64) && xpl_phase() != PHASE_SPL) {
>>> + ret = k3_mem_map_init();
>>> + if (ret) {
>>> + printf("%s: Error fixing up MMU memory map: %d\n",
>>> + __func__, ret);
>>> + return ret;
>> If can not set MMU table, then should be Hang , no ?
> That I have deferred to the caller which is initcall in our case which
> will hang the board if dram_init fails.
ok
>
>>> + }
>>> + }
>>> +
>>> ret = fdtdec_setup_mem_size_base_lowest();
>>> if (ret)
>>> printf("Error setting up mem size and base. %d\n", ret);
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table
2025-06-17 13:58 [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Anshul Dalal
2025-06-17 13:58 ` [PATCH v3 2/2] mach-k3: add dynamic mmu fixups for SPL stage Anshul Dalal
2025-06-18 10:26 ` [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Kumar, Udit
@ 2025-06-18 12:48 ` Anshul Dalal
2 siblings, 0 replies; 6+ messages in thread
From: Anshul Dalal @ 2025-06-18 12:48 UTC (permalink / raw)
To: Anshul Dalal, u-boot
Cc: vigneshr, trini, afd, m-chawdhry, n-francis, b-liu, nm, bb,
u-kumar1
On Tue Jun 17, 2025 at 7:28 PM IST, Anshul Dalal wrote:
> In u-boot we only provide a single MMU table for all k3 platforms,
> this does not scale for devices with reserved memory outside the range
> 0x9e780000 - 0xa0000000 (eg j722s[1]) or for devices with < 2GiB of
> memory (eg am62-SIP with 512MiB of RAM).
>
> To properly configure the MMU on various k3 platforms, the
> reserved-memory regions need to be queried at runtime from the
> device-tree and the MMU table should be updated accordingly.
>
> This patch adds the required fixups to the MMU table (during proper
> U-boot stage) by marking the reserved regions as non cacheable and
> keeping the remaining area as cacheable.
>
> For the A-core SPL, the 128MiB region starting from SPL_TEXT_BASE
> is marked as cacheable i.e 0x80080000 to 0x88080000.
>
> The 128MiB size is chosen to allow for future use cases such as falcon
> boot from the A-Core SPL which would require loading kernel image from
> the SPL stage. This change also ensures the reserved memory regions that
> all exist past 0x88080000 are non cacheable preventing speculative
> accesses to those addresses.
>
> [1]:
> https://git.ti.com/cgit/ti-u-boot/ti-u-boot/tree/arch/arm/mach-k3/arm64/arm64-mmu.c?h=ti-u-boot-2025.01-next#n54
>
> Signed-off-by: Anshul Dalal <anshuld@ti.com>
> ---
> Changes for v3:
> - Remove unused memory regions in SPL's map
> - Add runtime addition of MMU entry for the framebuffer in SPL
> - Refactor k3_mem_map_init to use standard u-boot APIs
> - Unmap reserved-memory regions instead of keeping them uncached
> v2: https://lore.kernel.org/u-boot/20250610160833.1705534-1-anshuld@ti.com/
>
> Changes in v2:
> - Removed dependency to:
> https://lore.kernel.org/u-boot/20250522150941.563959-1-anshuld@ti.com/
>
> v1: https://lore.kernel.org/u-boot/20250602120054.1466951-1-anshuld@ti.com/
> ---
[snip]
Superseded by v4:
https://lore.kernel.org/u-boot/20250618124210.1936140-1-anshuld@ti.com/
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-06-18 13:51 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-17 13:58 [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Anshul Dalal
2025-06-17 13:58 ` [PATCH v3 2/2] mach-k3: add dynamic mmu fixups for SPL stage Anshul Dalal
2025-06-18 10:26 ` [PATCH v3 1/2] mach-k3: add runtime memory carveouts for MMU table Kumar, Udit
2025-06-18 11:52 ` Anshul Dalal
2025-06-18 13:51 ` Kumar, Udit
2025-06-18 12:48 ` Anshul Dalal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox