summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtm <rtm>2006-06-15 16:02:20 +0000
committerrtm <rtm>2006-06-15 16:02:20 +0000
commita4c03dea09b7b5f2463147e979d20b035b81de96 (patch)
tree3ba362f412faf45f0fb0e93b72f613ecc3956193
parentcb83c71628378bc0e295dd71bf6641379fbcdf37 (diff)
downloadxv6-labs-a4c03dea09b7b5f2463147e979d20b035b81de96.tar.gz
xv6-labs-a4c03dea09b7b5f2463147e979d20b035b81de96.tar.bz2
xv6-labs-a4c03dea09b7b5f2463147e979d20b035b81de96.zip
primitive fork and exit system calls
-rw-r--r--Makefile5
-rw-r--r--Notes1
-rw-r--r--defs.h16
-rw-r--r--main.c33
-rw-r--r--proc.c35
-rw-r--r--proc.h1
-rw-r--r--string.c3
-rw-r--r--syscall.c50
-rw-r--r--syscall.h2
-rw-r--r--trap.c30
-rw-r--r--trapasm.S1
-rw-r--r--traps.h26
12 files changed, 166 insertions, 37 deletions
diff --git a/Makefile b/Makefile
index 22636ea..2a8c3ce 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,11 @@
-OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o
+OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o \
+ syscall.o
CC = i386-jos-elf-gcc
LD = i386-jos-elf-ld
OBJCOPY = i386-jos-elf-objcopy
OBJDUMP = i386-jos-elf-objdump
-CFLAGS = -nostdinc -I. -O
+CFLAGS = -nostdinc -I. -O -Wall
xv6.img : bootblock kernel
dd if=/dev/zero of=xv6.img count=10000
diff --git a/Notes b/Notes
index 4c06e74..06a9696 100644
--- a/Notes
+++ b/Notes
@@ -40,6 +40,7 @@ one segment array per cpu, or per process?
pass curproc explicitly, or implicit from cpu #?
e.g. argument to newproc()?
+ hmm, you need a global curproc[cpu] for trap() &c
test stack expansion
test running out of memory, process slots
diff --git a/defs.h b/defs.h
index ec41bfe..ad51167 100644
--- a/defs.h
+++ b/defs.h
@@ -1,6 +1,7 @@
// kalloc.c
char *kalloc(int n);
void kfree(char *cp, int len);
+void kinit(void);
// console.c
void cprintf(char *fmt, ...);
@@ -8,5 +9,16 @@ void panic(char *s);
// proc.c
struct proc;
-void setupsegs(struct proc *p);
-struct proc * newproc(struct proc *op);
+void setupsegs(struct proc *);
+struct proc * newproc(void);
+void swtch(void);
+
+// trap.c
+void tinit(void);
+
+// string.c
+void * memcpy(void *dst, void *src, unsigned n);
+void * memset(void *dst, int c, unsigned n);
+
+// syscall.c
+void syscall(void);
diff --git a/main.c b/main.c
index 3c75389..6b07d83 100644
--- a/main.c
+++ b/main.c
@@ -4,12 +4,16 @@
#include "proc.h"
#include "defs.h"
#include "x86.h"
+#include "traps.h"
+#include "syscall.h"
extern char edata[], end[];
+int
main()
{
struct proc *p;
+ int i;
// clear BSS
memset(edata, 0, end - edata);
@@ -27,6 +31,7 @@ main()
// create fake process zero
p = &proc[0];
+ curproc = p;
p->state = WAITING;
p->sz = PAGE;
p->mem = kalloc(p->sz);
@@ -39,14 +44,28 @@ main()
p->tf->tf_eflags = FL_IF;
setupsegs(p);
- p = newproc(&proc[0]);
- // xxx copy instructions to p->mem
- p->mem[0] = 0x90; // nop
- p->mem[1] = 0x90; // nop
- p->mem[2] = 0x42; // inc %edx
- p->mem[3] = 0x42; // inc %edx
+ p = newproc();
+
+ i = 0;
+ p->mem[i++] = 0x90; // nop
+ p->mem[i++] = 0xb8; // mov ..., %eax
+ p->mem[i++] = SYS_fork;
+ p->mem[i++] = 0;
+ p->mem[i++] = 0;
+ p->mem[i++] = 0;
+ p->mem[i++] = 0xcd; // int
+ p->mem[i++] = T_SYSCALL;
+ p->mem[i++] = 0xb8; // mov ..., %eax
+ p->mem[i++] = SYS_exit;
+ p->mem[i++] = 0;
+ p->mem[i++] = 0;
+ p->mem[i++] = 0;
+ p->mem[i++] = 0xcd; // int
+ p->mem[i++] = T_SYSCALL;
p->tf->tf_eip = 0;
p->tf->tf_esp = p->sz;
- swtch(&proc[0]);
+ swtch();
+
+ return 0;
}
diff --git a/proc.c b/proc.c
index 2b43237..1e90e37 100644
--- a/proc.c
+++ b/proc.c
@@ -6,6 +6,7 @@
#include "defs.h"
struct proc proc[NPROC];
+struct proc *curproc;
/*
* set up a process's task state and segment descriptors
@@ -25,7 +26,8 @@ setupsegs(struct proc *p)
p->gdt[0] = SEG_NULL;
p->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
p->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
- p->gdt[SEG_TSS] = SEG16(STS_T32A, (unsigned) &p->ts, sizeof(p->ts), 0);
+ p->gdt[SEG_TSS] = SEG16(STS_T32A, (unsigned) &p->ts,
+ sizeof(p->ts), 0);
p->gdt[SEG_TSS].sd_s = 0;
p->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (unsigned)p->mem, p->sz, 3);
p->gdt[SEG_UDATA] = SEG(STA_W, (unsigned)p->mem, p->sz, 3);
@@ -41,7 +43,7 @@ extern void trapret();
* sets up the stack to return as if from system call.
*/
struct proc *
-newproc(struct proc *op)
+newproc()
{
struct proc *np;
unsigned *sp;
@@ -52,29 +54,30 @@ newproc(struct proc *op)
if(np >= &proc[NPROC])
return 0;
- np->sz = op->sz;
- np->mem = kalloc(op->sz);
+ np->sz = curproc->sz;
+ np->mem = kalloc(curproc->sz);
if(np->mem == 0)
return 0;
- memcpy(np->mem, op->mem, np->sz);
+ memcpy(np->mem, curproc->mem, np->sz);
np->kstack = kalloc(KSTACKSIZE);
if(np->kstack == 0){
- kfree(np->mem, op->sz);
+ kfree(np->mem, curproc->sz);
return 0;
}
- np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe));
setupsegs(np);
- np->state = RUNNABLE;
// set up kernel stack to return to user space
- *(np->tf) = *(op->tf);
+ np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe));
+ *(np->tf) = *(curproc->tf);
sp = (unsigned *) np->tf;
*(--sp) = (unsigned) &trapret; // for return from swtch()
*(--sp) = 0; // previous bp for leave in swtch()
np->esp = (unsigned) sp;
np->ebp = (unsigned) sp;
- cprintf("newproc esp %x ebp %x mem %x\n", np->esp, np->ebp, np->mem);
+ np->state = RUNNABLE;
+
+ cprintf("newproc %x\n", np);
return np;
}
@@ -83,12 +86,12 @@ newproc(struct proc *op)
* find a runnable process and switch to it.
*/
void
-swtch(struct proc *op)
+swtch()
{
struct proc *np;
while(1){
- for(np = op + 1; np != op; np++){
+ for(np = curproc + 1; np != curproc; np++){
if(np == &proc[NPROC])
np = &proc[0];
if(np->state == RUNNABLE)
@@ -99,10 +102,12 @@ swtch(struct proc *op)
// idle...
}
- op->ebp = read_ebp();
- op->esp = read_esp();
+ curproc->ebp = read_ebp();
+ curproc->esp = read_esp();
+
+ cprintf("swtch %x -> %x\n", curproc, np);
- cprintf("switching\n");
+ curproc = np;
// XXX callee-saved registers?
diff --git a/proc.h b/proc.h
index e5c230c..39e1c49 100644
--- a/proc.h
+++ b/proc.h
@@ -32,3 +32,4 @@ struct proc{
};
extern struct proc proc[];
+extern struct proc *curproc;
diff --git a/string.c b/string.c
index aef4242..f27b025 100644
--- a/string.c
+++ b/string.c
@@ -1,3 +1,6 @@
+#include "types.h"
+#include "defs.h"
+
void *
memcpy(void *dst, void *src, unsigned n)
{
diff --git a/syscall.c b/syscall.c
new file mode 100644
index 0000000..9cb20dc
--- /dev/null
+++ b/syscall.c
@@ -0,0 +1,50 @@
+#include "types.h"
+#include "param.h"
+#include "mmu.h"
+#include "proc.h"
+#include "defs.h"
+#include "x86.h"
+#include "traps.h"
+#include "syscall.h"
+
+/*
+ * User code makes a system call with INT T_SYSCALL.
+ * System call number in %eax.
+ * Arguments on the stack.
+ *
+ * Return value? Error indication? Errno?
+ */
+
+void
+sys_fork()
+{
+ newproc();
+}
+
+void
+sys_exit()
+{
+ curproc->state = UNUSED;
+ // XXX free resources. notify parent. abandon children.
+ swtch();
+}
+
+void
+syscall()
+{
+ int num = curproc->tf->tf_regs.reg_eax;
+
+ cprintf("%x sys %d\n", curproc, num);
+ switch(num){
+ case SYS_fork:
+ sys_fork();
+ break;
+ case SYS_exit:
+ sys_exit();
+ break;
+ default:
+ cprintf("unknown sys call %d\n", num);
+ // XXX fault
+ break;
+ }
+}
diff --git a/syscall.h b/syscall.h
new file mode 100644
index 0000000..3155dbd
--- /dev/null
+++ b/syscall.h
@@ -0,0 +1,2 @@
+#define SYS_fork 1
+#define SYS_exit 2
diff --git a/trap.c b/trap.c
index ace4c95..89c6bf5 100644
--- a/trap.c
+++ b/trap.c
@@ -4,6 +4,7 @@
#include "proc.h"
#include "defs.h"
#include "x86.h"
+#include "traps.h"
struct Gatedesc idt[256];
struct Pseudodesc idt_pd = { 0, sizeof(idt) - 1, (unsigned) &idt };
@@ -12,29 +13,36 @@ extern unsigned vectors[]; /* vectors.S, array of 256 entry point addresses */
extern void trapenter();
extern void trapenter1();
-
-int xx;
-
void
tinit()
{
int i;
- xx = 0;
for(i = 0; i < 256; i++){
- SETGATE(idt[i], 1, SEG_KCODE << 3, vectors[i], 3);
+ SETGATE(idt[i], 1, SEG_KCODE << 3, vectors[i], 0);
}
+ SETGATE(idt[T_SYSCALL], T_SYSCALL, SEG_KCODE << 3, vectors[48], 3);
asm volatile("lidt %0" : : "g" (idt_pd.pd_lim));
}
void
trap(struct Trapframe *tf)
{
- /* which process are we running? */
- if(xx < 10)
- cprintf("%d\n", tf->tf_trapno);
- xx++;
- //while(1)
- //;
+ int v = tf->tf_trapno;
+ cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip);
+
+ if(v == T_SYSCALL){
+ curproc->tf = tf;
+ syscall();
+ return;
+ }
+
+ if(v == 32){
+ // probably clock
+ return;
+ }
+
+ while(1)
+ ;
// XXX probably ought to lgdt on trap return
}
diff --git a/trapasm.S b/trapasm.S
index c75ab39..c01cec0 100644
--- a/trapasm.S
+++ b/trapasm.S
@@ -13,6 +13,7 @@ alltraps:
movw %ax,%es # segments
pushl %esp # pass pointer to this trapframe
call trap # and call trap()
+ addl $4, %esp
# return falls through to trapret...
.globl trapret
diff --git a/traps.h b/traps.h
new file mode 100644
index 0000000..a81903c
--- /dev/null
+++ b/traps.h
@@ -0,0 +1,26 @@
+// system defined:
+#define T_DIVIDE 0 // divide error
+#define T_DEBUG 1 // debug exception
+#define T_NMI 2 // non-maskable interrupt
+#define T_BRKPT 3 // breakpoint
+#define T_OFLOW 4 // overflow
+#define T_BOUND 5 // bounds check
+#define T_ILLOP 6 // illegal opcode
+#define T_DEVICE 7 // device not available
+#define T_DBLFLT 8 // double fault
+/* #define T_COPROC 9 */ // reserved (not generated by recent processors)
+#define T_TSS 10 // invalid task switch segment
+#define T_SEGNP 11 // segment not present
+#define T_STACK 12 // stack exception
+#define T_GPFLT 13 // genernal protection fault
+#define T_PGFLT 14 // page fault
+/* #define T_RES 15 */ // reserved
+#define T_FPERR 16 // floating point error
+#define T_ALIGN 17 // aligment check
+#define T_MCHK 18 // machine check
+#define T_SIMDERR 19 // SIMD floating point error
+
+// These are arbitrarily chosen, but with care not to overlap
+// processor defined exceptions or interrupt vectors.
+#define T_SYSCALL 48 // system call
+#define T_DEFAULT 500 // catchall