primitive fork and exit system calls

This commit is contained in:
rtm 2006-06-15 16:02:20 +00:00
parent cb83c71628
commit a4c03dea09
12 changed files with 166 additions and 37 deletions

View file

@ -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

1
Notes
View file

@ -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

16
defs.h
View file

@ -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);

33
main.c
View file

@ -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;
}

35
proc.c
View file

@ -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("switching\n");
cprintf("swtch %x -> %x\n", curproc, np);
curproc = np;
// XXX callee-saved registers?

1
proc.h
View file

@ -32,3 +32,4 @@ struct proc{
};
extern struct proc proc[];
extern struct proc *curproc;

View file

@ -1,3 +1,6 @@
#include "types.h"
#include "defs.h"
void *
memcpy(void *dst, void *src, unsigned n)
{

50
syscall.c Normal file
View file

@ -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;
}
}

2
syscall.h Normal file
View file

@ -0,0 +1,2 @@
#define SYS_fork 1
#define SYS_exit 2

30
trap.c
View file

@ -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
}

View file

@ -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

26
traps.h Normal file
View file

@ -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