process control and context switch
This commit is contained in:
126
kernel.c
126
kernel.c
@@ -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]
|
||||
);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user