PebbleOS v4.45.0-142-gc51251f50
Loading...
Searching...
No Matches
Memory protection

Memory protection regions. More...

Data Structures

struct  pbl_mpu_region
 Memory region. More...
 

Macros

#define KERNEL_READONLY_DATA   PBL_SECTION(".kernel_unpriv_ro_bss")
 Places a variable where unprivileged code can read it but not write to it.
 
#define KERNEL_READONLY_DATA_SET(var, val)
 Assign a KERNEL_READONLY_DATA variable.
 
#define PBL_MPU_NO_ACCESS   0U
 No access.
 
#define PBL_MPU_P_RW   1U
 Privileged read/write, no unprivileged access.
 
#define PBL_MPU_P_RW_U_RO   2U
 Privileged read/write, unprivileged read-only.
 
#define PBL_MPU_P_RW_U_RW   3U
 Privileged and unprivileged read/write.
 
#define PBL_MPU_P_RO   4U
 Privileged read-only, no unprivileged access.
 
#define PBL_MPU_P_RO_U_RO   5U
 Privileged and unprivileged read-only.
 
#define PBL_MPU_ACCESS_MSK   7U
 Mask of the access attribute.
 
#define PBL_MPU_NORMAL_NC   (0U << 3)
 Normal memory, not cached.
 
#define PBL_MPU_NORMAL_WT   (1U << 3)
 Normal memory, write-through cached.
 
#define PBL_MPU_NORMAL_WB   (2U << 3)
 Normal memory, write-back cached.
 
#define PBL_MPU_DEVICE   (3U << 3)
 Device memory: accesses are not merged, reordered or cached.
 
#define PBL_MPU_TYPE_MSK   (3U << 3)
 Mask of the memory type attribute.
 
#define PBL_MPU_EXEC   (1U << 5)
 Instructions may be fetched from the region.
 
#define PBL_MPU_SHAREABLE   (1U << 6)
 Coherent with other bus masters.
 

Functions

int pbl_mpu_region_add (const struct pbl_mpu_region *region)
 Add a static region, for every thread and until reset.
 
void pbl_mpu_user_ro_write (void *dst, const void *src, size_t n)
 Write to the PBL_MPU_P_RW_U_RO region from privileged code.
 
bool pbl_mpu_region_is_stack_guard (uintptr_t start, uintptr_t end)
 Check whether a stack guard covers any of a memory range.
 
const struct pbl_mpu_region * pbl_mpu_region_firmware (void)
 Get the memory of the running firmware image, to check pointers against.
 
bool pbl_mpu_region_contains (const struct pbl_mpu_region *region, const void *ptr)
 Check whether a region contains an address.
 
bool pbl_mpu_region_contains_buffer (const struct pbl_mpu_region *region, const void *buf, size_t length)
 Check whether a region contains a whole buffer.
 
bool pbl_mpu_region_contains_cstring (const struct pbl_mpu_region *region, const char *str, size_t max_length)
 Check whether a region contains a whole NUL-terminated string.
 
void pbl_mpu_regions_print (void(*print)(void *ctx, const char *line), void *ctx)
 Print every programmed region, one line at a time.
 

Variables

const struct pbl_mpu_region pbl_soc_mpu_regions []
 Regions the SoC declares, with CONFIG_SOC_HAS_MPU_REGIONS.
 
const size_t pbl_soc_num_mpu_regions
 Number of entries in pbl_soc_mpu_regions.
 

Detailed Description

Memory protection regions.

A region describes a range of memory: who may access it and what kind of memory it is. The kernel owns the protection hardware, so callers never see its slots or register encodings.

Static regions apply to every thread and stay until reset. Thread regions are switched in with a thread, see pbl_thread_attr::regions.

Privileged code can access anything no region covers, through the default memory map. Unprivileged code can only access what a region grants. Static regions must not overlap.

static const struct pbl_mpu_region s_banks = {
.name = "banks",
.base = BANKS_BASE,
.size = BANKS_SIZE,
};
#define PBL_ASSERTN(expr)
Panic if an expression is false.
Definition assert.h:42
const char * name
Name shown by pbl_mpu_regions_print(); optional.
Definition mpu.h:93
Memory region.
Definition mpu.h:91
int pbl_mpu_region_add(const struct pbl_mpu_region *region)
Add a static region, for every thread and until reset.
#define PBL_MPU_P_RO_U_RO
Privileged and unprivileged read-only.
Definition mpu.h:65
#define PBL_MPU_NORMAL_WT
Normal memory, write-through cached.
Definition mpu.h:72

Data Structure Documentation

◆ pbl_mpu_region

struct pbl_mpu_region

Memory region.

The base and size must be multiples of 32 bytes. Not every range can be protected on every architecture: ARMv7-M needs it to line up with eighths of a power-of-two block.

Data Fields
uint32_t attr Access, memory type and flags: PBL_MPU_*.
uintptr_t base Lowest address.
const char * name Name shown by pbl_mpu_regions_print(); optional.
size_t size Size in bytes.

Macro Definition Documentation

◆ KERNEL_READONLY_DATA

#define KERNEL_READONLY_DATA   PBL_SECTION(".kernel_unpriv_ro_bss")

Places a variable where unprivileged code can read it but not write to it.

◆ KERNEL_READONLY_DATA_SET

#define KERNEL_READONLY_DATA_SET (   var,
  val 
)
Value:
do { \
typeof(var) val_ = (val); \
pbl_mpu_user_ro_write(&(var), &val_, sizeof(val_)); \
} while (0)

