compile "user programs"

curproc array
This commit is contained in:
rtm 2006-06-22 20:47:23 +00:00
parent bf49aedbed
commit df5cc91659
11 changed files with 139 additions and 64 deletions

View file

@ -20,18 +20,22 @@ bootblock : bootasm.S bootmain.c
$(OBJCOPY) -S -O binary bootblock.o bootblock $(OBJCOPY) -S -O binary bootblock.o bootblock
./sign.pl bootblock ./sign.pl bootblock
kernel : $(OBJS) bootother.S kernel : $(OBJS) bootother.S user1
$(CC) -nostdinc -I. -c bootother.S $(CC) -nostdinc -I. -c bootother.S
$(LD) -N -e start -Ttext 0x7000 -o bootother.out bootother.o $(LD) -N -e start -Ttext 0x7000 -o bootother.out bootother.o
$(OBJCOPY) -S -O binary bootother.out bootother $(OBJCOPY) -S -O binary bootother.out bootother
$(OBJDUMP) -S bootother.o > bootother.asm $(OBJDUMP) -S bootother.o > bootother.asm
$(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary bootother $(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary bootother user1
$(OBJDUMP) -S kernel > kernel.asm $(OBJDUMP) -S kernel > kernel.asm
vectors.S : vectors.pl vectors.S : vectors.pl
perl vectors.pl > vectors.S perl vectors.pl > vectors.S
user1 : user1.c
$(CC) -nostdinc -I. -c user1.c
$(LD) -N -e main -Ttext 0 -o user1 user1.o
-include *.d -include *.d
clean : clean :
rm -f *.o bootblock kernel kernel.asm xv6.img *.d rm -f *.o bootblock kernel kernel.asm xv6.img *.d user1

4
defs.h
View file

@ -33,7 +33,7 @@ void pic_init(void);
// mp.c // mp.c
void mp_init(void); void mp_init(void);
int lapic_cpu_number(void); int cpu(void);
int mp_isbcpu(void); int mp_isbcpu(void);
// spinlock.c // spinlock.c
@ -42,3 +42,5 @@ void acquire_spinlock(uint32_t* lock);
void release_spinlock(uint32_t* lock); void release_spinlock(uint32_t* lock);
void release_grant_spinlock(uint32_t* lock, int cpu); void release_grant_spinlock(uint32_t* lock, int cpu);
// main.c
void load_icode(struct proc *p, uint8_t *binary, unsigned size);

54
main.c
View file

@ -6,9 +6,13 @@
#include "x86.h" #include "x86.h"
#include "traps.h" #include "traps.h"
#include "syscall.h" #include "syscall.h"
#include "elf.h"
#include "param.h"
extern char edata[], end[]; extern char edata[], end[];
extern int acpu; extern int acpu;
extern char _binary_user1_start[];
extern char _binary_user1_size[];
char buf[512]; char buf[512];
@ -16,12 +20,14 @@ int
main() main()
{ {
struct proc *p; struct proc *p;
int i;
if (acpu) { if (acpu) {
cprintf("an application processor\n"); cprintf("an application processor\n");
release_spinlock(&kernel_lock); release_spinlock(&kernel_lock);
while (1) ; acquire_spinlock(&kernel_lock);
lapic_init(cpu());
curproc[cpu()] = &proc[0]; // XXX
swtch();
} }
acpu = 1; acpu = 1;
// clear BSS // clear BSS
@ -34,11 +40,9 @@ main()
tinit(); // traps and interrupts tinit(); // traps and interrupts
pic_init(); pic_init();
while (1);
// create fake process zero // create fake process zero
p = &proc[0]; p = &proc[0];
curproc = p; curproc[cpu()] = p;
p->state = WAITING; p->state = WAITING;
p->sz = PAGE; p->sz = PAGE;
p->mem = kalloc(p->sz); p->mem = kalloc(p->sz);
@ -54,17 +58,20 @@ main()
setupsegs(p); setupsegs(p);
// turn on interrupts // turn on interrupts
irq_setmask_8259A(0xff);
write_eflags(read_eflags() | FL_IF); write_eflags(read_eflags() | FL_IF);
irq_setmask_8259A(0);
#if 0 #if 0
ide_read(0, buf, 1); ide_read(0, buf, 1);
cprintf("sec0.0 %x\n", buf[0] & 0xff); cprintf("sec0.0 %x\n", buf[0] & 0xff);
#endif #endif
#if 0 #if 1
p = newproc(); p = newproc();
load_icode(p, _binary_user1_start, (unsigned) _binary_user1_size);
#endif
#if 0
i = 0; i = 0;
p->mem[i++] = 0x90; // nop p->mem[i++] = 0x90; // nop
p->mem[i++] = 0xb8; // mov ..., %eax p->mem[i++] = 0xb8; // mov ..., %eax
@ -96,3 +103,36 @@ main()
return 0; return 0;
} }
void
load_icode(struct proc *p, uint8_t *binary, unsigned size)
{
int i;
struct Elf *elf;
struct Proghdr *ph;
// Check magic number on binary
elf = (struct Elf*) binary;
cprintf("elf %x magic %x\n", elf, elf->e_magic);
if (elf->e_magic != ELF_MAGIC)
panic("load_icode: not an ELF binary");
p->tf->tf_eip = elf->e_entry;
p->tf->tf_esp = p->sz;
// Map and load segments as directed.
ph = (struct Proghdr*) (binary + elf->e_phoff);
for (i = 0; i < elf->e_phnum; i++, ph++) {
if (ph->p_type != ELF_PROG_LOAD)
continue;
cprintf("va %x memsz %d\n", ph->p_va, ph->p_memsz);
if (ph->p_va + ph->p_memsz < ph->p_va)
panic("load_icode: overflow in elf header segment");
if (ph->p_va + ph->p_memsz >= p->sz)
panic("load_icode: icode wants to be above UTOP");
// Load/clear the segment
memcpy(p->mem + ph->p_va, binary + ph->p_offset, ph->p_filesz);
memset(p->mem + ph->p_va + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz);
}
}

32
mp.c
View file

@ -97,7 +97,7 @@ static uint32_t *lapicaddr;
static struct cpu { static struct cpu {
uint8_t apicid; /* Local APIC ID */ uint8_t apicid; /* Local APIC ID */
int lintr[2]; /* Local APIC */ int lintr[2]; /* Local APIC */
} cpu[NCPU]; } cpus[NCPU];
static int ncpu; static int ncpu;
static struct cpu *bcpu; static struct cpu *bcpu;
@ -113,7 +113,7 @@ lapic_write(int r, int data)
*(lapicaddr+(r/sizeof(*lapicaddr))) = data; *(lapicaddr+(r/sizeof(*lapicaddr))) = data;
} }
static void void
lapic_init(int c) lapic_init(int c)
{ {
uint32_t r, lvt; uint32_t r, lvt;
@ -131,8 +131,8 @@ lapic_init(int c)
* LINT[01] are set to ExtINT. * LINT[01] are set to ExtINT.
* Acknowledge any outstanding interrupts. * Acknowledge any outstanding interrupts.
*/ */
lapic_write(LAPIC_LINT0, cpu[c].lintr[0]); lapic_write(LAPIC_LINT0, cpus[c].lintr[0]);
lapic_write(LAPIC_LINT1, cpu[c].lintr[1]); lapic_write(LAPIC_LINT1, cpus[c].lintr[1]);
lapic_write(LAPIC_EOI, 0); lapic_write(LAPIC_EOI, 0);
lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF; lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF;
@ -168,7 +168,7 @@ lapic_online(void)
} }
int int
lapic_cpu_number(void) cpu(void)
{ {
return (lapic_read(LAPIC_ID)>>24) & 0xFF; return (lapic_read(LAPIC_ID)>>24) & 0xFF;
} }
@ -312,12 +312,12 @@ mp_init()
switch(*p){ switch(*p){
case MPPROCESSOR: case MPPROCESSOR:
proc = (struct MPPE *) p; proc = (struct MPPE *) p;
cpu[ncpu].apicid = proc->apicid; cpus[ncpu].apicid = proc->apicid;
cpu[ncpu].lintr[0] = APIC_IMASK; cpus[ncpu].lintr[0] = APIC_IMASK;
cpu[ncpu].lintr[1] = APIC_IMASK; cpus[ncpu].lintr[1] = APIC_IMASK;
cprintf("a processor %x\n", cpu[ncpu].apicid); cprintf("a processor %x\n", cpus[ncpu].apicid);
if (proc->flags & MPBP) { if (proc->flags & MPBP) {
bcpu = &cpu[ncpu]; bcpu = &cpus[ncpu];
} }
ncpu++; ncpu++;
p += sizeof(struct MPPE); p += sizeof(struct MPPE);
@ -342,8 +342,8 @@ mp_init()
} }
} }
lapic_init(cpu-bcpu); lapic_init(bcpu-cpus);
cprintf("ncpu: %d boot %d\n", ncpu, cpu-bcpu); cprintf("ncpu: %d boot %d\n", ncpu, bcpu-cpus);
lapic_online(); lapic_online();
@ -352,12 +352,12 @@ mp_init()
(uint32_t) _binary_bootother_size); (uint32_t) _binary_bootother_size);
acquire_spinlock(&kernel_lock); acquire_spinlock(&kernel_lock);
for (c = cpu; c < &cpu[ncpu]; c++) { for (c = cpus; c < &cpus[ncpu]; c++) {
if (c == bcpu) continue; if (c == bcpu) continue;
cprintf ("starting processor %d\n", c - cpu); cprintf ("starting processor %d\n", c - cpus);
release_grant_spinlock(&kernel_lock, c - cpu); release_grant_spinlock(&kernel_lock, c - cpus);
lapic_startap(c, (uint32_t) KADDR(APBOOTCODE)); lapic_startap(c, (uint32_t) KADDR(APBOOTCODE));
acquire_spinlock(&kernel_lock); acquire_spinlock(&kernel_lock);
cprintf ("done starting processor %d\n", c - cpu); cprintf ("done starting processor %d\n", c - cpus);
} }
} }

