summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMole Shang <[email protected]>2024-01-18 17:35:27 +0800
committerMole Shang <[email protected]>2024-01-18 17:35:27 +0800
commit493159b9bb1a764926daa49fb09bff8f29e8e9e5 (patch)
treebcae49e20df0ab9d86dab9bd10226807cc432f88
parent33ca12a4653752d179e6296c7ca2f91a626d30f3 (diff)
downloadxv6-labs-syscall.tar.gz
xv6-labs-syscall.tar.bz2
xv6-labs-syscall.zip
lab syscall: finishsyscall
-rw-r--r--Makefile3
-rw-r--r--answers-syscall.txt9
-rw-r--r--kernel/defs.h6
-rw-r--r--kernel/kalloc.c14
-rw-r--r--kernel/proc.c20
-rw-r--r--kernel/proc.h1
-rw-r--r--kernel/syscall.c38
-rw-r--r--kernel/syscall.h2
-rw-r--r--kernel/sysinfo.c24
-rw-r--r--kernel/sysproc.c18
-rw-r--r--time.txt1
-rw-r--r--user/user.h3
-rwxr-xr-xuser/usys.pl2
13 files changed, 141 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 4f3fd54..def8b43 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,7 @@ OBJS = \
$K/trampoline.o \
$K/trap.o \
$K/syscall.o \
+ $K/sysinfo.o \
$K/sysproc.o \
$K/bio.o \
$K/fs.o \
@@ -193,6 +194,8 @@ UPROGS=\
$U/_primes\
$U/_find\
$U/_xargs\
+ $U/_trace\
+ $U/_sysinfotest\
diff --git a/answers-syscall.txt b/answers-syscall.txt
new file mode 100644
index 0000000..ca0ce77
--- /dev/null
+++ b/answers-syscall.txt
@@ -0,0 +1,9 @@
+usertrap()
+7
+SYS_exec
+user mode
+lw a3,0(zero)
+a3
+no
+yes, `scause` 0xd -> interrupt = 0, exception code = 13 -> instruction page fault (riscv-priviledged p71)
+'initcode', 1
diff --git a/kernel/defs.h b/kernel/defs.h
index a3c962b..c8eeef3 100644
--- a/kernel/defs.h
+++ b/kernel/defs.h
@@ -8,6 +8,7 @@ struct spinlock;
struct sleeplock;
struct stat;
struct superblock;
+struct sysinfo;
// bio.c
void binit(void);
@@ -63,6 +64,7 @@ void ramdiskrw(struct buf*);
void* kalloc(void);
void kfree(void *);
void kinit(void);
+int get_freemem(void);
// log.c
void initlog(int, struct superblock*);
@@ -106,6 +108,7 @@ void yield(void);
int either_copyout(int user_dst, uint64 dst, void *src, uint64 len);
int either_copyin(void *dst, int user_src, uint64 src, uint64 len);
void procdump(void);
+int get_nproc(void);
// swtch.S
void swtch(struct context*, struct context*);
@@ -141,6 +144,9 @@ int fetchstr(uint64, char*, int);
int fetchaddr(uint64, uint64*);
void syscall();
+// sysinfo.c
+int sys_info(uint64);
+
// trap.c
extern uint ticks;
void trapinit(void);
diff --git a/kernel/kalloc.c b/kernel/kalloc.c
index 0699e7e..c2fdb86 100644
--- a/kernel/kalloc.c
+++ b/kernel/kalloc.c
@@ -80,3 +80,17 @@ kalloc(void)
memset((char*)r, 5, PGSIZE); // fill with junk
return (void*)r;
}
+
+int
+get_freemem(void)
+{
+ int n;
+ struct run *r;
+
+ acquire(&kmem.lock);
+ for (n = 0, r = kmem.freelist; r; r = r->next)
+ n++;
+ release(&kmem.lock);
+
+ return n * PGSIZE;
+}
diff --git a/kernel/proc.c b/kernel/proc.c
index 58a8a0b..5aa616f 100644
--- a/kernel/proc.c
+++ b/kernel/proc.c
@@ -299,6 +299,9 @@ fork(void)
// copy saved user registers.
*(np->trapframe) = *(p->trapframe);
+ // inherit trace_mask
+ np->trace_mask = p->trace_mask;
+
// Cause fork to return 0 in the child.
np->trapframe->a0 = 0;
@@ -686,3 +689,20 @@ procdump(void)
printf("\n");
}
}
+
+int
+get_nproc(void)
+{
+ int n = 0;
+ struct proc *p;
+
+ for(int i = 0; i < NPROC; i++) {
+ p = &proc[i];
+ acquire(&p->lock);
+ if(p->state != UNUSED)
+ n++;
+ release(&p->lock);
+ }
+
+ return n;
+}
diff --git a/kernel/proc.h b/kernel/proc.h
index d021857..4a2ca6c 100644
--- a/kernel/proc.h
+++ b/kernel/proc.h
@@ -91,6 +91,7 @@ struct proc {
int killed; // If non-zero, have been killed
int xstate; // Exit status to be returned to parent's wait
int pid; // Process ID
+ int trace_mask; // SYS_trace mask (1 << SYS_xxx)
// wait_lock must be held when using this:
struct proc *parent; // Parent process
diff --git a/kernel/syscall.c b/kernel/syscall.c
index ed65409..94ae997 100644
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -101,6 +101,8 @@ extern uint64 sys_unlink(void);
extern uint64 sys_link(void);
extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
+extern uint64 sys_trace(void);
+extern uint64 sys_sysinfo(void);
// An array mapping syscall numbers from syscall.h
// to the function that handles the system call.
@@ -126,6 +128,35 @@ static uint64 (*syscalls[])(void) = {
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
+[SYS_trace] sys_trace,
+[SYS_sysinfo] sys_sysinfo,
+};
+
+// syscall name maps for SYS_trace:
+static char *syscall_names[] = {
+[SYS_fork] "fork",
+[SYS_exit] "exit",
+[SYS_wait] "wait",
+[SYS_pipe] "pipe",
+[SYS_read] "read",
+[SYS_kill] "kill",
+[SYS_exec] "exec",
+[SYS_fstat] "fstat",
+[SYS_chdir] "chdir",
+[SYS_dup] "dup",
+[SYS_getpid] "getpid",
+[SYS_sbrk] "sbrk",
+[SYS_sleep] "sleep",
+[SYS_uptime] "uptime",
+[SYS_open] "open",
+[SYS_write] "write",
+[SYS_mknod] "mknod",
+[SYS_unlink] "unlink",
+[SYS_link] "link",
+[SYS_mkdir] "mkdir",
+[SYS_close] "close",
+[SYS_trace] "trace",
+[SYS_sysinfo] "sysinfo",
};
void
@@ -139,6 +170,13 @@ syscall(void)
// Use num to lookup the system call function for num, call it,
// and store its return value in p->trapframe->a0
p->trapframe->a0 = syscalls[num]();
+
+ // SYS_trace: match all the syscalls which number < mask asked
+ // p->trace_mask == 1 << SYS_xxx
+ if(p->trace_mask >> num) {
+ printf("%d: syscall %s -> %d\n", p->pid, syscall_names[num], p->trapframe->a0);
+ }
+
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
diff --git a/kernel/syscall.h b/kernel/syscall.h
index bc5f356..0dfedc7 100644
--- a/kernel/syscall.h
+++ b/kernel/syscall.h
@@ -20,3 +20,5 @@
#define SYS_link 19
#define SYS_mkdir 20
#define SYS_close 21
+#define SYS_trace 22
+#define SYS_sysinfo 23
diff --git a/kernel/sysinfo.c b/kernel/sysinfo.c
new file mode 100644
index 0000000..c66324d
--- /dev/null
+++ b/kernel/sysinfo.c
@@ -0,0 +1,24 @@
+#include "types.h"
+#include "riscv.h"
+#include "param.h"
+#include "spinlock.h"
+#include "defs.h"
+#include "sysinfo.h"
+#include "proc.h"
+
+// Get current system info
+// addr is a user virtual address, pointing to a struct sysinfo.
+int
+sys_info(uint64 addr) {
+ struct proc *p = myproc();
+ struct sysinfo info;
+
+ // Fill nums into the sysinfo struct
+ info.freemem = get_freemem();
+ info.nproc = get_nproc();
+
+ if(copyout(p->pagetable, addr, (char *)&info, sizeof(info)) < 0)
+ return -1;
+ return 0;
+}
+
diff --git a/kernel/sysproc.c b/kernel/sysproc.c
index 3b4d5bd..fd2e069 100644
--- a/kernel/sysproc.c
+++ b/kernel/sysproc.c
@@ -91,3 +91,21 @@ sys_uptime(void)
release(&tickslock);
return xticks;
}
+
+uint64
+sys_trace(void)
+{
+ argint(0, &myproc()->trace_mask);
+
+ return -(myproc()->trace_mask <= 1);
+}
+
+uint64
+sys_sysinfo(void)
+{
+ uint64 si; // user pointer to struct sysinfo
+
+ argaddr(0, &si);
+ return sys_info(si);
+}
+
diff --git a/time.txt b/time.txt
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/time.txt
@@ -0,0 +1 @@
+4
diff --git a/user/user.h b/user/user.h
index 4d398d5..14f69e5 100644
--- a/user/user.h
+++ b/user/user.h
@@ -1,4 +1,5 @@
struct stat;
+struct sysinfo;
// system calls
int fork(void);
@@ -22,6 +23,8 @@ int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);
+int trace(int);
+int sysinfo(struct sysinfo*);
// ulib.c
int stat(const char*, struct stat*);
diff --git a/user/usys.pl b/user/usys.pl
index 01e426e..bc109fd 100755
--- a/user/usys.pl
+++ b/user/usys.pl
@@ -36,3 +36,5 @@ entry("getpid");
entry("sbrk");
entry("sleep");
entry("uptime");
+entry("trace");
+entry("sysinfo");