Assign a KERNEL_READONLY_DATA variable.

Privileged code only.

Parameters
varVariable.
valValue.

◆ PBL_MPU_ACCESS_MSK

#define PBL_MPU_ACCESS_MSK   7U

Mask of the access attribute.

◆ PBL_MPU_DEVICE

#define PBL_MPU_DEVICE   (3U << 3)

Device memory: accesses are not merged, reordered or cached.

◆ PBL_MPU_EXEC

#define PBL_MPU_EXEC   (1U << 5)

Instructions may be fetched from the region.

◆ PBL_MPU_NO_ACCESS

#define PBL_MPU_NO_ACCESS   0U

No access.

Below a stack, this makes a guard.

◆ PBL_MPU_NORMAL_NC

#define PBL_MPU_NORMAL_NC   (0U << 3)

Normal memory, not cached.

◆ PBL_MPU_NORMAL_WB

#define PBL_MPU_NORMAL_WB   (2U << 3)

Normal memory, write-back cached.

◆ PBL_MPU_NORMAL_WT

#define PBL_MPU_NORMAL_WT   (1U << 3)

Normal memory, write-through cached.

◆ PBL_MPU_P_RO

#define PBL_MPU_P_RO   4U

Privileged read-only, no unprivileged access.

◆ PBL_MPU_P_RO_U_RO

#define PBL_MPU_P_RO_U_RO   5U

Privileged and unprivileged read-only.

◆ PBL_MPU_P_RW

#define PBL_MPU_P_RW   1U

Privileged read/write, no unprivileged access.

◆ PBL_MPU_P_RW_U_RO

#define PBL_MPU_P_RW_U_RO   2U

Privileged read/write, unprivileged read-only.

◆ PBL_MPU_P_RW_U_RW

#define PBL_MPU_P_RW_U_RW   3U

Privileged and unprivileged read/write.

◆ PBL_MPU_SHAREABLE

#define PBL_MPU_SHAREABLE   (1U << 6)

Coherent with other bus masters.

Some cores do not cache shareable memory at all.

◆ PBL_MPU_TYPE_MSK

#define PBL_MPU_TYPE_MSK   (3U << 3)

Mask of the memory type attribute.

Function Documentation

◆ pbl_mpu_region_add()

int pbl_mpu_region_add ( const struct pbl_mpu_region *  region)

Add a static region, for every thread and until reset.

Parameters
regionRegion to add, which must stay valid.
Returns
0 on success.
Return values
-ENOSPCNo slot is left.
-EINVALThe region overlaps another static region.

◆ pbl_mpu_region_contains()

bool pbl_mpu_region_contains ( const struct pbl_mpu_region *  region,
const void *  ptr 
)

Check whether a region contains an address.

Parameters
regionRegion.
ptrAddress.
Returns
true if ptr is inside region.

◆ pbl_mpu_region_contains_buffer()

bool pbl_mpu_region_contains_buffer ( const struct pbl_mpu_region *  region,
const void *  buf,
size_t  length 
)

Check whether a region contains a whole buffer.

Parameters
regionRegion.
bufBuffer.
lengthBuffer size in bytes.
Returns
true if all of buf is inside region.

◆ pbl_mpu_region_contains_cstring()

bool pbl_mpu_region_contains_cstring ( const struct pbl_mpu_region *  region,
const char *  str,
size_t  max_length 
)

Check whether a region contains a whole NUL-terminated string.

Never reads outside of the region.

Parameters
regionRegion.
strString.
max_lengthLongest accepted string, without the terminator.
Returns
true if str and its terminator are inside region.

◆ pbl_mpu_region_firmware()

const struct pbl_mpu_region * pbl_mpu_region_firmware ( void  )

Get the memory of the running firmware image, to check pointers against.

Not always what the MPU protects: an architecture may have to round its region up.

Returns
Firmware image region.

◆ pbl_mpu_region_is_stack_guard()

bool pbl_mpu_region_is_stack_guard ( uintptr_t  start,
uintptr_t  end 
)

Check whether a stack guard covers any of a memory range.

Usable from fault handlers.

Parameters
startLowest address of the range.
endEnd of the range, exclusive.
Returns
true if the range overlaps the ISR stack guard or one of the running thread.

◆ pbl_mpu_regions_print()

void pbl_mpu_regions_print ( void(*)(void *ctx, const char *line)  print,
void *  ctx 
)

Print every programmed region, one line at a time.

Usable from fault handlers.

Parameters
printCalled with each line.
ctxPassed to print.

◆ pbl_mpu_user_ro_write()

void pbl_mpu_user_ro_write ( void *  dst,
const void *  src,
size_t  n 
)

Write to the PBL_MPU_P_RW_U_RO region from privileged code.

ARMv8-M cannot let only privileged code write to a region, so the region is lifted for the duration of the copy, with interrupts masked. Elsewhere this is a plain copy.

Parameters
dstDestination.
srcSource.
nNumber of bytes.

Variable Documentation

◆ pbl_soc_mpu_regions

const struct pbl_mpu_region pbl_soc_mpu_regions[]
extern

Regions the SoC declares, with CONFIG_SOC_HAS_MPU_REGIONS.

The kernel adds them first thing on boot, before pbl_soc_early_init().

◆ pbl_soc_num_mpu_regions

const size_t pbl_soc_num_mpu_regions
extern

Number of entries in pbl_soc_mpu_regions.