summaryrefslogtreecommitdiff
path: root/src/kernel/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/arch')
-rw-r--r--src/kernel/arch/i386/gdt/gdt.c5
-rw-r--r--src/kernel/arch/i386/interrupts/idt.c2
-rw-r--r--src/kernel/arch/i386/interrupts/isr_stub.s31
-rw-r--r--src/kernel/arch/i386/multiboot.s11
-rw-r--r--src/kernel/arch/i386/sysenter.s51
5 files changed, 57 insertions, 43 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 */