From 613145e8f679ec996ddf8d80d8c83915f054f0cb Mon Sep 17 00:00:00 2001 From: Amoelle Date: Wed, 23 Jul 2025 13:45:41 +0300 Subject: [PATCH] process control and context switch --- .gitignore | 1 + common.c | 72 +++++++++++++++--------------- kernel.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++--- kernel.h | 12 +++++ kernel.ld | 2 +- 5 files changed, 169 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index a1a1e76..b90999d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ *.bin *.log *.pcap +registers diff --git a/common.c b/common.c index 67894f4..992ee7a 100644 --- a/common.c +++ b/common.c @@ -1,5 +1,41 @@ #include "common.h" +void *memcpy(void *dst, const void *src, size_t n) { + uint8_t *d = (uint8_t *) dst; + const uint8_t *s = (const uint8_t *) src; + while (n--) + *d++ = *s++; + return dst; +} + +void *memset(void *buf, char c, size_t n) { + uint8_t *p = (uint8_t *) buf; + while (n--) + *p++ = c; + return buf; +} + +char *strcpy(char *dst, const char *src) { + char *d = dst; + while (*src) + *d++ = *src++; + *d = '\0'; + return dst; +} // The strcpy function continues copying even if + // src is longer than the memory area of dst. + // This can easily lead to bugs and vulnerabilities + +int strcmp(const char *s1, const char *s2) { + while (*s1 && *s2) { + if (*s1 != *s2) + break; + s1++; + s2++; + } + + return *(unsigned char *)s1 - *(unsigned char *)s2; +} + void putchar(char ch); void printf(const char *fmt, ...) { @@ -62,39 +98,3 @@ void printf(const char *fmt, ...) { end: va_end(vargs); } - -void *memcpy(void *dst, const void *src, size_t n) { - uint8_t *d = (uint8_t *) dst; - const uint8_t *s = (const uint8_t *) src; - while (n--) - *d++ = *s++; - return dst; -} - -void *memset(void *buf, char c, size_t n) { - uint8_t *p = (uint8_t *) buf; - while (n--) - *p++ = c; - return buf; -} - -char *strcpy(char *dst, const char *src) { - char *d = dst; - while (*src) - *d++ = *src++; - *d = '\0'; - return dst; -} // The strcpy function continues copying even if - // src is longer than the memory area of dst. - // This can easily lead to bugs and vulnerabilities - -int strcmp(const char *s1, const char *s2) { - while (*s1 && *s2) { - if (*s1 != *s2) - break; - s1++; - s2++; - } - - return *(unsigned char *)s1 - *(unsigned char *)s2; -} diff --git a/kernel.c b/kernel.c index f81463a..0f62167 100644 --- a/kernel.c +++ b/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] ); } - diff --git a/kernel.h b/kernel.h index ba69f82..e08972d 100644 --- a/kernel.h +++ b/kernel.h @@ -58,3 +58,15 @@ struct trap_frame { printf("YOU GOT A PANIC ERROR: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ while (1) {} \ } while (0) + +#define PROCS_MAX 8 // Maximum ammount of processes + +#define PROC_UNUSED 0 // Unused processes control structure +#define PROC_RUNNABLE 1 // Runnable proccess + +struct process { + int pid; // ID of a process + int state; // State of the process: either PROC_UNUSED or PROC_RUNNABLE + vaddr_t sp; // Stack pointer + uint8_t stack[8192]; // Kernel stack +}; diff --git a/kernel.ld b/kernel.ld index e473d33..d20d134 100644 --- a/kernel.ld +++ b/kernel.ld @@ -28,6 +28,6 @@ SECTIONS { . = ALIGN(4096); __free_ram = .; - . += 128 * 1024 * 1048; /* 128MB */ + . += 64 * 1024 * 1048; /* 64MB */ __free_ram_end = .; }