Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion hal/aarch64/pmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ static void _pmap_cacheOpAfterChange(descr_t newEntry, ptr_t vaddr, unsigned int


/* Function creates empty page table */
int pmap_create(pmap_t *pmap, pmap_t *kpmap, page_t *p, void *vaddr)
int pmap_create(pmap_t *pmap, pmap_t *kpmap, page_t *p, const syspage_prog_t *prog, void *vaddr)
{
pmap->ttl1 = vaddr;
pmap->addr = p->addr;
Expand Down
2 changes: 1 addition & 1 deletion hal/armv7a/pmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ static void _pmap_asidDealloc(pmap_t *pmap)


/* Function creates empty page table */
int pmap_create(pmap_t *pmap, pmap_t *kpmap, page_t *p, void *vaddr)
int pmap_create(pmap_t *pmap, pmap_t *kpmap, page_t *p, const syspage_prog_t *prog, void *vaddr)
{
pmap->pdir = vaddr;
pmap->addr = p->addr;
Expand Down
3 changes: 2 additions & 1 deletion hal/armv7m/arch/pmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define _PH_HAL_PMAP_ARMV7M_H_

#include "hal/types.h"
#include "syspage.h"

/* Architecture dependent page attributes - used for mapping */
#define PGHD_PRESENT 0x01U
Expand Down Expand Up @@ -55,7 +56,7 @@ typedef struct _page_t {
typedef struct _pmap_t {
void *start;
void *end;
u32 regions;
const hal_syspage_part_t *hal;
} pmap_t;

#endif
Expand Down
155 changes: 63 additions & 92 deletions hal/armv7m/pmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@
#include "config.h"
#include "syspage.h"
#include "halsyspage.h"
#include "lib/lib.h"
#include <arch/cpu.h>
#include <arch/spinlock.h>


#define MPU_BASE ((volatile u32 *)0xe000ed90U)


/* clang-format off */
enum { mpu_type, mpu_ctrl, mpu_rnr, mpu_rbar, mpu_rasr, mpu_rbar_a1, mpu_rasr_a1, mpu_rbar_a2, mpu_rasr_a2,
mpu_rbar_a3, mpu_rasr_a3 };
Expand All @@ -36,15 +41,20 @@ extern void *_init_vectors;

static struct {
volatile u32 *mpu;
unsigned int kernelCodeRegion;
spinlock_t lock;
unsigned int lastMPUCount;
} pmap_common;


/* Function creates empty page table */
int pmap_create(pmap_t *pmap, pmap_t *kpmap, page_t *p, void *vaddr)
int pmap_create(pmap_t *pmap, pmap_t *kpmap, page_t *p, const syspage_prog_t *prog, void *vaddr)
{
pmap->regions = pmap_common.kernelCodeRegion;
if (prog != NULL) {
pmap->hal = &prog->partition->hal;
}
else {
pmap->hal = NULL;
}
return 0;
}

Expand All @@ -55,55 +65,42 @@ addr_t pmap_destroy(pmap_t *pmap, unsigned int *i)
}


static unsigned int pmap_map2region(unsigned int map)
/* parasoft-suppress-next-line MISRAC2012-DIR_4_3-a "Optimized context switching code" */
void pmap_switch(pmap_t *pmap)
{
const volatile u32 *RBAR_ADDR = MPU_BASE + mpu_rbar;
unsigned int allocCnt;
spinlock_ctx_t sc;
unsigned int i;
unsigned int mask = 0;

for (i = 0; i < sizeof(syspage->hs.mpu.map) / sizeof(*syspage->hs.mpu.map); ++i) {
if (map == syspage->hs.mpu.map[i]) {
mask |= (1UL << i);
}
}

return mask;
}

const u32 *tableCurrent;

int pmap_addMap(pmap_t *pmap, unsigned int map)
{
unsigned int rmask = pmap_map2region(map);
if (rmask == 0U) {
return -1;
}
if ((pmap != NULL) && (pmap->hal != NULL)) {
hal_spinlockSet(&pmap_common.lock, &sc);

pmap->regions |= rmask;
allocCnt = pmap->hal->mpu.allocCnt;
tableCurrent = &pmap->hal->mpu.table[0].rbar;

return 0;
}
/* Disable MPU */
hal_cpuDataMemoryBarrier();
*(pmap_common.mpu + mpu_ctrl) &= ~1U;

for (i = 0; i < max(allocCnt, pmap_common.lastMPUCount); i += 4U) {
/* region number update is done by writes to RBAR */
__asm__ volatile(
"ldmia %[tableCurrent]!, {r3-r8, r10, r11} \n\t" /* Load 4 regions (rbar/rasr pairs) from table, update table pointer */
"stmia %[mpu_rbar], {r3-r8, r10, r11} \n\t" /* Write 4 regions via RBAR/RASR and aliases */
: [tableCurrent] "+&r"(tableCurrent)
: [mpu_rbar] "r"(RBAR_ADDR)
: "r3", "r4", "r5", "r6", "r7", "r8", "r10", "r11");
}

/* Enable MPU */
*(pmap_common.mpu + mpu_ctrl) |= 1U;
hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();

void pmap_switch(pmap_t *pmap)
{
unsigned int i, cnt = syspage->hs.mpu.allocCnt;
spinlock_ctx_t sc;
pmap_common.lastMPUCount = allocCnt;

if (pmap != NULL) {
hal_spinlockSet(&pmap_common.lock, &sc);
for (i = 0; i < cnt; ++i) {
/* Select region */
*(pmap_common.mpu + mpu_rnr) = i;
hal_cpuDataMemoryBarrier();

/* Enable/disable region according to the mask */
if ((pmap->regions & (1UL << i)) != 0U) {
*(pmap_common.mpu + mpu_rasr) |= 1U;
}
else {
*(pmap_common.mpu + mpu_rasr) &= ~1U;
}
hal_cpuDataMemoryBarrier();
}
hal_spinlockClear(&pmap_common.lock, &sc);
}
}
Expand All @@ -129,14 +126,23 @@ addr_t pmap_resolve(pmap_t *pmap, void *vaddr)

int pmap_isAllowed(pmap_t *pmap, const void *vaddr, size_t size)
{
unsigned int i;
const syspage_map_t *map = syspage_mapAddrResolve((addr_t)vaddr);
unsigned int rmask;
if (map == NULL) {
return 0;
}
rmask = pmap_map2region(map->id);

return ((pmap->regions & rmask) == 0U) ? 0 : 1;
if (pmap->hal == NULL) {
/* Kernel pmap has access to everything */
return 1;
}

for (i = 0; i < pmap->hal->mpu.allocCnt; ++i) {
if (pmap->hal->mpu.map[i] == map->id) {
return 1;
}
}
return 0;
}


Expand Down Expand Up @@ -175,11 +181,8 @@ int pmap_segment(unsigned int i, void **vaddr, size_t *size, vm_prot_t *prot, vo
/* parasoft-suppress-next-line MISRAC2012-DIR_4_3 "Assembly is required for low-level operations" */
void _pmap_init(pmap_t *pmap, void **vstart, void **vend)
{
const syspage_map_t *ikmap;
unsigned int ikregion;
u32 t;
addr_t pc;
unsigned int i, cnt = syspage->hs.mpu.allocCnt;
unsigned int cnt = (syspage->hs.mpuType >> 8U) & 0xffU;
unsigned int i;

(*vstart) = (void *)(((ptr_t)_init_vectors + 7U) & ~7U);
(*vend) = (*((char **)vstart)) + SIZE_PAGE;
Expand All @@ -189,8 +192,11 @@ void _pmap_init(pmap_t *pmap, void **vstart, void **vend)
/* Initial size of kernel map */
pmap->end = (void *)((addr_t)&__bss_start + 32U * 1024U);

pmap->hal = NULL;
pmap_common.lastMPUCount = cnt;

/* Configure MPU */
pmap_common.mpu = (void *)0xe000ed90U;
pmap_common.mpu = MPU_BASE;

/* Disable MPU just in case */
*(pmap_common.mpu + mpu_ctrl) &= ~1U;
Expand All @@ -201,52 +207,17 @@ void _pmap_init(pmap_t *pmap, void **vstart, void **vend)
hal_cpuDataMemoryBarrier();

for (i = 0; i < cnt; ++i) {
t = syspage->hs.mpu.table[i].rbar;
if ((t & (1UL << 4)) == 0U) {
continue;
}

*(pmap_common.mpu + mpu_rbar) = t;
hal_cpuDataMemoryBarrier();
/* Select region */
*(pmap_common.mpu + mpu_rnr) = i;

/* Disable regions for now */
t = syspage->hs.mpu.table[i].rasr & ~1U;
*(pmap_common.mpu + mpu_rasr) = t;
/* Disable all regions for now */
*(pmap_common.mpu + mpu_rasr) = 0U;
hal_cpuDataMemoryBarrier();
}

/* Enable MPU */
*(pmap_common.mpu + mpu_ctrl) |= 1U;
hal_cpuDataMemoryBarrier();

/* FIXME HACK
* allow all programs to execute (and read) kernel code map.
* Needed because of hal_jmp, syscalls handler and signals handler.
* In these functions we need to switch to the user mode when still
* executing kernel code. This will cause memory management fault
* if the application does not have access to the kernel instruction
* map. Possible fix - place return to the user code in the separate
* region and allow this region instead. */

/* Find kernel code region */
__asm__ volatile("\tmov %0, pc;" : "=r"(pc));
ikmap = syspage_mapAddrResolve(pc);
if (ikmap == NULL) {
hal_consolePrint(ATTR_BOLD, "pmap: Kernel code map not found. Bad system config\n");
for (;;) {
hal_cpuHalt();
}
}

ikregion = pmap_map2region(ikmap->id);
if (ikregion == 0U) {
hal_consolePrint(ATTR_BOLD, "pmap: Kernel code map has no assigned region. Bad system config\n");
for (;;) {
hal_cpuHalt();
}
}

pmap_common.kernelCodeRegion = ikregion;

hal_spinlockCreate(&pmap_common.lock, "pmap");
}
3 changes: 2 additions & 1 deletion hal/armv7r/arch/pmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define _PH_HAL_PMAP_ARMV7R_H_

#include "hal/types.h"
#include "syspage.h"

#define PGHD_PRESENT 0x01U
#define PGHD_USER 0x04U
Expand Down Expand Up @@ -54,7 +55,7 @@ typedef struct _page_t {
typedef struct _pmap_t {
void *start;
void *end;
u32 regions;
const hal_syspage_part_t *hal;
} pmap_t;

#endif
Expand Down
Loading
Loading