add pte _protect, _switch, _map impl, with partial _unprotect
This commit is contained in:
parent
a5048b3fa3
commit
7fc31929fd
1
am/am.h
1
am/am.h
|
@ -90,7 +90,6 @@ int _protect(_Protect *p);
|
|||
void _unprotect(_Protect *p);
|
||||
void _switch(_Protect *p);
|
||||
int _map(_Protect *p, void *va, void *pa, int prot);
|
||||
int _unmap(_Protect *p, void *va);
|
||||
_RegSet *_make_prot(_Protect *p, _Area ustack, _Area kstack,
|
||||
void (*entry)(void *), void *args);
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
static void *(*pgalloc_usr)(size_t);
|
||||
static void (*pgfree_usr)(void *);
|
||||
|
||||
static void *pgalloc(size_t size) {
|
||||
void *ret = pgalloc_usr(size);
|
||||
static void *pgalloc() {
|
||||
void *ret = pgalloc_usr(PGSIZE);
|
||||
if (!ret) _halt(34);
|
||||
for (int i = 0; i < PGSIZE / sizeof(uint32_t); i++) {
|
||||
((uint32_t *)ret)[i] = 0;
|
||||
|
@ -18,7 +18,6 @@ static void pgfree(void *ptr) {
|
|||
pgfree_usr(ptr);
|
||||
}
|
||||
|
||||
// must be called atomically per-cpu
|
||||
|
||||
static intptr_t first_proc = 1;
|
||||
static PDE *kpt;
|
||||
|
@ -32,6 +31,7 @@ static _Area segments[] = {
|
|||
{.start = (void*)0xf0000000, .end = (void*)(0)}, // High memory: APIC and VGA
|
||||
};
|
||||
|
||||
// must be called atomically per-cpu
|
||||
int _pte_init(void * (*pgalloc_f)(size_t), void (*pgfree_f)(void *)) {
|
||||
pgalloc_usr = pgalloc_f;
|
||||
pgfree_usr = pgfree_f;
|
||||
|
@ -39,58 +39,67 @@ int _pte_init(void * (*pgalloc_f)(size_t), void (*pgfree_f)(void *)) {
|
|||
if (first_proc) {
|
||||
// first processor, create kernel page table
|
||||
|
||||
kpt = pgalloc(PGSIZE);
|
||||
|
||||
kpt = pgalloc();
|
||||
for (int i = 0; i < sizeof(segments) / sizeof(segments[0]); i++) {
|
||||
_Area *area = &segments[i];
|
||||
for (uint32_t pa = (uint32_t)area->start; pa != (uint32_t)area->end; pa += PGSIZE) {
|
||||
// TODO: map @kpt: @pa (v) -> @pa (p)
|
||||
_Area *seg = &segments[i];
|
||||
for (uint32_t pa = (uint32_t)seg->start; pa != (uint32_t)seg->end; pa += PGSIZE) {
|
||||
PTE *ptab;
|
||||
if (!(kpt[PDX(pa)] & PTE_P)) {
|
||||
ptab = pgalloc();
|
||||
kpt[PDX(pa)] = PTE_P | PTE_W | (uint32_t)ptab;
|
||||
} else {
|
||||
ptab = (PTE*)PTE_ADDR(kpt[PDX(pa)]);
|
||||
}
|
||||
ptab[PTX(pa)] = PTE_P | PTE_W | pa;
|
||||
}
|
||||
}
|
||||
|
||||
set_cr3(kpt);
|
||||
set_cr0(get_cr0() | CR0_PG);
|
||||
_atomic_xchg(&first_proc, 0);
|
||||
}
|
||||
pgfree(NULL); // TODO: for bypass warnings
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _protect(_Protect *p) {
|
||||
p->pgsize = PGSIZE;
|
||||
p->area = prot_vm_range;
|
||||
p->ptr = NULL; // TODO: create a new one
|
||||
PDE *upt = pgalloc();
|
||||
for (int i = 0; i < PGSIZE / sizeof(PDE *); i++) {
|
||||
upt[i] = kpt[i];
|
||||
}
|
||||
p->ptr = upt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _unprotect(_Protect *p) {
|
||||
PDE *upt = p->ptr;
|
||||
// TODO: free up all spaces
|
||||
pgfree(upt);
|
||||
}
|
||||
|
||||
void _switch(_Protect *p) {
|
||||
set_cr3(p->ptr);
|
||||
}
|
||||
|
||||
int _map(_Protect *p, void *va, void *pa, int prot) {
|
||||
PDE *pt = (PDE*)p->ptr;
|
||||
PDE *pde = &pt[PDX(va)];
|
||||
|
||||
if (!(*pde & PTE_P)) {
|
||||
*pde = PTE_P | PTE_W | PTE_U | (uint32_t)(pgalloc());
|
||||
}
|
||||
|
||||
PTE *pte = &((PTE*)PTE_ADDR(*pde))[PTX(va)];
|
||||
if (prot & _PROT_NONE) {
|
||||
*pte = 0;
|
||||
} else {
|
||||
*pte = PTE_P | ((prot & _PROT_WRITE) ? PTE_W : 0) | PTE_U | (uint32_t)(pa);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
#define PG_ALIGN __attribute((aligned(PGSIZE)))
|
||||
|
||||
PDE kpdir[NR_PDE] PG_ALIGN;
|
||||
PDE kptab[NR_PDE * NR_PTE] PG_ALIGN;
|
||||
void* (*palloc_f)(size_t);
|
||||
void (*pfree_f)(void*);
|
||||
|
||||
int _pte_init(void* (*palloc)(size_t), void (*pfree)(void*)) {
|
||||
palloc_f = palloc;
|
||||
pfree_f = pfree;
|
||||
PDE *alloc = kptab;
|
||||
for (int i = 0; i < sizeof(segments) / sizeof(segments[0]); i++) {
|
||||
_Area *seg = &segments[i];
|
||||
PTE *ptab = NULL;
|
||||
for (uint32_t pa = (uint32_t)seg->start; pa != (uint32_t)seg->end; pa += PGSIZE) {
|
||||
if (!(kpdir[PDX(pa)] & PTE_P)) {
|
||||
ptab = alloc;
|
||||
alloc += NR_PDE;
|
||||
kpdir[PDX(pa)] = PTE_P | PTE_W | (uint32_t)ptab;
|
||||
}
|
||||
ptab[PTX(pa)] = PTE_P | PTE_W | pa;
|
||||
}
|
||||
}
|
||||
|
||||
set_cr3(kpdir);
|
||||
set_cr0(get_cr0() | CR0_PG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _protect(_Protect *p) {
|
||||
PDE *updir = (PDE*)(palloc_f(PGSIZE));
|
||||
p->pgsize = PGSIZE;
|
||||
|
|
|
@ -5,26 +5,53 @@
|
|||
int ntraps = 0;
|
||||
_RegSet* handler(_Event ev, _RegSet *regs) {
|
||||
switch (ev.event) {
|
||||
case _EVENT_IRQ_TIMER:
|
||||
break;
|
||||
case _EVENT_IRQ_IODEV:
|
||||
break;
|
||||
case _EVENT_YIELD:
|
||||
break;
|
||||
case _EVENT_IRQ_TIMER:
|
||||
case _EVENT_IRQ_IODEV:
|
||||
printf(".");
|
||||
break;
|
||||
case _EVENT_PAGEFAULT:
|
||||
printf("PF: %s%s%s\n",
|
||||
printf("PF: %x %s%s%s\n",
|
||||
ev.ref,
|
||||
(ev.cause & _PROT_NONE) ? "[not present]" : "",
|
||||
(ev.cause & _PROT_READ) ? "[read fail]" : "",
|
||||
(ev.cause & _PROT_WRITE) ? "[write fail]" : "");
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return regs;
|
||||
}
|
||||
|
||||
static uintptr_t st;
|
||||
|
||||
static void *alloc(size_t size) {
|
||||
while (st % size != 0) st++;
|
||||
void *ret = (void *)st;
|
||||
st += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void free(void *ptr) {
|
||||
}
|
||||
|
||||
_Protect prot;
|
||||
|
||||
int main(){
|
||||
st = (uintptr_t)_heap.start;
|
||||
_ioe_init();
|
||||
_asye_init(handler);
|
||||
_pte_init(NULL, NULL);
|
||||
_pte_init(alloc, free);
|
||||
|
||||
|
||||
_protect(&prot);
|
||||
_switch(&prot);
|
||||
|
||||
_map(&prot, (void*)0x40000000, alloc(4096), _PROT_WRITE);
|
||||
|
||||
volatile uint32_t *ptr = (uint32_t*)0x40000fff;
|
||||
*ptr = 1;
|
||||
|
||||
_intr_write(1);
|
||||
while (1) {
|
||||
|
|
Loading…
Reference in New Issue