94 lines
2.5 KiB
C
94 lines
2.5 KiB
C
|
#include "include/pmap.h"
|
||
|
#include <machine/metalp.h>
|
||
|
#include <machine/paging.h>
|
||
|
#include <machine/pmap.h>
|
||
|
#include <machine/mrt.h>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
// page table for boot
|
||
|
static struct vmpt boot_pt;
|
||
|
#define BOOT_PD_NUM (4)
|
||
|
static struct vmpd boot_pd[BOOT_PD_NUM];
|
||
|
static struct vmpd boot_dev_pd[BOOT_PD_NUM];
|
||
|
|
||
|
void
|
||
|
vm_insert_pd(struct vmpt * pt, struct vmpd * pd, unsigned int pgshift, paddr_t paddr)
|
||
|
{
|
||
|
const uint64_t pfn = vm_get_pfn(pd->vaddr, pgshift);
|
||
|
int hash = vm_vahash(pfn);
|
||
|
struct vmpte * vmpte = &pt->entries[hash];
|
||
|
pd->next = vmpte->first;
|
||
|
vmpte->first = paddr;
|
||
|
}
|
||
|
|
||
|
void paging_init()
|
||
|
{
|
||
|
int ret;
|
||
|
memset(&boot_pd, 0, sizeof(boot_pd));
|
||
|
memset(&boot_pt, 0, sizeof(boot_pt));
|
||
|
|
||
|
// ident map the first 4GB
|
||
|
paddr_t cur = 0;
|
||
|
for (int i = 0; i < BOOT_PD_NUM; i++) {
|
||
|
boot_pd[i].attr = VMPD_ATTR_P | VMPD_ATTR_AO_KRW;
|
||
|
boot_pd[i].paddr = cur;
|
||
|
boot_pd[i].vaddr = MEM_DIRECTMAP_BASE + cur;
|
||
|
cur += (1 << REGION_DMAP_PGSHIFT);
|
||
|
|
||
|
vm_insert_pd(&boot_pt, &boot_pd[i], REGION_DMAP_PGSHIFT, (paddr_t)DMVA2PA(&boot_pd[i]));
|
||
|
}
|
||
|
|
||
|
// ident map the first 4GB to device memory space
|
||
|
cur = 0;
|
||
|
for (int i = 0; i < BOOT_PD_NUM; i++) {
|
||
|
boot_dev_pd[i].attr = VMPD_ATTR_P | VMPD_ATTR_DEV | VMPD_ATTR_AO_KRW;
|
||
|
boot_dev_pd[i].paddr = cur;
|
||
|
boot_dev_pd[i].vaddr = MEM_DIRECTMAP_DEV_BASE + cur;
|
||
|
cur += (1 << REGION_DMAP_PGSHIFT);
|
||
|
|
||
|
vm_insert_pd(&boot_pt, &boot_dev_pd[i], REGION_DMAP_PGSHIFT, (paddr_t)DMVA2PA(&boot_dev_pd[i]));
|
||
|
}
|
||
|
|
||
|
// set page table base
|
||
|
paddr_t ptb = (paddr_t)DMVA2PA(&boot_pt);
|
||
|
int idx = MRT_SET_MPTB_DMAP;
|
||
|
METAL_MROUTINE_SETARG(MRT_SET_MPTB_ARG_IDX, idx);
|
||
|
METAL_MROUTINE_SETARG(MRT_SET_MPTB_ARG_PTB, ptb);
|
||
|
METAL_MENTER(MRT_SET_MPTB_IDX);
|
||
|
METAL_MROUTINE_GETRET(MRT_SET_MPTB_RET_STATUS, ret);
|
||
|
if (ret != 0) {
|
||
|
hlt();
|
||
|
}
|
||
|
|
||
|
// set page table attribute override bits
|
||
|
uint64_t mtp = MTP_KERNEL;
|
||
|
METAL_MROUTINE_SETARG(MRT_SET_MTP_ARG_MTP, mtp);
|
||
|
METAL_MENTER(MRT_SET_MTP_IDX);
|
||
|
|
||
|
// // set MAIR
|
||
|
// #define MAIR_VAL ((0b11111111) | (0b00000000 << 8))
|
||
|
// // 0 = b11111111 = Normal, Inner/Outer WB/WA/RA
|
||
|
// // 1 = b00000000 = Device-nGnRnE
|
||
|
// __asm__ volatile (
|
||
|
// "ldr x0, =(" METAL_STR(MAIR_VAL) ");"
|
||
|
// "msr mair_el1, x0;"
|
||
|
// :
|
||
|
// :
|
||
|
// : "x0"
|
||
|
// );
|
||
|
|
||
|
|
||
|
// reset page tables
|
||
|
uint64_t zero = 0;
|
||
|
__asm__ volatile (
|
||
|
"msr ttbr0_el1, %x0;"
|
||
|
"msr ttbr1_el1, %x0;"
|
||
|
"TLBI VMALLE1;"
|
||
|
:
|
||
|
: "r" (zero)
|
||
|
:
|
||
|
);
|
||
|
}
|