process control and context switch
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@
|
|||||||
*.bin
|
*.bin
|
||||||
*.log
|
*.log
|
||||||
*.pcap
|
*.pcap
|
||||||
|
registers
|
||||||
|
72
common.c
72
common.c
@@ -1,5 +1,41 @@
|
|||||||
#include "common.h"
|
#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 putchar(char ch);
|
||||||
|
|
||||||
void printf(const char *fmt, ...) {
|
void printf(const char *fmt, ...) {
|
||||||
@@ -62,39 +98,3 @@ void printf(const char *fmt, ...) {
|
|||||||
end:
|
end:
|
||||||
va_end(vargs);
|
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;
|
|
||||||
}
|
|
||||||
|
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);
|
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) {
|
void kernel_main(void) {
|
||||||
printf("\n\nHello %s\n", "friend :3");
|
printf("\n\nHello %s\n", "friend :3");
|
||||||
printf("60 + 9 = %d, %x\n", 60 + 9, 0x1234abcd);
|
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);
|
memset(__bss, 0, (size_t) __bss_end - (size_t) __bss);
|
||||||
|
|
||||||
paddr_t paddr0 = alloc_pages(2);
|
WRITE_CSR(stvec, (uint32_t) kernel_entry);
|
||||||
paddr_t paddr1 = alloc_pages(1);
|
|
||||||
printf("alloc_pages test paddr0=%x\n", paddr0);
|
|
||||||
printf("alloc_pages test paddr1=%x\n", paddr1);
|
|
||||||
|
|
||||||
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
|
// __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]
|
: [stack_top] "r" (__stack_top) // Pass the stack top address as %[stack_top]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
kernel.h
12
kernel.h
@@ -58,3 +58,15 @@ struct trap_frame {
|
|||||||
printf("YOU GOT A PANIC ERROR: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
|
printf("YOU GOT A PANIC ERROR: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||||
while (1) {} \
|
while (1) {} \
|
||||||
} while (0)
|
} 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
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user