diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/arch/i386/gdt/gdt.c | 5 | ||||
-rw-r--r-- | src/kernel/arch/i386/interrupts/idt.c | 2 | ||||
-rw-r--r-- | src/kernel/arch/i386/interrupts/isr_stub.s | 31 | ||||
-rw-r--r-- | src/kernel/arch/i386/multiboot.s | 11 | ||||
-rw-r--r-- | src/kernel/arch/i386/sysenter.s | 51 | ||||
-rw-r--r-- | src/kernel/linker.ld | 10 | ||||
-rw-r--r-- | src/kernel/proc.c | 7 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 10 |
8 files changed, 76 insertions, 51 deletions
diff --git a/src/kernel/arch/i386/gdt/gdt.c b/src/kernel/arch/i386/gdt/gdt.c index 56df995..f016caa 100644 --- a/src/kernel/arch/i386/gdt/gdt.c +++ b/src/kernel/arch/i386/gdt/gdt.c @@ -4,6 +4,7 @@ #include <stdbool.h> #include <stdint.h> +extern char _isr_stack_top; struct gdt_entry { uint64_t limit_low : 16; @@ -37,7 +38,9 @@ struct lgdt_arg { uint32_t base; } __attribute__((packed)); +__attribute__((section(".text.early"))) static struct gdt_entry GDT[SEG_end]; +__attribute__((section(".text.early"))) static struct tss_entry TSS; static struct lgdt_arg lgdt_arg; // probably doesn't need to be global @@ -80,7 +83,7 @@ static void gdt_prepare(void) { // tss memset(&TSS, 0, sizeof(TSS)); TSS.ss0 = SEG_r0data << 3; // kernel data segment - TSS.esp0 = (uintptr_t) &_bss_end; + TSS.esp0 = (uintptr_t) &_isr_stack_top; GDT[SEG_TSS] = (struct gdt_entry) { .limit_low = sizeof(TSS), diff --git a/src/kernel/arch/i386/interrupts/idt.c b/src/kernel/arch/i386/interrupts/idt.c index d27bc61..d295d84 100644 --- a/src/kernel/arch/i386/interrupts/idt.c +++ b/src/kernel/arch/i386/interrupts/idt.c @@ -23,7 +23,7 @@ struct lidt_arg { uint32_t base; } __attribute__((packed)); - +__attribute__((section(".text.early"))) static struct idt_entry IDT[256]; static struct lidt_arg lidt_arg; diff --git a/src/kernel/arch/i386/interrupts/isr_stub.s b/src/kernel/arch/i386/interrupts/isr_stub.s index 8efb1b7..9a903f6 100644 --- a/src/kernel/arch/i386/interrupts/isr_stub.s +++ b/src/kernel/arch/i386/interrupts/isr_stub.s @@ -1,4 +1,4 @@ -.section .text +.section .text.early .global _isr_stubs _isr_stubs: @@ -9,25 +9,34 @@ _isr_stubs: .endr _isr_stage2: - cld + cli // convert the return address into the vector nr pop %eax add $-_isr_stubs, %eax shr $3, %eax - // disable paging, if present - // it's done here so the stuff on the stack is in the right order - mov %cr0, %ebx - push %ebx - and $0x7FFFFFFF, %ebx - mov %ebx, %cr0 + // disable paging, if present + mov %cr0, %ebx + push %ebx // push original cr0 + and $0x7FFFFFFF, %ebx + mov %ebx, %cr0 - push %eax // push the vector nr + mov %esp, %ebp + mov $_bss_end, %esp // switch to kernel stack + push %eax // push the vector nr call isr_stage3 - add $4, %esp // "pop" the vector nr - pop %eax // restore old cr0 + + mov %ebp, %esp // switch back to isr_stack + pop %eax // restore old cr0 mov %eax, %cr0 popal iret + +.align 8 +_ist_stack_btm: +// TODO overflow check +.skip 64 // seems to be enough +.global _isr_stack_top +_isr_stack_top: diff --git a/src/kernel/arch/i386/multiboot.s b/src/kernel/arch/i386/multiboot.s index 62bc9fd..dc19b36 100644 --- a/src/kernel/arch/i386/multiboot.s +++ b/src/kernel/arch/i386/multiboot.s @@ -1,9 +1,7 @@ .set MAGIC, 0x1BADB002 -/* 1<<0 - align modules on page boundaries. - 1<<1 - fill the mem_ fields in multiboot_info - 1<<16 - enable manual addressing */ -.set FLAGS, 1<<0 | 1<<16 +/* 1<<0 - align modules on page boundaries. */ +.set FLAGS, 1<<0 .set CHECKSUM, -(MAGIC + FLAGS) .section .multiboot @@ -12,8 +10,3 @@ multiboot_header: .long MAGIC .long FLAGS .long CHECKSUM - .long multiboot_header // header_addr - .long multiboot_header // load_addr - .long _data_end // load_end_addr - .long _bss_end // bss_end_addr - .long _start // entry_addr diff --git a/src/kernel/arch/i386/sysenter.s b/src/kernel/arch/i386/sysenter.s index ade69ec..70e9f13 100644 --- a/src/kernel/arch/i386/sysenter.s +++ b/src/kernel/arch/i386/sysenter.s @@ -8,26 +8,6 @@ .set IA32_SYSENTER_EIP, 0x176 .section .text -.global _sysexit_real -.type _sysexit_real, @function -_sysexit_real: - mov $(SEG_r3data << 3 | 3), %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - - // enable paging - mov %cr0, %eax - or $0x80000000, %eax - mov %eax, %cr0 - - // restore the registers - mov $_sysexit_regs, %esp - popal - sysexit - - .global sysenter_setup .type sysenter_setup, @function sysenter_setup: @@ -38,7 +18,7 @@ sysenter_setup: wrmsr mov $IA32_SYSENTER_ESP, %ecx - mov $_bss_end, %eax + mov $0, %eax // unused wrmsr mov $IA32_SYSENTER_EIP, %ecx @@ -47,6 +27,35 @@ sysenter_setup: ret + +.section .text.early + +.global stored_eax +stored_eax: +.long 0 + +.global _sysexit_real +.type _sysexit_real, @function +_sysexit_real: + mov $(SEG_r3data << 3 | 3), %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + // restore the registers + mov $_sysexit_regs, %esp + popal + + // enable paging + mov %eax, stored_eax + mov %cr0, %eax + or $0x80000000, %eax + mov %eax, %cr0 + mov stored_eax, %eax + + sysexit + sysenter_stage1: cli /* prevent random IRQs in the middle of kernel code */ diff --git a/src/kernel/linker.ld b/src/kernel/linker.ld index 274abc3..84945b1 100644 --- a/src/kernel/linker.ld +++ b/src/kernel/linker.ld @@ -2,10 +2,18 @@ ENTRY(_start) SECTIONS { + . = 0; + .text.early BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text.early) + _text_early_len = .; + } + . = 1M; .text BLOCK(4K) : ALIGN(4K) { - *(.multiboot) + _kern_start = .; *(.text) } .rodata BLOCK(4K) : ALIGN(4K) diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 2b96c8f..636c237 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -26,10 +26,9 @@ struct process *process_seed(struct kmain_info *info) { pagedir_map(process_first->pages, (userptr_t)~PAGE_MASK, page_alloc(1), true, true); process_first->regs.esp = (userptr_t) ~0xF; - // map the kernel - // yup, .text is writeable too. the plan is to not map the kernel - // into user memory at all, but i'll implement that later. TODO - for (size_t p = 0x100000; p < (size_t)&_bss_end; p += PAGE_SIZE) + // map .text.early + extern char _text_early_len; + for (size_t p = 0; p < (size_t)&_text_early_len; p += PAGE_SIZE) pagedir_map(process_first->pages, (userptr_t)p, (void*)p, false, true); // map the init module as rw diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index af70e4e..4d64d32 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -253,6 +253,7 @@ int _syscall_fs_respond(char __user *buf, int ret) { int _syscall_memflag(void __user *addr, size_t len, int flags) { userptr_t goal = addr + len; struct pagedir *pages = process_current->pages; + void *phys; addr = (userptr_t)((int __force)addr & ~PAGE_MASK); // align to page boundary for (; addr < goal; addr += PAGE_SIZE) { @@ -261,13 +262,16 @@ int _syscall_memflag(void __user *addr, size_t len, int flags) { continue; } + phys = pagedir_virt2phys(pages, addr, false, false); + if (!(flags & MEMFLAG_PRESENT)) { - page_free(pagedir_unmap(pages, addr), 1); + if (phys) + page_free(pagedir_unmap(pages, addr), 1); continue; } - if (!pagedir_virt2phys(pages, addr, false, false)) { - void *phys = page_alloc(1); + if (!phys) { + phys = page_alloc(1); memset(phys, 0, PAGE_SIZE); // TODO somehow test this pagedir_map(pages, addr, phys, true, true); } |