254 lines
6.0 KiB
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();
|
|
}
|