46
proc.c
View file

@ -1,12 +1,12 @@
#include "types.h" #include "types.h"
#include "mmu.h" #include "mmu.h"
#include "x86.h" #include "x86.h"
#include "proc.h"
#include "param.h" #include "param.h"
#include "proc.h"
#include "defs.h" #include "defs.h"
struct proc proc[NPROC]; struct proc proc[NPROC];
struct proc *curproc; struct proc *curproc[NCPU];
int next_pid = 1; int next_pid = 1;
/* /*
@ -47,6 +47,7 @@ struct proc *
newproc() newproc()
{ {
struct proc *np; struct proc *np;
struct proc *op = curproc[cpu()];
unsigned *sp; unsigned *sp;
for(np = &proc[1]; np < &proc[NPROC]; np++) for(np = &proc[1]; np < &proc[NPROC]; np++)
@ -56,22 +57,22 @@ newproc()
return 0; return 0;
np->pid = next_pid++; np->pid = next_pid++;
np->ppid = curproc->pid; np->ppid = op->pid;
np->sz = curproc->sz; np->sz = op->sz;
np->mem = kalloc(curproc->sz); np->mem = kalloc(op->sz);
if(np->mem == 0) if(np->mem == 0)
return 0; return 0;
memcpy(np->mem, curproc->mem, np->sz); memcpy(np->mem, op->mem, np->sz);
np->kstack = kalloc(KSTACKSIZE); np->kstack = kalloc(KSTACKSIZE);
if(np->kstack == 0){ if(np->kstack == 0){
kfree(np->mem, curproc->sz); kfree(np->mem, op->sz);
return 0; return 0;
} }
setupsegs(np); setupsegs(np);
// set up kernel stack to return to user space // set up kernel stack to return to user space
np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe)); np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe));
*(np->tf) = *(curproc->tf); *(np->tf) = *(op->tf);
sp = (unsigned *) np->tf; sp = (unsigned *) np->tf;
*(--sp) = (unsigned) &trapret; // for return from swtch() *(--sp) = (unsigned) &trapret; // for return from swtch()
*(--sp) = 0; // previous bp for leave in swtch() *(--sp) = 0; // previous bp for leave in swtch()
@ -92,31 +93,38 @@ void
swtch() swtch()
{ {
struct proc *np; struct proc *np;
struct proc *op = curproc[cpu()];
cprintf("swtch cpu %d op %x proc0 %x\n", cpu(), op, proc);
while(1){ while(1){
for(np = curproc + 1; np != curproc; np++){ np = op + 1;
if(np == &proc[NPROC]) while(np != op){
np = &proc[0];
if(np->state == RUNNABLE) if(np->state == RUNNABLE)
break; break;
np++;
if(np == &proc[NPROC])
np = &proc[0];
} }
if(np->state == RUNNABLE) if(np->state == RUNNABLE)
break; break;
// idle... cprintf("swtch: nothing to run\n");
release_spinlock(&kernel_lock);
acquire_spinlock(&kernel_lock);
} }
curproc->ebp = read_ebp(); op->ebp = read_ebp();
curproc->esp = read_esp(); op->esp = read_esp();
cprintf("swtch %x -> %x\n", curproc, np); cprintf("cpu %d swtch %x -> %x\n", cpu(), op, np);
curproc = np; curproc[cpu()] = np;
np->state = RUNNING;
// XXX callee-saved registers? // XXX callee-saved registers?
// h/w sets busy bit in TSS descriptor sometimes, and faults // h/w sets busy bit in TSS descriptor sometimes, and faults
// if it's set in LTR. so clear tss descriptor busy bit. // if it's set in LTR. so clear tss descriptor busy bit.
curproc->gdt[SEG_TSS].sd_type = STS_T32A; np->gdt[SEG_TSS].sd_type = STS_T32A;
// XXX probably ought to lgdt on trap return too, in case // XXX probably ought to lgdt on trap return too, in case
// a system call has moved a program or changed its size. // a system call has moved a program or changed its size.
@ -134,8 +142,8 @@ swtch()
void void
sleep(void *chan) sleep(void *chan)
{ {
curproc->chan = chan; curproc[cpu()]->chan = chan;
curproc->state = WAITING; curproc[cpu()]->state = WAITING;
swtch(); swtch();
} }

4
proc.h
View file

@ -20,7 +20,7 @@ struct proc{
char *mem; // start of process's physical memory char *mem; // start of process's physical memory
unsigned sz; // total size of mem, including kernel stack unsigned sz; // total size of mem, including kernel stack
char *kstack; // kernel stack, separate from mem so it doesn't move char *kstack; // kernel stack, separate from mem so it doesn't move
enum { UNUSED, RUNNABLE, WAITING, ZOMBIE } state; enum { UNUSED, RUNNABLE, WAITING, ZOMBIE, RUNNING } state;
int pid; int pid;
int ppid; int ppid;
void *chan; // sleep void *chan; // sleep
@ -35,4 +35,4 @@ struct proc{
}; };
extern struct proc proc[]; extern struct proc proc[];
extern struct proc *curproc; extern struct proc *curproc[NCPU];

View file

@ -10,18 +10,18 @@ uint32_t kernel_lock = LOCK_FREE;
void void
acquire_spinlock(uint32_t* lock) acquire_spinlock(uint32_t* lock)
{ {
int cpu_id = lapic_cpu_number(); int cpu_id = cpu();
cprintf ("acquire: %d\n", cpu_id);
if (*lock == cpu_id) if (*lock == cpu_id)
return; return;
while ( cmpxchg(LOCK_FREE, cpu_id, lock) != cpu_id ) { ; } while ( cmpxchg(LOCK_FREE, cpu_id, lock) != cpu_id ) { ; }
cprintf ("acquired: %d\n", cpu_id);
} }
void void
release_spinlock(uint32_t* lock) release_spinlock(uint32_t* lock)
{ {
int cpu_id = lapic_cpu_number(); int cpu_id = cpu();
cprintf ("release: %d\n", cpu_id); cprintf ("release: %d\n", cpu_id);
if (*lock != cpu_id) if (*lock != cpu_id)
panic("release_spinlock: releasing a lock that i don't own\n"); panic("release_spinlock: releasing a lock that i don't own\n");
@ -31,7 +31,7 @@ release_spinlock(uint32_t* lock)
void void
release_grant_spinlock(uint32_t* lock, int c) release_grant_spinlock(uint32_t* lock, int c)
{ {
int cpu_id = lapic_cpu_number(); int cpu_id = cpu();
cprintf ("release_grant: %d -> %d\n", cpu_id, c); cprintf ("release_grant: %d -> %d\n", cpu_id, c);
if (*lock != cpu_id) if (*lock != cpu_id)
panic("release_spinlock: releasing a lock that i don't own\n"); panic("release_spinlock: releasing a lock that i don't own\n");

View file

@ -25,17 +25,18 @@ void
sys_exit() sys_exit()
{ {
struct proc *p; struct proc *p;
struct proc *cp = curproc[cpu()];
curproc->state = ZOMBIE; cp->state = ZOMBIE;
// wake up parent // wake up parent
for(p = proc; p < &proc[NPROC]; p++) for(p = proc; p < &proc[NPROC]; p++)
if(p->pid == curproc->ppid) if(p->pid == cp->ppid)
wakeup(p); wakeup(p);
// abandon children // abandon children
for(p = proc; p < &proc[NPROC]; p++) for(p = proc; p < &proc[NPROC]; p++)
if(p->ppid == curproc->pid) if(p->ppid == cp->pid)
p->pid = 1; p->pid = 1;
swtch(); swtch();
@ -45,37 +46,39 @@ void
sys_wait() sys_wait()
{ {
struct proc *p; struct proc *p;
struct proc *cp = curproc[cpu()];
int any; int any;
cprintf("waid pid %d ppid %d\n", curproc->pid, curproc->ppid); cprintf("waid pid %d ppid %d\n", cp->pid, cp->ppid);
while(1){ while(1){
any = 0; any = 0;
for(p = proc; p < &proc[NPROC]; p++){ for(p = proc; p < &proc[NPROC]; p++){
if(p->state == ZOMBIE && p->ppid == curproc->pid){ if(p->state == ZOMBIE && p->ppid == cp->pid){
kfree(p->mem, p->sz); kfree(p->mem, p->sz);
kfree(p->kstack, KSTACKSIZE); kfree(p->kstack, KSTACKSIZE);
p->state = UNUSED; p->state = UNUSED;
cprintf("%x collected %x\n", curproc, p); cprintf("%x collected %x\n", cp, p);
return; return;
} }
if(p->state != UNUSED && p->ppid == curproc->pid) if(p->state != UNUSED && p->ppid == cp->pid)
any = 1; any = 1;
} }
if(any == 0){ if(any == 0){
cprintf("%x nothing to wait for\n", curproc); cprintf("%x nothing to wait for\n", cp);
return; return;
} }
sleep(curproc); sleep(cp);
} }
} }
void void
syscall() syscall()
{ {
int num = curproc->tf->tf_regs.reg_eax; struct proc *cp = curproc[cpu()];
int num = cp->tf->tf_regs.reg_eax;
cprintf("%x sys %d\n", curproc, num); cprintf("%x sys %d\n", cp, num);
switch(num){ switch(num){
case SYS_fork: case SYS_fork:
sys_fork(); sys_fork();

5
trap.c
View file

@ -29,10 +29,13 @@ void
trap(struct Trapframe *tf) trap(struct Trapframe *tf)
{ {
int v = tf->tf_trapno; int v = tf->tf_trapno;
acquire_spinlock(&kernel_lock); // released in trapret in trapasm.S
cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip); cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip);
if(v == T_SYSCALL){ if(v == T_SYSCALL){
curproc->tf = tf; curproc[cpu()]->tf = tf;
syscall(); syscall();
return; return;
} }

View file

@ -22,6 +22,8 @@ alltraps:
* expects ESP to point to a Trapframe * expects ESP to point to a Trapframe
*/ */
trapret: trapret:
push $kernel_lock
call release_spinlock
popal popal
popl %es popl %es
popl %ds popl %ds

13
user1.c Normal file
View file

@ -0,0 +1,13 @@
void
fork()
{
asm("mov $1, %eax");
asm("int $48");
}
main()
{
fork();
while(1)
;
}