slkern/sysnew.c

254 lines
6.0 KiB
C

// This is NEW CODE implementing system calls (however the headers etc. still need to be refactored)
#include "syscall.h"
#include "types.h"
#include "riscv.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "sched.h"
#include "proc.h"
#include "drives.h"
#include "file.h"
#include "stat.h"
#include "kprintf.h"
//TODO: This is still using the "argfd" defined in sysfile.c for now.
int
argfd(int n, int *pfd, struct file **pf);
void* memcpy(void*, void*, long);
// new syscall added by Zak, sets the priority+limit of a process
// currently only works on the current process's pid!
uint64
sys_prio(void)
{
int tpid;
int newprio;
int newlimit;
argint(0, &tpid);
argint(1, &newprio);
argint(2, &newlimit);
if (tpid != myproc()->pid) {
return 0;
}
if (newprio >= NPRIO) {
newprio = NPRIO-1;
}
if (newlimit >= NPRIO) {
newlimit = NPRIO-1;
}
//struct proc* p = myproc();
if (newlimit < myproc()->maxprio) {
newlimit = myproc()->maxprio;
}
if (newprio < newlimit) {
newprio = newlimit;
}
myproc()->prio = newprio;
myproc()->maxprio = newlimit;
yield();
return 1;
}
uint64
sys_thrd(void)
{
int frompid;
uint64 fnc;
uint64 stk;
uint64 arg;
argint(0, &frompid);
argaddr(1, &fnc);
argaddr(2, &stk);
argaddr(3, &arg);
if (stk & 7) {
return -1;
}
if (frompid != myproc()->pid && !(myproc()->mainthread && frompid == myproc()->mainthread->pid)) {
return -1;
}
return thrd(fnc, stk, arg);
}
uint64
sys_affin(void)
{
int targetpid;
int range;
uint64 mask;
argint(0, &targetpid);
argint(1, &range);
argaddr(2, &mask);
if (targetpid != myproc()->pid || range != 0) {
return -1;
}
return affin(mask);
}
uint64 sys_drvinf() {
int driveid;
uint64 structaddr;
argint(0, &driveid);
argaddr(1, &structaddr);
// The actual information is first retrieved into a structure inside
// of kernel memory.
struct __syscdefs_driveinfo drvinf;
int result = drives_getinfo(myproc()->drives, driveid, &drvinf);
// The structure is copied whether the function succeeded or not, it
// will zero the structure on failure.
copyout(myproc()->pagetable, structaddr, (void*) &drvinf, sizeof(struct __syscdefs_driveinfo));
return result;
}
int readdirent(struct file* f, uint64 addr, int n) {
if (n != sizeof(fsformat_dirent_v1_t)) {
return -1;
}
if (f->type != FD_INODE || f->ip->type != T_DIR) {
return -1;
}
if (f->ip->instance->fsversion == 0) {
fsformat_dirent_v0_t dirent_old;
fsformat_dirent_v1_t dirent_new;
if (fsinstance_inode_read(f->ip, 0, (uint64) ((void*) &dirent_old), f->off, sizeof(fsformat_dirent_v0_t)) != sizeof(fsformat_dirent_v0_t)) {
return -1;
} else {
f->off += sizeof(fsformat_dirent_v0_t);
}
dirent_new.datainode = dirent_old.inodenumber;
dirent_new.metainode = -1;
memset(dirent_new.filename, 0, FSFORMAT_NAMESIZE_NEW);
memcpy(dirent_new.filename, dirent_old.filename, FSFORMAT_NAMESIZE_OLD);
copyout(myproc()->pagetable, addr, (void*) &dirent_new, sizeof(fsformat_dirent_v1_t));
return (int) sizeof(fsformat_dirent_v1_t);
} else {
if (fsinstance_inode_read(f->ip, 1, addr, f->off, n) != n) {
return -1;
}
f->off += sizeof(fsformat_dirent_v1_t);
return (int) sizeof(fsformat_dirent_v1_t);
}
}
uint64 sys_lsdir() {
struct file* f;
uint64 addr;
int size;
if (argfd(0, 0, &f) < 0) {
return -1;
}
argaddr(1, &addr);
argint(2, &size);
return readdirent(f, addr, size);
}
uint64 sys_kqueue1() {
int flags;
argint(0, &flags);
kprintf_panic("sys_kqueue1: TODO!");
return 0;
}
uint64 sys_kevent() {
kprintf_panic("sys_kevent: TODO!");
return 0;
}
// Definitions of old syscalls
uint64 sys_fork();
uint64 sys_exit();
uint64 sys_wait();
uint64 sys_pipe();
uint64 sys_read();
uint64 sys_kill();
uint64 sys_execve();
uint64 sys_fstat();
uint64 sys_chdir();
uint64 sys_dup();
uint64 sys_getpid();
uint64 sys_sbrk();
uint64 sys_sleep();
uint64 sys_uptime();
uint64 sys_open();
uint64 sys_write();
uint64 sys_mknod();
uint64 sys_unlink();
uint64 sys_link();
uint64 sys_mkdir();
uint64 sys_close();
typedef uint64 (*syscall_t)();
// The system is currently hard-coded to handle a table of exactly 64 syscalls.
// This number is convenient for masking in a 64-bit system.
syscall_t syscalls[64];
/* This is invoked when the syscall doesn't exist. */
uint64 sys_bad() {
printf("ERROR IN PROCESS %d '%s' BAD SYSCALL %d\n", myproc()->pid, myproc()->name, (int) myproc()->trapframe->a7);
return -1;
}
void syscall_init() {
int i;
for (i = 0 ; i < 64; i++) {
syscalls[i] = &sys_bad;
}
syscalls[SYS_fork] = &sys_fork;
syscalls[SYS_exit] = &sys_exit;
syscalls[SYS_wait] = &sys_wait;
syscalls[SYS_pipe] = &sys_pipe;
syscalls[SYS_read] = &sys_read;
syscalls[SYS_kill] = &sys_kill;
syscalls[SYS_execve] = &sys_execve;
syscalls[SYS_fstat] = &sys_fstat;
syscalls[SYS_chdir] = &sys_chdir;
syscalls[SYS_dup] = &sys_dup;
syscalls[SYS_getpid] = &sys_getpid;
syscalls[SYS_sbrk] = &sys_sbrk;
syscalls[SYS_sleep] = &sys_sleep;
syscalls[SYS_uptime] = &sys_uptime;
syscalls[SYS_open] = &sys_open;
syscalls[SYS_write] = &sys_write;
syscalls[SYS_mknod] = &sys_mknod;
syscalls[SYS_unlink] = &sys_unlink;
syscalls[SYS_link] = &sys_link;
syscalls[SYS_mkdir] = &sys_mkdir;
syscalls[SYS_close] = &sys_close;
// New system calls:
syscalls[SYS_prio] = &sys_prio;
syscalls[SYS_affin] = &sys_affin;
syscalls[SYS_thrd] = &sys_thrd;
syscalls[SYS_drvinf] = &sys_drvinf;
syscalls[SYS_lsdir] = &sys_lsdir;
syscalls[SYS_kqueue1] = &sys_kqueue1;
syscalls[SYS_kevent] = &sys_kevent;
}
// New syscall handling. This will just invoke sys_bad() if the syscall doesn't
// exist, this means there's one less error to check for.
void syscall() {
int x = myproc()->trapframe->a7;
//printf("Doing syscall #%d (0x%x)\n", x & 63, x & 63);
// TODO: This should be checked against a mask to allow and/or redirect syscalls.
syscall_t func = syscalls[x & 63];
//printf("Syscall func is at %p\n", func);
myproc()->trapframe->a0 = func();
}