summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authordzwdz2022-07-16 22:50:34 +0200
committerdzwdz2022-07-16 22:50:34 +0200
commita251c14f1a745f3388ce73a5a45ebc73cd1782b5 (patch)
tree2eab140ce2bcc729d8836e97a61bd0d731bb44d6 /src/kernel
parentc8ed6aa7476b7f506366d9fe56ed6f2e7a12b40d (diff)
amd64: back at the shell!
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/arch/amd64/32/boot.s1
-rw-r--r--src/kernel/arch/amd64/32/gdt.c8
-rw-r--r--src/kernel/arch/amd64/boot.c6
-rw-r--r--src/kernel/arch/amd64/driver/fsroot.c2
-rw-r--r--src/kernel/arch/amd64/interrupts/isr.c19
-rw-r--r--src/kernel/arch/amd64/pagedir.c45
-rw-r--r--src/kernel/arch/amd64/sysenter.s11
-rw-r--r--src/kernel/proc.c4
-rw-r--r--src/kernel/syscalls.c30
-rw-r--r--src/kernel/vfs/request.c2
-rw-r--r--src/kernel/vfs/request.h6
11 files changed, 69 insertions, 65 deletions
diff --git a/src/kernel/arch/amd64/32/boot.s b/src/kernel/arch/amd64/32/boot.s
index 06de66e..af32007 100644
--- a/src/kernel/arch/amd64/32/boot.s
+++ b/src/kernel/arch/amd64/32/boot.s
@@ -80,6 +80,7 @@ cpu_halt:
.global cpu_pause
.type cpu_pause, @function
cpu_pause:
+ xchgw %bx, %bx
sti
hlt
cli
diff --git a/src/kernel/arch/amd64/32/gdt.c b/src/kernel/arch/amd64/32/gdt.c
index 2229330..d3d4aed 100644
--- a/src/kernel/arch/amd64/32/gdt.c
+++ b/src/kernel/arch/amd64/32/gdt.c
@@ -87,15 +87,15 @@ void gdt_init(void) {
gdt_fillout(&GDT[SEG_r3data], 3, false);
lgdt_arg.limit = sizeof(GDT) - 1;
- lgdt_arg.base = (uint64_t) &GDT;
+ lgdt_arg.base = (uint64_t)(int)&GDT;
memset32(&TSS, 0, sizeof(TSS));
for (int i = 0; i < 3; i++)
- TSS.rsp[i] = (uint64_t) &_isr_mini_stack;
- TSS.ist[1] = (uint64_t) &_isr_mini_stack;
+ TSS.rsp[i] = (uint64_t)(int)&_isr_mini_stack;
+ TSS.ist[1] = (uint64_t)(int)&_isr_mini_stack;
- uint64_t tss_addr = (uint64_t) &TSS;
+ uint64_t tss_addr = (uint64_t)(int)&TSS;
GDT[SEG_TSS] = (struct gdt_entry) {
.limit_low = sizeof(TSS),
.limit_high = sizeof(TSS) >> 16,
diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c
index 0e61ed3..56cf8c8 100644
--- a/src/kernel/arch/amd64/boot.c
+++ b/src/kernel/arch/amd64/boot.c
@@ -15,13 +15,13 @@
static void find_init(struct multiboot_info *multiboot, struct kmain_info *info)
{
- struct multiboot_mod *module = (void*)multiboot->mods;
+ struct multiboot_mod *module = (void*)(long)multiboot->mods;
kprintf("mods count 0x%x", multiboot->mods_count);
if (multiboot->mods_count < 1) {
kprintf("can't find init! ");
panic_invalid_state();
}
- info->init.at = module->start;
+ info->init.at = (void*)(long)module->start;
info->init.size = module->end - module->start;
}
@@ -34,7 +34,7 @@ void kmain_early(struct multiboot_info *multiboot) {
kprintf("irq...");
irq_init();
- info.memtop = (void*) (multiboot->mem_upper * 1024);
+ info.memtop = (void*)(long)(multiboot->mem_upper * 1024);
find_init(multiboot, &info);
kprintf("mem...\n");
mem_init(&info);
diff --git a/src/kernel/arch/amd64/driver/fsroot.c b/src/kernel/arch/amd64/driver/fsroot.c
index 02a4a21..e651c47 100644
--- a/src/kernel/arch/amd64/driver/fsroot.c
+++ b/src/kernel/arch/amd64/driver/fsroot.c
@@ -45,7 +45,7 @@ static void req_preprocess(struct vfs_request *req, size_t max_len) {
static int handle(struct vfs_request *req) {
assert(req->caller);
- int id = (int)req->id;
+ int id = (int)(long)req->id;
switch (req->type) {
case VFSOP_OPEN:
if (exacteq(req, "/")) return HANDLE_ROOT;
diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c
index 4df8e57..bd560f5 100644
--- a/src/kernel/arch/amd64/interrupts/isr.c
+++ b/src/kernel/arch/amd64/interrupts/isr.c
@@ -11,20 +11,19 @@
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]);
+static void log_interrupt(int interrupt, uint64_t *stackframe) {
+ kprintf("interrupt %x, rip = k/%08x, cs 0x%x, code 0x%x\n",
+ interrupt, stackframe[0], stackframe[1], 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);
+ kprintf("addr 0x%x\n", addr);
}
+}
+void isr_stage3(int interrupt, uint64_t *stackframe) {
+ if (interrupt == 0xe || interrupt == 0xd) stackframe++;
switch (interrupt) {
- case 0x08: // double fault
- kprintf("#DF");
- panic_invalid_state();
-
case 0x34:
asm("nop" ::: "memory");
isr_test_interrupt_called = true;
@@ -41,8 +40,8 @@ void isr_stage3(int interrupt, uint64_t *stackframe) {
return;
default:
- if (stackframe[1] & 0x3 == 0) {
- kprintf("bye o7\n");
+ if ((stackframe[1] & 0x3) == 0) {
+ log_interrupt(interrupt, stackframe);
cpu_halt();
} else {
process_kill(process_current, interrupt);
diff --git a/src/kernel/arch/amd64/pagedir.c b/src/kernel/arch/amd64/pagedir.c
index 0d6078b..2075aac 100644
--- a/src/kernel/arch/amd64/pagedir.c
+++ b/src/kernel/arch/amd64/pagedir.c
@@ -69,35 +69,39 @@ struct pagedir *pagedir_new(void) {
}
void pagedir_free(struct pagedir *dir) {
- (void)dir;
- panic_unimplemented();
- /*
- // assumes all user pages are unique and can be freed
- struct pagetable_entry *pt;
- void *page;
-
- for (int i = 0; i < 1024; i++) {
+ for (int i = 0; i < 512; i++) {
if (!dir->e[i].present) continue;
+ assert(!dir->e[i].large);
+ pe_generic_t *pdpt = addr_extract(dir->e[i]);
- pt = (void*)(dir->e[i].address << 11);
+ for (int j = 0; j < 512; j++) {
+ if (!pdpt[j].present) continue;
+ assert(!pdpt[j].large);
+ pe_generic_t *pd = addr_extract(pdpt[j]);
- for (int j = 0; j < 1024; j++) {
- if (!pt[j].present) continue;
- if (!pt[j].user) continue;
+ for (int k = 0; k < 512; k++) {
+ if (!pd[k].present) continue;
+ assert(!pd[k].large);
+ pe_generic_t *pt = addr_extract(pd[k]);
- page = (void*)(pt[j].address << 11);
- page_free(page, 1);
+ for (int l = 0; l < 512; l++) {
+ if (!pt[l].present) continue;
+ if (!pt[l].user) continue;
+ page_free(addr_extract(pt[l]), 1);
+ }
+ page_free(pt, 1);
+ }
+ page_free(pd, 1);
}
- page_free(pt, 1);
+ page_free(pdpt, 1);
}
page_free(dir, 1);
- */
}
static pe_generic_t*
get_entry(struct pagedir *dir, const void __user *virt) {
pe_generic_t *pml4e, *pdpte, *pde, *pte;
- const union virt_addr v = {.full = (void*)virt};
+ const union virt_addr v = {.full = (void __user *)virt};
// TODO check if sign extension is valid
@@ -208,11 +212,12 @@ struct pagedir *pagedir_copy(const struct pagedir *pml4_old) {
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;
+ if (!pt_old[l].present) continue;
+ pt_new[l] = pt_old[l];
+
+ if (!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;
}
}
diff --git a/src/kernel/arch/amd64/sysenter.s b/src/kernel/arch/amd64/sysenter.s
index 74db018..3f035dc 100644
--- a/src/kernel/arch/amd64/sysenter.s
+++ b/src/kernel/arch/amd64/sysenter.s
@@ -12,15 +12,16 @@
.global sysenter_setup
.type sysenter_setup, @function
sysenter_setup:
- xor %rdx, %rdx
// the intel docs don't mention the lower 32 bits
- mov $( ((SEG_r3code << 3 | 3) << 48) | ((SEG_r0code << 3) << 32) ), %rax
+ mov $0, %eax
+ mov $( ((SEG_r3code << 3 | 3) << 16) | (SEG_r0code << 3) ), %edx
mov $IA32_STAR, %rcx
wrmsr
+ mov $sysenter_stage1, %eax
+ mov $0, %edx
mov $IA32_LSTAR, %rcx
- mov $sysenter_stage1, %rax
wrmsr
// hoping that the default RFLAGS mask is fine...
@@ -50,8 +51,6 @@ _sysexit_real:
mov %ax, %gs
*/
- xchgw %bx, %bx
-
mov $_sysexit_regs, %rsp
pop %r15
pop %r14
@@ -77,12 +76,10 @@ _sysexit_real:
mov (pagedir_current), %rsp
mov %rsp, %cr3
mov (stored_rsp), %rsp
- nop
sysretq
sysenter_stage1:
cli
- xchgw %bx, %bx
mov %rsp, (stored_rsp)
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index 4719a93..cfc4b5e 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -36,7 +36,9 @@ struct process *process_seed(struct kmain_info *info) {
for (uintptr_t off = 0; off < info->init.size; off += PAGE_SIZE)
pagedir_map(process_first->pages, init_base + off, info->init.at + off,
true, true);
- process_first->regs.rcx = init_base; // SYSRET jumps to %rcx
+ process_first->regs.rcx = (uintptr_t)init_base; // SYSRET jumps to %rcx
+
+ process_first->pages = pagedir_copy(process_first->pages); // TODO remove this
return process_first;
}
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 1d18ad1..c5e12b4 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -11,18 +11,18 @@
#include <stdint.h>
#define SYSCALL_RETURN(val) do { \
- uint32_t ret = (uint32_t)val; \
+ long ret = (long)val; \
assert(process_current->state == PS_RUNNING); \
regs_savereturn(&process_current->regs, ret); \
return 0; \
} while (0)
-_Noreturn void _syscall_exit(int ret) {
+_Noreturn void _syscall_exit(long ret) {
process_kill(process_current, ret);
process_switch_any();
}
-int _syscall_await(void) {
+long _syscall_await(void) {
bool has_children = false;
process_transition(process_current, PS_WAITS4CHILDDEATH);
@@ -43,7 +43,7 @@ int _syscall_await(void) {
return -1; // dummy
}
-int _syscall_fork(int flags, handle_t __user *fs_front) {
+long _syscall_fork(int flags, handle_t __user *fs_front) {
struct process *child;
handle_t front;
@@ -82,7 +82,7 @@ int _syscall_fork(int flags, handle_t __user *fs_front) {
SYSCALL_RETURN(1);
}
-handle_t _syscall_open(const char __user *path, int len, int flags) {
+handle_t _syscall_open(const char __user *path, long len, int flags) {
struct vfs_mount *mount;
char *path_buf = NULL;
@@ -125,7 +125,7 @@ fail:
SYSCALL_RETURN(-1);
}
-int _syscall_mount(handle_t hid, const char __user *path, int len) {
+long _syscall_mount(handle_t hid, const char __user *path, long len) {
struct vfs_mount *mount = NULL;
struct vfs_backend *backend = NULL;
char *path_buf = NULL;
@@ -200,7 +200,7 @@ handle_t _syscall_dup(handle_t from, handle_t to, int flags) {
SYSCALL_RETURN(to);
}
-int _syscall_read(handle_t handle_num, void __user *buf, size_t len, int offset) {
+long _syscall_read(handle_t handle_num, void __user *buf, size_t len, long offset) {
struct handle *h = process_handle_get(process_current, handle_num);
if (!h) SYSCALL_RETURN(-1);
switch (h->type) {
@@ -229,7 +229,7 @@ int _syscall_read(handle_t handle_num, void __user *buf, size_t len, int offset)
return -1; // dummy
}
-int _syscall_write(handle_t handle_num, const void __user *buf, size_t len, int offset) {
+long _syscall_write(handle_t handle_num, const void __user *buf, size_t len, long offset) {
struct handle *h = process_handle_get(process_current, handle_num);
if (!h) SYSCALL_RETURN(-1);
switch (h->type) {
@@ -258,7 +258,7 @@ int _syscall_write(handle_t handle_num, const void __user *buf, size_t len, int
return -1; // dummy
}
-int _syscall_close(handle_t hid) {
+long _syscall_close(handle_t hid) {
if (hid < 0 || hid >= HANDLE_MAX) return -1;
struct handle **h = &process_current->handles[hid];
if (!*h) SYSCALL_RETURN(-1);
@@ -267,7 +267,7 @@ int _syscall_close(handle_t hid) {
SYSCALL_RETURN(0);
}
-int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res) {
+long _syscall_fs_wait(char __user *buf, long max_len, struct fs_wait_response __user *res) {
struct vfs_backend *backend = process_current->controlled;
if (!backend) SYSCALL_RETURN(-1);
@@ -284,7 +284,7 @@ int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __us
return -1; // dummy
}
-int _syscall_fs_respond(void __user *buf, int ret, int flags) {
+long _syscall_fs_respond(void __user *buf, long ret, int flags) {
struct vfs_request *req = process_current->handled_req;
if (!req) SYSCALL_RETURN(-1);
@@ -306,7 +306,7 @@ int _syscall_fs_respond(void __user *buf, int ret, int flags) {
void __user *_syscall_memflag(void __user *addr, size_t len, int flags) {
struct pagedir *pages = process_current->pages;
void *phys;
- addr = (userptr_t)((int __force)addr & ~PAGE_MASK); // align to page boundary
+ addr = (userptr_t)((uintptr_t __force)addr & ~PAGE_MASK); // align to page boundary
if (flags & MEMFLAG_FINDFREE) {
addr = pagedir_findfree(pages, addr, len);
@@ -321,7 +321,7 @@ void __user *_syscall_memflag(void __user *addr, size_t len, int flags) {
continue;
}
- phys = pagedir_virt2phys(pages, iter, false, false);
+ phys = pagedir_virt2phys(pages, iter, false, false);
if (!(flags & MEMFLAG_PRESENT)) {
if (phys)
@@ -338,7 +338,7 @@ void __user *_syscall_memflag(void __user *addr, size_t len, int flags) {
SYSCALL_RETURN((uintptr_t)addr);
}
-int _syscall_pipe(handle_t __user user_ends[2], int flags) {
+long _syscall_pipe(handle_t __user user_ends[2], int flags) {
if (flags) SYSCALL_RETURN(-1);
handle_t ends[2];
struct handle *rend, *wend;
@@ -367,7 +367,7 @@ void _syscall_debug_klog(const void __user *buf, size_t len) {
// kprintf("[klog] %x\t%s\n", process_current->id, kbuf);
}
-int _syscall(int num, int a, int b, int c, int d) {
+long _syscall(long num, long a, long b, long c, long d) {
switch (num) {
case _SYSCALL_EXIT:
_syscall_exit(a);
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index 97c71a7..87d6208 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -29,7 +29,7 @@ void vfsreq_create(struct vfs_request req_) {
vfs_backend_tryaccept(req->backend);
}
-void vfsreq_finish(struct vfs_request *req, char __user *stored, int ret,
+void vfsreq_finish(struct vfs_request *req, char __user *stored, long ret,
int flags, struct process *handler)
{
if (req->type == VFSOP_OPEN && ret >= 0) {
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index fc1ef08..4201d44 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -48,7 +48,7 @@ struct vfs_request {
} output;
void __user *id; // handle.file.id
- int offset;
+ long offset;
int flags;
struct process *caller;
@@ -62,9 +62,9 @@ struct vfs_request {
/** Assigns the vfs_request to the caller, and dispatches the call */
void vfsreq_create(struct vfs_request);
-void vfsreq_finish(struct vfs_request*, char __user *stored, int ret, int flags, struct process *handler);
+void vfsreq_finish(struct vfs_request*, char __user *stored, long ret, int flags, struct process *handler);
-static inline void vfsreq_finish_short(struct vfs_request *req, int ret) {
+static inline void vfsreq_finish_short(struct vfs_request *req, long ret) {
vfsreq_finish(req, (void __user *)ret, ret, 0, NULL);
}