From 29cc0dc9854c66f12bd65e12516f68ccd9a741da Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 18 Aug 2010 18:24:55 -0700 Subject: [pk,fesvr] improved proxykernel build system Now uses a modified MCPPBS. Add --host=riscv to configure path. Front-end server now just searches PATH for riscv-pk, so just install the pk to somewhere in your path. --- pk/Makefile | 18 ++++++ pk/atomic.h | 43 ++++++++++++++ pk/boot.S | 23 ++++++++ pk/entry.S | 130 ++++++++++++++++++++++++++++++++++++++++ pk/file.c | 133 +++++++++++++++++++++++++++++++++++++++++ pk/file.h | 30 ++++++++++ pk/frontend.c | 26 ++++++++ pk/frontend.h | 8 +++ pk/handlers.c | 58 ++++++++++++++++++ pk/pcr.h | 23 ++++++++ pk/pk | Bin 0 -> 184993 bytes pk/pk.ac | 0 pk/pk.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++ pk/pk.h | 39 ++++++++++++ pk/pk.ld | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pk/pk.mk.in | 20 +++++++ pk/riscv-pk.c | 6 ++ pk/syscall.c | 129 ++++++++++++++++++++++++++++++++++++++++ 18 files changed, 1030 insertions(+) create mode 100644 pk/Makefile create mode 100644 pk/atomic.h create mode 100644 pk/boot.S create mode 100644 pk/entry.S create mode 100644 pk/file.c create mode 100644 pk/file.h create mode 100644 pk/frontend.c create mode 100644 pk/frontend.h create mode 100644 pk/handlers.c create mode 100644 pk/pcr.h create mode 100755 pk/pk create mode 100644 pk/pk.ac create mode 100644 pk/pk.c create mode 100644 pk/pk.h create mode 100644 pk/pk.ld create mode 100644 pk/pk.mk.in create mode 100644 pk/riscv-pk.c create mode 100644 pk/syscall.c (limited to 'pk') diff --git a/pk/Makefile b/pk/Makefile new file mode 100644 index 0000000..6a1accd --- /dev/null +++ b/pk/Makefile @@ -0,0 +1,18 @@ +CFLAGS := -O2 -std=gnu99 -G 0 +CC := riscv-gcc $(CFLAGS) + +TARGETS := pk + +all: $(TARGETS) + +pk: boot.o entry.o pk.o syscall.o file.o frontend.o handlers.o pk.ld + $(CC) -o pk entry.o pk.o syscall.o file.o frontend.o handlers.o -T pk.ld + +%.o: %.c *.h + $(CC) -c $< + +%.o: %.S *.h + $(CC) -c $< + +clean: + rm -f *.o $(TARGETS) diff --git a/pk/atomic.h b/pk/atomic.h new file mode 100644 index 0000000..3294b6c --- /dev/null +++ b/pk/atomic.h @@ -0,0 +1,43 @@ +#ifndef _RISCV_ATOMIC_H +#define _RISCV_ATOMIC_H + +typedef struct { long val; } atomic_t; +typedef struct { atomic_t lock; } spinlock_t; +#define SPINLOCK_INIT {{0}} + +static inline long atomic_add(atomic_t* a, long inc) +{ + long old = a->val; + a->val += inc; + return old; +} + +static inline long atomic_swap(atomic_t* a, long val) +{ + long old = a->val; + a->val = val; + return old; +} + +static inline void atomic_set(atomic_t* a, long val) +{ + a->val = val; +} + +static inline long atomic_read(atomic_t* a) +{ + return a->val; +} + +static inline void spinlock_lock(spinlock_t* lock) +{ + while(atomic_read(&lock->lock)) + while(atomic_swap(&lock->lock,-1)); +} + +static inline void spinlock_unlock(spinlock_t* lock) +{ + atomic_set(&lock->lock,0); +} + +#endif diff --git a/pk/boot.S b/pk/boot.S new file mode 100644 index 0000000..0619671 --- /dev/null +++ b/pk/boot.S @@ -0,0 +1,23 @@ +#include "pcr.h" + + .section boottext + .global __start + .ent __start +__start: + + # set up SR + li $t0, SR_S | SR_PS | SR_ET | SR_UX | SR_KX + mtpcr $t0, $0 + + # set up trap table + la $t0, trap_table + mtpcr $t0, $3 + + # set up stack + la $sp,stack_top-64 + + # call into kernel + la $t0, boot + jr $t0 + + .end __start diff --git a/pk/entry.S b/pk/entry.S new file mode 100644 index 0000000..db49a98 --- /dev/null +++ b/pk/entry.S @@ -0,0 +1,130 @@ + .text + .set noat + .ent save_tf +save_tf: # write the trap frame onto the stack + # save gprs + sd $1,8($k1) + sd $2,16($k1) + sd $3,24($k1) + sd $4,32($k1) + sd $5,40($k1) + sd $6,48($k1) + sd $7,56($k1) + sd $8,64($k1) + sd $9,72($k1) + sd $10,80($k1) + sd $11,88($k1) + sd $12,96($k1) + sd $13,104($k1) + sd $14,112($k1) + sd $15,120($k1) + sd $16,128($k1) + sd $17,136($k1) + sd $18,144($k1) + sd $19,152($k1) + sd $20,160($k1) + sd $21,168($k1) + sd $22,176($k1) + sd $23,184($k1) + sd $24,192($k1) + sd $25,200($k1) + sd $28,224($k1) + sd $29,232($k1) + sd $30,240($k1) + sd $k0,248($k1) # $ra is actually in $k0 + # get sr, epc, badvaddr + mfpcr $t0,$0 # sr + sd $t0,256($k1) + mfpcr $t0,$1 # epc + sd $t0,264($k1) + mfpcr $t0,$2 # badvaddr + sd $t0,272($k1) + jr $ra + .end save_tf + + .globl pop_tf + .ent pop_tf +pop_tf: # write the trap frame onto the stack + # restore gprs + ld $t0,256($a0) # restore sr, which should disable interrupts + mtpcr $t0,$0 + + move $k0,$a0 + ld $1,8($k0) + ld $2,16($k0) + ld $3,24($k0) + ld $4,32($k0) + ld $5,40($k0) + ld $6,48($k0) + ld $7,56($k0) + ld $8,64($k0) + ld $9,72($k0) + ld $10,80($k0) + ld $11,88($k0) + ld $12,96($k0) + ld $13,104($k0) + ld $14,112($k0) + ld $15,120($k0) + ld $16,128($k0) + ld $17,136($k0) + ld $18,144($k0) + ld $19,152($k0) + ld $20,160($k0) + ld $21,168($k0) + ld $22,176($k0) + ld $23,184($k0) + ld $24,192($k0) + ld $25,200($k0) + ld $28,224($k0) + ld $29,232($k0) + ld $30,240($k0) + ld $31,248($k0) + + # gtfo! + ld $k0,264($k0) + mtpcr $k0,$1 + eret + .end pop_tf + + + + #define TRAP_TABLE_ENTRY(x) \ + .align 7; \ + move $k0,$ra; \ + la $k1,stack_top-320; \ + jal save_tf; \ + move $sp,$k1; \ + move $a0,$k1; \ + ei; \ + jal x; \ + unimp + + .align 12 + .global trap_table + .ent trap_table +trap_table: + TRAP_TABLE_ENTRY(handle_illegal_instruction) + TRAP_TABLE_ENTRY(handle_privileged_instruction) + TRAP_TABLE_ENTRY(handle_fp_disabled) + TRAP_TABLE_ENTRY(handle_badtrap) + TRAP_TABLE_ENTRY(handle_misaligned_fetch) + TRAP_TABLE_ENTRY(handle_misaligned_ldst) + TRAP_TABLE_ENTRY(handle_fault_fetch) + TRAP_TABLE_ENTRY(handle_fault_ldst) + TRAP_TABLE_ENTRY(handle_syscall) + TRAP_TABLE_ENTRY(handle_breakpoint) + TRAP_TABLE_ENTRY(handle_badtrap) + TRAP_TABLE_ENTRY(handle_badtrap) + TRAP_TABLE_ENTRY(handle_badtrap) + TRAP_TABLE_ENTRY(handle_badtrap) + TRAP_TABLE_ENTRY(handle_badtrap) + TRAP_TABLE_ENTRY(handle_badtrap) + .align 12 + .end trap_table + + .bss + .global stack_bot + .global stack_top +stack_bot: + .skip 4096 +stack_top: diff --git a/pk/file.c b/pk/file.c new file mode 100644 index 0000000..fd063d9 --- /dev/null +++ b/pk/file.c @@ -0,0 +1,133 @@ +#include +#include +#include "file.h" +#include "pk.h" +#include "frontend.h" + +#define MAX_FDS 1000 +file_t* fds[MAX_FDS]; +#define MAX_FILES 1000 +file_t files[MAX_FILES] = {[0 ... MAX_FILES-1] = {-1,{0}}}; +file_t *stdout, *stdin, *stderr; + +static void file_incref(file_t* f) +{ + atomic_add(&f->refcnt,1); +} + +static void file_decref(file_t* f) +{ + if(atomic_add(&f->refcnt,-1) == 2) + { + if(f->kfd != -1) + { + frontend_syscall(SYS_close,f->kfd,0,0,0); + f->kfd = -1; + } + atomic_add(&f->refcnt,-1); // I think this could just be atomic_set(..,0) + } +} + +static file_t* file_get_free() +{ + for(int i = 0; i < MAX_FILES; i++) + { + if(atomic_read(&files[i].refcnt) == 0) + { + if(atomic_add(&files[i].refcnt,1) == 0) + { + atomic_add(&files[i].refcnt,1); + return &files[i]; + } + file_decref(&files[i]); + } + } + return NULL; +} + +static int fd_get_free() +{ + for(int i = 0; i < MAX_FDS; i++) + if(fds[i] == NULL) + return i; + return -1; +} + +int file_dup(file_t* f) +{ + int fd = fd_get_free(); + if(fd == -1) + return -1; + file_incref(f); + fds[fd] = f; + return fd; +} + +void file_init() +{ + stdin = file_get_free(); + stdout = file_get_free(); + stderr = file_get_free(); + kassert(stdin && stdout && stderr); + + stdin->kfd = 0; + stdout->kfd = 1; + stderr->kfd = 2; + + kassert(file_dup(stdin) == 0); + kassert(file_dup(stdout) == 1); + kassert(file_dup(stderr) == 2); +} + +file_t* file_get(int fd) +{ + return fd < 0 || fd >= MAX_FDS ? NULL : fds[fd]; +} + +sysret_t file_open(const char* fn, size_t len, int flags, int mode) +{ + file_t* f = file_get_free(); + if(!f) + return (sysret_t){-1,ENOMEM}; + + sysret_t ret = frontend_syscall(SYS_open,(long)fn,len,flags,mode); + if(ret.result != -1) + { + f->kfd = ret.result; + ret.result = (long)f; + } + else + file_decref(f); + + return ret; +} + +int fd_close(int fd) +{ + file_t* f = file_get(fd); + if(!f) + return -1; + fds[fd] = NULL; + file_decref(f); + return 0; +} + +sysret_t file_read(file_t* f, void* buf, size_t size) +{ + return frontend_syscall(SYS_read,f->kfd,(long)buf,size,0); +} + +sysret_t file_write(file_t* f, const void* buf, size_t size) +{ + return frontend_syscall(SYS_write,f->kfd,(long)buf,size,0); +} + +sysret_t file_stat(file_t* f, struct stat* s) +{ + return frontend_syscall(SYS_fstat,f->kfd,(long)s,0,0); +} + +sysret_t file_lseek(file_t* f, size_t ptr, int dir) +{ + return frontend_syscall(SYS_fstat,f->kfd,ptr,dir,0); +} diff --git a/pk/file.h b/pk/file.h new file mode 100644 index 0000000..95bf02c --- /dev/null +++ b/pk/file.h @@ -0,0 +1,30 @@ +#ifndef _FILE_H +#define _FILE_H + +#include +#include +#include "atomic.h" + +typedef struct file +{ + int kfd; // file descriptor on the appserver side + atomic_t refcnt; +} file_t; + +extern file_t *stdin, *stdout, *stderr; + +file_t* file_get(int fd); +sysret_t file_open(const char* fn, size_t len, int flags, int mode); +int file_dup(file_t*); + +sysret_t file_write(file_t* f, const void* buf, size_t n); +sysret_t file_read(file_t* f, void* buf, size_t n); +sysret_t file_stat(file_t* f, struct stat* s); +sysret_t file_lseek(file_t* f, size_t ptr, int dir); +int fd_close(int fd); + +void file_init(); + +#define cons_write(buf,sz) file_write(stdout,buf,sz) + +#endif diff --git a/pk/frontend.c b/pk/frontend.c new file mode 100644 index 0000000..c4e799b --- /dev/null +++ b/pk/frontend.c @@ -0,0 +1,26 @@ +#include "pk.h" +#include "atomic.h" +#include "frontend.h" +#include "pcr.h" + +sysret_t frontend_syscall(long n, long a0, long a1, long a2, long a3) +{ + static volatile long magic_mem[8]; + + static spinlock_t lock = SPINLOCK_INIT; + spinlock_lock(&lock); + + magic_mem[0] = n; + magic_mem[1] = a0; + magic_mem[2] = a1; + magic_mem[3] = a2; + magic_mem[4] = a3; + + mtpcr(magic_mem,16); + while(mfpcr(17) == 0); + + sysret_t ret = {magic_mem[0],magic_mem[1]}; + + spinlock_unlock(&lock); + return ret; +} diff --git a/pk/frontend.h b/pk/frontend.h new file mode 100644 index 0000000..86a8917 --- /dev/null +++ b/pk/frontend.h @@ -0,0 +1,8 @@ +#ifndef _RISCV_FRONTEND_H +#define _RISCV_FRONTEND_H + +#include + +sysret_t frontend_syscall(long n, long a0, long a1, long a2, long a3); + +#endif diff --git a/pk/handlers.c b/pk/handlers.c new file mode 100644 index 0000000..6cc5958 --- /dev/null +++ b/pk/handlers.c @@ -0,0 +1,58 @@ +#include "pcr.h" +#include "pk.h" + +void handle_breakpoint(trapframe_t* tf) +{ + printk("Breakpoint\n"); + dump_tf(tf); + tf->epc += 4; + pop_tf(tf); +} + +void handle_fp_disabled(trapframe_t* tf) +{ + tf->sr |= SR_EF; + pop_tf(tf); +} + +void handle_badtrap(trapframe_t* tf) +{ + dump_tf(tf); + panic("Bad trap vector!"); +} + +void handle_privileged_instruction(trapframe_t* tf) +{ + dump_tf(tf); + panic("A privileged instruction was executed!"); +} + +void handle_illegal_instruction(trapframe_t* tf) +{ + dump_tf(tf); + panic("An illegal instruction was executed!"); +} + +void handle_misaligned_fetch(trapframe_t* tf) +{ + dump_tf(tf); + panic("Misaligned instruction access!"); +} + +void handle_misaligned_ldst(trapframe_t* tf) +{ + dump_tf(tf); + panic("Misaligned data access!"); +} + +void handle_fault_fetch(trapframe_t* tf) +{ + dump_tf(tf); + panic("Faulting instruction access!"); +} + +void handle_fault_ldst(trapframe_t* tf) +{ + dump_tf(tf); + panic("Faulting data access!"); +} diff --git a/pk/pcr.h b/pk/pcr.h new file mode 100644 index 0000000..23e6185 --- /dev/null +++ b/pk/pcr.h @@ -0,0 +1,23 @@ +#ifndef _RISCV_COP0_H +#define _RISCV_COP0_H + +#define SR_ET 0x0000000000000001 +#define SR_PS 0x0000000000000004 +#define SR_S 0x0000000000000008 +#define SR_EF 0x0000000000000010 +#define SR_UX 0x0000000000000020 +#define SR_KX 0x0000000000000040 +#define SR_IM 0x000000000000FF00 + +#ifndef __ASSEMBLER__ + +#define mtpcr(val,reg) ({ long __tmp = (long)(val); \ + asm volatile ("mtpcr %0,$%1"::"r"(__tmp),"i"(reg)); }) + +#define mfpcr(reg) ({ long __tmp; \ + asm volatile ("mfpcr %0,$%1" : "=r"(__tmp) : "i"(reg)); \ + __tmp; }) + +#endif + +#endif diff --git a/pk/pk b/pk/pk new file mode 100755 index 0000000..4deb79e Binary files /dev/null and b/pk/pk differ diff --git a/pk/pk.ac b/pk/pk.ac new file mode 100644 index 0000000..e69de29 diff --git a/pk/pk.c b/pk/pk.c new file mode 100644 index 0000000..2f0ba17 --- /dev/null +++ b/pk/pk.c @@ -0,0 +1,158 @@ +#include "pcr.h" +#include "pk.h" +#include "file.h" +#include "frontend.h" +#include +#include +#include + +static void vsprintk(char* out, const char* s, va_list vl) +{ + bool format = false; + bool longarg = false; + for( ; *s; s++) + { + if(format) + { + switch(*s) + { + case 'l': + longarg = true; + break; + case 'x': + { + long n = longarg ? va_arg(vl,long) : va_arg(vl,int); + for(int i = 2*(longarg ? sizeof(long) : sizeof(int))-1; i >= 0; i--) + { + int d = (n >> (4*i)) & 0xF; + *out++ = (d < 10 ? '0'+d : 'A'+d-10); + } + longarg = false; + format = false; + break; + } + case 'd': + { + long n = longarg ? va_arg(vl,long) : va_arg(vl,int); + if(n < 0) + { + n = -n; + *out++ = '-'; + } + long digits = 1; + for(long nn = n ; nn /= 10; digits++); + for(int i = digits-1; i >= 0; i--) + { + out[i] = '0' + n%10; + n /= 10; + } + out += digits; + longarg = false; + format = false; + break; + } + case 's': + { + const char* s2 = va_arg(vl,const char*); + while(*s2) + *out++ = *s2++; + longarg = false; + format = false; + break; + } + case 'c': + { + *out++ = (char)va_arg(vl,int); + longarg = false; + format = false; + break; + } + default: + panic("bad fmt"); + } + } + else if(*s == '%') + format = true; + else + *out++ = *s; + } + *out++ = '\0'; +} + +void printk(const char* s, ...) +{ + va_list vl; + va_start(vl,s); + + char out[1024]; // XXX + vsprintk(out,s,vl); + cons_write(out,strlen(out)); + + va_end(vl); +} + +void sprintk(char* out, const char* s, ...) +{ + va_list vl; + va_start(vl,s); + + vsprintk(out,s,vl); + + va_end(vl); +} + +void dump_tf(trapframe_t* tf) +{ + static const char* regnames[] = { + "z ", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" + }; + + tf->gpr[0] = 0; + + for(int i = 0; i < 32; i+=4) + { + for(int j = 0; j < 4; j++) + printk("%s %lx%c",regnames[i+j],tf->gpr[i+j],j < 3 ? ' ' : '\n'); + } + printk("sr %lx pc %lx va %lx\n",tf->sr,tf->epc,tf->badvaddr); +} + +void init_tf(trapframe_t* tf, long pc, long sp) +{ + memset(tf,0,sizeof(*tf)); + tf->sr = SR_S | SR_KX | SR_UX; // SR_PS=0 (usermode); SR_ET=0 + tf->gpr[29] = USER_MEM_SIZE-USER_MAINVARS_SIZE; + tf->epc = USER_START; +} + +void bss_init() +{ + extern char edata,end; + memset(&edata,0,&end-&edata); +} + +void mainvars_init() +{ + sysret_t r = frontend_syscall(SYS_getmainvars, + USER_MEM_SIZE-USER_MAINVARS_SIZE, USER_MAINVARS_SIZE, 0, 0); + + kassert(r.result == 0); +} + +void jump_usrstart() +{ + trapframe_t tf; + init_tf(&tf, USER_START, USER_MEM_SIZE-USER_MAINVARS_SIZE); + pop_tf(&tf); +} + +void boot() +{ + bss_init(); + file_init(); + mainvars_init(); + jump_usrstart(); +} diff --git a/pk/pk.h b/pk/pk.h new file mode 100644 index 0000000..dfe68f7 --- /dev/null +++ b/pk/pk.h @@ -0,0 +1,39 @@ +#ifndef _PK_H +#define _PK_H + +typedef struct +{ + long gpr[32]; + long sr; + long epc; + long badvaddr; +} trapframe_t; + +#define USER_MEM_SIZE 0x70000000 +#define USER_MAINVARS_SIZE 0x1000 +#define USER_START 0x10000 + +#define panic(s,...) do { printk(s"\n", ##__VA_ARGS__); sys_exit(-1); } while(0) +#define kassert(cond) do { if(!(cond)) panic("assertion failed: "#cond); } while(0) + +#ifdef __cplusplus +extern "C" { +#endif + +void printk(const char* s, ...); +void init_tf(trapframe_t*, long pc, long sp); +void pop_tf(trapframe_t*); +void dump_tf(trapframe_t*); + +void unhandled_trap(trapframe_t*); +void handle_syscall(trapframe_t*); +void handle_breakpoint(trapframe_t*); +void boot(); + +void sys_exit(int code) __attribute__((noreturn)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pk/pk.ld b/pk/pk.ld new file mode 100644 index 0000000..f1ec715 --- /dev/null +++ b/pk/pk.ld @@ -0,0 +1,186 @@ +OUTPUT_ARCH( "mips:riscv" ) + +ENTRY( __start ) + +GROUP( -lc -lgloss -lgcc ) + + +SECTIONS +{ + + /*--------------------------------------------------------------------*/ + /* Code and read-only segment */ + /*--------------------------------------------------------------------*/ + + /* Begining of code and text segment */ + . = 0x00000000; + .boottext : + { + *(.boottext) + } + + . = 0x70000000; + _ftext = .; + PROVIDE( eprol = . ); + + /* text: Program code section */ + .text : + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + /* init: Code to execute before main (called by crt1.S) */ + .init : + { + KEEP( *(.init) ) + } + + /* fini: Code to execute after main (called by crt1.S) */ + .fini : + { + KEEP( *(.fini) ) + } + + /* rodata: Read-only data */ + .rodata : + { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + } + + /* End of code and read-only segment */ + PROVIDE( etext = . ); + _etext = .; + + /*--------------------------------------------------------------------*/ + /* Global constructor/destructor segement */ + /*--------------------------------------------------------------------*/ + /* The .ctors/.dtors sections are special sections which contain a + list of constructor/destructor function pointers. crtbegin.o + includes code in a .init section which goes through the .ctors list + and calls each constuctor. crtend.o includes code in a .fini + section which goes through the .dtors list and calls each + destructor. crtbegin.o includes a special null pointer in its own + .ctors/.dtors sections which acts as a start indicator for those + lists. crtend.o also includes a special null pointer in its own + .ctors/.dtors sections which acts as an end indictor. The linker + commands below are setup so that crtbegin.o's .ctors/.dtors + sections are always first and crtend.o's .ctors/.dtors sections are + always last. This is the only way the list of functions will have + the begin and end indicators in the right place. */ + + /* ctors : Array of global constructor function pointers */ + .ctors : + { + KEEP( *crtbegin.o(.ctors) ) + KEEP( *(EXCLUDE_FILE(*crtend.o) .ctors) ) + KEEP( *(SORT(.ctors.*)) ) + KEEP( *(.ctors) ) + } + + /* dtors : Array of global destructor function pointers */ + .dtors : + { + KEEP( *crtbegin.o(.dtors) ) + KEEP( *(EXCLUDE_FILE(*crtend.o) .dtors) ) + KEEP( *(SORT(.dtors.*)) ) + KEEP( *(.dtors) ) + } + + /*--------------------------------------------------------------------*/ + /* Other misc gcc segments (this was in idt32.ld) */ + /*--------------------------------------------------------------------*/ + /* I am not quite sure about these sections but it seems they are for + C++ exception handling. I think .jcr is for "Java Class + Registration" but it seems to end up in C++ binaries as well. */ + + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : { KEEP( *(.eh_frame) ) } + .gcc_except_table : { *(.gcc_except_table) } + .jcr : { KEEP (*(.jcr)) } + + /*--------------------------------------------------------------------*/ + /* Initialized data segment */ + /*--------------------------------------------------------------------*/ + + /* Start of initialized data segment */ + . = ALIGN(16); + _fdata = .; + + /* data: Writable data */ + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + } + + /* lit4: Single precision floating point constants created by gas */ + .lit4 : + { + *(.lit4) + } + + /* lit8: Double precision floating point constants created by gas */ + .lit8 : + { + *(.lit8) + } + + /* End of initialized data segment */ + . = ALIGN(4); + PROVIDE( edata = . ); + _edata = .; + + /*--------------------------------------------------------------------*/ + /* Uninitialized data segment */ + /*--------------------------------------------------------------------*/ + + /* Start of uninitialized data segment */ + . = .; + _fbss = .; + + /* sbss: Uninitialized writeable small data section */ + . = .; + _sbss_start = .; + .sbss : + { + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + } + + /* bss: Uninitialized writeable data section */ + . = .; + _bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } + + /* End of uninitialized data segment (used by syscalls.c for heap) */ + PROVIDE( end = . ); + _end = .; + + /*--------------------------------------------------------------------*/ + /* Special gcc sections (this was in idt32.ld) */ + /*--------------------------------------------------------------------*/ + + .mdebug.abi32 0 : { KEEP(*(.mdebug.abi32)) } + .mdebug.abiN32 0 : { KEEP(*(.mdebug.abiN32)) } + .mdebug.abi64 0 : { KEEP(*(.mdebug.abi64)) } + .mdebug.abiO64 0 : { KEEP(*(.mdebug.abiO64)) } + .mdebug.eabi32 0 : { KEEP(*(.mdebug.eabi32)) } + .mdebug.eabi64 0 : { KEEP(*(.mdebug.eabi64)) } + .gcc_compiled_long32 0 : { KEEP(*(.gcc_compiled_long32)) } + .gcc_compiled_long64 0 : { KEEP(*(.gcc_compiled_long64)) } + +} diff --git a/pk/pk.mk.in b/pk/pk.mk.in new file mode 100644 index 0000000..a89ee2b --- /dev/null +++ b/pk/pk.mk.in @@ -0,0 +1,20 @@ +pk_subproject_deps = \ + +pk_hdrs = \ + pk.h \ + +pk_srcs = \ + pk.c \ + file.c \ + syscall.c \ + handlers.c \ + frontend.c \ + +pk_asm_srcs = \ + entry.S \ + boot.S \ + +pk_test_srcs = + +pk_install_prog_srcs = \ + riscv-pk.c \ diff --git a/pk/riscv-pk.c b/pk/riscv-pk.c new file mode 100644 index 0000000..b25b339 --- /dev/null +++ b/pk/riscv-pk.c @@ -0,0 +1,6 @@ +// force the linker to pull in our __start from boot.S. +void* dummy() +{ + extern void __start(); + return &__start; +} diff --git a/pk/syscall.c b/pk/syscall.c new file mode 100644 index 0000000..f14c2e4 --- /dev/null +++ b/pk/syscall.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include "pk.h" +#include "file.h" +#include "frontend.h" + +typedef sysret_t (*syscall_t)(long,long,long,long,long); + +void sys_exit(int code) +{ + frontend_syscall(SYS_exit,code,0,0,0); + panic("exit didn't exit!"); +} + +sysret_t sys_read(int fd, char* buf, size_t n) +{ + sysret_t r = {-1,EBADF}; + file_t* f = file_get(fd); + if(!f) + return r; + + return file_read(f,buf,n); +} + +sysret_t sys_write(int fd, const char* buf, size_t n) +{ + sysret_t r = {-1,EBADF}; + file_t* f = file_get(fd); + if(!f) + return r; + + return file_write(f,buf,n); +} + +sysret_t sys_open(const char* name, size_t len, int flags, int mode) +{ + sysret_t ret = file_open(name, len, flags, mode); + if(ret.result == -1) + return ret; + + if((ret.result = file_dup((file_t*)ret.result)) == -1) + ret.err = ENOMEM; + + return ret; +} + +sysret_t sys_close(int fd) +{ + return (sysret_t){fd_close(fd),EBADF}; +} + +sysret_t sys_fstat(int fd, void* st) +{ + sysret_t r = {-1,EBADF}; + file_t* f = file_get(fd); + if(!f) + return r; + + return file_stat(f,st); +} + +sysret_t sys_lseek(int fd, size_t ptr, int dir) +{ + sysret_t r = {-1,EBADF}; + file_t* f = file_get(fd); + if(!f) + return r; + + return file_lseek(f,ptr,dir); +} + +sysret_t sys_stat(const char* name, size_t len, void* st) +{ + return frontend_syscall(SYS_stat,(long)name,len,(long)st,0); +} + +sysret_t sys_lstat(const char* name, size_t len, void* st) +{ + return frontend_syscall(SYS_lstat,(long)name,len,(long)st,0); +} + +sysret_t sys_link(const char* old_name, size_t old_len, + const char* new_name, size_t new_len) +{ + return frontend_syscall(SYS_link,(long)old_name,old_len, + (long)new_name,new_len); +} + +sysret_t sys_unlink(const char* name, size_t len) +{ + return frontend_syscall(SYS_unlink,(long)name,len,0,0); +} + +void handle_syscall(trapframe_t* tf) +{ + const static void* syscall_table[] = { + [SYS_exit] = sys_exit, + [SYS_read] = sys_read, + [SYS_write] = sys_write, + [SYS_open] = sys_open, + [SYS_close] = sys_close, + [SYS_fstat] = sys_fstat, + [SYS_lseek] = sys_lseek, + [SYS_stat] = sys_stat, + [SYS_lstat] = sys_lstat, + [SYS_link] = sys_link, + [SYS_unlink] = sys_unlink, + }; + + syscall_t p; + unsigned long n = tf->gpr[2]; + if(n >= sizeof(syscall_table)/sizeof(void*) || !syscall_table[n]) + { + dump_tf(tf); + panic("bad syscall #%ld!",n); + } + else + p = (syscall_t)syscall_table[n]; + + sysret_t ret = p(tf->gpr[4],tf->gpr[5],tf->gpr[6],tf->gpr[7],n); + tf->gpr[2] = ret.result; + tf->gpr[3] = ret.result == -1 ? ret.err : 0; + + //printk("syscall %d (%x,%x,%x,%x) from %x == %d\n",n,tf->gpr[4],tf->gpr[5],tf->gpr[6],tf->gpr[7],tf->gpr[31],tf->gpr[2]); + + tf->epc += 4; + pop_tf(tf); +} -- cgit v1.1