summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-06-23 08:28:19 +1000
committerJake Mannens <jake72360@gmail.com>2018-06-23 08:28:19 +1000
commit2c429f6e1ac51ea27f203005eeef20d2b05c759e (patch)
tree5d9ba6851e87876a97a4780905a3248af165f33e
parentce9932308abed8000f9f6e06a61f726b29aa9e3a (diff)
Re-wrote interrupt handling. Now, flush_idt only initializes IDT entries
32-255. A separate routine in the new file traps.s initializes the first 32 entries with addresses pointing to exception handlers within said file. Modified the register_isr function to now accept a descriptor privilege level which it will assign to the modified IDT entry. Added a task state segment and corresponding entry to the GDT. The TSS will store the kernel's stack pointer and stack segment when switching to userspace. NOTE: The stack pointer MUST be saved manually before switching to userspace! Added the framework for a system call interface at interrupt vector 0x80 (128).
-rw-r--r--kernel/boot.s92
-rw-r--r--kernel/kmain.c4
-rw-r--r--kernel/syscall.c12
-rw-r--r--kernel/timer.s3
-rw-r--r--kernel/traps.s227
-rw-r--r--kernel/usrbin/usrbin.binbin76 -> 59 bytes
-rw-r--r--kernel/usrbin/usrbin.s26
-rw-r--r--kernel/usrspace.s7
8 files changed, 320 insertions, 51 deletions
diff --git a/kernel/boot.s b/kernel/boot.s
index 024abf0..bc42a5d 100644
--- a/kernel/boot.s
+++ b/kernel/boot.s
@@ -1,7 +1,12 @@
+global gdt
+global idt
global kboot
global register_isr
+global tss
extern kmain
+extern syscall_init
extern timer_init
+extern traps_init
; Multiboot header
section .mboothdr
@@ -15,15 +20,32 @@ section .text
kboot:
cli
+ ; put the stack pointer near the end of conventional memory
+ mov esp, 0x80000
+ ; setup descriptor tables
call flush_gdt
call flush_idt
- ;call timer_init
+ ; last minute setup, then transfer to kmain
+ call timer_init
call kmain
+ ; if kmain decides to return (which it shouldn't),
+ ; disable interrupts and halt the system.
cli
hlt
tss:
- times 104 db 0
+ dd 0
+ dd 0 ; kernel stack pointer
+ dd 0x10 ; kernel stack segment
+ times 60 db 0
+ dd 0x13 ; ES segment
+ dd 0x0B ; CS segment
+ dd 0x13 ; SS segment
+ dd 0x13 ; DS segment
+ dd 0x13 ; FS segment
+ dd 0x13 ; GS segment
+ times 8 db 0
+.end:
gdt:
; null descriptor
@@ -57,14 +79,31 @@ gdt:
db 0xCF
db 0x00
; task state segment
+.tss:
+ dq 0 ; we initialize this later
+.end:
gdtp:
- dw ($-gdt-1)
+ dw (gdt.end-gdt-1)
dd gdt
flush_gdt:
push ebp
mov ebp, esp
+ ; initialize the TSS entry
+ mov eax, tss
+ mov [gdt.tss+2], ax
+ shr eax, 16
+ mov [gdt.tss+4], al
+ mov [gdt.tss+7], ah
+ mov eax, (tss.end-tss-1)
+ mov [gdt.tss], ax
+ shr eax, 16
+ and al, 0x0F
+ mov [gdt.tss+6], al
+ mov al, 0xE9
+ mov [gdt.tss+5], al
+ ; now, load the GDT
lgdt [gdtp]
mov ax, 0x10
mov ds, ax
@@ -74,65 +113,72 @@ flush_gdt:
mov ss, ax
jmp 0x08:.end
.end:
+ ; initialize the task state register
+ mov ax, 0x002B
+ ltr ax
pop ebp
ret
idt:
times (256*8) db 0
+.end:
idtp:
- dw ($-idt-1)
+ dw (idt.end-idt-1)
dd idt
int_handler:
iret
-irq_handler:
- iret
-
flush_idt:
push ebp
mov ebp, esp
+ ; install the exception handlers (vectors 0-31)
+ call traps_init
+ ; install the default handlers (vectors 32-255)
mov ecx, 0
- mov edx, idt
+ lea edx, [idt+(32*8)]
.loop:
mov eax, int_handler
- cmp ecx, 0x20
- jl .skip
- cmp ecx, 0x2f
- jg .skip
- mov eax, irq_handler
-.skip:
mov [edx], ax
- mov word [edx+2], 0x08
- mov byte [edx+4], 0
- mov byte [edx+5], 0x8E
shr eax, 16
mov [edx+6], ax
- add edx, 8
+ mov word [edx+2], 0x08
+ mov byte [edx+4], 0x00
+ mov byte [edx+5], 0x8E
inc ecx
- cmp ecx, 256
+ cmp ecx, (256-32)
je .end
+ add edx, 8
jmp .loop
.end:
+ ; install the system call handler
+ call syscall_init
+ ; load the IDT, initialize the PIC's, and enable interrupts
lidt [idtp]
call pic_init
sti
pop ebp
ret
-; void register_isr(uint8_t n, void *handler);
+; void register_isr(uint8_t n, uint8_t dpl, void *handler);
register_isr:
push ebp
mov ebp, esp
mov edx, [ebp+8]
shl edx, 3
add edx, idt
- mov eax, [ebp+12]
+ mov eax, [ebp+16]
mov [edx], ax
- add edx, 6
shr eax, 16
- mov [edx], ax
+ mov [edx+6], ax
+ mov eax, [ebp+12]
+ and al, 3
+ shl al, 5
+ mov cl, [edx+5]
+ and cl, 0x9F
+ or cl, al
+ mov [edx+5], cl
pop ebp
ret
diff --git a/kernel/kmain.c b/kernel/kmain.c
index 81fe741..bf6b9ae 100644
--- a/kernel/kmain.c
+++ b/kernel/kmain.c
@@ -10,8 +10,8 @@ extern void userspace_init(void);
void kmain(void) {
con_init();
- printf("Kernel booting...\n\n");
- printf("\nKernel booted!\n");
+ printf("Kernel booting...\n");
+ printf("Kernel booted!\n\n");
userspace_init();
}
diff --git a/kernel/syscall.c b/kernel/syscall.c
new file mode 100644
index 0000000..8fa5da0
--- /dev/null
+++ b/kernel/syscall.c
@@ -0,0 +1,12 @@
+#include <kernel/con.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+/* main syscall handler */
+void syscall(va_list ap) {
+ uint8_t call;
+ char *s;
+
+ printf("Call Number: 0x%02x\n", va_arg(ap, uint8_t));
+ printf(va_arg(ap, char*));
+}
diff --git a/kernel/timer.s b/kernel/timer.s
index de01ea6..53c81ed 100644
--- a/kernel/timer.s
+++ b/kernel/timer.s
@@ -17,9 +17,10 @@ timer_init:
mov ebp, esp
; register the tick_handler
push tick_handler
+ push dword 0
push dword 0x20
call register_isr
- add esp, 8
+ add esp, 12
; initialize the pit
mov ax, 0x36
out 0x43, al
diff --git a/kernel/traps.s b/kernel/traps.s
new file mode 100644
index 0000000..7b7446b
--- /dev/null
+++ b/kernel/traps.s
@@ -0,0 +1,227 @@
+;
+; traps.s provides entry points to the exception handlers
+; as well as the system call interface.
+;
+
+global syscall_init
+global traps_init
+extern idt
+extern register_isr
+extern syscall
+
+%macro SAVE 0
+ pusha
+ ; save the data segment selectors
+ mov ax, ds
+ push ax
+ ; switch to kernel data segments
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+%endmacro
+
+%macro SAVE_ERR 0
+ pusha
+ ; fetch the error code that was pushed
+ mov ebx, [esp+32]
+ ; save the data segment selectors
+ mov ax, ds
+ push ax
+ ; switch to kernel data segments
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+%endmacro
+
+%macro RESTORE 0
+ ; restore the data segment selectors
+ pop ax
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ popa
+ iret
+%endmacro
+
+%macro RESTORE_ERR 0
+ ; restore the data segment selectors
+ pop ax
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ popa
+ add esp, 4
+ iret
+%endmacro
+
+traps:
+ dd exc_div
+ dd exc_debug
+ dd exc_nmi
+ dd exc_brk
+ dd exc_ovf
+ dd exc_bounds
+ dd exc_invop
+ dd exc_nomath
+ dd exc_dbf
+ dd exc_coseg
+ dd exc_invtss
+ dd exc_segnotpres
+ dd exc_stackf
+ dd exc_gprot
+ dd exc_pagef
+ dd exc_reserved
+ dd exc_mathf
+ dd exc_alignchk
+ dd exc_machinechk
+ dd exc_simdfp
+ dd exc_virt
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+ dd exc_reserved
+
+traps_init:
+ push ebp
+ mov ebp, esp
+ mov ecx, 0
+ mov edx, idt
+.loop:
+ mov eax, ecx
+ shl eax, 2
+ add eax, traps
+ mov eax, [eax]
+ mov [edx], ax
+ shr eax, 16
+ mov [edx+6], ax
+ mov word [edx+2], 0x08
+ mov byte [edx+4], 0x00
+ mov byte [edx+5], 0x8E
+ inc ecx
+ cmp ecx, 32
+ je .end
+ add edx, 8
+ jmp .loop
+.end:
+ pop ebp
+ ret
+
+exc_div:
+ SAVE
+ RESTORE
+
+exc_debug:
+ SAVE
+ RESTORE
+
+exc_nmi:
+ SAVE
+ RESTORE
+
+exc_brk:
+ SAVE
+ RESTORE
+
+exc_ovf:
+ SAVE
+ RESTORE
+
+exc_bounds:
+ SAVE
+ RESTORE
+
+exc_invop:
+ SAVE
+ RESTORE
+
+exc_nomath:
+ SAVE
+ RESTORE
+
+exc_dbf:
+ SAVE_ERR
+ RESTORE_ERR
+
+exc_coseg:
+ SAVE
+ RESTORE
+
+exc_invtss:
+ SAVE_ERR
+ RESTORE_ERR
+
+exc_segnotpres:
+ SAVE_ERR
+ RESTORE_ERR
+
+exc_stackf:
+ SAVE_ERR
+ RESTORE_ERR
+
+exc_gprot:
+ SAVE_ERR
+ RESTORE_ERR
+
+exc_pagef:
+ SAVE_ERR
+ RESTORE_ERR
+
+exc_mathf:
+ SAVE
+ RESTORE
+
+exc_alignchk:
+ SAVE
+ RESTORE
+
+exc_machinechk:
+ SAVE
+ RESTORE
+
+exc_simdfp:
+ SAVE
+ RESTORE
+
+exc_virt:
+ SAVE
+ RESTORE
+
+exc_reserved:
+ SAVE
+ RESTORE
+
+syscall_handler:
+ SAVE
+
+ ; pass the saved ESP value to the REAL handler
+ mov eax, [esp+46]
+ push eax
+ call syscall
+ add esp, 4
+
+ RESTORE
+
+
+syscall_init:
+ push ebp
+ mov ebp, esp
+ push syscall_handler
+ push dword 3
+ push dword 0x80
+ call register_isr
+ add esp, 12
+ pop ebp
+ ret
diff --git a/kernel/usrbin/usrbin.bin b/kernel/usrbin/usrbin.bin
index a7d7730..bdf8c29 100644
--- a/kernel/usrbin/usrbin.bin
+++ b/kernel/usrbin/usrbin.bin
Binary files differ
diff --git a/kernel/usrbin/usrbin.s b/kernel/usrbin/usrbin.s
index 91dd94a..248d823 100644
--- a/kernel/usrbin/usrbin.s
+++ b/kernel/usrbin/usrbin.s
@@ -3,30 +3,10 @@ org 0x100000
main:
push .msg
- call puts
+ push byte 0
+ int 0x80
add esp, 4
.loop:
; loop forever
jmp .loop
-.msg: db "Hello World from Userspace!", 0
-
-puts:
- push ebp
- mov ebp, esp
- push esi
- push edi
- mov esi, [ebp+8]
- mov edi, 0xB8000
-.loop:
- lodsb
- cmp al, 0
- je .end
- mov [edi], al
- mov byte [edi+1], 0x07
- add edi, 2
- jmp .loop
-.end:
- pop edi
- pop esi
- pop ebp
- ret
+.msg: db "Hello World from Userspace, using syscalls!", 10, 0
diff --git a/kernel/usrspace.s b/kernel/usrspace.s
index e52f2e0..1d20f71 100644
--- a/kernel/usrspace.s
+++ b/kernel/usrspace.s
@@ -1,6 +1,7 @@
global userspace_init
-extern _binary_usrbin_bin_start
extern _binary_usrbin_bin_size
+extern _binary_usrbin_bin_start
+extern tss
userspace_init:
push ebp
@@ -32,8 +33,10 @@ usrcall:
mov fs, ax
mov gs, ax
mov eax, esp
+ ; save ESP in the TSS
+ mov [tss+4], eax
push dword 0x23
- push eax
+ push dword 0x00180000
pushf
push dword 0x1B
push dword 0x00100000