diff --git a/bootmain.c b/bootmain.c index 4a70652..8985776 100644 --- a/bootmain.c +++ b/bootmain.c @@ -45,18 +45,18 @@ cmain(void) readseg((uint32_t) ELFHDR, SECTSIZE*8, 0); // is this a valid ELF? - if (ELFHDR->e_magic != ELF_MAGIC) + if (ELFHDR->magic != ELF_MAGIC) goto bad; // load each program segment (ignores ph flags) - ph = (struct Proghdr *) ((uint8_t *) ELFHDR + ELFHDR->e_phoff); - eph = ph + ELFHDR->e_phnum; + ph = (struct Proghdr *) ((uint8_t *) ELFHDR + ELFHDR->phoff); + eph = ph + ELFHDR->phnum; for (; ph < eph; ph++) - readseg(ph->p_va, ph->p_memsz, ph->p_offset); + readseg(ph->va, ph->memsz, ph->offset); // call the entry point from the ELF header // note: does not return! - ((void (*)(void)) (ELFHDR->e_entry & 0xFFFFFF))(); + ((void (*)(void)) (ELFHDR->entry & 0xFFFFFF))(); bad: outw(0x8A00, 0x8A00); diff --git a/defs.h b/defs.h index cb129a4..0288a62 100644 --- a/defs.h +++ b/defs.h @@ -64,6 +64,8 @@ int cpu(void); struct spinlock; void acquire(struct spinlock * lock); void release(struct spinlock * lock); +void acquire1(struct spinlock * lock, struct proc *); +void release1(struct spinlock * lock, struct proc *); // main.c void load_icode(struct proc *p, uint8_t *binary, unsigned size); diff --git a/elf.h b/elf.h index ea9f964..cbcf38e 100644 --- a/elf.h +++ b/elf.h @@ -1,43 +1,39 @@ -#ifndef JOS_INC_ELF_H -#define JOS_INC_ELF_H - #define ELF_MAGIC 0x464C457FU /* "\x7FELF" in little endian */ struct Elf { - uint32_t e_magic; // must equal ELF_MAGIC - uint8_t e_elf[12]; - uint16_t e_type; - uint16_t e_machine; - uint32_t e_version; - uint32_t e_entry; - uint32_t e_phoff; - uint32_t e_shoff; - uint32_t e_flags; - uint16_t e_ehsize; - uint16_t e_phentsize; - uint16_t e_phnum; - uint16_t e_shentsize; - uint16_t e_shnum; - uint16_t e_shstrndx; + uint32_t magic; // must equal ELF_MAGIC + uint8_t elf[12]; + uint16_t type; + uint16_t machine; + uint32_t version; + uint32_t entry; + uint32_t phoff; + uint32_t shoff; + uint32_t flags; + uint16_t ehsize; + uint16_t phentsize; + uint16_t phnum; + uint16_t shentsize; + uint16_t shnum; + uint16_t shstrndx; }; struct Proghdr { - uint32_t p_type; - uint32_t p_offset; - uint32_t p_va; - uint32_t p_pa; - uint32_t p_filesz; - uint32_t p_memsz; - uint32_t p_flags; - uint32_t p_align; + uint32_t type; + uint32_t offset; + uint32_t va; + uint32_t pa; + uint32_t filesz; + uint32_t memsz; + uint32_t flags; + uint32_t align; }; -// Values for Proghdr::p_type +// Values for Proghdr type #define ELF_PROG_LOAD 1 -// Flag bits for Proghdr::p_flags +// Flag bits for Proghdr flags #define ELF_PROG_FLAG_EXEC 1 #define ELF_PROG_FLAG_WRITE 2 #define ELF_PROG_FLAG_READ 4 -#endif /* !JOS_INC_ELF_H */ diff --git a/main.c b/main.c index 5f2d698..63e8e35 100644 --- a/main.c +++ b/main.c @@ -62,9 +62,9 @@ main() p->kstack = kalloc(KSTACKSIZE); p->tf = (struct Trapframe *) (p->kstack + KSTACKSIZE - sizeof(struct Trapframe)); memset(p->tf, 0, sizeof(struct Trapframe)); - p->tf->tf_es = p->tf->tf_ds = p->tf->tf_ss = (SEG_UDATA << 3) | 3; - p->tf->tf_cs = (SEG_UCODE << 3) | 3; - p->tf->tf_eflags = FL_IF; + p->tf->es = p->tf->ds = p->tf->ss = (SEG_UDATA << 3) | 3; + p->tf->cs = (SEG_UCODE << 3) | 3; + p->tf->eflags = FL_IF; p->pid = 0; p->ppid = 0; setupsegs(p); @@ -103,26 +103,26 @@ load_icode(struct proc *p, uint8_t *binary, unsigned size) // 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) + cprintf("elf %x magic %x\n", elf, elf->magic); + if (elf->magic != ELF_MAGIC) panic("load_icode: not an ELF binary"); - p->tf->tf_eip = elf->e_entry; - p->tf->tf_esp = p->sz; + p->tf->eip = elf->entry; + p->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) + ph = (struct Proghdr*) (binary + elf->phoff); + for (i = 0; i < elf->phnum; i++, ph++) { + if (ph->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) + cprintf("va %x memsz %d\n", ph->va, ph->memsz); + if (ph->va + ph->memsz < ph->va) panic("load_icode: overflow in elf header segment"); - if (ph->p_va + ph->p_memsz >= p->sz) + if (ph->va + ph->memsz >= p->sz) panic("load_icode: icode wants to be above UTOP"); // Load/clear the segment - memmove(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); + memmove(p->mem + ph->va, binary + ph->offset, ph->filesz); + memset(p->mem + ph->va + ph->filesz, 0, ph->memsz - ph->filesz); } } diff --git a/mmu.h b/mmu.h index 776db23..b90a9e3 100644 --- a/mmu.h +++ b/mmu.h @@ -147,19 +147,19 @@ // Segment Descriptors struct Segdesc { - unsigned sd_lim_15_0 : 16; // Low bits of segment limit - unsigned sd_base_15_0 : 16; // Low bits of segment base address - unsigned sd_base_23_16 : 8; // Middle bits of segment base address - unsigned sd_type : 4; // Segment type (see STS_ constants) - unsigned sd_s : 1; // 0 = system, 1 = application - unsigned sd_dpl : 2; // Descriptor Privilege Level - unsigned sd_p : 1; // Present - unsigned sd_lim_19_16 : 4; // High bits of segment limit - unsigned sd_avl : 1; // Unused (available for software use) - unsigned sd_rsv1 : 1; // Reserved - unsigned sd_db : 1; // 0 = 16-bit segment, 1 = 32-bit segment - unsigned sd_g : 1; // Granularity: limit scaled by 4K when set - unsigned sd_base_31_24 : 8; // High bits of segment base address + unsigned lim_15_0 : 16; // Low bits of segment limit + unsigned base_15_0 : 16; // Low bits of segment base address + unsigned base_23_16 : 8; // Middle bits of segment base address + unsigned type : 4; // Segment type (see STS_ constants) + unsigned s : 1; // 0 = system, 1 = application + unsigned dpl : 2; // Descriptor Privilege Level + unsigned p : 1; // Present + unsigned lim_19_16 : 4; // High bits of segment limit + unsigned avl : 1; // Unused (available for software use) + unsigned rsv1 : 1; // Reserved + unsigned db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + unsigned g : 1; // Granularity: limit scaled by 4K when set + unsigned base_31_24 : 8; // High bits of segment base address }; // Null segment #define SEG_NULL (struct Segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } @@ -210,56 +210,56 @@ struct Segdesc { // Task state segment format (as described by the Pentium architecture book) struct Taskstate { - uint32_t ts_link; // Old ts selector - uintptr_t ts_esp0; // Stack pointers and segment selectors - uint16_t ts_ss0; // after an increase in privilege level - uint16_t ts_padding1; - uintptr_t ts_esp1; - uint16_t ts_ss1; - uint16_t ts_padding2; - uintptr_t ts_esp2; - uint16_t ts_ss2; - uint16_t ts_padding3; - physaddr_t ts_cr3; // Page directory base - uintptr_t ts_eip; // Saved state from last task switch - uint32_t ts_eflags; - uint32_t ts_eax; // More saved state (registers) - uint32_t ts_ecx; - uint32_t ts_edx; - uint32_t ts_ebx; - uintptr_t ts_esp; - uintptr_t ts_ebp; - uint32_t ts_esi; - uint32_t ts_edi; - uint16_t ts_es; // Even more saved state (segment selectors) - uint16_t ts_padding4; - uint16_t ts_cs; - uint16_t ts_padding5; - uint16_t ts_ss; - uint16_t ts_padding6; - uint16_t ts_ds; - uint16_t ts_padding7; - uint16_t ts_fs; - uint16_t ts_padding8; - uint16_t ts_gs; - uint16_t ts_padding9; - uint16_t ts_ldt; - uint16_t ts_padding10; - uint16_t ts_t; // Trap on task switch - uint16_t ts_iomb; // I/O map base address + uint32_t link; // Old ts selector + uintptr_t esp0; // Stack pointers and segment selectors + uint16_t ss0; // after an increase in privilege level + uint16_t padding1; + uintptr_t esp1; + uint16_t ss1; + uint16_t padding2; + uintptr_t esp2; + uint16_t ss2; + uint16_t padding3; + physaddr_t cr3; // Page directory base + uintptr_t eip; // Saved state from last task switch + uint32_t eflags; + uint32_t eax; // More saved state (registers) + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uintptr_t esp; + uintptr_t ebp; + uint32_t esi; + uint32_t edi; + uint16_t es; // Even more saved state (segment selectors) + uint16_t padding4; + uint16_t cs; + uint16_t padding5; + uint16_t ss; + uint16_t padding6; + uint16_t ds; + uint16_t padding7; + uint16_t fs; + uint16_t padding8; + uint16_t gs; + uint16_t padding9; + uint16_t ldt; + uint16_t padding10; + uint16_t t; // Trap on task switch + uint16_t iomb; // I/O map base address }; // Gate descriptors for interrupts and traps struct Gatedesc { - unsigned gd_off_15_0 : 16; // low 16 bits of offset in segment - unsigned gd_ss : 16; // segment selector - unsigned gd_args : 5; // # args, 0 for interrupt/trap gates - unsigned gd_rsv1 : 3; // reserved(should be zero I guess) - unsigned gd_type : 4; // type(STS_{TG,IG32,TG32}) - unsigned gd_s : 1; // must be 0 (system) - unsigned gd_dpl : 2; // descriptor(meaning new) privilege level - unsigned gd_p : 1; // Present - unsigned gd_off_31_16 : 16; // high bits of offset in segment + unsigned off_15_0 : 16; // low 16 bits of offset in segment + unsigned ss : 16; // segment selector + unsigned args : 5; // # args, 0 for interrupt/trap gates + unsigned rsv1 : 3; // reserved(should be zero I guess) + unsigned type : 4; // type(STS_{TG,IG32,TG32}) + unsigned s : 1; // must be 0 (system) + unsigned dpl : 2; // descriptor(meaning new) privilege level + unsigned p : 1; // Present + unsigned off_31_16 : 16; // high bits of offset in segment }; // Set up a normal interrupt/trap gate descriptor. @@ -269,38 +269,38 @@ struct Gatedesc { // - dpl: Descriptor Privilege Level - // the privilege level required for software to invoke // this interrupt/trap gate explicitly using an int instruction. -#define SETGATE(gate, istrap, sel, off, dpl) \ +#define SETGATE(gate, istrap, sel, off, d) \ { \ - (gate).gd_off_15_0 = (uint32_t) (off) & 0xffff; \ - (gate).gd_ss = (sel); \ - (gate).gd_args = 0; \ - (gate).gd_rsv1 = 0; \ - (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32; \ - (gate).gd_s = 0; \ - (gate).gd_dpl = (dpl); \ - (gate).gd_p = 1; \ - (gate).gd_off_31_16 = (uint32_t) (off) >> 16; \ + (gate).off_15_0 = (uint32_t) (off) & 0xffff; \ + (gate).ss = (sel); \ + (gate).args = 0; \ + (gate).rsv1 = 0; \ + (gate).type = (istrap) ? STS_TG32 : STS_IG32; \ + (gate).s = 0; \ + (gate).dpl = (d); \ + (gate).p = 1; \ + (gate).off_31_16 = (uint32_t) (off) >> 16; \ } // Set up a call gate descriptor. -#define SETCALLGATE(gate, ss, off, dpl) \ +#define SETCALLGATE(gate, ss, off, d) \ { \ - (gate).gd_off_15_0 = (uint32_t) (off) & 0xffff; \ - (gate).gd_ss = (ss); \ - (gate).gd_args = 0; \ - (gate).gd_rsv1 = 0; \ - (gate).gd_type = STS_CG32; \ - (gate).gd_s = 0; \ - (gate).gd_dpl = (dpl); \ - (gate).gd_p = 1; \ - (gate).gd_off_31_16 = (uint32_t) (off) >> 16; \ + (gate).off_15_0 = (uint32_t) (off) & 0xffff; \ + (gate).ss = (ss); \ + (gate).args = 0; \ + (gate).rsv1 = 0; \ + (gate).type = STS_CG32; \ + (gate).s = 0; \ + (gate).dpl = (d); \ + (gate).p = 1; \ + (gate).off_31_16 = (uint32_t) (off) >> 16; \ } // Pseudo-descriptors used for LGDT, LLDT and LIDT instructions. struct Pseudodesc { - uint16_t pd__garbage; // LGDT supposed to be from address 4N+2 - uint16_t pd_lim; // Limit - uint32_t pd_base __attribute__ ((packed)); // Base address + uint16_t _garbage; // LGDT supposed to be from address 4N+2 + uint16_t lim; // Limit + uint32_t base __attribute__ ((packed)); // Base address }; #define PD_ADDR(desc) (&(desc).pd_lim) diff --git a/proc.c b/proc.c index 31de6fc..f24f4f8 100644 --- a/proc.c +++ b/proc.c @@ -25,8 +25,8 @@ void setupsegs(struct proc *p) { memset(&p->ts, 0, sizeof(struct Taskstate)); - p->ts.ts_ss0 = SEG_KDATA << 3; - p->ts.ts_esp0 = (unsigned)(p->kstack + KSTACKSIZE); + p->ts.ss0 = SEG_KDATA << 3; + p->ts.esp0 = (unsigned)(p->kstack + KSTACKSIZE); // XXX it may be wrong to modify the current segment table! @@ -35,12 +35,12 @@ setupsegs(struct proc *p) 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].sd_s = 0; + p->gdt[SEG_TSS].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); - p->gdt_pd.pd__garbage = 0; - p->gdt_pd.pd_lim = sizeof(p->gdt) - 1; - p->gdt_pd.pd_base = (unsigned) p->gdt; + p->gdt_pd._garbage = 0; + p->gdt_pd.lim = sizeof(p->gdt) - 1; + p->gdt_pd.base = (unsigned) p->gdt; } // Look in the process table for an UNUSED proc. @@ -107,12 +107,12 @@ copyproc(struct proc* p) *np->tf = *p->tf; // Clear %eax so that fork system call returns 0 in child. - np->tf->tf_regs.reg_eax = 0; + np->tf->regs.eax = 0; // Set up new jmpbuf to start executing at forkret (see below). memset(&np->jmpbuf, 0, sizeof np->jmpbuf); - np->jmpbuf.jb_eip = (unsigned)forkret; - np->jmpbuf.jb_esp = (unsigned)np->tf; + np->jmpbuf.eip = (unsigned)forkret; + np->jmpbuf.esp = (unsigned)np->tf; // Copy file descriptors for(i = 0; i < NOFILE; i++){ @@ -153,13 +153,13 @@ scheduler(void) // It can run on the other stack. // h/w sets busy bit in TSS descriptor sometimes, and faults // if it's set in LTR. so clear tss descriptor busy bit. - p->gdt[SEG_TSS].sd_type = STS_T32A; + p->gdt[SEG_TSS].type = STS_T32A; // XXX should probably have an lgdt() function in x86.h // to confine all the inline assembly. // XXX probably ought to lgdt on trap return too, in case // a system call has moved a program or changed its size. - asm volatile("lgdt %0" : : "g" (p->gdt_pd.pd_lim)); + asm volatile("lgdt %0" : : "g" (p->gdt_pd.lim)); ltr(SEG_TSS << 3); // Switch to chosen process. It is the process's job diff --git a/proc.h b/proc.h index 60ef7f5..72bdcf3 100644 --- a/proc.h +++ b/proc.h @@ -22,15 +22,15 @@ struct jmpbuf { // they are constant across kernel contexts // save all the regular registers so we don't care which are caller save // don't save eax because that's the return register - // layout known to swtch.S - int jb_ebx; - int jb_ecx; - int jb_edx; - int jb_esi; - int jb_edi; - int jb_esp; - int jb_ebp; - int jb_eip; + // layout known to setjmp.S + int ebx; + int ecx; + int edx; + int esi; + int edi; + int esp; + int ebp; + int eip; }; enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; diff --git a/syscall.c b/syscall.c index decf393..f86fa22 100644 --- a/syscall.c +++ b/syscall.c @@ -51,7 +51,7 @@ fetcharg(int argno, void *ip) { unsigned esp; - esp = (unsigned) curproc[cpu()]->tf->tf_esp; + esp = (unsigned) curproc[cpu()]->tf->esp; return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip); } @@ -263,7 +263,7 @@ void syscall(void) { struct proc *cp = curproc[cpu()]; - int num = cp->tf->tf_regs.reg_eax; + int num = cp->tf->regs.eax; int ret = -1; //cprintf("%x sys %d\n", cp, num); @@ -301,10 +301,13 @@ syscall(void) case SYS_panic: ret = sys_panic(); break; + case SYS_cons_puts: + ret = sys_cons_puts(); + break; default: cprintf("unknown sys call %d\n", num); // XXX fault break; } - cp->tf->tf_regs.reg_eax = ret; + cp->tf->regs.eax = ret; } diff --git a/trap.c b/trap.c index 4c8a4bd..74ea864 100644 --- a/trap.c +++ b/trap.c @@ -28,17 +28,17 @@ tvinit() void idtinit() { - asm volatile("lidt %0" : : "g" (idt_pd.pd_lim)); + asm volatile("lidt %0" : : "g" (idt_pd.lim)); } void trap(struct Trapframe *tf) { - int v = tf->tf_trapno; + int v = tf->trapno; if(v == T_SYSCALL){ struct proc *cp = curproc[cpu()]; - int num = cp->tf->tf_regs.reg_eax; + int num = cp->tf->regs.eax; if(cp == 0) panic("syscall with no proc"); if(cp->killed) @@ -78,7 +78,7 @@ trap(struct Trapframe *tf) // (If the kernel was executing at time of interrupt, // don't kill the process. Let the process get back // out to its regular system call return.) - if((tf->tf_cs&3) == 3 && cp->killed) + if((tf->cs&3) == 3 && cp->killed) proc_exit(); // Force process to give up CPU and let others run. diff --git a/x86.h b/x86.h index ee7e6ce..6c67df7 100644 --- a/x86.h +++ b/x86.h @@ -320,33 +320,33 @@ sti(void) struct PushRegs { /* registers as pushed by pusha */ - uint32_t reg_edi; - uint32_t reg_esi; - uint32_t reg_ebp; - uint32_t reg_oesp; /* Useless */ - uint32_t reg_ebx; - uint32_t reg_edx; - uint32_t reg_ecx; - uint32_t reg_eax; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t oesp; /* Useless */ + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; }; struct Trapframe { - struct PushRegs tf_regs; - uint16_t tf_es; - uint16_t tf_padding1; - uint16_t tf_ds; - uint16_t tf_padding2; - uint32_t tf_trapno; + struct PushRegs regs; + uint16_t es; + uint16_t padding1; + uint16_t ds; + uint16_t padding2; + uint32_t trapno; /* below here defined by x86 hardware */ - uint32_t tf_err; - uintptr_t tf_eip; - uint16_t tf_cs; - uint16_t tf_padding3; - uint32_t tf_eflags; + uint32_t err; + uintptr_t eip; + uint16_t cs; + uint16_t padding3; + uint32_t eflags; /* below here only when crossing rings, such as from user to kernel */ - uintptr_t tf_esp; - uint16_t tf_ss; - uint16_t tf_padding4; + uintptr_t esp; + uint16_t ss; + uint16_t padding4; }; #define MAX_IRQS 16 // Number of IRQs