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 _unprotect(_Protect *p);
|
||||||
void _switch(_Protect *p);
|
void _switch(_Protect *p);
|
||||||
int _map(_Protect *p, void *va, void *pa, int prot);
|
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,
|
_RegSet *_make_prot(_Protect *p, _Area ustack, _Area kstack,
|
||||||
void (*entry)(void *), void *args);
|
void (*entry)(void *), void *args);
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
static void *(*pgalloc_usr)(size_t);
|
static void *(*pgalloc_usr)(size_t);
|
||||||
static void (*pgfree_usr)(void *);
|
static void (*pgfree_usr)(void *);
|
||||||
|
|
||||||
static void *pgalloc(size_t size) {
|
static void *pgalloc() {
|
||||||
void *ret = pgalloc_usr(size);
|
void *ret = pgalloc_usr(PGSIZE);
|
||||||
if (!ret) _halt(34);
|
if (!ret) _halt(34);
|
||||||
for (int i = 0; i < PGSIZE / sizeof(uint32_t); i++) {
|
for (int i = 0; i < PGSIZE / sizeof(uint32_t); i++) {
|
||||||
((uint32_t *)ret)[i] = 0;
|
((uint32_t *)ret)[i] = 0;
|
||||||
|
@ -18,7 +18,6 @@ static void pgfree(void *ptr) {
|
||||||
pgfree_usr(ptr);
|
pgfree_usr(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be called atomically per-cpu
|
|
||||||
|
|
||||||
static intptr_t first_proc = 1;
|
static intptr_t first_proc = 1;
|
||||||
static PDE *kpt;
|
static PDE *kpt;
|
||||||
|
@ -32,6 +31,7 @@ static _Area segments[] = {
|
||||||
{.start = (void*)0xf0000000, .end = (void*)(0)}, // High memory: APIC and VGA
|
{.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 *)) {
|
int _pte_init(void * (*pgalloc_f)(size_t), void (*pgfree_f)(void *)) {
|
||||||
pgalloc_usr = pgalloc_f;
|
pgalloc_usr = pgalloc_f;
|
||||||
pgfree_usr = pgfree_f;
|
pgfree_usr = pgfree_f;
|
||||||
|
@ -39,58 +39,67 @@ int _pte_init(void * (*pgalloc_f)(size_t), void (*pgfree_f)(void *)) {
|
||||||
if (first_proc) {
|
if (first_proc) {
|
||||||
// first processor, create kernel page table
|
// first processor, create kernel page table
|
||||||
|
|
||||||
kpt = pgalloc(PGSIZE);
|
kpt = pgalloc();
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(segments) / sizeof(segments[0]); i++) {
|
for (int i = 0; i < sizeof(segments) / sizeof(segments[0]); i++) {
|
||||||
_Area *area = &segments[i];
|
_Area *seg = &segments[i];
|
||||||
for (uint32_t pa = (uint32_t)area->start; pa != (uint32_t)area->end; pa += PGSIZE) {
|
for (uint32_t pa = (uint32_t)seg->start; pa != (uint32_t)seg->end; pa += PGSIZE) {
|
||||||
// TODO: map @kpt: @pa (v) -> @pa (p)
|
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);
|
_atomic_xchg(&first_proc, 0);
|
||||||
}
|
}
|
||||||
pgfree(NULL); // TODO: for bypass warnings
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _protect(_Protect *p) {
|
int _protect(_Protect *p) {
|
||||||
p->pgsize = PGSIZE;
|
p->pgsize = PGSIZE;
|
||||||
p->area = prot_vm_range;
|
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;
|
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) {
|
int _protect(_Protect *p) {
|
||||||
PDE *updir = (PDE*)(palloc_f(PGSIZE));
|
PDE *updir = (PDE*)(palloc_f(PGSIZE));
|
||||||
p->pgsize = PGSIZE;
|
p->pgsize = PGSIZE;
|
||||||
|
|
|
@ -5,26 +5,53 @@
|
||||||
int ntraps = 0;
|
int ntraps = 0;
|
||||||
_RegSet* handler(_Event ev, _RegSet *regs) {
|
_RegSet* handler(_Event ev, _RegSet *regs) {
|
||||||
switch (ev.event) {
|
switch (ev.event) {
|
||||||
case _EVENT_IRQ_TIMER:
|
|
||||||
break;
|
|
||||||
case _EVENT_IRQ_IODEV:
|
|
||||||
break;
|
|
||||||
case _EVENT_YIELD:
|
case _EVENT_YIELD:
|
||||||
break;
|
break;
|
||||||
|
case _EVENT_IRQ_TIMER:
|
||||||
|
case _EVENT_IRQ_IODEV:
|
||||||
|
printf(".");
|
||||||
|
break;
|
||||||
case _EVENT_PAGEFAULT:
|
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_NONE) ? "[not present]" : "",
|
||||||
(ev.cause & _PROT_READ) ? "[read fail]" : "",
|
(ev.cause & _PROT_READ) ? "[read fail]" : "",
|
||||||
(ev.cause & _PROT_WRITE) ? "[write fail]" : "");
|
(ev.cause & _PROT_WRITE) ? "[write fail]" : "");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
return regs;
|
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(){
|
int main(){
|
||||||
|
st = (uintptr_t)_heap.start;
|
||||||
_ioe_init();
|
_ioe_init();
|
||||||
_asye_init(handler);
|
_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);
|
_intr_write(1);
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
Loading…
Reference in New Issue