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 @@ -265,7 +265,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 @@ -175,7 +175,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 0x01
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_prog_t *hal;
} pmap_t;

#endif
Expand Down
153 changes: 61 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 *)0xe000ed90)


/* 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 @@ -35,13 +40,19 @@ static struct {
volatile u32 *mpu;
unsigned int kernelCodeRegion;
spinlock_t lock;
int last_mpu_count;
} 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->hal;
}
else {
pmap->hal = NULL;
}
return 0;
}

Expand All @@ -52,55 +63,40 @@ addr_t pmap_destroy(pmap_t *pmap, int *i)
}


static unsigned int pmap_map2region(unsigned int map)
void pmap_switch(pmap_t *pmap)
{
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 |= (1 << i);
}
}

return mask;
}

static const volatile u32 *RBAR_ADDR = MPU_BASE + mpu_rbar;
unsigned int allocCnt;
spinlock_ctx_t sc;
unsigned int i;
const u32 *tableCurrent;

int pmap_addMap(pmap_t *pmap, unsigned int map)
{
unsigned int rmask = pmap_map2region(map);
if (rmask == 0) {
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) &= ~1;

for (i = 0; i < max(allocCnt, pmap_common.last_mpu_count); i += 4) {
/* RNR 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) |= 1;
hal_cpuDataSyncBarrier();

void pmap_switch(pmap_t *pmap)
{
unsigned int i, cnt = syspage->hs.mpu.allocCnt;
spinlock_ctx_t sc;
pmap_common.last_mpu_count = 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 & (1 << i)) != 0) {
*(pmap_common.mpu + mpu_rasr) |= 1;
}
else {
*(pmap_common.mpu + mpu_rasr) &= ~1;
}
hal_cpuDataMemoryBarrier();
}
hal_spinlockClear(&pmap_common.lock, &sc);
}
}
Expand All @@ -127,13 +123,21 @@ addr_t pmap_resolve(pmap_t *pmap, void *vaddr)
int pmap_isAllowed(pmap_t *pmap, const void *vaddr, size_t size)
{
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) == 0) ? 0 : 1;
if (pmap->hal == NULL) {
/* Kernel pmap has access to everything */
return 1;
}

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


Expand Down Expand Up @@ -170,11 +174,8 @@ int pmap_segment(unsigned int i, void **vaddr, size_t *size, vm_prot_t *prot, vo

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 + 7) & ~7);
(*vend) = (*((char **)vstart)) + SIZE_PAGE;
Expand All @@ -184,8 +185,11 @@ void _pmap_init(pmap_t *pmap, void **vstart, void **vend)
/* Initial size of kernel map */
pmap->end = (void *)((addr_t)&__bss_start + 32 * 1024);

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

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

/* Disable MPU just in case */
*(pmap_common.mpu + mpu_ctrl) &= ~1;
Expand All @@ -196,52 +200,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 & (1 << 4)) == 0) {
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 & ~1;
*(pmap_common.mpu + mpu_rasr) = t;
/* Disable all regions for now */
*(pmap_common.mpu + mpu_rasr) = 0;
hal_cpuDataMemoryBarrier();
}

/* Enable MPU */
*(pmap_common.mpu + mpu_ctrl) |= 1;
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 == 0) {
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_prog_t *hal;
} pmap_t;

#endif
Expand Down
Loading
Loading