summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-07-28 05:31:09 +1000
committerJake Mannens <jake72360@gmail.com>2018-07-28 05:31:09 +1000
commit4a91e12af177dc50a2427d335fd522658d821194 (patch)
tree2d2d231ff426db952be2acb819deb7263e24529b /kernel
parent9400716f56057d9f2fcd7f7ad033dfcb131105a2 (diff)
Added new function register_trap() which creates trap gate entries in
the IDT. This function takes the same parameters as register_isr() which creates interrupt gate entries in the IDT. The register_isr() function now sets the gate type to 0x0E regardless of what was already in the descriptor. This is to break reliance on the IDT already being initialized to a known state as well as avoiding conflicts with the new register_trap() function. Added declaration for the 'ticks' variable in kernel/sched.h so that it's value may be used throughout the kernel. Changed the system call gate to a trap gate. This means that interrupts will not be disabled prior to entry into the system call handler. This will allow hardware functions such as the timer to operate continuously even if the user makes a system call. Added checks to the timer interrupt handler. These checks prevent the scheduler from being called if the interrupt occurred during kernel mode execution. The idea here, is that the timer interrupt handler only services the hardware (increments the tick count and sends an EOI to the PIC's) if a system call was already running in the kernel. The system call handler has also been expanded to check if the timer fired prior to returning to userspace. If the timer did fire, the syscall handler will invoke the scheduler (as the timer handler would have), so that it can decide if it's time to switch tasks.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/boot.s24
-rw-r--r--kernel/sys.c6
-rw-r--r--kernel/timer.s13
-rw-r--r--kernel/traps.s14
4 files changed, 42 insertions, 15 deletions
diff --git a/kernel/boot.s b/kernel/boot.s
index db846c9..d609611 100644
--- a/kernel/boot.s
+++ b/kernel/boot.s
@@ -2,6 +2,7 @@ global gdt
global idt
global kboot
global register_isr
+global register_trap
extern con_init
extern hd_init
extern kmain
@@ -191,8 +192,27 @@ register_isr:
mov eax, [ebp+12]
and al, 3
shl al, 5
- mov cl, [edx+5]
- and cl, 0x9F
+ mov cl, 0x8E
+ or cl, al
+ mov [edx+5], cl
+ pop ebp
+ ret
+
+; void register_trap(uint8_t n, uint8_t dpl, void *handler);
+register_trap:
+ push ebp
+ mov ebp, esp
+ mov edx, [ebp+8]
+ shl edx, 3
+ add edx, idt
+ mov eax, [ebp+16]
+ mov [edx], ax
+ shr eax, 16
+ mov [edx+6], ax
+ mov eax, [ebp+12]
+ and al, 3
+ shl al, 5
+ mov cl, 0x8F
or cl, al
mov [edx+5], cl
pop ebp
diff --git a/kernel/sys.c b/kernel/sys.c
index 86fae41..20494de 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -7,13 +7,7 @@
#include <time.h>
#include <unistd.h>
-extern uint32_t ticks;
-
int sys_puts(char *s) {
- uint32_t sigs = 5;
- printk("[kernel] Setting signals %01x for PID 0x%04x\n", sigs, ctask->pid);
- ctask->signal |= sigs;
-
printk("[%04x] ", ctask->pid);
return printk(s);
}
diff --git a/kernel/timer.s b/kernel/timer.s
index c3af34b..b96e1f1 100644
--- a/kernel/timer.s
+++ b/kernel/timer.s
@@ -1,9 +1,11 @@
+global ticked
global ticks
global timer_init
extern check_signals
extern register_isr
extern sched_tick
+ticked: dd 0
ticks: dd 0
tick_handler:
@@ -17,17 +19,20 @@ tick_handler:
mov es, ax
mov fs, ax
mov gs, ax
-
; handle the timer tick
+ mov dword [ticked], 1
inc dword [ticks]
mov al, 0x20
out 0x20, al
-
- ; call the scheduler
+ ; check that the user isn't executing in kernel space
+ mov eax, [esp+38]
+ test eax, 0x03
+ jz .end
+ ; if it isn't, call the scheduler
call sched_tick
; handle any pending signals before returning to normal execution
call check_signals
-
+.end:
; restore the data segment selectors
pop ax
mov ds, ax
diff --git a/kernel/traps.s b/kernel/traps.s
index 73e7f64..36b3423 100644
--- a/kernel/traps.s
+++ b/kernel/traps.s
@@ -11,8 +11,10 @@ extern ctask
extern idt
extern panic
extern printk
-extern register_isr
+extern register_trap
+extern reschedule
extern sighandler_default
+extern ticked
; here we define offsets into task_struct.
; if task_struct is modified, this must be
@@ -269,6 +271,7 @@ exc_reserved:
syscall_handler:
SAVE
+ mov dword [ticked], 0
; push the arguments onto the stack, then
; calculate the offset for the appropriate
; handler function and call it
@@ -282,8 +285,13 @@ syscall_handler:
add esp, 12
; preserve the syscall's return value
mov [esp+30], eax
- mov eax, esp
+ ; check if the timer fired while we were in kernel mode
+ mov eax, [ticked]
+ jz .skip
+ call reschedule
+.skip:
; check pending signals and handle them (if any)
+ mov eax, esp
push eax
call check_signals
add esp, 4
@@ -379,7 +387,7 @@ syscall_init:
push syscall_handler
push dword 3
push dword 0x80
- call register_isr
+ call register_trap
add esp, 12
pop ebp
ret