You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.9 KiB
C
96 lines
2.9 KiB
C
#include "kernel.h"
|
|
#include "kinclude/ktypes.h"
|
|
#include "kinclude/ecall.h"
|
|
#include "kinclude/sched.h"
|
|
#include "kinclude/io.h"
|
|
#include "kinclude/malloc.h"
|
|
#include "kinclude/csr.h"
|
|
|
|
void read_binary_table();
|
|
void setup_mem_protection();
|
|
|
|
// this array is populated when the memory image is built, therefore it should
|
|
// resign in a section which is not overwritten with zeros on startup
|
|
loaded_binary binary_table[PACKAGED_BINARY_COUNT] __attribute__ ((section(".data")));
|
|
|
|
// access the memset function defined in boot.S
|
|
extern void memset(unsigned int, void*, void*);
|
|
|
|
// access linker symbols:
|
|
extern byte* _end, _ftext;
|
|
|
|
extern void init()
|
|
{
|
|
dbgln("Kernel started!", 15);
|
|
// setup phsycial memory protection
|
|
setup_mem_protection();
|
|
// initialize scheduler
|
|
scheudler_init();
|
|
// initialize tabel for associating ecall codes with their handlers
|
|
init_ecall_table();
|
|
// read supplied binaries, this will call malloc_init with the memory layout
|
|
// then it will create a new process for each loaded binary
|
|
read_binary_table();
|
|
// give control to the scheudler and start runnign user programs
|
|
scheduler_run_next();
|
|
}
|
|
|
|
void read_binary_table()
|
|
{
|
|
char msg[28] = "found bin with id 0 at pos 0";
|
|
|
|
struct malloc_info info = {
|
|
.allocate_memory_end = (void*) END_OF_USABLE_MEM,
|
|
.allocate_memory_start = (void*) 0
|
|
};
|
|
|
|
// calculate the end of loaded binaries
|
|
for (int i = 0; i < PACKAGED_BINARY_COUNT; i++) {
|
|
if (binary_table[i].binid == 0)
|
|
break;
|
|
|
|
if (DEBUGGING) {
|
|
// print message
|
|
msg[18] = (char) binary_table[i].binid + '0';
|
|
msg[27] = (char) i + '0';
|
|
dbgln(msg, 28);
|
|
}
|
|
|
|
info.allocate_memory_start = binary_table[i].bounds[1];
|
|
}
|
|
|
|
// initialize malloc
|
|
malloc_init(&info);
|
|
|
|
for (int i = 0; i < PACKAGED_BINARY_COUNT; i++) {
|
|
if (binary_table[i].binid == 0)
|
|
break;
|
|
|
|
// create a new process for each binary found
|
|
// it should have around 4kb stack
|
|
optional_pcbptr res = create_new_process(binary_table + i);
|
|
if (has_error(res)) {
|
|
dbgln("Error creating initial process!", 31);
|
|
}
|
|
}
|
|
}
|
|
|
|
void setup_mem_protection()
|
|
{
|
|
// this pmp config uses Top-of-Range mode - read more in the privileged spec p.49
|
|
// we disallow all access to 0x0-0x100 from user and machine mode
|
|
// and all access to 0x100-kernel_end from user mode
|
|
// to do this, we must first calculate the kernel bin length
|
|
uint32 kernel_bin_len = ((uint32) &_end) - ((uint32) &_ftext);
|
|
|
|
CSR_WRITE(CSR_PMPADDR, 0x100);
|
|
CSR_WRITE(CSR_PMPADDR + 1, 0x100 + kernel_bin_len);
|
|
|
|
// this contains two pmp configs:
|
|
// fields: L A RWX
|
|
// pmpcfg0: 0b1_00_01_000 <- disallow RWX from U and M mode
|
|
// pmpcfg1: 0b0_00_01_000 <- disallow RWX from U mode
|
|
// the resulint number is 0b0000100010001000, hex 0x888
|
|
CSR_WRITE(CSR_PMPCFG, 0x888);
|
|
}
|