diff --git a/asm.h b/asm.h index 879e40d..ddea060 100644 --- a/asm.h +++ b/asm.h @@ -11,9 +11,9 @@ .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) -#define STA_X 0x8 // Executable segment -#define STA_E 0x4 // Expand down (non-executable segments) -#define STA_C 0x4 // Conforming code segment (executable only) -#define STA_W 0x2 // Writeable (non-executable segments) -#define STA_R 0x2 // Readable (executable segments) -#define STA_A 0x1 // Accessed +#define STA_X 0x8 // Executable segment +#define STA_E 0x4 // Expand down (non-executable segments) +#define STA_C 0x4 // Conforming code segment (executable only) +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) +#define STA_A 0x1 // Accessed diff --git a/bio.c b/bio.c index 62675bf..ab5f41f 100644 --- a/bio.c +++ b/bio.c @@ -41,7 +41,8 @@ getblk(uint dev, uint sector) for(;;){ for(b = bufhead.next; b != &bufhead; b = b->next) - if((b->flags & (B_BUSY|B_VALID)) && b->dev == dev && b->sector == sector) + if((b->flags & (B_BUSY|B_VALID)) && + b->dev == dev && b->sector == sector) break; if(b != &bufhead){ diff --git a/bootasm.S b/bootasm.S index 7f1348d..9f03c4d 100644 --- a/bootasm.S +++ b/bootasm.S @@ -4,7 +4,7 @@ .set PROT_MODE_DSEG,0x10 # data segment selector .set CR0_PE_ON,0x1 # protected mode enable flag -################################################################################### +######################################################################### # ENTRY POINT # This code should be stored in the first sector of the hard disk. # After the BIOS initializes the hardware on startup or system reset, @@ -15,7 +15,7 @@ # # This code switches into 32-bit protected mode so that all of # memory can accessed, then calls into C. -################################################################################### +######################################################################### .globl start # Entry point start: @@ -32,13 +32,13 @@ start: # Set up the stack pointer, growing downward from 0x7c00. movw $start,%sp # Stack Pointer -#### Enable A20: -#### For fascinating historical reasons (related to the fact that -#### the earliest 8086-based PCs could only address 1MB of physical memory -#### and subsequent 80286-based PCs wanted to retain maximum compatibility), -#### physical address line 20 is tied to low when the machine boots. -#### Obviously this a bit of a drag for us, especially when trying to -#### address memory above 1MB. This code undoes this. + # Enable A20: + # For fascinating historical reasons (related to the fact that + # the earliest 8086-based PCs could only address 1MB of physical + # memory and subsequent 80286-based PCs wanted to retain maximum + # compatibility), physical address line 20 is tied to low when the + # machine boots. Obviously this a bit of a drag for us, especially + # when trying to address memory above 1MB. This code undoes this. seta20.1: inb $0x64,%al # Get status @@ -54,22 +54,22 @@ seta20.2: movb $0xdf,%al # Enable outb %al,$0x60 # A20 -#### Switch from real to protected mode -#### The descriptors in our GDT allow all physical memory to be accessed. -#### Furthermore, the descriptors have base addresses of 0, so that the -#### segment translation is a NOP, ie. virtual addresses are identical to -#### their physical addresses. With this setup, immediately after -#### enabling protected mode it will still appear to this code -#### that it is running directly on physical memory with no translation. -#### This initial NOP-translation setup is required by the processor -#### to ensure that the transition to protected mode occurs smoothly. + # Switch from real to protected mode + # The descriptors in our GDT allow all physical memory to be accessed. + # Furthermore, the descriptors have base addresses of 0, so that the + # segment translation is a NOP, ie. virtual addresses are identical to + # their physical addresses. With this setup, immediately after + # enabling protected mode it will still appear to this code + # that it is running directly on physical memory with no translation. + # This initial NOP-translation setup is required by the processor + # to ensure that the transition to protected mode occurs smoothly. real_to_prot: - cli # Mandatory since we dont set up an IDT - lgdt gdtdesc # load GDT -- mandatory in protected mode - movl %cr0, %eax # turn on protected mode - orl $CR0_PE_ON, %eax # - movl %eax, %cr0 # + cli # Mandatory since we dont set up an IDT + lgdt gdtdesc # load GDT -- mandatory in protected mode + movl %cr0, %eax # turn on protected mode + orl $CR0_PE_ON, %eax # + movl %eax, %cr0 # ### CPU magic: jump to relocation, flush prefetch queue, and reload %cs ### Has the effect of just jmp to the next instruction, but simultaneous ### loads CS with $PROT_MODE_CSEG. diff --git a/bootmain.c b/bootmain.c index c0c7a24..3a6f5b3 100644 --- a/bootmain.c +++ b/bootmain.c @@ -1,6 +1,3 @@ -#include "types.h" -#include "elf.h" -#include "x86.h" // This a dirt simple boot loader, whose sole job is to boot // an elf kernel image from the first IDE hard disk. // @@ -25,7 +22,12 @@ // * control starts in bootloader.S -- which sets up protected mode, // and a stack so C code then run, then calls cmain() // -// * cmain() in this file takes over, reads in the kernel and jumps to it. +// * cmain() in this file takes over, +// reads in the kernel and jumps to it. + +#include "types.h" +#include "elf.h" +#include "x86.h" #define SECTSIZE 512 #define ELFHDR ((struct elfhdr*) 0x10000) // scratch space diff --git a/bootother.S b/bootother.S index c5ab0bf..f5bd856 100644 --- a/bootother.S +++ b/bootother.S @@ -1,20 +1,17 @@ #include "asm.h" -/* - * Start an Application Processor. This must be placed on a 4KB boundary - * somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However, - * due to some shortcuts below it's restricted further to within the 1st - * 64KB. The AP starts in real-mode, with - * CS selector set to the startup memory address/16; - * CS base set to startup memory address; - * CS limit set to 64KB; - * CPL and IP set to 0. - * - * mp.c causes each non-boot CPU in turn to jump to start. - * mp.c puts the correct %esp in start-4, and the place to jump - * to in start-8. - * - */ +# Start an Application Processor. This must be placed on a 4KB boundary +# somewhere in the 1st MB of conventional memory (APBOOTSTRAP). However, +# due to some shortcuts below it's restricted further to within the 1st +# 64KB. The AP starts in real-mode, with +# CS selector set to the startup memory address/16; +# CS base set to startup memory address; +# CS limit set to 64KB; +# CPL and IP set to 0. +# +# mp.c causes each non-boot CPU in turn to jump to start. +# mp.c puts the correct %esp in start-4, and the place to jump +# to in start-8. .set PROT_MODE_CSEG,0x8 # code segment selector .set PROT_MODE_DSEG,0x10 # data segment selector @@ -22,39 +19,40 @@ .globl start start: - .code16 # This runs in real mode - cli # Disable interrupts - cld # String operations increment + .code16 # This runs in real mode + cli # Disable interrupts + cld # String operations increment # Set up the important data segment registers (DS, ES, SS). - xorw %ax,%ax # Segment number zero - movw %ax,%ds # -> Data Segment - movw %ax,%es # -> Extra Segment - movw %ax,%ss # -> Stack Segment + xorw %ax,%ax # Segment number zero + movw %ax,%ds # -> Data Segment + movw %ax,%es # -> Extra Segment + movw %ax,%ss # -> Stack Segment # Set up the stack pointer, growing downward from 0x7000-8. - movw $start-8,%sp # Stack Pointer + movw $start-8,%sp # Stack Pointer -#### Switch from real to protected mode -#### The descriptors in our GDT allow all physical memory to be accessed. -#### Furthermore, the descriptors have base addresses of 0, so that the -#### segment translation is a NOP, ie. virtual addresses are identical to -#### their physical addresses. With this setup, immediately after -#### enabling protected mode it will still appear to this code -#### that it is running directly on physical memory with no translation. -#### This initial NOP-translation setup is required by the processor -#### to ensure that the transition to protected mode occurs smoothly. + # Switch from real to protected mode + # The descriptors in our GDT allow all physical memory to be accessed. + # Furthermore, the descriptors have base addresses of 0, so that the + # segment translation is a NOP, ie. virtual addresses are identical to + # their physical addresses. With this setup, immediately after + # enabling protected mode it will still appear to this code + # that it is running directly on physical memory with no translation. + # This initial NOP-translation setup is required by the processor + # to ensure that the transition to protected mode occurs smoothly. - lgdt gdtdesc # load GDT -- mandatory in protected mode - movl %cr0, %eax # turn on protected mode - orl $CR0_PE_ON, %eax # - movl %eax, %cr0 # - ### CPU magic: jump to relocation, flush prefetch queue, and reload %cs - ### Has the effect of just jmp to the next instruction, but simultaneous - ### loads CS with $PROT_MODE_CSEG. + lgdt gdtdesc # load GDT -- mandatory in protected mode + movl %cr0, %eax # turn on protected mode + orl $CR0_PE_ON, %eax # + movl %eax, %cr0 # + + # CPU magic: jump to relocation, flush prefetch queue, and reload %cs + # Has the effect of just jmp to the next instruction, but simultaneous + # loads CS with $PROT_MODE_CSEG. ljmp $PROT_MODE_CSEG, $protcseg -#### we are in 32-bit protected mode (hence the .code32) +# We are now in 32-bit protected mode (hence the .code32) .code32 protcseg: # Set up the protected-mode data segment registers @@ -69,7 +67,7 @@ protcseg: movl start-4, %esp jmp *%eax -.p2align 2 # force 4 byte alignment +.p2align 2 # force 4 byte alignment gdt: SEG_NULLASM # null seg SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg diff --git a/fs.c b/fs.c index e94ae5e..a2fc767 100644 --- a/fs.c +++ b/fs.c @@ -450,7 +450,8 @@ writei(struct inode *ip, char *addr, uint off, uint n) // NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off. // return 0 if name doesn't exist. struct inode* -namei(char *path, int mode, uint *ret_off, char **ret_last, struct inode **ret_ip) +namei(char *path, int mode, uint *ret_off, + char **ret_last, struct inode **ret_ip) { struct inode *dp; struct proc *p = curproc[cpu()]; diff --git a/ioapic.h b/ioapic.h index f266f16..a85f810 100644 --- a/ioapic.h +++ b/ioapic.h @@ -1,5 +1,5 @@ -#define IO_APIC_BASE 0xFEC00000 // default physical locations of an IO APIC -#define IOAPIC_WINDOW 0x10 // window register offset +#define IO_APIC_BASE 0xFEC00000 // Default phys addr of IO APIC +#define IOAPIC_WINDOW 0x10 // Window register offset // Constants relating to APIC ID registers #define APIC_ID_MASK 0xff000000 diff --git a/lapic.c b/lapic.c index 38bb30a..8dc6d82 100644 --- a/lapic.c +++ b/lapic.c @@ -106,7 +106,8 @@ void lapic_timerinit(void) { lapic_write(LAPIC_TDCR, LAPIC_X1); - lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC | (IRQ_OFFSET + IRQ_TIMER)); + lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC | + (IRQ_OFFSET + IRQ_TIMER)); lapic_write(LAPIC_TCCR, 10000000); lapic_write(LAPIC_TICR, 10000000); } @@ -122,17 +123,19 @@ lapic_init(int c) { uint r, lvt; - lapic_write(LAPIC_DFR, 0xFFFFFFFF); // set destination format register - r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // read APIC ID - lapic_write(LAPIC_LDR, (1<>24) & 0xFF; // Read APIC ID + lapic_write(LAPIC_LDR, (1<>16) & 0xFF; if(lvt >= 4) @@ -143,7 +146,8 @@ lapic_init(int c) // Issue an INIT Level De-Assert to synchronise arbitration ID's. lapic_write(LAPIC_ICRHI, 0); - lapic_write(LAPIC_ICRLO, LAPIC_ALLINC|APIC_LEVEL|LAPIC_DEASSERT|APIC_INIT); + lapic_write(LAPIC_ICRLO, LAPIC_ALLINC|APIC_LEVEL| + LAPIC_DEASSERT|APIC_INIT); while(lapic_read(LAPIC_ICRLO) & APIC_DELIVS) ; } @@ -181,10 +185,12 @@ lapic_startap(uchar apicid, int v) crhi = apicid<<24; lapic_write(LAPIC_ICRHI, crhi); - lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|LAPIC_ASSERT|APIC_INIT); + lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL| + LAPIC_ASSERT|APIC_INIT); while(j++ < 10000) {;} - lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|LAPIC_DEASSERT|APIC_INIT); + lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL| + LAPIC_DEASSERT|APIC_INIT); while(j++ < 1000000) {;} diff --git a/ls.c b/ls.c index 6bee6b7..f42a165 100644 --- a/ls.c +++ b/ls.c @@ -58,7 +58,7 @@ main(int argc, char *argv[]) case T_DIR: sz = st.st_size; for(off = 0; off < sz; off += sizeof(struct dirent)) { - if(read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) { + if(read(fd, &dirent, sizeof dirent) != sizeof dirent) { printf(1, "ls: read error\n"); break; } diff --git a/mmu.h b/mmu.h index 770d3ee..037ce55 100644 --- a/mmu.h +++ b/mmu.h @@ -1,4 +1,5 @@ -// This file contains definitions for the x86 memory management unit (MMU). +// This file contains definitions for the +// x86 memory management unit (MMU). // Eflags register #define FL_CF 0x00000001 // Carry Flag @@ -41,7 +42,7 @@ struct segdesc { }; // Null segment -#define SEG_NULL (struct segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +#define SEG_NULL (struct segdesc){ 0,0,0,0,0,0,0,0,0,0,0,0,0 } // Normal segment #define SEG(type, base, lim, dpl) (struct segdesc) \ @@ -55,26 +56,26 @@ struct segdesc { (uint) (base) >> 24 } // Application segment type bits -#define STA_X 0x8 // Executable segment -#define STA_E 0x4 // Expand down (non-executable segments) -#define STA_C 0x4 // Conforming code segment (executable only) -#define STA_W 0x2 // Writeable (non-executable segments) -#define STA_R 0x2 // Readable (executable segments) -#define STA_A 0x1 // Accessed +#define STA_X 0x8 // Executable segment +#define STA_E 0x4 // Expand down (non-executable segments) +#define STA_C 0x4 // Conforming code segment (executable only) +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) +#define STA_A 0x1 // Accessed // System segment type bits -#define STS_T16A 0x1 // Available 16-bit TSS -#define STS_LDT 0x2 // Local Descriptor Table -#define STS_T16B 0x3 // Busy 16-bit TSS -#define STS_CG16 0x4 // 16-bit Call Gate -#define STS_TG 0x5 // Task Gate / Coum Transmitions -#define STS_IG16 0x6 // 16-bit Interrupt Gate -#define STS_TG16 0x7 // 16-bit Trap Gate -#define STS_T32A 0x9 // Available 32-bit TSS -#define STS_T32B 0xB // Busy 32-bit TSS -#define STS_CG32 0xC // 32-bit Call Gate -#define STS_IG32 0xE // 32-bit Interrupt Gate -#define STS_TG32 0xF // 32-bit Trap Gate +#define STS_T16A 0x1 // Available 16-bit TSS +#define STS_LDT 0x2 // Local Descriptor Table +#define STS_T16B 0x3 // Busy 16-bit TSS +#define STS_CG16 0x4 // 16-bit Call Gate +#define STS_TG 0x5 // Task Gate / Coum Transmitions +#define STS_IG16 0x6 // 16-bit Interrupt Gate +#define STS_TG16 0x7 // 16-bit Trap Gate +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_T32B 0xB // Busy 32-bit TSS +#define STS_CG32 0xC // 32-bit Call Gate +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate // Task state segment format struct taskstate { diff --git a/mp.c b/mp.c index 3b67b50..f2bb142 100644 --- a/mp.c +++ b/mp.c @@ -174,11 +174,12 @@ mp_init(void) } } - if(mp->imcrp) { // it appears that bochs doesn't support IMCR, and code won't run - outb(0x22, 0x70); // select IMCR - byte = inb(0x23); // current contents - byte |= 0x01; // mask external INTR - outb(0x23, byte); // disconnect 8259s/NMI + if(mp->imcrp) { + // It appears that Bochs doesn't support IMCR, so code won't run. + outb(0x22, 0x70); // Select IMCR + byte = inb(0x23); // Current contents + byte |= 0x01; // Mask external INTR + outb(0x23, byte); // Disconnect 8259s/NMI } } @@ -204,11 +205,20 @@ mp_startthem(void) (uint) _binary_bootother_size); for(c = 0; c < ncpu; c++){ + // Our current cpu has already started. if(c == cpu()) continue; - *(uint*)(APBOOTCODE-4) = (uint) (cpus[c].mpstack) + MPSTACK; // tell it what to use for %esp - *(uint*)(APBOOTCODE-8) = (uint)mpmain; // tell it where to jump to + + // Set target %esp + *(uint*)(APBOOTCODE-4) = (uint) (cpus[c].mpstack) + MPSTACK; + + // Set target %eip + *(uint*)(APBOOTCODE-8) = (uint)mpmain; + + // Go! lapic_startap(cpus[c].apicid, (uint) APBOOTCODE); + + // Wait for cpu to get through bootstrap. while(cpus[c].booted == 0) ; } diff --git a/mp.h b/mp.h index 638eb4f..b7c72d8 100644 --- a/mp.h +++ b/mp.h @@ -2,11 +2,11 @@ struct mp { // floating pointer uchar signature[4]; // "_MP_" - void *physaddr; // physical address of MP configuration table + void *physaddr; // phys addr of MP config table uchar length; // 1 uchar specrev; // [14] uchar checksum; // all bytes must add up to 0 - uchar type; // MP system configuration type + uchar type; // MP system config type uchar imcrp; uchar reserved[3]; }; @@ -17,10 +17,10 @@ struct mpctb { // configuration table header uchar version; // [14] uchar checksum; // all bytes must add up to 0 uchar product[20]; // product id - uint *oemtable; // OEM table pointer + uint *oemtable; // OEM table pointer ushort oemlength; // OEM table length ushort entry; // entry count - uint *lapicaddr; // address of local APIC + uint *lapicaddr; // address of local APIC ushort xlength; // extended table length uchar xchecksum; // extended table checksum uchar reserved; @@ -76,7 +76,7 @@ enum { // table entry types MPBP = 0x02, // bootstrap processor // PCMPiointr and PCMPlintr flags - MPPOMASK = 0x03, // polarity conforms to specifications of bus + MPPOMASK = 0x03, // polarity conforms to bus specs MPHIGH = 0x01, // active high MPLOW = 0x03, // active low MPELMASK = 0x0C, // trigger mode of APIC input signals diff --git a/picirq.c b/picirq.c index fe9aaea..184e693 100644 --- a/picirq.c +++ b/picirq.c @@ -41,8 +41,8 @@ pic_init(void) // ICW2: Vector offset outb(IO_PIC1+1, IRQ_OFFSET); - // ICW3: bit mask of IR lines connected to slave PICs (master PIC), - // 3-bit No of IR line at which slave connects to master(slave PIC). + // ICW3: (master PIC) bit mask of IR lines connected to slaves + // (slave PIC) 3-bit # of slave's connection to master outb(IO_PIC1+1, 1<= NOFILE) return -1; @@ -78,7 +80,9 @@ sys_read(void) uint addr; struct proc *p = curproc[cpu()]; - if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0) + if(fetcharg(0, &fd) < 0 || + fetcharg(1, &addr) < 0 || + fetcharg(2, &n) < 0) return -1; if(fd < 0 || fd >= NOFILE) return -1; diff --git a/trap.c b/trap.c index daf334f..4fb3039 100644 --- a/trap.c +++ b/trap.c @@ -8,7 +8,7 @@ #include "syscall.h" struct gatedesc idt[256]; -extern uint vectors[]; // in vectors.S: array of 256 entry point addresses +extern uint vectors[]; // in vectors.S: array of 256 entry pointers extern void trapenter(void); extern void trapenter1(void); @@ -85,7 +85,7 @@ trap(struct trapframe *tf) } if(curproc[cpu()]) { - cprintf("pid %d: unhandled trap %d on cpu %d eip %x---terminate process\n", + cprintf("pid %d: unhandled trap %d on cpu %d eip %x -- kill proc\n", curproc[cpu()]->pid, v, cpu(), tf->eip); proc_exit(); } diff --git a/traps.h b/traps.h index 1f3af30..b1bafa0 100644 --- a/traps.h +++ b/traps.h @@ -1,31 +1,31 @@ // 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 +#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 used since 486) +#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 +#define T_SYSCALL 48 // system call +#define T_DEFAULT 500 // catchall -#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET +#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET #define IRQ_KBD 1 #define IRQ_IDE 14 diff --git a/userfs.c b/userfs.c index 201db40..b409f1e 100644 --- a/userfs.c +++ b/userfs.c @@ -124,7 +124,8 @@ writetest1(void) exit(); } if(((int*)buf)[0] != n) { - printf(stdout, "read content of block %d is %d\n", n, ((int*)buf)[0]); + printf(stdout, "read content of block %d is %d\n", + n, ((int*)buf)[0]); exit(); } n++;