commit - 17683e896fc6162a038d5fb2711ca94055188dfb
commit + d06837bca243482704cb1f5077d0c180a88f17f9
blob - 89788503a89a7d78c692d45b4e8240c5b2eaa64f
blob + 0cedacc0e680a7dd1060bcee065eeaf36a744393
--- alpha/main.c
+++ alpha/main.c
alpha_main(struct mmap *km)
{
struct task *t = task_new((void *)XHCI_ENTRY);
- struct sysc_context_switch scs;
+ u64 *ptr = (u64 *)0;
if (t == nil)
send_msg("alpha: failed to create task!\n");
send_msg("alpha: running\n");
- scs.sysc.type = SYSC_CONTEXT_SWITCH;
- scs.threadid = t->thread;
-
- sys_send((struct sysc *)&scs);
-
for (;;);
}
blob - c03eeaa10e4b75159709cacf3ae014e5987bf1f1
blob + 30b8a7dd5b4fe5fe44a7d27e8602741b79984258
--- kernel/idt.c
+++ kernel/idt.c
#include "kdebug.h"
#include "types.h"
+#include "kpic.h"
+#include "kthreads.h"
#define APIC_EOI_REG ((volatile u32*)0xFEE000B0)
u64 tint = 0;
-void
+struct thread*
timer_handler_c()
{
- kprint("Timer interrupt: "); kprinti(tint++); kprint("\n");
+ struct thread *next;
+ next = thread_next();
+
+ if (next != nil) {
+ tss_switch_rsp0((u64)next->base + PAGE_SIZE * 3);
+ cthread = next;
+ }
+
*APIC_EOI_REG = 0; // Tells register interrupt was received
+
+ return next;
}
blob - 34ebc5a87627fa395b52dc5677e1bf73d40d3eaa
blob + b2366e527a26372c6ecb83786edcd572fdce0e7c
--- kernel/kgdt.c
+++ kernel/kgdt.c
gdt.tss.ubase = (base >> 32) & 0xff;
gdt.tss.reserved = 0;
}
+
+void
+tss_switch_rsp0(u64 rsp0)
+{
+ tss.rsp0 = rsp0;
+}
blob - 5ebcf6e1480e25bb0cbe91bb902bdc7fb8c72303
blob + cdc2d5b4dc9a349890c07f32c786f010284c9a41
--- kernel/kmain.c
+++ kernel/kmain.c
{
struct thread *athread = thread_create((void (*)(void))(u64)amodule->entry);
- if (athread == nil) {
+ if (athread == nil)
kprint("Failed to create thread\n");
- repeat: goto repeat;
- }
thread_schedule(ammap, athread);
}
blob - d211bc91c43c414d564c555a3e919631416d419e
blob + 5d47634680e64c171b408ace77a8a70e18c5ad0f
--- kernel/kpic.h
+++ kernel/kpic.h
#pragma once
void kpic_setup(void);
+void tss_switch_rsp0(u64 rsp0);
blob - 2accf334df9298693dd6ee50980ab5275610c0a0
blob + fe438fa7f5b494e80edf47a178b5aaf4e06d97f9
--- kernel/kthreads.c
+++ kernel/kthreads.c
#include "types.h"
+#include "kpic.h"
#include "kmmap.h"
#include "kdebug.h"
#include "kthreads.h"
#define MAX_USER_THREADS 64
static struct thread uthreads[MAX_USER_THREADS];
-static struct thread *cthread;
+struct thread *cthread;
struct thread*
thread_create(void (*entry)(void))
return nil;
}
- thread->base = allocate_memory(PAGE_SIZE);
+ thread->base = allocate_memory(PAGE_SIZE * 3);
if (thread->base == nil) {
thread->assigned = 0;
}
usp = (u64)thread->base + PAGE_SIZE;
- sp = (u64 *)((u8*)thread->base + PAGE_SIZE);
+ sp = (u64 *)((u8*)thread->base + PAGE_SIZE * 3);
+ *(--sp) = 0x1B; // user SS/DS see kgdt.c
*(--sp) = usp; // user sp
- *(--sp) = (u64)entry; // RIP
*(--sp) = 0x202; // RFLAGS
+ *(--sp) = 0x23; // User CS
+ *(--sp) = (u64)entry; // RIP
*(--sp) = 0; // rbp
*(--sp) = 0; // rbx
*(--sp) = 0; // r15
thread->top = sp;
thread->rsp = (u64)sp;
+ thread->state = THREAD_READY;
return thread;
}
// This is defined in switch.s
void start_alpha(struct mmap *ammap, struct thread *thread);
-void switch_context(struct thread *old, struct thread *new);
void
thread_schedule(struct mmap *ammap, struct thread *th)
{
cthread = th;
+ tss_switch_rsp0((u64)th->base + PAGE_SIZE * 3);
start_alpha(ammap, th);
-
- repeat: goto repeat;
}
-void
-thread_switch(struct thread *th)
-{
- struct thread *othread;
-
- if (th == cthread) {
- kprint("Huh?\n");
- return;
- }
-
- othread = cthread;
- cthread = th;
- switch_context(othread, cthread);
-}
-
struct thread*
thread_get_uthread(u64 id)
{
return &uthreads[id];
return nil;
}
+
+struct thread*
+thread_next()
+{
+ s64 cid = thread_getuid(cthread);
+ s64 uid = cid;
+
+ for (u64 count = 0; count < MAX_USER_THREADS; count++) {
+ uid = (uid + 1) % MAX_USER_THREADS;
+
+ struct thread *th = &uthreads[uid];
+
+ if (th->assigned)
+ return th;
+ }
+ return nil;
+}
blob - b962ab43fc5883d0f878a41c640fde2977e15761
blob + db7769a823069ca6a111484422253a3d2584125a
--- kernel/kthreads.h
+++ kernel/kthreads.h
u64 rsp;
u8 assigned;
- enum thread_state sate;
+ enum thread_state state;
};
+extern struct thread *cthread;
+
struct thread *thread_create(void (*entry)(void));
s64 thread_getuid(struct thread *th);
void thread_schedule(struct mmap *, struct thread *);
-void thread_switch(struct thread *);
+struct thread* thread_next(void);
struct thread *thread_get_uthread(u64 id);
blob - 086afdfc65590671baca91ac1a342feeec475041
blob + f575e2ff8206bacbd765276605e8d4a67a36add4
--- kernel/lidt.s
+++ kernel/lidt.s
[bits 64]
global load_idt
+extern cthread
global debug_exception_handler
extern debug_exception_handler_c
hlt
timer_handler:
+ cli
+ push rbp
+ push rbx
+ push r12
+ push r13
+ push r14
+ push r15
+
+ mov rax, [rel cthread]
+ test rax, rax
+ jz .schedule
+
+ mov [rax + RSP_OFFSET], rsp
+
+.schedule:
call timer_handler_c
+
+ test rax, rax
+ jz .same_thread
+ mov rsp, [rax + RSP_OFFSET]
+
+.same_thread:
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbx
+ pop rbp
+
iretq
+
+RSP_OFFSET equ 16
blob - 3f9d9b17844b3cce85cd36d45a2155f652ce8dbd
blob + 616bc48d63becb64fdcaab0c1cbdb7d1689e51f1
--- kernel/switch.s
+++ kernel/switch.s
;
; We are forced to push rbp-r15 because SystemV
-global switch_context
global start_alpha
start_alpha:
cli
- push rbp
- push rbx
- push r12
- push r13
- push r14
- push r15
-
- jmp switch_context.load
-
-switch_context:
- cli
- push rbp
- push rbx
- push r12
- push r13
- push r14
- push r15
-
- test rdi, rdi
- jz .load
- mov [rdi + RSP_OFFSET], rsp ; Save stack
-
-.load:
- mov rsp, [rsi + RSP_OFFSET] ; Loads stack
-
+ mov rsp, [rsi + RSP_OFFSET]
pop r15
pop r14
pop r13
pop rbx
pop rbp
- pop r11 ; pop RFLAGS in r11
- pop rcx ; pop RIP into RCX
- pop rax ; pop userspace rsp into rax
+ iretq
- mov rsp, rax
-
- o64 sysret
-
; See kthread struct
RSP_OFFSET equ 16
blob - 97983d5a50a7c11a00eb9b8167610e5a3babe57c
blob + 506f0acdbc5f659191e10538612fa9e4b82aa5cd
--- kernel/syscalls.c
+++ kernel/syscalls.c
}
void
-syscall_context_switch_h(struct sysc_context_switch *scs)
-{
- struct thread *cthread = thread_get_uthread(scs->threadid);
-
- if (cthread == nil) {
- kprint("No current thread :/\n");
- return;
- }
-
- thread_switch(cthread);
-}
-
-void
syscall_handler(struct sysc *call)
{
switch (call->type) {
case SYSC_NEW_THREAD:
syscall_new_thread_h((struct sysc_new_thread *)call);
break;
- case SYSC_CONTEXT_SWITCH:
- syscall_context_switch_h((struct sysc_context_switch *)call);
- break;
default:
break;
}
blob - 21f83e7165a15cd1c685c241a710f00554ce5f0a
blob + 9e460d889acdd7664a8a494521a753f1e9ed08d5
--- kernel/sysentry.s
+++ kernel/sysentry.s
[bits 64]
+extern cthread
extern syscall_handler
global rdmsr
syscall_entry:
mov rax, rsp
- mov rsp, 0x90000
+ mov r10, [rel cthread]
+ mov rsp, [r10 + RSP_OFFSET]
+
push rax
push rcx
push r11
shl rdx, 32
or rax, rdx
ret
+
+RSP_OFFSET equ 16 ; see kthreads.h
blob - da421226ae4e2a0a08618efb2483844a76f2533d
blob + ee332a1157cd391ca49fd5dec16b823f91d3c4dd
--- syscalls/syscalls.s
+++ syscalls/syscalls.s
ret
sys_recv:
- mov rax, SYS_RECV
syscall
ret
-
-; List of system calls IDs
-
-SYS_SEND equ 1
-SYS_RECV equ 2