Compare commits
2 commits
7336f9e6d6
...
94fbea02ca
Author | SHA1 | Date | |
---|---|---|---|
94fbea02ca | |||
d5d92555ae |
6 changed files with 367 additions and 201 deletions
|
@ -8,6 +8,7 @@ arch_sources += [
|
||||||
elf = executable(
|
elf = executable(
|
||||||
'kernel.elf',
|
'kernel.elf',
|
||||||
arch_sources,
|
arch_sources,
|
||||||
|
include_directories: includes,
|
||||||
link_args: [
|
link_args: [
|
||||||
'-Wl,-T,' + meson.current_source_dir() + '/platform.ld',
|
'-Wl,-T,' + meson.current_source_dir() + '/platform.ld',
|
||||||
'-static'
|
'-static'
|
||||||
|
|
62
kernel/drivers/opensbi/include/opensbi.h
Normal file
62
kernel/drivers/opensbi/include/opensbi.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef unsigned long uintmax_t;
|
||||||
|
|
||||||
|
namespace drivers {
|
||||||
|
namespace opensbi {
|
||||||
|
|
||||||
|
// We use uintmax_t to make sure this works on 32 and 64 bit
|
||||||
|
// At least thats how I hope this works..
|
||||||
|
// TODO: Add assert() to make sure this is the case
|
||||||
|
struct sbiret_t {
|
||||||
|
uintmax_t error;
|
||||||
|
uintmax_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2,
|
||||||
|
uintmax_t a3,
|
||||||
|
uintmax_t a4,
|
||||||
|
uintmax_t a5);
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2,
|
||||||
|
uintmax_t a3,
|
||||||
|
uintmax_t a4);
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2,
|
||||||
|
uintmax_t a3);
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2);
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1);
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0);
|
||||||
|
|
||||||
|
} // End namespace opensbi
|
||||||
|
} // End namespace drivers
|
9
kernel/drivers/opensbi/meson.build
Normal file
9
kernel/drivers/opensbi/meson.build
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
kernel_sources += [
|
||||||
|
files(
|
||||||
|
'opensbi.cpp'
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
kernel_includes += include_directories(
|
||||||
|
'include'
|
||||||
|
)
|
78
kernel/drivers/opensbi/opensbi.cpp
Normal file
78
kernel/drivers/opensbi/opensbi.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include <cstdint>
|
||||||
|
#include <opensbi.h>
|
||||||
|
|
||||||
|
namespace drivers {
|
||||||
|
namespace opensbi {
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2,
|
||||||
|
uintmax_t a3,
|
||||||
|
uintmax_t a4,
|
||||||
|
uintmax_t a5) {
|
||||||
|
register uintmax_t r_a7 asm("a7") = extension;
|
||||||
|
register uintmax_t r_a6 asm("a6") = function;
|
||||||
|
register uintmax_t r_a0 asm("a0") = a0;
|
||||||
|
register uintmax_t r_a1 asm("a1") = a1;
|
||||||
|
register uintmax_t r_a2 asm("a2") = a2;
|
||||||
|
register uintmax_t r_a3 asm("a3") = a3;
|
||||||
|
register uintmax_t r_a4 asm("a4") = a4;
|
||||||
|
register uintmax_t r_a5 asm("a5") = a5;
|
||||||
|
asm volatile("ecall" : // Instruction
|
||||||
|
"=r"(r_a0), "=r"(r_a1) : // Inputs
|
||||||
|
"r"(r_a7), "r"(r_a6), // Outputs
|
||||||
|
"r"(r_a0), "r"(r_a1), "r"(r_a2),
|
||||||
|
"r"(r_a3), "r"(r_a4), "r"(r_a5));
|
||||||
|
return {.error = a0, .value = a1};
|
||||||
|
}
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2,
|
||||||
|
uintmax_t a3,
|
||||||
|
uintmax_t a4) {
|
||||||
|
return call(extension, function, a0, a1, a2, a3, a4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2,
|
||||||
|
uintmax_t a3) {
|
||||||
|
return call(extension, function, a0, a1, a2, a3, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1,
|
||||||
|
uintmax_t a2) {
|
||||||
|
return call(extension, function, a0, a1, a2, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0,
|
||||||
|
uintmax_t a1) {
|
||||||
|
return call(extension, function, a0, a1, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sbiret_t call(
|
||||||
|
uintmax_t extension,
|
||||||
|
uintmax_t function,
|
||||||
|
uintmax_t a0) {
|
||||||
|
return call(extension, function, a0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace opensbi
|
||||||
|
} // End namespace drivers
|
|
@ -1,164 +1,168 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include <opensbi.h>
|
||||||
|
|
||||||
#define read_csr(csr) \
|
#define read_csr(csr) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v; \
|
unsigned long __v; \
|
||||||
asm volatile ("csrr %0, " csr : "=r"(__v) : : "memory");\
|
asm volatile ("csrr %0, " csr : "=r"(__v) : : "memory");\
|
||||||
__v;\
|
__v;\
|
||||||
})
|
})
|
||||||
|
|
||||||
#define write_csr(csr, v) \
|
#define write_csr(csr, v) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (v); \
|
unsigned long __v = (v); \
|
||||||
asm volatile ("csrw " csr ", %0" : : "r"(__v) : "memory");\
|
asm volatile ("csrw " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
})
|
})
|
||||||
|
|
||||||
#define set_csr_bits(csr, bits) \
|
#define set_csr_bits(csr, bits) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (bits); \
|
unsigned long __v = (bits); \
|
||||||
asm volatile ("csrs " csr ", %0" : : "r"(__v) : "memory");\
|
asm volatile ("csrs " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
})
|
})
|
||||||
|
|
||||||
#define clear_csr_bits(csr, bits) \
|
#define clear_csr_bits(csr, bits) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long __v = (bits); \
|
unsigned long __v = (bits); \
|
||||||
asm volatile ("csrc " csr ", %0" : : "r"(__v) : "memory");\
|
asm volatile ("csrc " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
})
|
})
|
||||||
|
|
||||||
typedef unsigned long sbi_word;
|
typedef unsigned long sbi_word;
|
||||||
|
|
||||||
|
/*
|
||||||
void sbi_call1(int ext, int func, sbi_word arg0) {
|
void sbi_call1(int ext, int func, sbi_word arg0) {
|
||||||
register sbi_word rExt asm("a7") = ext;
|
register sbi_word rExt asm("a7") = ext;
|
||||||
register sbi_word rFunc asm("a6") = func;
|
register sbi_word rFunc asm("a6") = func;
|
||||||
register sbi_word rArg0 asm("a0") = arg0;
|
register sbi_word rArg0 asm("a0") = arg0;
|
||||||
register sbi_word rArg1 asm("a1");
|
register sbi_word rArg1 asm("a1");
|
||||||
asm volatile("ecall" : "+r"(rArg0), "=r"(rArg1) : "r"(rExt), "r"(rFunc));
|
asm volatile("ecall" : "+r"(rArg0), "=r"(rArg1) : "r"(rExt), "r"(rFunc));
|
||||||
if(rArg0)
|
if(rArg0)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbi_call2(int ext, int func, sbi_word arg0, sbi_word arg1) {
|
void sbi_call2(int ext, int func, sbi_word arg0, sbi_word arg1) {
|
||||||
register sbi_word rExt asm("a7") = ext;
|
register sbi_word rExt asm("a7") = ext;
|
||||||
register sbi_word rFunc asm("a6") = func;
|
register sbi_word rFunc asm("a6") = func;
|
||||||
register sbi_word rArg0 asm("a0") = arg0;
|
register sbi_word rArg0 asm("a0") = arg0;
|
||||||
register sbi_word rArg1 asm("a1") = arg1;
|
register sbi_word rArg1 asm("a1") = arg1;
|
||||||
asm volatile("ecall" : "+r"(rArg0), "+r"(rArg1) : "r"(rExt), "r"(rFunc));
|
asm volatile("ecall" : "+r"(rArg0), "+r"(rArg1) : "r"(rExt), "r"(rFunc));
|
||||||
if(rArg0)
|
if(rArg0)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void fmt(const char *f, ...) {
|
void fmt(const char *f, ...) {
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, f);
|
va_start(va, f);
|
||||||
while(*f) {
|
while(*f) {
|
||||||
if(*f != '{') {
|
if(*f != '{') {
|
||||||
sbi_call1(1, 0, *(f++));
|
drivers::opensbi::call(1, 0, *(f++));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
f++;
|
f++;
|
||||||
|
|
||||||
while(*f != '}') {
|
while(*f != '}') {
|
||||||
if(!(*f))
|
if(!(*f))
|
||||||
return;
|
return;
|
||||||
f++;
|
f++;
|
||||||
}
|
}
|
||||||
f++;
|
f++;
|
||||||
|
|
||||||
unsigned long v = va_arg(va, unsigned long);
|
unsigned long v = va_arg(va, unsigned long);
|
||||||
for(int i = 0; i < 16; ++i) {
|
for(int i = 0; i < 16; ++i) {
|
||||||
const char *digits = "0123456789abcdef";
|
const char *digits = "0123456789abcdef";
|
||||||
int d = (v >> (60 - i * 4)) & 0xF;
|
int d = (v >> (60 - i * 4)) & 0xF;
|
||||||
sbi_call1(1, 0, digits[d]);
|
drivers::opensbi::call(1, 0, digits[d]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
pte_valid = 1 << 0,
|
pte_valid = 1 << 0,
|
||||||
pte_r = 1 << 1,
|
pte_r = 1 << 1,
|
||||||
pte_w = 1 << 2,
|
pte_w = 1 << 2,
|
||||||
pte_x = 1 << 3,
|
pte_x = 1 << 3,
|
||||||
pte_user = 1 << 4,
|
pte_user = 1 << 4,
|
||||||
pte_access = 1 << 6,
|
pte_access = 1 << 6,
|
||||||
pte_dirty = 1 << 7,
|
pte_dirty = 1 << 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
pte_ppn_shift = 10
|
pte_ppn_shift = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pt_t {
|
struct pt_t {
|
||||||
unsigned long ptes[512];
|
unsigned long ptes[512];
|
||||||
} __attribute__((aligned(4096)));
|
} __attribute__((aligned(4096)));
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
satp_sv48 = 9UL << 60
|
satp_sv48 = 9UL << 60
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *exception_strings[] = {
|
const char *exception_strings[] = {
|
||||||
"instruction misaligned",
|
"instruction misaligned",
|
||||||
"instruction access fault",
|
"instruction access fault",
|
||||||
"illegal instruction",
|
"illegal instruction",
|
||||||
"breakpoint",
|
"breakpoint",
|
||||||
"load misaligned",
|
"load misaligned",
|
||||||
"load access fault",
|
"load access fault",
|
||||||
"store misaligned",
|
"store misaligned",
|
||||||
"store access fault",
|
"store access fault",
|
||||||
"u-mode ecall",
|
"u-mode ecall",
|
||||||
"s-mode ecall",
|
"s-mode ecall",
|
||||||
"reserved (10)",
|
"reserved (10)",
|
||||||
"reserved (11)",
|
"reserved (11)",
|
||||||
"instruction page fault",
|
"instruction page fault",
|
||||||
"load page fault",
|
"load page fault",
|
||||||
"reserved (14)",
|
"reserved (14)",
|
||||||
"store page fault",
|
"store page fault",
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
sie_s_software = (1 << 1),
|
sie_s_software = (1 << 1),
|
||||||
sie_s_timer = (1 << 5)
|
sie_s_timer = (1 << 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
sstatus_sie = (1 << 1)
|
sstatus_sie = (1 << 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
void cli() {
|
void cli() {
|
||||||
clear_csr_bits("sstatus", sstatus_sie);
|
clear_csr_bits("sstatus", sstatus_sie);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sti() {
|
void sti() {
|
||||||
set_csr_bits("sstatus", sstatus_sie);
|
set_csr_bits("sstatus", sstatus_sie);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *sp;
|
void *sp;
|
||||||
} continuation_t;
|
} continuation_t;
|
||||||
|
|
||||||
struct task_t;
|
struct task_t;
|
||||||
|
|
||||||
struct isr_frame_t {
|
struct isr_frame_t {
|
||||||
task_t *task;
|
task_t *task;
|
||||||
isr_frame_t *next;
|
isr_frame_t *next;
|
||||||
unsigned long ra; // Offset 0x10.
|
unsigned long ra; // Offset 0x10.
|
||||||
unsigned long a[8]; // Offset 0x18.
|
unsigned long a[8]; // Offset 0x18.
|
||||||
unsigned long t[7]; // Offset 0x58.
|
unsigned long t[7]; // Offset 0x58.
|
||||||
unsigned long s1; // Offset 0x90.
|
unsigned long s1; // Offset 0x90.
|
||||||
unsigned long sstatus; // Offset 0x98.
|
unsigned long sstatus; // Offset 0x98.
|
||||||
unsigned long sepc; // Offset 0xA0.
|
unsigned long sepc; // Offset 0xA0.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kernel_stack_size = 0x10000
|
kernel_stack_size = 0x10000
|
||||||
};
|
};
|
||||||
|
|
||||||
struct task_t {
|
struct task_t {
|
||||||
continuation_t cont;
|
continuation_t cont;
|
||||||
isr_frame_t isr_frames[2];
|
isr_frame_t isr_frames[2];
|
||||||
isr_frame_t *next_isr;
|
isr_frame_t *next_isr;
|
||||||
char kernel_stack[kernel_stack_size];
|
char kernel_stack[kernel_stack_size];
|
||||||
};
|
};
|
||||||
|
|
||||||
task_t task1;
|
task_t task1;
|
||||||
|
@ -166,80 +170,80 @@ task_t task2;
|
||||||
task_t *current_task;
|
task_t *current_task;
|
||||||
|
|
||||||
continuation_t prepare_stack(void *s_top, void (*mainfn)(continuation_t)) {
|
continuation_t prepare_stack(void *s_top, void (*mainfn)(continuation_t)) {
|
||||||
void *sp = (void *)((uintptr_t)s_top - 0x78);
|
void *sp = (void *)((uintptr_t)s_top - 0x78);
|
||||||
*((uint64_t *)((uintptr_t)sp + 0x70)) = (uint64_t)mainfn;
|
*((uint64_t *)((uintptr_t)sp + 0x70)) = (uint64_t)mainfn;
|
||||||
return (continuation_t){.sp = sp};
|
return (continuation_t){.sp = sp};
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void save_stack(void (*f)(void *, continuation_t), void *ctx);
|
extern "C" void save_stack(void (*f)(void *, continuation_t), void *ctx);
|
||||||
extern "C" void restore_stack(continuation_t c);
|
extern "C" void restore_stack(continuation_t c);
|
||||||
|
|
||||||
void create_task(task_t *task, void (*mainfn)(continuation_t)) {
|
void create_task(task_t *task, void (*mainfn)(continuation_t)) {
|
||||||
task->isr_frames[0].task = task;
|
task->isr_frames[0].task = task;
|
||||||
task->isr_frames[1].task = task;
|
task->isr_frames[1].task = task;
|
||||||
task->isr_frames[0].next = &task->isr_frames[1];
|
task->isr_frames[0].next = &task->isr_frames[1];
|
||||||
task->isr_frames[1].next = 0;
|
task->isr_frames[1].next = 0;
|
||||||
task->next_isr = &task->isr_frames[0];
|
task->next_isr = &task->isr_frames[0];
|
||||||
|
|
||||||
task->cont = prepare_stack((void *)(task->kernel_stack + kernel_stack_size), mainfn);
|
task->cont = prepare_stack((void *)(task->kernel_stack + kernel_stack_size), mainfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void switch_task(void *ctx, continuation_t c) {
|
void switch_task(void *ctx, continuation_t c) {
|
||||||
task_t *task = (task_t *)ctx;
|
task_t *task = (task_t *)ctx;
|
||||||
if(task) {
|
if(task) {
|
||||||
task->next_isr = (isr_frame_t *)read_csr("sscratch");
|
task->next_isr = (isr_frame_t *)read_csr("sscratch");
|
||||||
task->cont = c;
|
task->cont = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
task_t *next;
|
task_t *next;
|
||||||
if(task == &task1) {
|
if(task == &task1) {
|
||||||
next = &task2;
|
next = &task2;
|
||||||
}else{
|
}else{
|
||||||
next = &task1;
|
next = &task1;
|
||||||
}
|
}
|
||||||
current_task = next;
|
current_task = next;
|
||||||
|
|
||||||
write_csr("sscratch", (unsigned long)next->next_isr);
|
write_csr("sscratch", (unsigned long)next->next_isr);
|
||||||
|
|
||||||
restore_stack(next->cont);
|
restore_stack(next->cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void isr();
|
extern "C" void isr();
|
||||||
|
|
||||||
extern "C" void handle_isr(isr_frame_t *frame) {
|
extern "C" void handle_isr(isr_frame_t *frame) {
|
||||||
unsigned long cause = read_csr("scause");
|
unsigned long cause = read_csr("scause");
|
||||||
unsigned long code = cause & ~(1UL << 63);
|
unsigned long code = cause & ~(1UL << 63);
|
||||||
if(cause & (1UL << 63)) {
|
if(cause & (1UL << 63)) {
|
||||||
if(code == 1) {
|
if(code == 1) {
|
||||||
fmt("it's an IPI\n");
|
fmt("it's an IPI\n");
|
||||||
clear_csr_bits("sip", sie_s_software);
|
clear_csr_bits("sip", sie_s_software);
|
||||||
}else if(code == 5) { // Timer interrupt.
|
}else if(code == 5) { // Timer interrupt.
|
||||||
//clear_csr_bits("sie", sie_s_timer);
|
//clear_csr_bits("sie", sie_s_timer);
|
||||||
unsigned long time = read_csr("time");
|
unsigned long time = read_csr("time");
|
||||||
sbi_call1(0x54494D45, 0, time + 100000);
|
drivers::opensbi::call(0x54494D45, 0, time + 100000);
|
||||||
save_stack(switch_task, current_task);
|
save_stack(switch_task, current_task);
|
||||||
}else{
|
}else{
|
||||||
fmt("it's an unhandled interrupt, code: {}\n", code);
|
fmt("it's an unhandled interrupt, code: {}\n", code);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(code == 8) { // Syscall.
|
if(code == 8) { // Syscall.
|
||||||
sbi_call1(1, 0, frame->a[0]);
|
drivers::opensbi::call(1, 0, frame->a[0]);
|
||||||
}else{
|
}else{
|
||||||
unsigned long sepc = read_csr("sepc");
|
unsigned long sepc = read_csr("sepc");
|
||||||
fmt("it's an exception at {}\n", sepc);
|
fmt("it's an exception at {}\n", sepc);
|
||||||
const char *s = exception_strings[cause];
|
const char *s = exception_strings[cause];
|
||||||
while(*s)
|
while(*s)
|
||||||
sbi_call1(1, 0, *(s++));
|
drivers::opensbi::call(1, 0, *(s++));
|
||||||
while(1)
|
while(1)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void isr_frame_overflow() {
|
extern "C" void isr_frame_overflow() {
|
||||||
fmt("isr frame overflow\n");
|
fmt("isr frame overflow\n");
|
||||||
while(1)
|
while(1)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
pt_t pml4;
|
pt_t pml4;
|
||||||
|
@ -247,65 +251,66 @@ pt_t pml4;
|
||||||
extern "C" void enter_umode(void *entry);
|
extern "C" void enter_umode(void *entry);
|
||||||
|
|
||||||
void syscall(int n, unsigned long arg0) {
|
void syscall(int n, unsigned long arg0) {
|
||||||
register sbi_word rArg0 asm("a0") = arg0;
|
register sbi_word rArg0 asm("a0") = arg0;
|
||||||
register sbi_word rN asm("a7") = n;
|
register sbi_word rN asm("a7") = n;
|
||||||
asm volatile("ecall" : "+r"(rArg0) : "r"(rN) : "memory");
|
asm volatile("ecall" : "+r"(rArg0) : "r"(rN) : "memory");
|
||||||
if(rArg0)
|
if(rArg0)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void task1_umode() {
|
void task1_umode() {
|
||||||
while(1)
|
while(1)
|
||||||
syscall(0, '!');
|
syscall(0, '!');
|
||||||
}
|
}
|
||||||
|
|
||||||
void task1_main(continuation_t c) {
|
void task1_main(continuation_t c) {
|
||||||
fmt("hello from task1\n");
|
fmt("hello from task1\n");
|
||||||
sti();
|
sti();
|
||||||
//syscall(0, '!');
|
//syscall(0, '!');
|
||||||
//enter_umode((void *)task1_umode);
|
//enter_umode((void *)task1_umode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void task2_main(continuation_t c) {
|
void task2_main(continuation_t c) {
|
||||||
fmt("hello from task2\n");
|
fmt("hello from task2\n");
|
||||||
sti();
|
sti();
|
||||||
//while(1)
|
//while(1)
|
||||||
//fmt(".");
|
//fmt(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
isr_frame_t global_isr_frames[2];
|
isr_frame_t global_isr_frames[2];
|
||||||
|
|
||||||
extern "C" void kmain(unsigned long hart, void *dtb) {
|
extern "C" void kmain(unsigned long hart, void *dtb) {
|
||||||
(void)hart;
|
(void)hart;
|
||||||
(void)dtb;
|
(void)dtb;
|
||||||
|
|
||||||
//fmt("test\n");
|
fmt("test\n");
|
||||||
|
|
||||||
|
fmt("uintmax: {} bits\n", sizeof(uintmax_t) * 8);
|
||||||
|
fmt("HART: {}, DTB: {}\n", hart, dtb);
|
||||||
|
|
||||||
/*
|
|
||||||
volatile uint32_t *cfg = (uint32_t *)0x2000060;
|
volatile uint32_t *cfg = (uint32_t *)0x2000060;
|
||||||
volatile uint32_t *dat = (uint32_t *)0x2000070;
|
volatile uint32_t *dat = (uint32_t *)0x2000070;
|
||||||
|
|
||||||
*cfg = 0x10;
|
*cfg = 0x10;
|
||||||
*dat = 0xFF;
|
*dat = 0xFF;
|
||||||
*/
|
|
||||||
|
|
||||||
fmt("y");
|
while(1);
|
||||||
|
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
global_isr_frames[0].next = &global_isr_frames[1];
|
global_isr_frames[0].next = &global_isr_frames[1];
|
||||||
write_csr("sscratch", (unsigned long)&global_isr_frames[0]);
|
write_csr("sscratch", (unsigned long)&global_isr_frames[0]);
|
||||||
write_csr("stvec", ((unsigned long)&isr));
|
write_csr("stvec", ((unsigned long)&isr));
|
||||||
|
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
set_csr_bits("sie", sie_s_software | sie_s_timer);
|
set_csr_bits("sie", sie_s_software | sie_s_timer);
|
||||||
|
|
||||||
// Self-IPI.
|
// Self-IPI.
|
||||||
sbi_call2(0x735049, 0, 1 << hart, 0);
|
drivers::opensbi::call(0x735049, 0, 1 << hart, 0);
|
||||||
|
|
||||||
sti();
|
sti();
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
unsigned long time;
|
unsigned long time;
|
||||||
//volatile uint32_t *meme = (uint32_t *)0x6011010;
|
//volatile uint32_t *meme = (uint32_t *)0x6011010;
|
||||||
|
@ -315,37 +320,37 @@ extern "C" void kmain(unsigned long hart, void *dtb) {
|
||||||
//*meme = *meme | (0xA57 << 1) | (1 << 0);
|
//*meme = *meme | (0xA57 << 1) | (1 << 0);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// Identity map the first 512GiB.
|
// Identity map the first 512GiB.
|
||||||
pml4.ptes[0] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
pml4.ptes[0] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
||||||
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
||||||
// Map 512GiB -> 0.
|
// Map 512GiB -> 0.
|
||||||
pml4.ptes[1] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
pml4.ptes[1] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
||||||
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
||||||
|
|
||||||
fmt("Writing paging memes\n");
|
fmt("Writing paging memes\n");
|
||||||
unsigned long pml4p = (unsigned long)&pml4;
|
unsigned long pml4p = (unsigned long)&pml4;
|
||||||
fmt("pml4p @ {}\n", pml4p);
|
fmt("pml4p @ {}\n", pml4p);
|
||||||
fmt("Setting SStatus\n");
|
fmt("Setting SStatus\n");
|
||||||
set_csr_bits("sstatus", 1 << 18);
|
set_csr_bits("sstatus", 1 << 18);
|
||||||
fmt("Setting Satp\n");
|
fmt("Setting Satp\n");
|
||||||
write_csr("satp", (pml4p >> 12) | satp_sv48);
|
write_csr("satp", (pml4p >> 12) | satp_sv48);
|
||||||
|
|
||||||
fmt("Paging might work?...\n");
|
fmt("Paging might work?...\n");
|
||||||
|
|
||||||
s = "paging works!\n";
|
s = "paging works!\n";
|
||||||
s += 512UL * 1024 * 1024 * 1024;
|
s += 512UL * 1024 * 1024 * 1024;
|
||||||
while(*s)
|
while(*s)
|
||||||
sbi_call1(1, 0, *(s++));
|
drivers::opensbi::call(1, 0, *(s++));
|
||||||
|
|
||||||
create_task(&task1, task1_main);
|
create_task(&task1, task1_main);
|
||||||
create_task(&task2, task2_main);
|
create_task(&task2, task2_main);
|
||||||
|
|
||||||
time = read_csr("time");
|
time = read_csr("time");
|
||||||
sbi_call1(0x54494D45, 0, time + 100000);
|
drivers::opensbi::call(0x54494D45, 0, time + 100000);
|
||||||
|
|
||||||
save_stack(switch_task, 0);
|
save_stack(switch_task, 0);
|
||||||
|
|
||||||
sbi_call1(8, 0, 0);
|
drivers::opensbi::call(8, 0, 0);
|
||||||
|
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,16 @@ kernel_sources = [
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
kernel_includes = [
|
||||||
|
include_directories('include')
|
||||||
|
]
|
||||||
|
|
||||||
|
subdir('drivers/opensbi')
|
||||||
|
|
||||||
|
includes = [
|
||||||
|
# arch_includes,
|
||||||
|
kernel_includes
|
||||||
|
]
|
||||||
|
|
||||||
subdir('arch/' + arch)
|
subdir('arch/' + arch)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue