summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordzwdz2022-07-16 21:03:40 +0200
committerdzwdz2022-07-16 21:03:40 +0200
commitc8ed6aa7476b7f506366d9fe56ed6f2e7a12b40d (patch)
treeeac26e380be691734d767bb1238e30751e0351e2 /src
parentb26098268eb443f1ed3dc50d902b2beee40c8342 (diff)
amd64: init can print to the terminal now
Diffstat (limited to 'src')
-rw-r--r--src/kernel/arch/amd64/debug.c2
-rw-r--r--src/kernel/arch/amd64/interrupts/isr.c22
-rw-r--r--src/kernel/arch/amd64/pagedir.c117
-rw-r--r--src/kernel/arch/amd64/sysenter.c7
-rw-r--r--src/kernel/arch/amd64/sysenter.h2
-rw-r--r--src/kernel/main.c9
-rw-r--r--src/kernel/proc.c2
-rw-r--r--src/kernel/syscalls.c1
-rw-r--r--src/user/app/main.c2
9 files changed, 79 insertions, 85 deletions
diff --git a/src/kernel/arch/amd64/debug.c b/src/kernel/arch/amd64/debug.c
index 52127da..c17c906 100644
--- a/src/kernel/arch/amd64/debug.c
+++ b/src/kernel/arch/amd64/debug.c
@@ -2,7 +2,7 @@
void *debug_caller(size_t depth) {
void **rbp;
- asm("mov %%rbp, %0"
+ asm("mov %%rbp, %0"
: "=r" (rbp));
while (depth--) {
if (!rbp) return NULL;
diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c
index b55bc8b..4df8e57 100644
--- a/src/kernel/arch/amd64/interrupts/isr.c
+++ b/src/kernel/arch/amd64/interrupts/isr.c
@@ -14,17 +14,17 @@ bool isr_test_interrupt_called = false;
void isr_stage3(int interrupt, uint64_t *stackframe) {
if (interrupt == 0xe) stackframe++;
kprintf("interrupt %x, rip = k/%08x, cs 0x%x\n", interrupt, stackframe[0], stackframe[1]);
+ if (interrupt == 0xe) {
+ uint64_t addr = 0x69;
+ asm("mov %%cr2, %0" : "=r"(addr));
+ kprintf("error code 0x%x, addr 0x%x\n", stackframe[-1], addr);
+ }
+
switch (interrupt) {
case 0x08: // double fault
kprintf("#DF");
panic_invalid_state();
- case 0xe:
- uint64_t addr = 0x69;
- asm("mov %%cr2, %0" : "=r"(addr));
- kprintf("error code 0x%x, addr 0x%x\n", stackframe[-1], addr);
- panic_unimplemented();
-
case 0x34:
asm("nop" ::: "memory");
isr_test_interrupt_called = true;
@@ -41,8 +41,12 @@ void isr_stage3(int interrupt, uint64_t *stackframe) {
return;
default:
- // TODO check if the exception was in the kernel
- process_kill(process_current, interrupt);
- process_switch_any();
+ if (stackframe[1] & 0x3 == 0) {
+ kprintf("bye o7\n");
+ cpu_halt();
+ } else {
+ process_kill(process_current, interrupt);
+ process_switch_any();
+ }
}
}
diff --git a/src/kernel/arch/amd64/pagedir.c b/src/kernel/arch/amd64/pagedir.c
index 56c541a..0d6078b 100644
--- a/src/kernel/arch/amd64/pagedir.c
+++ b/src/kernel/arch/amd64/pagedir.c
@@ -94,19 +94,28 @@ void pagedir_free(struct pagedir *dir) {
*/
}
-/*
-static struct pagetable_entry*
+static pe_generic_t*
get_entry(struct pagedir *dir, const void __user *virt) {
- uint32_t pd_idx = ((uintptr_t)virt) >> 22;
- uint32_t pt_idx = ((uintptr_t)virt) >> 12 & 0x03FF;
- struct pagetable_entry *pagetable;
+ pe_generic_t *pml4e, *pdpte, *pde, *pte;
+ const union virt_addr v = {.full = (void*)virt};
+
+ // TODO check if sign extension is valid
+
+ pml4e = &dir->e[v.pml4];
+ if (!pml4e->present) return NULL;
+ assert(!pml4e->large);
+
+ pdpte = &((pe_generic_t*)addr_extract(*pml4e))[v.pdpt];
+ if (!pdpte->present) return NULL;
+ assert(!pdpte->large);
- if (!dir->e[pd_idx].present) return NULL;
+ pde = &((pe_generic_t*)addr_extract(*pdpte))[v.pd];
+ if (!pde->present) return NULL;
+ assert(!pde->large);
- pagetable = (void*)(dir->e[pd_idx].address << 11);
- return &pagetable[pt_idx];
+ pte = &((pe_generic_t*)addr_extract(*pde))[v.pt];
+ return pte;
}
-*/
void *pagedir_unmap(struct pagedir *dir, void __user *virt) {
(void)dir; (void)virt;
@@ -129,7 +138,6 @@ void pagedir_map(struct pagedir *dir, void __user *virt, void *phys,
pml4e = &dir->e[v.pml4];
if (!pml4e->present) {
- kprintf("allocating pdpt\n");
pml4e->as_ptr = addr_validate(page_zalloc(1));
pml4e->present = 1;
pml4e->writeable = 1;
@@ -139,7 +147,6 @@ void pagedir_map(struct pagedir *dir, void __user *virt, void *phys,
pdpte = &((pe_generic_t*)addr_extract(*pml4e))[v.pdpt];
if (!pdpte->present) {
- kprintf("allocating pd\n");
pdpte->as_ptr = addr_validate(page_zalloc(1));
pdpte->present = 1;
pdpte->writeable = 1;
@@ -149,7 +156,6 @@ void pagedir_map(struct pagedir *dir, void __user *virt, void *phys,
pde = &((pe_generic_t*)addr_extract(*pdpte))[v.pd];
if (!pde->present) {
- kprintf("allocating pt\n");
pde->as_ptr = addr_validate(page_zalloc(1));
pde->present = 1;
pde->writeable = 1;
@@ -174,68 +180,67 @@ void pagedir_switch(struct pagedir *dir) {
}
// creates a new pagedir with exact copies of the user pages
-struct pagedir *pagedir_copy(const struct pagedir *orig) {
- /*
- struct pagedir *clone = page_alloc(1);
- struct pagetable_entry *orig_pt, *clone_pt;
- void *orig_page, *clone_page;
-
- for (int i = 0; i < 1024; i++) {
- clone->e[i] = orig->e[i];
- if (!orig->e[i].present) continue;
-
- orig_pt = (void*)(orig->e[i].address << 11);
- clone_pt = page_alloc(1);
- clone->e[i].address = (uintptr_t) clone_pt >> 11;
-
- for (int j = 0; j < 1024; j++) {
- clone_pt[j] = orig_pt[j];
- if (!orig_pt[j].present) continue;
- if (!orig_pt[j].user) continue;
- // i could use .global?
-
- orig_page = (void*)(orig_pt[j].address << 11);
- clone_page = page_alloc(1);
- clone_pt[j].address = (uintptr_t) clone_page >> 11;
-
- memcpy(clone_page, orig_page, PAGE_SIZE);
+struct pagedir *pagedir_copy(const struct pagedir *pml4_old) {
+ struct pagedir *pml4_new = page_zalloc(1);
+
+ for (int i = 0; i < 512; i++) {
+ if (!pml4_old->e[i].present) continue;
+ assert(!pml4_old->e[i].large);
+ const pe_generic_t *pdpt_old = addr_extract(pml4_old->e[i]);
+ pe_generic_t *pdpt_new = page_zalloc(1);
+ pml4_new->e[i] = pml4_old->e[i];
+ pml4_new->e[i].address = (uintptr_t) pdpt_new >> 12;
+
+ for (int j = 0; j < 512; j++) {
+ if (!pdpt_old[j].present) continue;
+ assert(!pdpt_old[j].large);
+ const pe_generic_t *pd_old = addr_extract(pdpt_old[j]);
+ pe_generic_t *pd_new = page_zalloc(1);
+ pdpt_new[j] = pdpt_old[j];
+ pdpt_new[j].address = (uintptr_t) pd_new >> 12;
+
+ for (int k = 0; k < 512; k++) {
+ if (!pd_old[k].present) continue;
+ assert(!pd_old[k].large);
+ const pe_generic_t *pt_old = addr_extract(pd_old[k]);
+ pe_generic_t *pt_new = page_zalloc(1);
+ pd_new[k] = pd_old[k];
+ pd_new[k].address = (uintptr_t) pt_new >> 12;
+
+ for (int l = 0; l < 512; l++) {
+ if (!pt_old[l].present || !pt_old[l].user)
+ continue;
+ void *page_new = page_alloc(1);
+ memcpy(page_new, addr_extract(pt_old[l]), PAGE_SIZE);
+ pt_new[l] = pt_old[l];
+ pt_new[l].address = (uintptr_t) page_new >> 12;
+ }
+ }
}
}
- return clone;
- */
- panic_unimplemented();
+ return pml4_new;
}
bool pagedir_iskern(struct pagedir *dir, const void __user *virt) {
- /*
- struct pagetable_entry *page = get_entry(dir, virt);
+ pe_generic_t *page = get_entry(dir, virt);
return page && page->present && !page->user;
- */
- panic_unimplemented();
}
void *pagedir_virt2phys(struct pagedir *dir, const void __user *virt,
bool user, bool writeable)
{
- /*
- struct pagetable_entry *page;
- uintptr_t phys;
- page = get_entry(dir, virt);
+ pe_generic_t *page = get_entry(dir, virt);
if (!page || !page->present) return NULL;
if (user && !page->user) return NULL;
if (writeable && !page->writeable) return NULL;
- phys = page->address << 11;
- phys |= ((uintptr_t)virt) & 0xFFF;
- return (void*)phys;
- */
- panic_unimplemented();
+ return addr_extract(*page) + ((uintptr_t)virt & PAGE_MASK);
}
void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t len) {
- /*
- struct pagetable_entry *page;
+ // TODO dogshit slow
+ pe_generic_t *page;
char __user *iter;
start = (userptr_t)(((uintptr_t __force)start + PAGE_MASK) & ~PAGE_MASK); // round up to next page
iter = start;
@@ -251,6 +256,4 @@ void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t le
iter += PAGE_SIZE;
}
return NULL;
- */
- panic_unimplemented();
}
diff --git a/src/kernel/arch/amd64/sysenter.c b/src/kernel/arch/amd64/sysenter.c
index 543e5bc..7591d83 100644
--- a/src/kernel/arch/amd64/sysenter.c
+++ b/src/kernel/arch/amd64/sysenter.c
@@ -5,19 +5,14 @@
struct registers _sysexit_regs;
-void sysexit(struct registers regs) {
+_Noreturn void sysexit(struct registers regs) {
_sysexit_regs = regs;
- kprintf("ring3...\n");
_sysexit_real();
- __builtin_unreachable();
}
_Noreturn void sysenter_stage2(void) {
struct registers *regs = &process_current->regs;
*regs = _sysexit_regs;
-
- kprintf("ring0!\n");
-
_syscall(regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8);
process_switch_any();
}
diff --git a/src/kernel/arch/amd64/sysenter.h b/src/kernel/arch/amd64/sysenter.h
index b88c186..d1274de 100644
--- a/src/kernel/arch/amd64/sysenter.h
+++ b/src/kernel/arch/amd64/sysenter.h
@@ -5,4 +5,4 @@ extern struct registers _sysexit_regs;
_Noreturn void sysenter_stage2(void);
// sysenter.s
-void _sysexit_real(void);
+_Noreturn void _sysexit_real(void);
diff --git a/src/kernel/main.c b/src/kernel/main.c
index bbdd234..75d9a29 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -18,14 +18,7 @@ void kmain(struct kmain_info info) {
}
void shutdown(void) {
- size_t states[PS_LAST] = {0};
- for (struct process *p = process_first; p; p = process_next(p))
- states[p->state]++;
-
- kprintf("\n\n\nshutting off\n");
- for (size_t i = 0; i < sizeof(states) / sizeof(*states); i++)
- kprintf("state 0x%x: 0x%x\n", i, states[i]);
-
+ kprintf("shutting off\n");
mem_debugprint();
cpu_shutdown();
}
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index a202549..4719a93 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -23,10 +23,8 @@ struct process *process_seed(struct kmain_info *info) {
process_first->id = next_pid++;
// map the stack to the last page in memory
- kprintf("0x%x\n", (userptr_t)~PAGE_MASK);
pagedir_map(process_first->pages, (userptr_t)~PAGE_MASK, page_zalloc(1), true, true);
process_first->regs.rsp = (userptr_t) ~0xF;
- kprintf("post stack\n");
// map .shared
extern char _shared_len;
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 293edae..1d18ad1 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -368,7 +368,6 @@ void _syscall_debug_klog(const void __user *buf, size_t len) {
}
int _syscall(int num, int a, int b, int c, int d) {
- kprintf("%x %x %x %x %x\n", num, a, b, c, d);
switch (num) {
case _SYSCALL_EXIT:
_syscall_exit(a);
diff --git a/src/user/app/main.c b/src/user/app/main.c
index 92aa56c..527d29f 100644
--- a/src/user/app/main.c
+++ b/src/user/app/main.c
@@ -23,6 +23,8 @@ int main(void) {
file_reopen(stdout, "/com1", 0);
printf("preinit\n");
+ _syscall_exit(0); // temporary
+
/* move everything provided by the kernel to /kdev */
MOUNT("/kdev/", fs_passthru(NULL));
if (!fork2_n_mount("/")) {