add pte _protect, _switch, _map impl, with partial _unprotect

This commit is contained in:
Yanyan Jiang 2018-08-08 06:12:32 +00:00
parent a5048b3fa3
commit 7fc31929fd
3 changed files with 81 additions and 46 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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) {