Work on scheduler
This commit is contained in:
parent
cbc51f523e
commit
14bced8243
8 changed files with 98 additions and 79 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
build/
|
||||||
|
iso_root/
|
||||||
|
limine/
|
||||||
|
test/
|
||||||
|
|
@ -12,7 +12,7 @@ in the `build` folder you should have a `SFB25.iso` file.
|
||||||
|
|
||||||
To try out SFB/25 you can use QEMU:
|
To try out SFB/25 you can use QEMU:
|
||||||
|
|
||||||
`qemu-system-x86_64 build/SFB25.iso -m 512M`
|
`qemu-system-x86_64 build/SFB25.iso -machine q35 -m 512M`
|
||||||
|
|
||||||
## External projects
|
## External projects
|
||||||
|
|
||||||
|
|
|
||||||
17
autodebug.sh
Executable file
17
autodebug.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# how it works:
|
||||||
|
# Args are fed to QEMU, then GDB and everything else does shit automagically
|
||||||
|
# 1st arg: terminal name to spawn GDB
|
||||||
|
# 2nd arg: place to breakpoint in
|
||||||
|
termname=$1
|
||||||
|
breakpoint=$2
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
qemu-system-x86_64 "$@" &
|
||||||
|
|
||||||
|
wait 1
|
||||||
|
|
||||||
|
"$termname" -e gdb -ex 'target remote localhost:1234' -ex 'break _start' -ex 'continue' build/SFB25.elf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Timeout in seconds that Limine will use before automatically booting.
|
# Timeout in seconds that Limine will use before automatically booting.
|
||||||
timeout: 5
|
timeout: 0
|
||||||
|
|
||||||
# The entry name that will be displayed in the boot menu.
|
# The entry name that will be displayed in the boot menu.
|
||||||
/SFB25 (KASLR on)
|
/SFB/25 (KASLR on)
|
||||||
# We use the Limine boot protocol.
|
# We use the Limine boot protocol.
|
||||||
protocol: limine
|
protocol: limine
|
||||||
|
|
||||||
|
|
@ -10,7 +10,7 @@ timeout: 5
|
||||||
kernel_path: boot():/SFB25.elf
|
kernel_path: boot():/SFB25.elf
|
||||||
|
|
||||||
# Same thing, but without KASLR.
|
# Same thing, but without KASLR.
|
||||||
/SFB25 (KASLR off)
|
/SFB/25 (KASLR off)
|
||||||
# We use the Limine boot protocol.
|
# We use the Limine boot protocol.
|
||||||
protocol: limine
|
protocol: limine
|
||||||
|
|
||||||
|
|
|
||||||
1
src/flanterm
Submodule
1
src/flanterm
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 55d228ff16234513b0df0dd12de8bc58160fc196
|
||||||
|
|
@ -1,47 +1,53 @@
|
||||||
default rel
|
|
||||||
|
|
||||||
global switch_context
|
global switch_context
|
||||||
|
global get_context
|
||||||
|
|
||||||
%macro save_context 0
|
; switch_context(struct context *old, struct context *new)
|
||||||
push rbx
|
; ^RDI ^RSI
|
||||||
push rsp
|
|
||||||
push rbp
|
|
||||||
push r12
|
|
||||||
push r13
|
|
||||||
push r14
|
|
||||||
push r15
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
%macro load_context 0
|
|
||||||
pop r15
|
|
||||||
pop r14
|
|
||||||
pop r13
|
|
||||||
pop r12
|
|
||||||
pop rbp
|
|
||||||
pop rsp
|
|
||||||
pop rbx
|
|
||||||
%endmacro
|
|
||||||
|
|
||||||
; Switch context from old to new
|
|
||||||
; void switch_context(context *old, context* new);
|
|
||||||
; rdi rsi
|
|
||||||
switch_context:
|
switch_context:
|
||||||
|
|
||||||
save_context
|
pop r8 ; Fetch RIP from stack
|
||||||
|
|
||||||
mov rdi, rsp
|
|
||||||
mov rsp, rsi
|
|
||||||
|
|
||||||
load_context
|
|
||||||
|
|
||||||
retfq
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; Save callee-saved registers to the old struct
|
||||||
|
mov [rdi + 0x00], rbx
|
||||||
|
mov [rdi + 0x08], rsp
|
||||||
|
mov [rdi + 0x10], rbp
|
||||||
|
mov [rdi + 0x18], r12
|
||||||
|
mov [rdi + 0x20], r13
|
||||||
|
mov [rdi + 0x28], r14
|
||||||
|
mov [rdi + 0x30], r15
|
||||||
|
mov [rdi + 0x38], r8
|
||||||
|
|
||||||
|
; Load the new context
|
||||||
|
mov rbx, [rsi + 0x00]
|
||||||
|
mov rsp, [rsi + 0x08]
|
||||||
|
mov rbp, [rsi + 0x10]
|
||||||
|
mov r12, [rsi + 0x18]
|
||||||
|
mov r13, [rsi + 0x20]
|
||||||
|
mov r14, [rsi + 0x28]
|
||||||
|
mov r15, [rsi + 0x30]
|
||||||
|
|
||||||
|
push r8
|
||||||
|
|
||||||
|
jmp [rsi + 0x38]
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; get_context(struct context *ctx)
|
||||||
|
get_context:
|
||||||
|
pop r8 ; Fetch RIP from stack
|
||||||
|
|
||||||
|
; Save callee-saved registers to the old struct
|
||||||
|
mov [rdi + 0x00], rbx
|
||||||
|
mov [rdi + 0x08], rsp
|
||||||
|
mov [rdi + 0x10], rbp
|
||||||
|
mov [rdi + 0x18], r12
|
||||||
|
mov [rdi + 0x20], r13
|
||||||
|
mov [rdi + 0x28], r14
|
||||||
|
mov [rdi + 0x30], r15
|
||||||
|
mov [rdi + 0x38], r8
|
||||||
|
|
||||||
|
push r8
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
@ -16,7 +16,6 @@ int next_pid = 1;
|
||||||
|
|
||||||
void idle_task(){
|
void idle_task(){
|
||||||
kprintf("Hello world from bruhd task!\n");
|
kprintf("Hello world from bruhd task!\n");
|
||||||
for(;;);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_task(){
|
void test_task(){
|
||||||
|
|
@ -26,45 +25,33 @@ void test_task(){
|
||||||
|
|
||||||
/* Setup a process structure */
|
/* Setup a process structure */
|
||||||
proc *alloc_process(void){
|
proc *alloc_process(void){
|
||||||
asm("cli");
|
proc *proc_list = get_cpu_struct()->process_list;
|
||||||
|
|
||||||
cpu_state *state = get_cpu_struct();
|
|
||||||
kprintf("hi10\n");
|
|
||||||
proc *proc_list = state->process_list;
|
|
||||||
|
|
||||||
uint8_t *sp;
|
|
||||||
|
|
||||||
for(uint64_t i = 0; i < PROC_MAX; i++){
|
for(uint64_t i = 0; i < PROC_MAX; i++){
|
||||||
if(proc_list[i].state == UNUSED){
|
if(proc_list[i].state == UNUSED){
|
||||||
/* Set the process ready to be executed */
|
proc *p = &proc_list[i];
|
||||||
kprintf("hi6\n");
|
|
||||||
proc_list[i].state = READY;
|
|
||||||
proc_list[i].kstack = kmalloc(INITIAL_STACK_SIZE);
|
|
||||||
|
|
||||||
if(proc_list[i].kstack == NULL){
|
p->state = READY;
|
||||||
klog(LOG_ERROR, __func__, "Failed to alloc stack");
|
kprintf("pstate = 0x{x}\n", READY);
|
||||||
}
|
kprintf("actual: 0x{x}\n", p->state);
|
||||||
kprintf("hi7\n");
|
p->kstack = kmalloc(INITIAL_STACK_SIZE);
|
||||||
|
|
||||||
proc_list[i].pid = next_pid++;
|
p->pid = next_pid++;
|
||||||
|
|
||||||
sp = (uint8_t*)((uint64_t)proc_list[i].kstack + INITIAL_STACK_SIZE);
|
memset(&p->context, 0, sizeof(context));
|
||||||
|
|
||||||
proc_list[i].context.rip = 0;
|
p->context.rbp = (uint64_t)p->kstack;
|
||||||
proc_list[i].context.rsp = (uint64_t)sp;
|
p->context.rsp = (uint64_t)p->context.rbp + INITIAL_STACK_SIZE;
|
||||||
|
|
||||||
|
kprintf("actua2l: 0x{x}\n", p->state);
|
||||||
|
|
||||||
kprintf("hi8\n");
|
return p;
|
||||||
|
|
||||||
asm("sti");
|
|
||||||
|
|
||||||
return &proc_list[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
asm("sti");
|
|
||||||
|
|
||||||
return NULL;
|
kprintf("Couldn't find free process!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kstatus add_task(uint64_t *entry){
|
kstatus add_task(uint64_t *entry){
|
||||||
proc *proc = alloc_process();
|
proc *proc = alloc_process();
|
||||||
|
|
||||||
|
|
@ -79,28 +66,31 @@ kstatus add_task(uint64_t *entry){
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduler_init(){
|
void scheduler_init(){
|
||||||
|
if(!get_cpu_struct_initialized()){
|
||||||
|
kprintf("sched: cpu struct not initialized!");
|
||||||
|
kkill();
|
||||||
|
}
|
||||||
|
|
||||||
cpu_state *state = get_cpu_struct();
|
cpu_state *state = get_cpu_struct();
|
||||||
|
|
||||||
if(state->current_process != NULL){
|
if(state->current_process != NULL){
|
||||||
kprintf("sched: scheduler on CPU {d} already initialized!\n", state->lapic_id);
|
kprintf("sched: scheduler on CPU {d} already initialized!\n", state->lapic_id);
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("hi1\n");
|
kprintf("hi1\n");
|
||||||
proc *proc_list = state->process_list;
|
proc *proc_list = state->process_list;
|
||||||
|
|
||||||
/* Put the idle task */
|
memset(proc_list, 0, sizeof(proc) * 512);
|
||||||
proc idle = {0, 0, 0, READY, {0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
|
||||||
|
|
||||||
/* Make the idle structure the firstr process */
|
int pid = add_task((uint64_t*)idle_task);
|
||||||
proc_list[0] = idle;
|
|
||||||
|
|
||||||
kprintf("hi2\n");
|
|
||||||
add_task((uint64_t*)test_task);
|
add_task((uint64_t*)test_task);
|
||||||
kprintf("hi5\n");
|
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
for(int i = 0; i < PROC_MAX; i++){
|
for(int i = 0; i < PROC_MAX; i++){
|
||||||
if(proc_list[i].state == READY){
|
if(proc_list[i].state == READY){
|
||||||
|
|
||||||
|
kprintf("Hell yeah");
|
||||||
|
|
||||||
context old_state = state->current_process->context;
|
context old_state = state->current_process->context;
|
||||||
|
|
||||||
|
|
@ -118,6 +108,7 @@ void scheduler_tick(){
|
||||||
cpu_state *state = get_cpu_struct();
|
cpu_state *state = get_cpu_struct();
|
||||||
proc *proc_list = state->process_list;
|
proc *proc_list = state->process_list;
|
||||||
|
|
||||||
|
switch_context(&state->current_process->context, &state->scheduler_context);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,15 +3,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef enum proc_state {
|
typedef enum proc_state {
|
||||||
RUNNING,
|
RUNNING = 3,
|
||||||
READY,
|
READY = 2,
|
||||||
SLEEPING,
|
SLEEPING = 1,
|
||||||
UNUSED = 0
|
UNUSED = 0
|
||||||
}proc_state;
|
}proc_state;
|
||||||
|
|
||||||
typedef struct context {
|
typedef struct context {
|
||||||
uint64_t rbx, rsp, rbp, r12, r13, r14, r15;
|
uint64_t rbx, rsp, rbp, r12, r13, r14, r15;
|
||||||
uint64_t rip, rflags;
|
uint64_t rip;
|
||||||
} __attribute((packed))context;
|
} __attribute((packed))context;
|
||||||
|
|
||||||
typedef struct proc {
|
typedef struct proc {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue