process control and context switch

This commit is contained in:
2025-07-23 13:45:41 +03:00
parent af7b8d2851
commit 613145e8f6
5 changed files with 169 additions and 44 deletions

126
kernel.c
View File

@@ -125,6 +125,114 @@ void handle_trap(struct trap_frame *f) {
PANIC("Unexpected trap: scause=%x, stval=%x, sepc=%x\n", scause, stval, user_pc);
}
__attribute__((naked)) void switch_context(uint32_t *prev_sp,
uint32_t *next_sp) {
__asm__ __volatile__(
// Save calle-saved registers onto the stack of current proccess
"addi sp, sp, -13 * 4\n" // Allocate stack space for 13 4-byte registers
"sw ra, 0 * 4(sp)\n" // Save calle-saved registers only
"sw s0, 1 * 4(sp)\n"
"sw s1, 2 * 4(sp)\n"
"sw s2, 3 * 4(sp)\n"
"sw s3, 4 * 4(sp)\n"
"sw s4, 5 * 4(sp)\n"
"sw s5, 6 * 4(sp)\n"
"sw s6, 7 * 4(sp)\n"
"sw s7, 8 * 4(sp)\n"
"sw s8, 9 * 4(sp)\n"
"sw s9, 10 * 4(sp)\n"
"sw s10, 11 * 4(sp)\n"
"sw s11, 12 * 4(sp)\n"
// Switch stack pointer
"sw sp, (a0)\n" // *prev_sp = a0;
"lw sp, (a1)\n" // Switch stack pointer (sp) here
// Restore calle-saved registers from the next process's stack
"lw ra, 0 * 4(sp)\n" // Save calle-saved registers only
"lw s0, 1 * 4(sp)\n"
"lw s1, 2 * 4(sp)\n"
"lw s2, 3 * 4(sp)\n"
"lw s3, 4 * 4(sp)\n"
"lw s4, 5 * 4(sp)\n"
"lw s5, 6 * 4(sp)\n"
"lw s6, 7 * 4(sp)\n"
"lw s7, 8 * 4(sp)\n"
"lw s8, 9 * 4(sp)\n"
"lw s9, 10 * 4(sp)\n"
"lw s10, 11 * 4(sp)\n"
"lw s11, 12 * 4(sp)\n"
"addi sp, sp, 13 * 4\n" // We've popped 13 4-byte registers from the stack
"ret\n"
);
}
struct process procs[PROCS_MAX];
struct process *create_process(uint32_t pc) {
// Find an unused proccess control structure
struct process *proc = NULL;
int i;
for (i = 0; i <= PROCS_MAX; i++) {
if (procs[i].state == PROC_UNUSED) {
proc = &procs[i];
break;
}
}
if (!proc)
PANIC("No free process slots found! Fuck off!");
// Stack calle-saved registers
uint32_t *sp = (uint32_t *) &proc->stack[sizeof(proc->stack)];
*--sp = 0; // s11
*--sp = 0; // s10
*--sp = 0; // s9
*--sp = 0; // s8
*--sp = 0; // s7
*--sp = 0; // s6
*--sp = 0; // s5
*--sp = 0; // s4
*--sp = 0; // s3
*--sp = 0; // s2
*--sp = 0; // s1
*--sp = 0; // s0
*--sp = (uint32_t) pc; // ra
// Initialize fields
proc->pid = i + 1;
proc->state = PROC_RUNNABLE;
proc->sp = (uint32_t) sp;
return proc;
}
void delay(void) {
for (int i = 0; i < 69696969; i++)
__asm__ __volatile__("nop"); // do nothing
}
struct process *proc_a;
struct process *proc_b;
void proc_a_entry(void) {
printf("Start process A\n");
while (1) {
putchar('6');
switch_context(&proc_a->sp, &proc_b->sp);
delay();
}
}
void proc_b_entry(void) {
printf("Start process B\n");
while (1) {
putchar('9');
switch_context(&proc_b->sp, &proc_a->sp);
delay();
}
}
void kernel_main(void) {
printf("\n\nHello %s\n", "friend :3");
printf("60 + 9 = %d, %x\n", 60 + 9, 0x1234abcd);
@@ -135,14 +243,19 @@ void kernel_main(void) {
memset(__bss, 0, (size_t) __bss_end - (size_t) __bss);
paddr_t paddr0 = alloc_pages(2);
paddr_t paddr1 = alloc_pages(1);
printf("alloc_pages test paddr0=%x\n", paddr0);
printf("alloc_pages test paddr1=%x\n", paddr1);
WRITE_CSR(stvec, (uint32_t) kernel_entry);
PANIC("You booted successfully :3");
// paddr_t paddr0 = alloc_pages(2);
// paddr_t paddr1 = alloc_pages(1);
// printf("alloc_pages test paddr0=%x\n", paddr0);
// printf("alloc_pages test paddr1=%x\n", paddr1);
proc_a = create_process((uint32_t) proc_a_entry);
proc_b = create_process((uint32_t) proc_b_entry);
proc_a_entry();
PANIC("Your boot ended successfully :3");
// WRITE_CSR(stvec, (uint32_t) kernel_entry);
// __asm__ __volatile__("unimp"); // calls a unimp which triggers kernel panic
//
@@ -160,4 +273,3 @@ void boot(void) {
: [stack_top] "r" (__stack_top) // Pass the stack top address as %[stack_top]
);
}