Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7811ef1
Started a ThreadX module port for the Cortex-R52, headers first
fdesbiens Aug 18, 2026
315fb72
Added the PMSAv8-R region setup and fault handler for the module port
fdesbiens Aug 18, 2026
21210e5
Completed the portable half of the R52 module manager sources
fdesbiens Aug 18, 2026
efe85af
Programmed MPU regions directly instead of through PRSELR, and moved …
fdesbiens Aug 18, 2026
c95e594
Added the module scheduler's region switch, with the offsets checked …
fdesbiens Aug 18, 2026
c102b7c
Added the abort-vector fault capture, and found three bugs writing it
fdesbiens Aug 18, 2026
3e8570d
Added the module user-mode entry, the only way a module reaches the k…
fdesbiens Aug 18, 2026
140140e
Added the supervisor call handler: the privilege boundary itself
fdesbiens Aug 18, 2026
fdedbed
Added the module thread stack build, which decides the mode a module …
fdesbiens Aug 18, 2026
451cb11
Moved module-port threads to SYS mode, which the context paths depend on
fdesbiens Aug 18, 2026
d5194a4
Disabled the port dispatch, and added the module-side library
fdesbiens Aug 18, 2026
d02d9f4
Added the module preamble, which checks its own declared size
fdesbiens Aug 18, 2026
523ccef
Added a sample module that tests the boundary rather than the API
fdesbiens Aug 18, 2026
dabb02f
Added the module manager sample, whose expected result is a fault
fdesbiens Aug 18, 2026
23c653a
Routed the board's SVC and abort vectors to the module port, when bui…
fdesbiens Aug 18, 2026
970542e
Built the module manager example, and found five ways it can look rig…
fdesbiens Aug 18, 2026
87536af
Built the module as its own image, because one link cannot hold both
fdesbiens Aug 19, 2026
a07d21f
Gave the kernel a window onto the module area, owned by the scheduler
fdesbiens Aug 19, 2026
d8f898e
Moved the scheduler into System mode, and borrowed SVC for the return
fdesbiens Aug 19, 2026
6f4b211
Seeded r0 and r1 so the module shell entry has its arguments
fdesbiens Aug 19, 2026
c1c9396
Moved the module's kernel gateway out of the kernel's code region
fdesbiens Aug 19, 2026
4d201ae
Drove the manager from a thread, and gave it the object pool it needs
fdesbiens Aug 19, 2026
61b8111
Stored the preamble's entry points relative to their own words
fdesbiens Aug 19, 2026
f8ed88b
Added the silicon run and diagnostic scripts for the module demonstra…
fdesbiens Aug 19, 2026
09a5c76
Made modules relocatable, so one blob runs at any address
fdesbiens Aug 19, 2026
08776d4
Proved the relocation by running the same blob from two addresses
fdesbiens Aug 19, 2026
89bc0fe
Fixed the module fault-notify path and covered both abort types
fdesbiens Aug 19, 2026
7636b0c
Masked the shared region's limit to the protection granule
fdesbiens Aug 20, 2026
483c173
Added the module isolation regression on the Armv8-R AEM FVP
fdesbiens Aug 20, 2026
87ee71e
Added the shared-region regression to both module examples
fdesbiens Aug 20, 2026
272309b
Applied the kernel warning set to the module port, and unified the mo…
fdesbiens Aug 20, 2026
a7bf618
Woke the CLZ priority search, which had never once run under GCC
fdesbiens Aug 20, 2026
ca4d600
Documented the CLZ search, and corrected the readme's AP claim
fdesbiens Aug 20, 2026
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ build_r52_vfp/
build_r52_uart/
build_r52_mpu/
build_r52_all/
build_mod/
build_fvp/

# Keil uVision per-user state, regenerated when a project is opened.
# The .uvprojx / .uvproj project files are the ones worth tracking.
Expand Down
329 changes: 328 additions & 1 deletion ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt

Large diffs are not rendered by default.

149 changes: 149 additions & 0 deletions ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/***************************************************************************
* Copyright (c) 2026 Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5).
* The AI-generated portions may be considered public domain (CC0-1.0)
* and not subject to the project's licence. The human contributor has
* reviewed and verified that the code is correct.
*
* SPDX-License-Identifier: MIT and CC0-1.0
**************************************************************************/

/**************************************************************************/
/* */
/* BOARD SUPPORT RELEASE */
/* */
/* cache.c Cortex-R52/GNU */
/* 6.5.2 */
/* AUTHOR */
/* */
/* Frédéric Desbiens, Eclipse Foundation */
/* */
/* DESCRIPTION */
/* */
/* Cache maintenance for a loader that copies code. See cache.h for */
/* why only these three functions exist. */
/* */
/* MISRA C:2012 deviations (justified) */
/* */
/* Directive 4.3 -- cache maintenance and CTR are reachable only */
/* through CP15; every access is encapsulated in a one-line accessor */
/* below and nowhere else in this file. */
/* Rule 11.6 (conversion between a pointer and an integer) -- a cache */
/* maintenance operation takes a virtual address as a register value, */
/* so the conversion is what the instruction requires. */
/* */
/**************************************************************************/

#include "cache.h"

/* The smallest data-cache line in the machine, from CTR.DminLine. Held as a
log2 of the number of 32-bit words, so the byte count is 4 << DminLine.
DminLine and not the L1 geometry: a maintenance-by-address walk has to step
by the smallest line any level implements, or it skips lines in that level. */

#define CTR_DMINLINE_SHIFT 16U
#define CTR_DMINLINE_MASK 0xFUL


/**************************************************************************/
/* CP15 accessors. The only assembly in this file (MISRA C:2012 Dir 4.3).*/
/**************************************************************************/

static unsigned long read_ctr(void)
{
unsigned long value;
__asm__ volatile("mrc p15, 0, %0, c0, c0, 1" : "=r"(value));
return value;
}

static void clean_dcache_line(unsigned long address)
{
__asm__ volatile("mcr p15, 0, %0, c7, c10, 1" :: "r"(address) : "memory");
}

static void invalidate_icache_all_op(void)
{
unsigned long zero = 0UL;
__asm__ volatile("mcr p15, 0, %0, c7, c5, 0" :: "r"(zero) : "memory");
}

static void data_sync_barrier(void)
{
__asm__ volatile("dsb sy" ::: "memory");
}

static void instruction_barrier(void)
{
__asm__ volatile("isb" ::: "memory");
}


/**************************************************************************/
/* cache_dcache_line_bytes */
/**************************************************************************/

unsigned long cache_dcache_line_bytes(void)
{
return 4UL << ((read_ctr() >> CTR_DMINLINE_SHIFT) & CTR_DMINLINE_MASK);
}


/**************************************************************************/
/* cache_clean_range */
/* */
/* Clean by virtual address over [start, start + length). */
/* */
/* The start is rounded DOWN to a line boundary and the walk continues */
/* past the end until the last line containing a requested byte has been */
/* cleaned. Rounding the start up instead would leave the first partial */
/* line dirty, which is the whole failure this exists to prevent and is */
/* invisible whenever the caller happens to be line aligned. */
/**************************************************************************/

void cache_clean_range(const void *start_address, unsigned long length)
{
unsigned long line = cache_dcache_line_bytes();
unsigned long address;
unsigned long end;

if (length == 0UL)
{
return;
}

address = (unsigned long) start_address;
end = address + length;

address &= ~(line - 1UL);

while (address < end)
{
clean_dcache_line(address);
address += line;
}

/* The stores have to be complete before anything fetches from the range. */

data_sync_barrier();
}


/**************************************************************************/
/* cache_invalidate_icache_all */
/**************************************************************************/

void cache_invalidate_icache_all(void)
{
invalidate_icache_all_op();

/* DSB then ISB: the invalidate must complete, and the pipeline must be
flushed of anything fetched before it did. */

data_sync_barrier();
instruction_barrier();
}
72 changes: 72 additions & 0 deletions ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/***************************************************************************
* Copyright (c) 2026 Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5).
* The AI-generated portions may be considered public domain (CC0-1.0)
* and not subject to the project's licence. The human contributor has
* reviewed and verified that the code is correct.
*
* SPDX-License-Identifier: MIT and CC0-1.0
**************************************************************************/

/**************************************************************************/
/* */
/* BOARD SUPPORT RELEASE */
/* */
/* cache.h Cortex-R52/GNU */
/* 6.5.2 */
/* AUTHOR */
/* */
/* Frédéric Desbiens, Eclipse Foundation */
/* */
/* DESCRIPTION */
/* */
/* The cache maintenance a loader owes the instruction side, and */
/* nothing else. */
/* */
/* The S32Z280 board support carries a full cache driver -- enable, */
/* disable, geometry, set/way sweeps -- because silicon bring-up needed */
/* to ask the hardware what it had. None of that is needed here: the */
/* caches are turned on once in mpu_init and never turned off, and the */
/* model's geometry is not in question. What IS needed is the pair of */
/* operations that make copied code executable, so that is all this is. */
/* */
/* Why it is needed at all: the module area is Normal write-back memory, */
/* so a byte copy of module code leaves the bytes in dirty data-cache */
/* lines while the instruction side -- which is not coherent with the */
/* data cache on this core -- fetches whatever main memory still holds. */
/* Cleaning by address range and then invalidating the instruction cache */
/* is what closes that gap. */
/* */
/* By range rather than by set/way, deliberately. A set/way sweep needs */
/* the cache geometry and touches every line in the machine; the loader */
/* knows exactly which bytes it wrote, so the range form is both tighter */
/* and shorter to get right. */
/* */
/**************************************************************************/

#ifndef CACHE_H
#define CACHE_H

/* Clean (write back) the data cache over one address range, so that main
memory holds what the copy wrote. Rounds outwards to cache-line
boundaries; a length of zero does nothing. */

void cache_clean_range(const void *start_address, unsigned long length);

/* Invalidate the whole instruction cache, so no stale line from a previous
image at the same address can be served. Invalidate-all rather than by
range because it is one register write and this runs once per load. */

void cache_invalidate_icache_all(void);

/* Data cache line length in bytes, from CTR.DminLine. Published because the
range walk above depends on it and a caller may want to report it. */

unsigned long cache_dcache_line_bytes(void);

#endif /* CACHE_H */
Loading
Loading