spacing fixes: no tabs, 2-space indents (for rtm)

This commit is contained in:
rsc 2006-09-06 17:04:06 +00:00
parent 45854caa93
commit a650c606fe
33 changed files with 913 additions and 905 deletions

27
asm.h
View file

@ -2,17 +2,18 @@
// macros to create x86 segments from assembler // macros to create x86 segments from assembler
// //
#define SEG_NULLASM \ #define SEG_NULLASM \
.word 0, 0; \ .word 0, 0; \
.byte 0, 0, 0, 0 .byte 0, 0, 0, 0
#define SEG_ASM(type,base,lim) \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
#define STA_X 0x8 // Executable segment #define SEG_ASM(type,base,lim) \
#define STA_E 0x4 // Expand down (non-executable segments) .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \
#define STA_C 0x4 // Conforming code segment (executable only) .byte (((base) >> 16) & 0xff), (0x90 | (type)), \
#define STA_W 0x2 // Writeable (non-executable segments) (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
#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

111
bootasm.S
View file

@ -1,8 +1,8 @@
#include "asm.h" #include "asm.h"
.set PROT_MODE_CSEG,0x8 # code segment selector .set PROT_MODE_CSEG,0x8 # code segment selector
.set PROT_MODE_DSEG,0x10 # data segment selector .set PROT_MODE_DSEG,0x10 # data segment selector
.set CR0_PE_ON,0x1 # protected mode enable flag .set CR0_PE_ON,0x1 # protected mode enable flag
################################################################################### ###################################################################################
# ENTRY POINT # ENTRY POINT
@ -17,19 +17,20 @@
# memory can accessed, then calls into C. # memory can accessed, then calls into C.
################################################################################### ###################################################################################
.globl start # Entry point .globl start # Entry point
start: .code16 # This runs in real mode start:
cli # Disable interrupts .code16 # This runs in real mode
cld # String operations increment cli # Disable interrupts
cld # String operations increment
# Set up the important data segment registers (DS, ES, SS). # Set up the important data segment registers (DS, ES, SS).
xorw %ax,%ax # Segment number zero xorw %ax,%ax # Segment number zero
movw %ax,%ds # -> Data Segment movw %ax,%ds # -> Data Segment
movw %ax,%es # -> Extra Segment movw %ax,%es # -> Extra Segment
movw %ax,%ss # -> Stack Segment movw %ax,%ss # -> Stack Segment
# Set up the stack pointer, growing downward from 0x7c00. # Set up the stack pointer, growing downward from 0x7c00.
movw $start,%sp # Stack Pointer movw $start,%sp # Stack Pointer
#### Enable A20: #### Enable A20:
#### For fascinating historical reasons (related to the fact that #### For fascinating historical reasons (related to the fact that
@ -39,58 +40,64 @@ start: .code16 # This runs in real mode
#### Obviously this a bit of a drag for us, especially when trying to #### Obviously this a bit of a drag for us, especially when trying to
#### address memory above 1MB. This code undoes this. #### address memory above 1MB. This code undoes this.
seta20.1: inb $0x64,%al # Get status seta20.1:
testb $0x2,%al # Busy? inb $0x64,%al # Get status
jnz seta20.1 # Yes testb $0x2,%al # Busy?
movb $0xd1,%al # Command: Write jnz seta20.1 # Yes
outb %al,$0x64 # output port movb $0xd1,%al # Command: Write
seta20.2: inb $0x64,%al # Get status outb %al,$0x64 # output port
testb $0x2,%al # Busy?
jnz seta20.2 # Yes seta20.2:
movb $0xdf,%al # Enable inb $0x64,%al # Get status
outb %al,$0x60 # A20 testb $0x2,%al # Busy?
jnz seta20.2 # Yes
movb $0xdf,%al # Enable
outb %al,$0x60 # A20
#### Switch from real to protected mode #### Switch from real to protected mode
#### The descriptors in our GDT allow all physical memory to be accessed. #### The descriptors in our GDT allow all physical memory to be accessed.
#### Furthermore, the descriptors have base addresses of 0, so that the #### Furthermore, the descriptors have base addresses of 0, so that the
#### segment translation is a NOP, ie. virtual addresses are identical to #### segment translation is a NOP, ie. virtual addresses are identical to
#### their physical addresses. With this setup, immediately after #### their physical addresses. With this setup, immediately after
#### enabling protected mode it will still appear to this code #### enabling protected mode it will still appear to this code
#### that it is running directly on physical memory with no translation. #### that it is running directly on physical memory with no translation.
#### This initial NOP-translation setup is required by the processor #### This initial NOP-translation setup is required by the processor
#### to ensure that the transition to protected mode occurs smoothly. #### to ensure that the transition to protected mode occurs smoothly.
real_to_prot: cli # Mandatory since we dont set up an IDT real_to_prot:
lgdt gdtdesc # load GDT -- mandatory in protected mode cli # Mandatory since we dont set up an IDT
movl %cr0, %eax # turn on protected mode lgdt gdtdesc # load GDT -- mandatory in protected mode
orl $CR0_PE_ON, %eax # movl %cr0, %eax # turn on protected mode
movl %eax, %cr0 # orl $CR0_PE_ON, %eax #
### CPU magic: jump to relocation, flush prefetch queue, and reload %cs movl %eax, %cr0 #
### Has the effect of just jmp to the next instruction, but simultaneous ### CPU magic: jump to relocation, flush prefetch queue, and reload %cs
### loads CS with $PROT_MODE_CSEG. ### Has the effect of just jmp to the next instruction, but simultaneous
ljmp $PROT_MODE_CSEG, $protcseg ### loads CS with $PROT_MODE_CSEG.
ljmp $PROT_MODE_CSEG, $protcseg
#### we are in 32-bit protected mode (hence the .code32) #### we are in 32-bit protected mode (hence the .code32)
.code32 .code32
protcseg: protcseg:
# Set up the protected-mode data segment registers # Set up the protected-mode data segment registers
movw $PROT_MODE_DSEG, %ax # Our data segment selector movw $PROT_MODE_DSEG, %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment movw %ax, %es # -> ES: Extra Segment
movw %ax, %fs # -> FS movw %ax, %fs # -> FS
movw %ax, %gs # -> GS movw %ax, %gs # -> GS
movw %ax, %ss # -> SS: Stack Segment movw %ax, %ss # -> SS: Stack Segment
call cmain # finish the boot load from C. call cmain # finish the boot load from C.
# cmain() should not return # cmain() should not return
spin: jmp spin # ..but in case it does, spin spin:
jmp spin # ..but in case it does, spin
.p2align 2 # force 4 byte alignment
.p2align 2 # force 4 byte alignment
gdt: gdt:
SEG_NULLASM # null seg SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
gdtdesc: gdtdesc:
.word 0x17 # sizeof(gdt) - 1 .word 0x17 # sizeof(gdt) - 1
.long gdt # address gdt .long gdt # address gdt

View file

@ -30,8 +30,8 @@
* * 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.
**********************************************************************/ **********************************************************************/
#define SECTSIZE 512 #define SECTSIZE 512
#define ELFHDR ((struct elfhdr *) 0x10000) // scratch space #define ELFHDR ((struct elfhdr *) 0x10000) // scratch space
void readsect(void*, uint); void readsect(void*, uint);
void readseg(uint, uint, uint); void readseg(uint, uint, uint);
@ -39,30 +39,30 @@ void readseg(uint, uint, uint);
void void
cmain(void) cmain(void)
{ {
struct proghdr *ph, *eph; struct proghdr *ph, *eph;
// read 1st page off disk // read 1st page off disk
readseg((uint) ELFHDR, SECTSIZE*8, 0); readseg((uint) ELFHDR, SECTSIZE*8, 0);
// is this a valid ELF? // is this a valid ELF?
if (ELFHDR->magic != ELF_MAGIC) if (ELFHDR->magic != ELF_MAGIC)
goto bad; goto bad;
// load each program segment (ignores ph flags) // load each program segment (ignores ph flags)
ph = (struct proghdr *) ((uchar *) ELFHDR + ELFHDR->phoff); ph = (struct proghdr *) ((uchar *) ELFHDR + ELFHDR->phoff);
eph = ph + ELFHDR->phnum; eph = ph + ELFHDR->phnum;
for (; ph < eph; ph++) for (; ph < eph; ph++)
readseg(ph->va, ph->memsz, ph->offset); readseg(ph->va, ph->memsz, ph->offset);
// call the entry point from the ELF header // call the entry point from the ELF header
// note: does not return! // note: does not return!
((void (*)(void)) (ELFHDR->entry & 0xFFFFFF))(); ((void (*)(void)) (ELFHDR->entry & 0xFFFFFF))();
bad: bad:
outw(0x8A00, 0x8A00); outw(0x8A00, 0x8A00);
outw(0x8A00, 0x8E00); outw(0x8A00, 0x8E00);
while(1) while(1)
/* do nothing */; /* do nothing */;
} }
// Read 'count' bytes at 'offset' from kernel into virtual address 'va'. // Read 'count' bytes at 'offset' from kernel into virtual address 'va'.
@ -70,52 +70,52 @@ bad:
void void
readseg(uint va, uint count, uint offset) readseg(uint va, uint count, uint offset)
{ {
uint end_va; uint end_va;
va &= 0xFFFFFF; va &= 0xFFFFFF;
end_va = va + count; end_va = va + count;
// round down to sector boundary // round down to sector boundary
va &= ~(SECTSIZE - 1); va &= ~(SECTSIZE - 1);
// translate from bytes to sectors, and kernel starts at sector 1 // translate from bytes to sectors, and kernel starts at sector 1
offset = (offset / SECTSIZE) + 1; offset = (offset / SECTSIZE) + 1;
// If this is too slow, we could read lots of sectors at a time. // If this is too slow, we could read lots of sectors at a time.
// We'd write more to memory than asked, but it doesn't matter -- // We'd write more to memory than asked, but it doesn't matter --
// we load in increasing order. // we load in increasing order.
while (va < end_va) { while (va < end_va) {
readsect((uchar*) va, offset); readsect((uchar*) va, offset);
va += SECTSIZE; va += SECTSIZE;
offset++; offset++;
} }
} }
void void
waitdisk(void) waitdisk(void)
{ {
// wait for disk reaady // wait for disk reaady
while ((inb(0x1F7) & 0xC0) != 0x40) while ((inb(0x1F7) & 0xC0) != 0x40)
/* do nothing */; /* do nothing */;
} }
void void
readsect(void *dst, uint offset) readsect(void *dst, uint offset)
{ {
// wait for disk to be ready // wait for disk to be ready
waitdisk(); waitdisk();
outb(0x1F2, 1); // count = 1 outb(0x1F2, 1); // count = 1
outb(0x1F3, offset); outb(0x1F3, offset);
outb(0x1F4, offset >> 8); outb(0x1F4, offset >> 8);
outb(0x1F5, offset >> 16); outb(0x1F5, offset >> 16);
outb(0x1F6, (offset >> 24) | 0xE0); outb(0x1F6, (offset >> 24) | 0xE0);
outb(0x1F7, 0x20); // cmd 0x20 - read sectors outb(0x1F7, 0x20); // cmd 0x20 - read sectors
// wait for disk to be ready // wait for disk to be ready
waitdisk(); waitdisk();
// read a sector // read a sector
insl(0x1F0, dst, SECTSIZE/4); insl(0x1F0, dst, SECTSIZE/4);
} }

View file

@ -16,64 +16,65 @@
* *
*/ */
.set PROT_MODE_CSEG,0x8 # code segment selector .set PROT_MODE_CSEG,0x8 # code segment selector
.set PROT_MODE_DSEG,0x10 # data segment selector .set PROT_MODE_DSEG,0x10 # data segment selector
.set CR0_PE_ON,0x1 # protected mode enable flag .set CR0_PE_ON,0x1 # protected mode enable flag
.globl start .globl start
start: .code16 # This runs in real mode start:
cli # Disable interrupts .code16 # This runs in real mode
cld # String operations increment cli # Disable interrupts
cld # String operations increment
# Set up the important data segment registers (DS, ES, SS). # Set up the important data segment registers (DS, ES, SS).
xorw %ax,%ax # Segment number zero xorw %ax,%ax # Segment number zero
movw %ax,%ds # -> Data Segment movw %ax,%ds # -> Data Segment
movw %ax,%es # -> Extra Segment movw %ax,%es # -> Extra Segment
movw %ax,%ss # -> Stack Segment movw %ax,%ss # -> Stack Segment
# Set up the stack pointer, growing downward from 0x7000-8. # 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 #### Switch from real to protected mode
#### The descriptors in our GDT allow all physical memory to be accessed. #### The descriptors in our GDT allow all physical memory to be accessed.
#### Furthermore, the descriptors have base addresses of 0, so that the #### Furthermore, the descriptors have base addresses of 0, so that the
#### segment translation is a NOP, ie. virtual addresses are identical to #### segment translation is a NOP, ie. virtual addresses are identical to
#### their physical addresses. With this setup, immediately after #### their physical addresses. With this setup, immediately after
#### enabling protected mode it will still appear to this code #### enabling protected mode it will still appear to this code
#### that it is running directly on physical memory with no translation. #### that it is running directly on physical memory with no translation.
#### This initial NOP-translation setup is required by the processor #### This initial NOP-translation setup is required by the processor
#### to ensure that the transition to protected mode occurs smoothly. #### to ensure that the transition to protected mode occurs smoothly.
lgdt gdtdesc # load GDT -- mandatory in protected mode lgdt gdtdesc # load GDT -- mandatory in protected mode
movl %cr0, %eax # turn on protected mode movl %cr0, %eax # turn on protected mode
orl $CR0_PE_ON, %eax # orl $CR0_PE_ON, %eax #
movl %eax, %cr0 # movl %eax, %cr0 #
### CPU magic: jump to relocation, flush prefetch queue, and reload %cs ### CPU magic: jump to relocation, flush prefetch queue, and reload %cs
### Has the effect of just jmp to the next instruction, but simultaneous ### Has the effect of just jmp to the next instruction, but simultaneous
### loads CS with $PROT_MODE_CSEG. ### loads CS with $PROT_MODE_CSEG.
ljmp $PROT_MODE_CSEG, $protcseg ljmp $PROT_MODE_CSEG, $protcseg
#### we are in 32-bit protected mode (hence the .code32) #### we are in 32-bit protected mode (hence the .code32)
.code32 .code32
protcseg: protcseg:
# Set up the protected-mode data segment registers # Set up the protected-mode data segment registers
movw $PROT_MODE_DSEG, %ax # Our data segment selector movw $PROT_MODE_DSEG, %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment movw %ax, %es # -> ES: Extra Segment
movw %ax, %fs # -> FS movw %ax, %fs # -> FS
movw %ax, %gs # -> GS movw %ax, %gs # -> GS
movw %ax, %ss # -> SS: Stack Segment movw %ax, %ss # -> SS: Stack Segment
movl start-8, %eax movl start-8, %eax
movl start-4, %esp movl start-4, %esp
jmp *%eax jmp *%eax
.p2align 2 # force 4 byte alignment .p2align 2 # force 4 byte alignment
gdt: gdt:
SEG_NULLASM # null seg SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
gdtdesc: gdtdesc:
.word 0x17 # sizeof(gdt) - 1 .word 0x17 # sizeof(gdt) - 1
.long gdt # address gdt .long gdt # address gdt

8
cat.c
View file

@ -30,10 +30,10 @@ main(int argc, char *argv[])
for(i = 1; i < argc; i++){ for(i = 1; i < argc; i++){
fd = open(argv[i], 0); fd = open(argv[i], 0);
if(fd < 0){ if(fd < 0){
puts("cat: cannot open "); puts("cat: cannot open ");
puts(argv[i]); puts(argv[i]);
puts("\n"); puts("\n");
exit(); exit();
} }
rfile(fd); rfile(fd);
close(fd); close(fd);

174
console.c
View file

@ -18,13 +18,13 @@ int use_console_lock = 0;
static void static void
lpt_putc(int c) lpt_putc(int c)
{ {
int i; int i;
for (i = 0; !(inb(0x378+1) & 0x80) && i < 12800; i++) for (i = 0; !(inb(0x378+1) & 0x80) && i < 12800; i++)
; ;
outb(0x378+0, c); outb(0x378+0, c);
outb(0x378+2, 0x08|0x04|0x01); outb(0x378+2, 0x08|0x04|0x01);
outb(0x378+2, 0x08); outb(0x378+2, 0x08);
} }
static void static void
@ -183,117 +183,117 @@ console_write (int minor, char *buf, int n)
/* This is i8042reg.h + kbdreg.h from NetBSD. */ /* This is i8042reg.h + kbdreg.h from NetBSD. */
#define KBSTATP 0x64 /* kbd controller status port(I) */ #define KBSTATP 0x64 /* kbd controller status port(I) */
#define KBS_DIB 0x01 /* kbd data in buffer */ #define KBS_DIB 0x01 /* kbd data in buffer */
#define KBDATAP 0x60 /* kbd data port(I) */ #define KBDATAP 0x60 /* kbd data port(I) */
#define NO 0 #define NO 0
#define SHIFT (1<<0) #define SHIFT (1<<0)
#define CTL (1<<1) #define CTL (1<<1)
#define ALT (1<<2) #define ALT (1<<2)
#define CAPSLOCK (1<<3) #define CAPSLOCK (1<<3)
#define NUMLOCK (1<<4) #define NUMLOCK (1<<4)
#define SCROLLLOCK (1<<5) #define SCROLLLOCK (1<<5)
#define E0ESC (1<<6) #define E0ESC (1<<6)
// Special keycodes // Special keycodes
#define KEY_HOME 0xE0 #define KEY_HOME 0xE0
#define KEY_END 0xE1 #define KEY_END 0xE1
#define KEY_UP 0xE2 #define KEY_UP 0xE2
#define KEY_DN 0xE3 #define KEY_DN 0xE3
#define KEY_LF 0xE4 #define KEY_LF 0xE4
#define KEY_RT 0xE5 #define KEY_RT 0xE5
#define KEY_PGUP 0xE6 #define KEY_PGUP 0xE6
#define KEY_PGDN 0xE7 #define KEY_PGDN 0xE7
#define KEY_INS 0xE8 #define KEY_INS 0xE8
#define KEY_DEL 0xE9 #define KEY_DEL 0xE9
static uchar shiftcode[256] = static uchar shiftcode[256] =
{ {
[0x1D] CTL, [0x1D] CTL,
[0x2A] SHIFT, [0x2A] SHIFT,
[0x36] SHIFT, [0x36] SHIFT,
[0x38] ALT, [0x38] ALT,
[0x9D] CTL, [0x9D] CTL,
[0xB8] ALT [0xB8] ALT
}; };
static uchar togglecode[256] = static uchar togglecode[256] =
{ {
[0x3A] CAPSLOCK, [0x3A] CAPSLOCK,
[0x45] NUMLOCK, [0x45] NUMLOCK,
[0x46] SCROLLLOCK [0x46] SCROLLLOCK
}; };
static uchar normalmap[256] = static uchar normalmap[256] =
{ {
NO, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00 NO, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00
'7', '8', '9', '0', '-', '=', '\b', '\t', '7', '8', '9', '0', '-', '=', '\b', '\t',
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10
'o', 'p', '[', ']', '\n', NO, 'a', 's', 'o', 'p', '[', ']', '\n', NO, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20
'\'', '`', NO, '\\', 'z', 'x', 'c', 'v', '\'', '`', NO, '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', NO, '*', // 0x30 'b', 'n', 'm', ',', '.', '/', NO, '*', // 0x30
NO, ' ', NO, NO, NO, NO, NO, NO, NO, ' ', NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 NO, NO, NO, NO, NO, NO, NO, '7', // 0x40
'8', '9', '-', '4', '5', '6', '+', '1', '8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', NO, NO, NO, NO, // 0x50 '2', '3', '0', '.', NO, NO, NO, NO, // 0x50
[0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/, [0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/,
[0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP, [0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP,
[0xC9] KEY_PGUP, [0xCB] KEY_LF, [0xC9] KEY_PGUP, [0xCB] KEY_LF,
[0xCD] KEY_RT, [0xCF] KEY_END, [0xCD] KEY_RT, [0xCF] KEY_END,
[0xD0] KEY_DN, [0xD1] KEY_PGDN, [0xD0] KEY_DN, [0xD1] KEY_PGDN,
[0xD2] KEY_INS, [0xD3] KEY_DEL [0xD2] KEY_INS, [0xD3] KEY_DEL
}; };
static uchar shiftmap[256] = static uchar shiftmap[256] =
{ {
NO, 033, '!', '@', '#', '$', '%', '^', // 0x00 NO, 033, '!', '@', '#', '$', '%', '^', // 0x00
'&', '*', '(', ')', '_', '+', '\b', '\t', '&', '*', '(', ')', '_', '+', '\b', '\t',
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10
'O', 'P', '{', '}', '\n', NO, 'A', 'S', 'O', 'P', '{', '}', '\n', NO, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20
'"', '~', NO, '|', 'Z', 'X', 'C', 'V', '"', '~', NO, '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', NO, '*', // 0x30 'B', 'N', 'M', '<', '>', '?', NO, '*', // 0x30
NO, ' ', NO, NO, NO, NO, NO, NO, NO, ' ', NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 NO, NO, NO, NO, NO, NO, NO, '7', // 0x40
'8', '9', '-', '4', '5', '6', '+', '1', '8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', NO, NO, NO, NO, // 0x50 '2', '3', '0', '.', NO, NO, NO, NO, // 0x50
[0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/, [0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/,
[0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP, [0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP,
[0xC9] KEY_PGUP, [0xCB] KEY_LF, [0xC9] KEY_PGUP, [0xCB] KEY_LF,
[0xCD] KEY_RT, [0xCF] KEY_END, [0xCD] KEY_RT, [0xCF] KEY_END,
[0xD0] KEY_DN, [0xD1] KEY_PGDN, [0xD0] KEY_DN, [0xD1] KEY_PGDN,
[0xD2] KEY_INS, [0xD3] KEY_DEL [0xD2] KEY_INS, [0xD3] KEY_DEL
}; };
#define C(x) (x - '@') #define C(x) (x - '@')
static uchar ctlmap[256] = static uchar ctlmap[256] =
{ {
NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO,
C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'), C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'),
C('O'), C('P'), NO, NO, '\r', NO, C('A'), C('S'), C('O'), C('P'), NO, NO, '\r', NO, C('A'), C('S'),
C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), NO, C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), NO,
NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'), NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'),
C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO, C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO,
[0x97] KEY_HOME, [0x97] KEY_HOME,
[0xB5] C('/'), [0xC8] KEY_UP, [0xB5] C('/'), [0xC8] KEY_UP,
[0xC9] KEY_PGUP, [0xCB] KEY_LF, [0xC9] KEY_PGUP, [0xCB] KEY_LF,
[0xCD] KEY_RT, [0xCF] KEY_END, [0xCD] KEY_RT, [0xCF] KEY_END,
[0xD0] KEY_DN, [0xD1] KEY_PGDN, [0xD0] KEY_DN, [0xD1] KEY_PGDN,
[0xD2] KEY_INS, [0xD3] KEY_DEL [0xD2] KEY_INS, [0xD3] KEY_DEL
}; };
static uchar *charcode[4] = { static uchar *charcode[4] = {
normalmap, normalmap,
shiftmap, shiftmap,
ctlmap, ctlmap,
ctlmap ctlmap
}; };
#define KBD_BUF 64 #define KBD_BUF 64

46
elf.h
View file

@ -5,32 +5,32 @@
#define ELF_MAGIC 0x464C457FU /* "\x7FELF" in little endian */ #define ELF_MAGIC 0x464C457FU /* "\x7FELF" in little endian */
struct elfhdr { struct elfhdr {
uint magic; // must equal ELF_MAGIC uint magic; // must equal ELF_MAGIC
uchar elf[12]; uchar elf[12];
ushort type; ushort type;
ushort machine; ushort machine;
uint version; uint version;
uint entry; uint entry;
uint phoff; uint phoff;
uint shoff; uint shoff;
uint flags; uint flags;
ushort ehsize; ushort ehsize;
ushort phentsize; ushort phentsize;
ushort phnum; ushort phnum;
ushort shentsize; ushort shentsize;
ushort shnum; ushort shnum;
ushort shstrndx; ushort shstrndx;
}; };
struct proghdr { struct proghdr {
uint type; uint type;
uint offset; uint offset;
uint va; uint va;
uint pa; uint pa;
uint filesz; uint filesz;
uint memsz; uint memsz;
uint flags; uint flags;
uint align; uint align;
}; };
// Values for Proghdr type // Values for Proghdr type

24
fs.c
View file

@ -270,15 +270,15 @@ itrunc(struct inode *ip)
for (i = 0; i < NADDRS; i++) { for (i = 0; i < NADDRS; i++) {
if (ip->addrs[i] != 0) { if (ip->addrs[i] != 0) {
if (i == INDIRECT) { if (i == INDIRECT) {
inbp = bread(ip->dev, ip->addrs[INDIRECT]); inbp = bread(ip->dev, ip->addrs[INDIRECT]);
uint *a = (uint *) inbp->data; uint *a = (uint *) inbp->data;
for (j = 0; j < NINDIRECT; j++) { for (j = 0; j < NINDIRECT; j++) {
if (a[j] != 0) { if (a[j] != 0) {
bfree(ip->dev, a[j]); bfree(ip->dev, a[j]);
a[j] = 0; a[j] = 0;
} }
} }
brelse(inbp); brelse(inbp);
} }
bfree(ip->dev, ip->addrs[i]); bfree(ip->dev, ip->addrs[i]);
ip->addrs[i] = 0; ip->addrs[i] = 0;
@ -411,8 +411,8 @@ writei(struct inode *ip, char *addr, uint off, uint n)
lbn = off / BSIZE; lbn = off / BSIZE;
if (lbn >= MAXFILE) return r; if (lbn >= MAXFILE) return r;
if (newblock(ip, lbn) < 0) { if (newblock(ip, lbn) < 0) {
cprintf("newblock failed\n"); cprintf("newblock failed\n");
return r; return r;
} }
m = min(BSIZE - off % BSIZE, n-r); m = min(BSIZE - off % BSIZE, n-r);
bp = bread(ip->dev, bmap(ip, lbn)); bp = bread(ip->dev, bmap(ip, lbn));
@ -424,8 +424,8 @@ writei(struct inode *ip, char *addr, uint off, uint n)
} }
if (r > 0) { if (r > 0) {
if (off > ip->size) { if (off > ip->size) {
if (ip->type == T_DIR) ip->size = ((off / BSIZE) + 1) * BSIZE; if (ip->type == T_DIR) ip->size = ((off / BSIZE) + 1) * BSIZE;
else ip->size = off; else ip->size = off;
} }
iupdate(ip); iupdate(ip);
} }

7
ide.c
View file

@ -11,8 +11,8 @@
#include "traps.h" #include "traps.h"
#include "spinlock.h" #include "spinlock.h"
#define IDE_BSY 0x80 #define IDE_BSY 0x80
#define IDE_DRDY 0x40 #define IDE_DRDY 0x40
#define IDE_DF 0x20 #define IDE_DF 0x20
#define IDE_ERR 0x01 #define IDE_ERR 0x01
@ -23,6 +23,7 @@ struct ide_request {
uint nsecs; uint nsecs;
uint read; uint read;
}; };
struct ide_request request[NREQUEST]; struct ide_request request[NREQUEST];
int head, tail; int head, tail;
struct spinlock ide_lock; struct spinlock ide_lock;
@ -165,7 +166,7 @@ ide_write(int diskno, uint secno, const void *src, uint nsecs)
outb(0x1F4, (secno >> 8) & 0xFF); outb(0x1F4, (secno >> 8) & 0xFF);
outb(0x1F5, (secno >> 16) & 0xFF); outb(0x1F5, (secno >> 16) & 0xFF);
outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));
outb(0x1F7, 0x30); // CMD 0x30 means write sector outb(0x1F7, 0x30); // CMD 0x30 means write sector
for (; nsecs > 0; nsecs--, src += 512) { for (; nsecs > 0; nsecs--, src += 512) {
if ((r = ide_wait_ready(1)) < 0) if ((r = ide_wait_ready(1)) < 0)

View file

@ -11,8 +11,8 @@ struct ioapic {
}; };
#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2) #define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2)
#define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1) #define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1)
static uint static uint
ioapic_read(struct ioapic *io, int reg) ioapic_read(struct ioapic *io, int reg)

138
ioapic.h
View file

@ -1,90 +1,90 @@
#define IO_APIC_BASE 0xFEC00000 /* default physical locations of an IO APIC */ #define IO_APIC_BASE 0xFEC00000 /* default physical locations of an IO APIC */
#define IOAPIC_WINDOW 0x10 /* window register offset */ #define IOAPIC_WINDOW 0x10 /* window register offset */
/* constants relating to APIC ID registers */ /* constants relating to APIC ID registers */
#define APIC_ID_MASK 0xff000000 #define APIC_ID_MASK 0xff000000
#define APIC_ID_SHIFT 24 #define APIC_ID_SHIFT 24
#define APIC_ID_CLUSTER 0xf0 #define APIC_ID_CLUSTER 0xf0
#define APIC_ID_CLUSTER_ID 0x0f #define APIC_ID_CLUSTER_ID 0x0f
#define APIC_MAX_CLUSTER 0xe #define APIC_MAX_CLUSTER 0xe
#define APIC_MAX_INTRACLUSTER_ID 3 #define APIC_MAX_INTRACLUSTER_ID 3
#define APIC_ID_CLUSTER_SHIFT 4 #define APIC_ID_CLUSTER_SHIFT 4
/* fields in VER */ /* fields in VER */
#define APIC_VER_VERSION 0x000000ff #define APIC_VER_VERSION 0x000000ff
#define APIC_VER_MAXLVT 0x00ff0000 #define APIC_VER_MAXLVT 0x00ff0000
#define MAXLVTSHIFT 16 #define MAXLVTSHIFT 16
/* Indexes into IO APIC */ /* Indexes into IO APIC */
#define IOAPIC_ID 0x00 #define IOAPIC_ID 0x00
#define IOAPIC_VER 0x01 #define IOAPIC_VER 0x01
#define IOAPIC_ARB 0x02 #define IOAPIC_ARB 0x02
#define IOAPIC_REDTBL 0x10 #define IOAPIC_REDTBL 0x10
#define IOAPIC_REDTBL0 IOAPIC_REDTBL #define IOAPIC_REDTBL0 IOAPIC_REDTBL
#define IOAPIC_REDTBL1 (IOAPIC_REDTBL+0x02) #define IOAPIC_REDTBL1 (IOAPIC_REDTBL+0x02)
#define IOAPIC_REDTBL2 (IOAPIC_REDTBL+0x04) #define IOAPIC_REDTBL2 (IOAPIC_REDTBL+0x04)
#define IOAPIC_REDTBL3 (IOAPIC_REDTBL+0x06) #define IOAPIC_REDTBL3 (IOAPIC_REDTBL+0x06)
#define IOAPIC_REDTBL4 (IOAPIC_REDTBL+0x08) #define IOAPIC_REDTBL4 (IOAPIC_REDTBL+0x08)
#define IOAPIC_REDTBL5 (IOAPIC_REDTBL+0x0a) #define IOAPIC_REDTBL5 (IOAPIC_REDTBL+0x0a)
#define IOAPIC_REDTBL6 (IOAPIC_REDTBL+0x0c) #define IOAPIC_REDTBL6 (IOAPIC_REDTBL+0x0c)
#define IOAPIC_REDTBL7 (IOAPIC_REDTBL+0x0e) #define IOAPIC_REDTBL7 (IOAPIC_REDTBL+0x0e)
#define IOAPIC_REDTBL8 (IOAPIC_REDTBL+0x10) #define IOAPIC_REDTBL8 (IOAPIC_REDTBL+0x10)
#define IOAPIC_REDTBL9 (IOAPIC_REDTBL+0x12) #define IOAPIC_REDTBL9 (IOAPIC_REDTBL+0x12)
#define IOAPIC_REDTBL10 (IOAPIC_REDTBL+0x14) #define IOAPIC_REDTBL10 (IOAPIC_REDTBL+0x14)
#define IOAPIC_REDTBL11 (IOAPIC_REDTBL+0x16) #define IOAPIC_REDTBL11 (IOAPIC_REDTBL+0x16)
#define IOAPIC_REDTBL12 (IOAPIC_REDTBL+0x18) #define IOAPIC_REDTBL12 (IOAPIC_REDTBL+0x18)
#define IOAPIC_REDTBL13 (IOAPIC_REDTBL+0x1a) #define IOAPIC_REDTBL13 (IOAPIC_REDTBL+0x1a)
#define IOAPIC_REDTBL14 (IOAPIC_REDTBL+0x1c) #define IOAPIC_REDTBL14 (IOAPIC_REDTBL+0x1c)
#define IOAPIC_REDTBL15 (IOAPIC_REDTBL+0x1e) #define IOAPIC_REDTBL15 (IOAPIC_REDTBL+0x1e)
#define IOAPIC_REDTBL16 (IOAPIC_REDTBL+0x20) #define IOAPIC_REDTBL16 (IOAPIC_REDTBL+0x20)
#define IOAPIC_REDTBL17 (IOAPIC_REDTBL+0x22) #define IOAPIC_REDTBL17 (IOAPIC_REDTBL+0x22)
#define IOAPIC_REDTBL18 (IOAPIC_REDTBL+0x24) #define IOAPIC_REDTBL18 (IOAPIC_REDTBL+0x24)
#define IOAPIC_REDTBL19 (IOAPIC_REDTBL+0x26) #define IOAPIC_REDTBL19 (IOAPIC_REDTBL+0x26)
#define IOAPIC_REDTBL20 (IOAPIC_REDTBL+0x28) #define IOAPIC_REDTBL20 (IOAPIC_REDTBL+0x28)
#define IOAPIC_REDTBL21 (IOAPIC_REDTBL+0x2a) #define IOAPIC_REDTBL21 (IOAPIC_REDTBL+0x2a)
#define IOAPIC_REDTBL22 (IOAPIC_REDTBL+0x2c) #define IOAPIC_REDTBL22 (IOAPIC_REDTBL+0x2c)
#define IOAPIC_REDTBL23 (IOAPIC_REDTBL+0x2e) #define IOAPIC_REDTBL23 (IOAPIC_REDTBL+0x2e)
/* /*
* fields in the IO APIC's redirection table entries * fields in the IO APIC's redirection table entries
*/ */
#define IOART_DEST APIC_ID_MASK /* broadcast addr: all APICs */ #define IOART_DEST APIC_ID_MASK /* broadcast addr: all APICs */
#define IOART_RESV 0x00fe0000 /* reserved */ #define IOART_RESV 0x00fe0000 /* reserved */
#define IOART_INTMASK 0x00010000 /* R/W: INTerrupt mask */ #define IOART_INTMASK 0x00010000 /* R/W: INTerrupt mask */
#define IOART_INTMCLR 0x00000000 /* clear, allow INTs */ #define IOART_INTMCLR 0x00000000 /* clear, allow INTs */
#define IOART_INTMSET 0x00010000 /* set, inhibit INTs */ #define IOART_INTMSET 0x00010000 /* set, inhibit INTs */
#define IOART_TRGRMOD 0x00008000 /* R/W: trigger mode */ #define IOART_TRGRMOD 0x00008000 /* R/W: trigger mode */
#define IOART_TRGREDG 0x00000000 /* edge */ #define IOART_TRGREDG 0x00000000 /* edge */
#define IOART_TRGRLVL 0x00008000 /* level */ #define IOART_TRGRLVL 0x00008000 /* level */
#define IOART_REM_IRR 0x00004000 /* RO: remote IRR */ #define IOART_REM_IRR 0x00004000 /* RO: remote IRR */
#define IOART_INTPOL 0x00002000 /* R/W: INT input pin polarity */ #define IOART_INTPOL 0x00002000 /* R/W: INT input pin polarity */
#define IOART_INTAHI 0x00000000 /* active high */ #define IOART_INTAHI 0x00000000 /* active high */
#define IOART_INTALO 0x00002000 /* active low */ #define IOART_INTALO 0x00002000 /* active low */
#define IOART_DELIVS 0x00001000 /* RO: delivery status */ #define IOART_DELIVS 0x00001000 /* RO: delivery status */
#define IOART_DESTMOD 0x00000800 /* R/W: destination mode */ #define IOART_DESTMOD 0x00000800 /* R/W: destination mode */
#define IOART_DESTPHY 0x00000000 /* physical */ #define IOART_DESTPHY 0x00000000 /* physical */
#define IOART_DESTLOG 0x00000800 /* logical */ #define IOART_DESTLOG 0x00000800 /* logical */
#define IOART_DELMOD 0x00000700 /* R/W: delivery mode */ #define IOART_DELMOD 0x00000700 /* R/W: delivery mode */
#define IOART_DELFIXED 0x00000000 /* fixed */ #define IOART_DELFIXED 0x00000000 /* fixed */
#define IOART_DELLOPRI 0x00000100 /* lowest priority */ #define IOART_DELLOPRI 0x00000100 /* lowest priority */
#define IOART_DELSMI 0x00000200 /* System Management INT */ #define IOART_DELSMI 0x00000200 /* System Management INT */
#define IOART_DELRSV1 0x00000300 /* reserved */ #define IOART_DELRSV1 0x00000300 /* reserved */
#define IOART_DELNMI 0x00000400 /* NMI signal */ #define IOART_DELNMI 0x00000400 /* NMI signal */
#define IOART_DELINIT 0x00000500 /* INIT signal */ #define IOART_DELINIT 0x00000500 /* INIT signal */
#define IOART_DELRSV2 0x00000600 /* reserved */ #define IOART_DELRSV2 0x00000600 /* reserved */
#define IOART_DELEXINT 0x00000700 /* External INTerrupt */ #define IOART_DELEXINT 0x00000700 /* External INTerrupt */
#define IOART_INTVEC 0x000000ff /* R/W: INTerrupt vector field */ #define IOART_INTVEC 0x000000ff /* R/W: INTerrupt vector field */
/* fields in VER */ /* fields in VER */
#define IOART_VER_VERSION 0x000000ff #define IOART_VER_VERSION 0x000000ff
#define IOART_VER_MAXREDIR 0x00ff0000 #define IOART_VER_MAXREDIR 0x00ff0000
#define MAXREDIRSHIFT 16 #define MAXREDIRSHIFT 16

18
ls.c
View file

@ -59,17 +59,17 @@ main(int argc, char *argv[])
sz = st.st_size; sz = st.st_size;
for(off = 0; off < sz; off += sizeof(struct dirent)) { for(off = 0; off < sz; off += sizeof(struct dirent)) {
if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) { if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) {
printf(1, "ls: read error\n"); printf(1, "ls: read error\n");
break; break;
} }
if (dirent.inum != 0) { if (dirent.inum != 0) {
// xxx prepend to name the pathname supplied to ls (e.g. .. in ls ..) // xxx prepend to name the pathname supplied to ls (e.g. .. in ls ..)
if (stat (dirent.name, &st) < 0) { if (stat (dirent.name, &st) < 0) {
printf(1, "stat: failed %s\n", dirent.name); printf(1, "stat: failed %s\n", dirent.name);
continue; continue;
} }
pname(dirent.name); pname(dirent.name);
printf(1, "%d %d %d\n", st.st_type, dirent.inum, st.st_size); printf(1, "%d %d %d\n", st.st_type, dirent.inum, st.st_size);
} }
} }
break; break;

2
main.c
View file

@ -97,7 +97,7 @@ mpmain(void)
// make sure there's a TSS // make sure there's a TSS
setupsegs(0); setupsegs(0);
cpuid(0, 0, 0, 0, 0); // memory barrier cpuid(0, 0, 0, 0, 0); // memory barrier
cpus[cpu()].booted = 1; cpus[cpu()].booted = 1;
// Enable interrupts on this processor. // Enable interrupts on this processor.

20
mkfs.c
View file

@ -81,8 +81,8 @@ main(int argc, char *argv[])
usedblocks = ninodes / IPB + 3 + bitblocks; usedblocks = ninodes / IPB + 3 + bitblocks;
freeblock = usedblocks; freeblock = usedblocks;
printf ("used %d (bit %d ninode %d) free %d total %d\n", usedblocks, printf("used %d (bit %d ninode %d) free %d total %d\n", usedblocks,
bitblocks, ninodes/IPB + 1, freeblock, nblocks+usedblocks); bitblocks, ninodes/IPB + 1, freeblock, nblocks+usedblocks);
assert (nblocks + usedblocks == size); assert (nblocks + usedblocks == size);
@ -246,22 +246,22 @@ iappend(uint inum, void *xp, int n)
assert(fbn < MAXFILE); assert(fbn < MAXFILE);
if (fbn < NDIRECT) { if (fbn < NDIRECT) {
if(xint(din.addrs[fbn]) == 0) { if(xint(din.addrs[fbn]) == 0) {
din.addrs[fbn] = xint(freeblock++); din.addrs[fbn] = xint(freeblock++);
usedblocks++; usedblocks++;
} }
x = xint(din.addrs[fbn]); x = xint(din.addrs[fbn]);
} else { } else {
if(xint(din.addrs[INDIRECT]) == 0) { if(xint(din.addrs[INDIRECT]) == 0) {
printf("allocate indirect block\n"); printf("allocate indirect block\n");
din.addrs[INDIRECT] = xint(freeblock++); din.addrs[INDIRECT] = xint(freeblock++);
usedblocks++; usedblocks++;
} }
printf("read indirect block\n"); printf("read indirect block\n");
rsect(xint(din.addrs[INDIRECT]), (char *) indirect); rsect(xint(din.addrs[INDIRECT]), (char *) indirect);
if (indirect[fbn - NDIRECT] == 0) { if (indirect[fbn - NDIRECT] == 0) {
indirect[fbn - NDIRECT] = xint(freeblock++); indirect[fbn - NDIRECT] = xint(freeblock++);
usedblocks++; usedblocks++;
wsect(xint(din.addrs[INDIRECT]), (char *) indirect); wsect(xint(din.addrs[INDIRECT]), (char *) indirect);
} }
x = xint(indirect[fbn-NDIRECT]); x = xint(indirect[fbn-NDIRECT]);
} }

236
mmu.h
View file

@ -3,133 +3,133 @@
*/ */
// Eflags register // Eflags register
#define FL_CF 0x00000001 // Carry Flag #define FL_CF 0x00000001 // Carry Flag
#define FL_PF 0x00000004 // Parity Flag #define FL_PF 0x00000004 // Parity Flag
#define FL_AF 0x00000010 // Auxiliary carry Flag #define FL_AF 0x00000010 // Auxiliary carry Flag
#define FL_ZF 0x00000040 // Zero Flag #define FL_ZF 0x00000040 // Zero Flag
#define FL_SF 0x00000080 // Sign Flag #define FL_SF 0x00000080 // Sign Flag
#define FL_TF 0x00000100 // Trap Flag #define FL_TF 0x00000100 // Trap Flag
#define FL_IF 0x00000200 // Interrupt Flag #define FL_IF 0x00000200 // Interrupt Flag
#define FL_DF 0x00000400 // Direction Flag #define FL_DF 0x00000400 // Direction Flag
#define FL_OF 0x00000800 // Overflow Flag #define FL_OF 0x00000800 // Overflow Flag
#define FL_IOPL_MASK 0x00003000 // I/O Privilege Level bitmask #define FL_IOPL_MASK 0x00003000 // I/O Privilege Level bitmask
#define FL_IOPL_0 0x00000000 // IOPL == 0 #define FL_IOPL_0 0x00000000 // IOPL == 0
#define FL_IOPL_1 0x00001000 // IOPL == 1 #define FL_IOPL_1 0x00001000 // IOPL == 1
#define FL_IOPL_2 0x00002000 // IOPL == 2 #define FL_IOPL_2 0x00002000 // IOPL == 2
#define FL_IOPL_3 0x00003000 // IOPL == 3 #define FL_IOPL_3 0x00003000 // IOPL == 3
#define FL_NT 0x00004000 // Nested Task #define FL_NT 0x00004000 // Nested Task
#define FL_RF 0x00010000 // Resume Flag #define FL_RF 0x00010000 // Resume Flag
#define FL_VM 0x00020000 // Virtual 8086 mode #define FL_VM 0x00020000 // Virtual 8086 mode
#define FL_AC 0x00040000 // Alignment Check #define FL_AC 0x00040000 // Alignment Check
#define FL_VIF 0x00080000 // Virtual Interrupt Flag #define FL_VIF 0x00080000 // Virtual Interrupt Flag
#define FL_VIP 0x00100000 // Virtual Interrupt Pending #define FL_VIP 0x00100000 // Virtual Interrupt Pending
#define FL_ID 0x00200000 // ID flag #define FL_ID 0x00200000 // ID flag
// Segment Descriptor // Segment Descriptor
struct segdesc { struct segdesc {
uint lim_15_0 : 16; // Low bits of segment limit uint lim_15_0 : 16; // Low bits of segment limit
uint base_15_0 : 16; // Low bits of segment base address uint base_15_0 : 16; // Low bits of segment base address
uint base_23_16 : 8; // Middle bits of segment base address uint base_23_16 : 8; // Middle bits of segment base address
uint type : 4; // Segment type (see STS_ constants) uint type : 4; // Segment type (see STS_ constants)
uint s : 1; // 0 = system, 1 = application uint s : 1; // 0 = system, 1 = application
uint dpl : 2; // Descriptor Privilege Level uint dpl : 2; // Descriptor Privilege Level
uint p : 1; // Present uint p : 1; // Present
uint lim_19_16 : 4; // High bits of segment limit uint lim_19_16 : 4; // High bits of segment limit
uint avl : 1; // Unused (available for software use) uint avl : 1; // Unused (available for software use)
uint rsv1 : 1; // Reserved uint rsv1 : 1; // Reserved
uint db : 1; // 0 = 16-bit segment, 1 = 32-bit segment uint db : 1; // 0 = 16-bit segment, 1 = 32-bit segment
uint g : 1; // Granularity: limit scaled by 4K when set uint g : 1; // Granularity: limit scaled by 4K when set
uint base_31_24 : 8; // High bits of segment base address uint base_31_24 : 8; // High bits of segment base address
}; };
// Null segment // 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 // Normal segment
#define SEG(type, base, lim, dpl) (struct segdesc) \ #define SEG(type, base, lim, dpl) (struct segdesc) \
{ ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ { ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \
type, 1, dpl, 1, (uint) (lim) >> 28, 0, 0, 1, 1, \ type, 1, dpl, 1, (uint) (lim) >> 28, 0, 0, 1, 1, \
(uint) (base) >> 24 } (uint) (base) >> 24 }
#define SEG16(type, base, lim, dpl) (struct segdesc) \ #define SEG16(type, base, lim, dpl) (struct segdesc) \
{ (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ { (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \
type, 1, dpl, 1, (uint) (lim) >> 16, 0, 0, 1, 0, \ type, 1, dpl, 1, (uint) (lim) >> 16, 0, 0, 1, 0, \
(uint) (base) >> 24 } (uint) (base) >> 24 }
// Application segment type bits // Application segment type bits
#define STA_X 0x8 // Executable segment #define STA_X 0x8 // Executable segment
#define STA_E 0x4 // Expand down (non-executable segments) #define STA_E 0x4 // Expand down (non-executable segments)
#define STA_C 0x4 // Conforming code segment (executable only) #define STA_C 0x4 // Conforming code segment (executable only)
#define STA_W 0x2 // Writeable (non-executable segments) #define STA_W 0x2 // Writeable (non-executable segments)
#define STA_R 0x2 // Readable (executable segments) #define STA_R 0x2 // Readable (executable segments)
#define STA_A 0x1 // Accessed #define STA_A 0x1 // Accessed
// System segment type bits // System segment type bits
#define STS_T16A 0x1 // Available 16-bit TSS #define STS_T16A 0x1 // Available 16-bit TSS
#define STS_LDT 0x2 // Local Descriptor Table #define STS_LDT 0x2 // Local Descriptor Table
#define STS_T16B 0x3 // Busy 16-bit TSS #define STS_T16B 0x3 // Busy 16-bit TSS
#define STS_CG16 0x4 // 16-bit Call Gate #define STS_CG16 0x4 // 16-bit Call Gate
#define STS_TG 0x5 // Task Gate / Coum Transmitions #define STS_TG 0x5 // Task Gate / Coum Transmitions
#define STS_IG16 0x6 // 16-bit Interrupt Gate #define STS_IG16 0x6 // 16-bit Interrupt Gate
#define STS_TG16 0x7 // 16-bit Trap Gate #define STS_TG16 0x7 // 16-bit Trap Gate
#define STS_T32A 0x9 // Available 32-bit TSS #define STS_T32A 0x9 // Available 32-bit TSS
#define STS_T32B 0xB // Busy 32-bit TSS #define STS_T32B 0xB // Busy 32-bit TSS
#define STS_CG32 0xC // 32-bit Call Gate #define STS_CG32 0xC // 32-bit Call Gate
#define STS_IG32 0xE // 32-bit Interrupt Gate #define STS_IG32 0xE // 32-bit Interrupt Gate
#define STS_TG32 0xF // 32-bit Trap Gate #define STS_TG32 0xF // 32-bit Trap Gate
// Task state segment format // Task state segment format
struct taskstate { struct taskstate {
uint link; // Old ts selector uint link; // Old ts selector
uint esp0; // Stack pointers and segment selectors uint esp0; // Stack pointers and segment selectors
ushort ss0; // after an increase in privilege level ushort ss0; // after an increase in privilege level
ushort padding1; ushort padding1;
uint * esp1; uint * esp1;
ushort ss1; ushort ss1;
ushort padding2; ushort padding2;
uint * esp2; uint * esp2;
ushort ss2; ushort ss2;
ushort padding3; ushort padding3;
void * cr3; // Page directory base void * cr3; // Page directory base
uint * eip; // Saved state from last task switch uint * eip; // Saved state from last task switch
uint eflags; uint eflags;
uint eax; // More saved state (registers) uint eax; // More saved state (registers)
uint ecx; uint ecx;
uint edx; uint edx;
uint ebx; uint ebx;
uint * esp; uint * esp;
uint * ebp; uint * ebp;
uint esi; uint esi;
uint edi; uint edi;
ushort es; // Even more saved state (segment selectors) ushort es; // Even more saved state (segment selectors)
ushort padding4; ushort padding4;
ushort cs; ushort cs;
ushort padding5; ushort padding5;
ushort ss; ushort ss;
ushort padding6; ushort padding6;
ushort ds; ushort ds;
ushort padding7; ushort padding7;
ushort fs; ushort fs;
ushort padding8; ushort padding8;
ushort gs; ushort gs;
ushort padding9; ushort padding9;
ushort ldt; ushort ldt;
ushort padding10; ushort padding10;
ushort t; // Trap on task switch ushort t; // Trap on task switch
ushort iomb; // I/O map base address ushort iomb; // I/O map base address
}; };
// Gate descriptors for interrupts and traps // Gate descriptors for interrupts and traps
struct gatedesc { struct gatedesc {
uint off_15_0 : 16; // low 16 bits of offset in segment uint off_15_0 : 16; // low 16 bits of offset in segment
uint ss : 16; // segment selector uint ss : 16; // segment selector
uint args : 5; // # args, 0 for interrupt/trap gates uint args : 5; // # args, 0 for interrupt/trap gates
uint rsv1 : 3; // reserved(should be zero I guess) uint rsv1 : 3; // reserved(should be zero I guess)
uint type : 4; // type(STS_{TG,IG32,TG32}) uint type : 4; // type(STS_{TG,IG32,TG32})
uint s : 1; // must be 0 (system) uint s : 1; // must be 0 (system)
uint dpl : 2; // descriptor(meaning new) privilege level uint dpl : 2; // descriptor(meaning new) privilege level
uint p : 1; // Present uint p : 1; // Present
uint off_31_16 : 16; // high bits of offset in segment uint off_31_16 : 16; // high bits of offset in segment
}; };
// Set up a normal interrupt/trap gate descriptor. // Set up a normal interrupt/trap gate descriptor.
@ -138,18 +138,18 @@ struct gatedesc {
// - sel: Code segment selector for interrupt/trap handler // - sel: Code segment selector for interrupt/trap handler
// - off: Offset in code segment for interrupt/trap handler // - off: Offset in code segment for interrupt/trap handler
// - dpl: Descriptor Privilege Level - // - dpl: Descriptor Privilege Level -
// the privilege level required for software to invoke // the privilege level required for software to invoke
// this interrupt/trap gate explicitly using an int instruction. // this interrupt/trap gate explicitly using an int instruction.
#define SETGATE(gate, istrap, sel, off, d) \ #define SETGATE(gate, istrap, sel, off, d) \
{ \ { \
(gate).off_15_0 = (uint) (off) & 0xffff; \ (gate).off_15_0 = (uint) (off) & 0xffff; \
(gate).ss = (sel); \ (gate).ss = (sel); \
(gate).args = 0; \ (gate).args = 0; \
(gate).rsv1 = 0; \ (gate).rsv1 = 0; \
(gate).type = (istrap) ? STS_TG32 : STS_IG32; \ (gate).type = (istrap) ? STS_TG32 : STS_IG32; \
(gate).s = 0; \ (gate).s = 0; \
(gate).dpl = (d); \ (gate).dpl = (d); \
(gate).p = 1; \ (gate).p = 1; \
(gate).off_31_16 = (uint) (off) >> 16; \ (gate).off_31_16 = (uint) (off) >> 16; \
} }

58
mp.c
View file

@ -8,25 +8,25 @@
#include "proc.h" #include "proc.h"
static char* buses[] = { static char* buses[] = {
"CBUSI ", "CBUSI ",
"CBUSII", "CBUSII",
"EISA ", "EISA ",
"FUTURE", "FUTURE",
"INTERN", "INTERN",
"ISA ", "ISA ",
"MBI ", "MBI ",
"MBII ", "MBII ",
"MCA ", "MCA ",
"MPI ", "MPI ",
"MPSA ", "MPSA ",
"NUBUS ", "NUBUS ",
"PCI ", "PCI ",
"PCMCIA", "PCMCIA",
"TC ", "TC ",
"VL ", "VL ",
"VME ", "VME ",
"XPRESS", "XPRESS",
0, 0,
}; };
struct cpu cpus[NCPU]; struct cpu cpus[NCPU];
@ -146,7 +146,7 @@ mp_init(void)
proc = (struct mppe *) p; proc = (struct mppe *) p;
cpus[ncpu].apicid = proc->apicid; cpus[ncpu].apicid = proc->apicid;
if (proc->flags & MPBP) { if (proc->flags & MPBP) {
bcpu = &cpus[ncpu]; bcpu = &cpus[ncpu];
} }
ncpu++; ncpu++;
p += sizeof(struct mppe); p += sizeof(struct mppe);
@ -154,8 +154,8 @@ mp_init(void)
case MPBUS: case MPBUS:
bus = (struct mpbe *) p; bus = (struct mpbe *) p;
for(i = 0; buses[i]; i++){ for(i = 0; buses[i]; i++){
if(strncmp(buses[i], bus->string, sizeof(bus->string)) == 0) if(strncmp(buses[i], bus->string, sizeof(bus->string)) == 0)
break; break;
} }
p += sizeof(struct mpbe); p += sizeof(struct mpbe);
continue; continue;
@ -171,18 +171,18 @@ mp_init(void)
default: default:
cprintf("mpinit: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p); cprintf("mpinit: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
while(p < e){ while(p < e){
cprintf("%uX ", *p); cprintf("%uX ", *p);
p++; p++;
} }
break; break;
} }
} }
if (mp->imcrp) { // it appears that bochs doesn't support IMCR, and code won't run if (mp->imcrp) { // it appears that bochs doesn't support IMCR, and code won't run
outb(0x22, 0x70); /* select IMCR */ outb(0x22, 0x70); /* select IMCR */
byte = inb(0x23); /* current contents */ byte = inb(0x23); /* current contents */
byte |= 0x01; /* mask external INTR */ byte |= 0x01; /* mask external INTR */
outb(0x23, byte); /* disconnect 8259s/NMI */ outb(0x23, byte); /* disconnect 8259s/NMI */
} }
} }
@ -205,7 +205,7 @@ mp_startthem(void)
int c; int c;
memmove((void *) APBOOTCODE,_binary_bootother_start, memmove((void *) APBOOTCODE,_binary_bootother_start,
(uint) _binary_bootother_size); (uint) _binary_bootother_size);
for(c = 0; c < ncpu; c++){ for(c = 0; c < ncpu; c++){
if (c == cpu()) continue; if (c == cpu()) continue;

170
mp.h
View file

@ -3,121 +3,121 @@
* *
*/ */
struct mp { /* floating pointer */ struct mp { /* floating pointer */
uchar signature[4]; /* "_MP_" */ uchar signature[4]; /* "_MP_" */
void* physaddr; /* physical address of MP configuration table */ void* physaddr; /* physical address of MP configuration table */
uchar length; /* 1 */ uchar length; /* 1 */
uchar specrev; /* [14] */ uchar specrev; /* [14] */
uchar checksum; /* all bytes must add up to 0 */ uchar checksum; /* all bytes must add up to 0 */
uchar type; /* MP system configuration type */ uchar type; /* MP system configuration type */
uchar imcrp; uchar imcrp;
uchar reserved[3]; uchar reserved[3];
}; };
struct mpctb { /* configuration table header */ struct mpctb { /* configuration table header */
uchar signature[4]; /* "PCMP" */ uchar signature[4]; /* "PCMP" */
ushort length; /* total table length */ ushort length; /* total table length */
uchar version; /* [14] */ uchar version; /* [14] */
uchar checksum; /* all bytes must add up to 0 */ uchar checksum; /* all bytes must add up to 0 */
uchar product[20]; /* product id */ uchar product[20]; /* product id */
uint * oemtable; /* OEM table pointer */ uint * oemtable; /* OEM table pointer */
ushort oemlength; /* OEM table length */ ushort oemlength; /* OEM table length */
ushort entry; /* entry count */ ushort entry; /* entry count */
uint * lapicaddr; /* address of local APIC */ uint * lapicaddr; /* address of local APIC */
ushort xlength; /* extended table length */ ushort xlength; /* extended table length */
uchar xchecksum; /* extended table checksum */ uchar xchecksum; /* extended table checksum */
uchar reserved; uchar reserved;
}; };
struct mppe { /* processor table entry */ struct mppe { /* processor table entry */
uchar type; /* entry type (0) */ uchar type; /* entry type (0) */
uchar apicid; /* local APIC id */ uchar apicid; /* local APIC id */
uchar version; /* local APIC verison */ uchar version; /* local APIC verison */
uchar flags; /* CPU flags */ uchar flags; /* CPU flags */
uchar signature[4]; /* CPU signature */ uchar signature[4]; /* CPU signature */
uint feature; /* feature flags from CPUID instruction */ uint feature; /* feature flags from CPUID instruction */
uchar reserved[8]; uchar reserved[8];
}; };
struct mpbe { /* bus table entry */ struct mpbe { /* bus table entry */
uchar type; /* entry type (1) */ uchar type; /* entry type (1) */
uchar busno; /* bus id */ uchar busno; /* bus id */
char string[6]; /* bus type string */ char string[6]; /* bus type string */
}; };
struct mpioapic { /* I/O APIC table entry */ struct mpioapic { /* I/O APIC table entry */
uchar type; /* entry type (2) */ uchar type; /* entry type (2) */
uchar apicno; /* I/O APIC id */ uchar apicno; /* I/O APIC id */
uchar version; /* I/O APIC version */ uchar version; /* I/O APIC version */
uchar flags; /* I/O APIC flags */ uchar flags; /* I/O APIC flags */
uint * addr; /* I/O APIC address */ uint * addr; /* I/O APIC address */
}; };
struct mpie { /* interrupt table entry */ struct mpie { /* interrupt table entry */
uchar type; /* entry type ([34]) */ uchar type; /* entry type ([34]) */
uchar intr; /* interrupt type */ uchar intr; /* interrupt type */
ushort flags; /* interrupt flag */ ushort flags; /* interrupt flag */
uchar busno; /* source bus id */ uchar busno; /* source bus id */
uchar irq; /* source bus irq */ uchar irq; /* source bus irq */
uchar apicno; /* destination APIC id */ uchar apicno; /* destination APIC id */
uchar intin; /* destination APIC [L]INTIN# */ uchar intin; /* destination APIC [L]INTIN# */
}; };
enum { /* table entry types */ enum { /* table entry types */
MPPROCESSOR = 0x00, /* one entry per processor */ MPPROCESSOR = 0x00, /* one entry per processor */
MPBUS = 0x01, /* one entry per bus */ MPBUS = 0x01, /* one entry per bus */
MPIOAPIC = 0x02, /* one entry per I/O APIC */ MPIOAPIC = 0x02, /* one entry per I/O APIC */
MPIOINTR = 0x03, /* one entry per bus interrupt source */ MPIOINTR = 0x03, /* one entry per bus interrupt source */
MPLINTR = 0x04, /* one entry per system interrupt source */ MPLINTR = 0x04, /* one entry per system interrupt source */
MPSASM = 0x80, MPSASM = 0x80,
MPHIERARCHY = 0x81, MPHIERARCHY = 0x81,
MPCBASM = 0x82, MPCBASM = 0x82,
/* PCMPprocessor and PCMPioapic flags */ /* PCMPprocessor and PCMPioapic flags */
MPEN = 0x01, /* enabled */ MPEN = 0x01, /* enabled */
MPBP = 0x02, /* bootstrap processor */ MPBP = 0x02, /* bootstrap processor */
/* PCMPiointr and PCMPlintr flags */ /* PCMPiointr and PCMPlintr flags */
MPPOMASK = 0x03, /* polarity conforms to specifications of bus */ MPPOMASK = 0x03, /* polarity conforms to specifications of bus */
MPHIGH = 0x01, /* active high */ MPHIGH = 0x01, /* active high */
MPLOW = 0x03, /* active low */ MPLOW = 0x03, /* active low */
MPELMASK = 0x0C, /* trigger mode of APIC input signals */ MPELMASK = 0x0C, /* trigger mode of APIC input signals */
MPEDGE = 0x04, /* edge-triggered */ MPEDGE = 0x04, /* edge-triggered */
MPLEVEL = 0x0C, /* level-triggered */ MPLEVEL = 0x0C, /* level-triggered */
/* PCMPiointr and PCMPlintr interrupt type */ /* PCMPiointr and PCMPlintr interrupt type */
MPINT = 0x00, /* vectored interrupt from APIC Rdt */ MPINT = 0x00, /* vectored interrupt from APIC Rdt */
MPNMI = 0x01, /* non-maskable interrupt */ MPNMI = 0x01, /* non-maskable interrupt */
MPSMI = 0x02, /* system management interrupt */ MPSMI = 0x02, /* system management interrupt */
MPExtINT = 0x03, /* vectored interrupt from external PIC */ MPExtINT = 0x03, /* vectored interrupt from external PIC */
}; };
/* /*
* Common bits for * Common bits for
* I/O APIC Redirection Table Entry; * I/O APIC Redirection Table Entry;
* Local APIC Local Interrupt Vector Table; * Local APIC Local Interrupt Vector Table;
* Local APIC Inter-Processor Interrupt; * Local APIC Inter-Processor Interrupt;
* Local APIC Timer Vector Table. * Local APIC Timer Vector Table.
*/ */
enum { enum {
APIC_FIXED = 0x00000000, /* [10:8] Delivery Mode */ APIC_FIXED = 0x00000000, /* [10:8] Delivery Mode */
APIC_LOWEST = 0x00000100, /* Lowest priority */ APIC_LOWEST = 0x00000100, /* Lowest priority */
APIC_SMI = 0x00000200, /* System Management Interrupt */ APIC_SMI = 0x00000200, /* System Management Interrupt */
APIC_RR = 0x00000300, /* Remote Read */ APIC_RR = 0x00000300, /* Remote Read */
APIC_NMI = 0x00000400, APIC_NMI = 0x00000400,
APIC_INIT = 0x00000500, /* INIT/RESET */ APIC_INIT = 0x00000500, /* INIT/RESET */
APIC_STARTUP = 0x00000600, /* Startup IPI */ APIC_STARTUP = 0x00000600, /* Startup IPI */
APIC_EXTINT = 0x00000700, APIC_EXTINT = 0x00000700,
APIC_PHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */ APIC_PHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */
APIC_LOGICAL = 0x00000800, APIC_LOGICAL = 0x00000800,
APIC_DELIVS = 0x00001000, /* [12] Delivery Status (RO) */ APIC_DELIVS = 0x00001000, /* [12] Delivery Status (RO) */
APIC_HIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */ APIC_HIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */
APIC_LOW = 0x00002000, APIC_LOW = 0x00002000,
APIC_REMOTEIRR = 0x00004000, /* [14] Remote IRR (RO) */ APIC_REMOTEIRR = 0x00004000, /* [14] Remote IRR (RO) */
APIC_EDGE = 0x00000000, /* [15] Trigger Mode (RW) */ APIC_EDGE = 0x00000000, /* [15] Trigger Mode (RW) */
APIC_LEVEL = 0x00008000, APIC_LEVEL = 0x00008000,
APIC_IMASK = 0x00010000, /* [16] Interrupt Mask */ APIC_IMASK = 0x00010000, /* [16] Interrupt Mask */
}; };

View file

@ -4,10 +4,10 @@
#include "defs.h" #include "defs.h"
// I/O Addresses of the two 8259A programmable interrupt controllers // I/O Addresses of the two 8259A programmable interrupt controllers
#define IO_PIC1 0x20 // Master (IRQs 0-7) #define IO_PIC1 0x20 // Master (IRQs 0-7)
#define IO_PIC2 0xA0 // Slave (IRQs 8-15) #define IO_PIC2 0xA0 // Slave (IRQs 8-15)
#define IRQ_SLAVE 2 // IRQ at which slave connects to master #define IRQ_SLAVE 2 // IRQ at which slave connects to master
// Current IRQ mask. // Current IRQ mask.
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A). // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
@ -49,19 +49,19 @@ pic_init(void)
// n: 1 = special fully nested mode // n: 1 = special fully nested mode
// b: 1 = buffered mode // b: 1 = buffered mode
// m: 0 = slave PIC, 1 = master PIC // m: 0 = slave PIC, 1 = master PIC
// (ignored when b is 0, as the master/slave role // (ignored when b is 0, as the master/slave role
// can be hardwired). // can be hardwired).
// a: 1 = Automatic EOI mode // a: 1 = Automatic EOI mode
// p: 0 = MCS-80/85 mode, 1 = intel x86 mode // p: 0 = MCS-80/85 mode, 1 = intel x86 mode
outb(IO_PIC1+1, 0x3); outb(IO_PIC1+1, 0x3);
// Set up slave (8259A-2) // Set up slave (8259A-2)
outb(IO_PIC2, 0x11); // ICW1 outb(IO_PIC2, 0x11); // ICW1
outb(IO_PIC2+1, IRQ_OFFSET + 8); // ICW2 outb(IO_PIC2+1, IRQ_OFFSET + 8); // ICW2
outb(IO_PIC2+1, IRQ_SLAVE); // ICW3 outb(IO_PIC2+1, IRQ_SLAVE); // ICW3
// NB Automatic EOI mode doesn't tend to work on the slave. // NB Automatic EOI mode doesn't tend to work on the slave.
// Linux source code says it's "to be investigated". // Linux source code says it's "to be investigated".
outb(IO_PIC2+1, 0x3); // ICW4 outb(IO_PIC2+1, 0x3); // ICW4
// OCW3: 0ef01prs // OCW3: 0ef01prs
// ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask

View file

@ -65,8 +65,8 @@ printf(int fd, char *fmt, ...)
s++; s++;
} }
} else if(c == 'c'){ } else if(c == 'c'){
putc(fd, *ap); putc(fd, *ap);
ap++; ap++;
} else if(c == '%'){ } else if(c == '%'){
putc(fd, c); putc(fd, c);
} else { } else {

View file

@ -1,37 +1,35 @@
.globl setjmp .globl setjmp
setjmp: setjmp:
movl 4(%esp), %eax movl 4(%esp), %eax
movl %ebx, 0(%eax) movl %ebx, 0(%eax)
movl %ecx, 4(%eax) movl %ecx, 4(%eax)
movl %edx, 8(%eax) movl %edx, 8(%eax)
movl %esi, 12(%eax) movl %esi, 12(%eax)
movl %edi, 16(%eax) movl %edi, 16(%eax)
movl %esp, 20(%eax) movl %esp, 20(%eax)
movl %ebp, 24(%eax) movl %ebp, 24(%eax)
pushl 0(%esp) /* %eip */ pushl 0(%esp) /* %eip */
popl 28(%eax) popl 28(%eax)
movl $0, %eax /* return value */ movl $0, %eax /* return value */
ret ret
.globl longjmp .globl longjmp
longjmp: longjmp:
movl 4(%esp), %eax movl 4(%esp), %eax
movl 0(%eax), %ebx movl 0(%eax), %ebx
movl 4(%eax), %ecx movl 4(%eax), %ecx
movl 8(%eax), %edx movl 8(%eax), %edx
movl 12(%eax), %esi movl 12(%eax), %esi
movl 16(%eax), %edi movl 16(%eax), %edi
movl 20(%eax), %esp movl 20(%eax), %esp
movl 24(%eax), %ebp movl 24(%eax), %ebp
addl $4, %esp /* pop %eip into thin air */
pushl 28(%eax) /* push new %eip */
movl $1, %eax /* return value (appears to come from setjmp!) */
ret
addl $4, %esp /* pop %eip into thin air */
pushl 28(%eax) /* push new %eip */
movl $1, %eax /* return value (appears to come from setjmp!) */
ret

114
sh.c
View file

@ -68,28 +68,28 @@ parse(char *s)
while (1) { while (1) {
switch ((c = gettoken(0, &t))) { switch ((c = gettoken(0, &t))) {
case 'w': // Add an argument case 'w': // Add an argument
if (cmdlist[nextcmd].argc >= MAXARGS) { if (cmdlist[nextcmd].argc >= MAXARGS) {
printf(2, "too many arguments\n"); printf(2, "too many arguments\n");
return -1; return -1;
} }
cmdlist[nextcmd].argv[cmdlist[nextcmd].argc++] = t; cmdlist[nextcmd].argv[cmdlist[nextcmd].argc++] = t;
break; break;
case '<': // Input redirection case '<': // Input redirection
// Grab the filename from the argument list // Grab the filename from the argument list
if (gettoken(0, &t) != 'w') { if (gettoken(0, &t) != 'w') {
printf(2, "syntax error: < not followed by word\n"); printf(2, "syntax error: < not followed by word\n");
return -1; return -1;
} }
addio('<', t); addio('<', t);
break; break;
case '>': // Output redirection case '>': // Output redirection
// Grab the filename from the argument list // Grab the filename from the argument list
if (gettoken(0, &t) != 'w') { if (gettoken(0, &t) != 'w') {
printf(2, "syntax error: > not followed by word\n"); printf(2, "syntax error: > not followed by word\n");
return -1; return -1;
} }
addio('>', t); addio('>', t);
break; break;
@ -100,7 +100,7 @@ parse(char *s)
nextcmd++; nextcmd++;
break; break;
case 0: // String is complete case 0: // String is complete
return 0; return 0;
default: default:
@ -141,9 +141,9 @@ runcmd(void)
if (debug) { if (debug) {
printf(2, "[%d] SPAWN:", getpid()); printf(2, "[%d] SPAWN:", getpid());
for (i = 0; cmdlist[c].argv[i]; i++) for (i = 0; cmdlist[c].argv[i]; i++)
printf(2, " %s", cmdlist[c].argv[i]); printf(2, " %s", cmdlist[c].argv[i]);
for (i = 0; i < nextio; i++) { for (i = 0; i < nextio; i++) {
printf(2, "%c %s", iolist[i].token, iolist[i].s); printf(2, "%c %s", iolist[i].token, iolist[i].s);
} }
printf(2, "\n"); printf(2, "\n");
} }
@ -156,55 +156,55 @@ runcmd(void)
if (cmdlist[c].token == '|') if (cmdlist[c].token == '|')
if (pipe(fdarray) < 0) if (pipe(fdarray) < 0)
printf(2, "cmd %d pipe failed\n", c); printf(2, "cmd %d pipe failed\n", c);
pid = fork(); pid = fork();
if (pid == 0) { if (pid == 0) {
if (cmdlist[c].token == '|') { if (cmdlist[c].token == '|') {
if (close(1) < 0) if (close(1) < 0)
printf(2, "close 1 failed\n"); printf(2, "close 1 failed\n");
if ((tfd = dup(fdarray[1])) < 0) if ((tfd = dup(fdarray[1])) < 0)
printf(2, "dup failed\n"); printf(2, "dup failed\n");
if (close(fdarray[0]) < 0) if (close(fdarray[0]) < 0)
printf(2, "close fdarray[0] failed\n"); printf(2, "close fdarray[0] failed\n");
if (close(fdarray[1]) < 0) if (close(fdarray[1]) < 0)
printf(2, "close fdarray[1] failed\n"); printf(2, "close fdarray[1] failed\n");
} }
if (c > 0 && cmdlist[c-1].token == '|') { if (c > 0 && cmdlist[c-1].token == '|') {
if (close(0) < 0) if (close(0) < 0)
printf(2, "close 0 failed\n"); printf(2, "close 0 failed\n");
if ((tfd = dup(fdarray[0])) < 0) if ((tfd = dup(fdarray[0])) < 0)
printf(2, "dup failed\n"); printf(2, "dup failed\n");
if (close(fdarray[0]) < 0) if (close(fdarray[0]) < 0)
printf(2, "close fdarray[0] failed\n"); printf(2, "close fdarray[0] failed\n");
if (close(fdarray[1]) < 0) if (close(fdarray[1]) < 0)
printf(2, "close fdarray[1] failed\n"); printf(2, "close fdarray[1] failed\n");
} }
if (ioredirection() < 0) if (ioredirection() < 0)
exit(); exit();
if ((r = exec(cmdlist[c].argv0buf, (char**) cmdlist[c].argv)) < 0) { if ((r = exec(cmdlist[c].argv0buf, (char**) cmdlist[c].argv)) < 0) {
printf(2, "exec %s: %d\n", cmdlist[c].argv[0], r); printf(2, "exec %s: %d\n", cmdlist[c].argv[0], r);
exit(); exit();
} }
} else if (pid > 0) { } else if (pid > 0) {
int p; int p;
if (debug) if (debug)
printf(2, "[%d] FORKED child %d\n", getpid(), pid); printf(2, "[%d] FORKED child %d\n", getpid(), pid);
if (c > 0 && cmdlist[c-1].token == '|') { if (c > 0 && cmdlist[c-1].token == '|') {
close(fdarray[0]); close(fdarray[0]);
close(fdarray[1]); close(fdarray[1]);
} }
if (cmdlist[c].token != '|') { if (cmdlist[c].token != '|') {
if (debug) if (debug)
printf(2, "[%d] WAIT for children\n", getpid()); printf(2, "[%d] WAIT for children\n", getpid());
do { do {
p = wait(); p = wait();
if (debug) if (debug)
printf(2, "[%d] WAIT child %d finished\n", getpid(), p); printf(2, "[%d] WAIT child %d finished\n", getpid(), p);
} while (p > 0); } while (p > 0);
if (debug) if (debug)
printf(2, "[%d] wait finished\n", getpid()); printf(2, "[%d] wait finished\n", getpid());
} }
} }
} }
@ -219,23 +219,23 @@ ioredirection(void)
switch (iolist[i].token) { switch (iolist[i].token) {
case '<': case '<':
if (close(0) < 0) if (close(0) < 0)
printf(2, "close 0 failed\n"); printf(2, "close 0 failed\n");
if ((fd = open(iolist[i].s, O_RDONLY)) < 0) { if ((fd = open(iolist[i].s, O_RDONLY)) < 0) {
printf(2, "failed to open %s for read: %d", iolist[i].s, fd); printf(2, "failed to open %s for read: %d", iolist[i].s, fd);
return -1; return -1;
} }
if (debug) if (debug)
printf(2, "redirect 0 from %s\n", iolist[i].s); printf(2, "redirect 0 from %s\n", iolist[i].s);
break; break;
case '>': case '>':
if (close(1) < 0) if (close(1) < 0)
printf(2, "close 1 failed\n"); printf(2, "close 1 failed\n");
if ((fd = open(iolist[i].s, O_WRONLY|O_CREATE)) < 0) { if ((fd = open(iolist[i].s, O_WRONLY|O_CREATE)) < 0) {
printf(2, "failed to open %s for write: %d", iolist[i].s, fd); printf(2, "failed to open %s for write: %d", iolist[i].s, fd);
exit(); exit();
} }
if (debug) if (debug)
printf(2, "redirect 1 to %s\n", iolist[i].s); printf(2, "redirect 1 to %s\n", iolist[i].s);
break; break;
} }
} }
@ -283,11 +283,11 @@ gettoken(char *s, char **p1)
// Get the next token from string s. // Get the next token from string s.
// Set *p1 to the beginning of the token and *p2 just past the token. // Set *p1 to the beginning of the token and *p2 just past the token.
// Returns // Returns
// 0 for end-of-string; // 0 for end-of-string;
// < for <; // < for <;
// > for >; // > for >;
// | for |; // | for |;
// w for a word. // w for a word.
// //
// Eventually (once we parse the space where the \0 will go), // Eventually (once we parse the space where the \0 will go),
// words get nul-terminated. // words get nul-terminated.

View file

@ -5,8 +5,8 @@ open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!";
$n = sysread(SIG, $buf, 1000); $n = sysread(SIG, $buf, 1000);
if($n > 510){ if($n > 510){
print STDERR "boot block too large: $n bytes (max 510)\n"; print STDERR "boot block too large: $n bytes (max 510)\n";
exit 1; exit 1;
} }
print STDERR "boot block is $n bytes (max 510)\n"; print STDERR "boot block is $n bytes (max 510)\n";

View file

@ -40,7 +40,7 @@ acquire(struct spinlock * lock)
while(cmpxchg(0, 1, &lock->locked) == 1) while(cmpxchg(0, 1, &lock->locked) == 1)
; ;
cpuid(0, 0, 0, 0, 0); // memory barrier cpuid(0, 0, 0, 0, 0); // memory barrier
getcallerpcs(&lock, lock->pcs); getcallerpcs(&lock, lock->pcs);
lock->cpu = cpu() + 10; lock->cpu = cpu() + 10;
} }
@ -54,7 +54,7 @@ release(struct spinlock * lock)
lock->pcs[0] = 0; lock->pcs[0] = 0;
lock->cpu = 0xffffffff; lock->cpu = 0xffffffff;
cpuid(0, 0, 0, 0, 0); // memory barrier cpuid(0, 0, 0, 0, 0); // memory barrier
lock->locked = 0; lock->locked = 0;
if(--cpus[cpu()].nlock == 0) if(--cpus[cpu()].nlock == 0)
sti(); sti();

View file

@ -50,10 +50,10 @@ memmove(void *dst, const void *src, uint n)
int int
strncmp(const char *p, const char *q, uint n) strncmp(const char *p, const char *q, uint n)
{ {
while (n > 0 && *p && *p == *q) while (n > 0 && *p && *p == *q)
n--, p++, q++; n--, p++, q++;
if (n == 0) if (n == 0)
return 0; return 0;
else else
return (int) ((uchar) *p - (uchar) *q); return (int) ((uchar) *p - (uchar) *q);
} }

2
trap.c
View file

@ -86,7 +86,7 @@ trap(struct trapframe *tf)
if(curproc[cpu()]) { 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---terminate process\n",
curproc[cpu()]->pid, v, cpu(), tf->eip); curproc[cpu()]->pid, v, cpu(), tf->eip);
proc_exit(); proc_exit();
} }
cprintf("unexpected trap %d from cpu %d eip %x\n", v, cpu(), tf->eip); cprintf("unexpected trap %d from cpu %d eip %x\n", v, cpu(), tf->eip);

View file

@ -1,38 +1,38 @@
.text .text
.globl trap .globl trap
.globl trapret1 .globl trapret1
.globl alltraps .globl alltraps
alltraps: alltraps:
/* vectors.S sends all traps here */ /* vectors.S sends all traps here */
pushl %ds # build pushl %ds # build
pushl %es # trap pushl %es # trap
pushal # frame pushal # frame
movl $16,%eax # SEG_KDATA << 3 movl $16,%eax # SEG_KDATA << 3
movw %ax,%ds # kernel movw %ax,%ds # kernel
movw %ax,%es # segments movw %ax,%es # segments
pushl %esp # pass pointer to this trapframe pushl %esp # pass pointer to this trapframe
call trap # and call trap() call trap # and call trap()
addl $4, %esp addl $4, %esp
# return falls through to trapret... # return falls through to trapret...
/* /*
* a forked process RETs here * a forked process RETs here
* expects ESP to point to a Trapframe * expects ESP to point to a Trapframe
*/ */
.globl trapret .globl trapret
trapret: trapret:
popal popal
popl %es popl %es
popl %ds popl %ds
addl $0x8, %esp /* trapno and errcode */ addl $0x8, %esp /* trapno and errcode */
iret iret
.globl forkret1 .globl forkret1
forkret1: forkret1:
movl 4(%esp), %esp movl 4(%esp), %esp
jmp trapret jmp trapret
.globl acpu .globl acpu
acpu: acpu:
.long 0 .long 0

48
traps.h
View file

@ -1,33 +1,33 @@
// system defined: // system defined:
#define T_DIVIDE 0 // divide error #define T_DIVIDE 0 // divide error
#define T_DEBUG 1 // debug exception #define T_DEBUG 1 // debug exception
#define T_NMI 2 // non-maskable interrupt #define T_NMI 2 // non-maskable interrupt
#define T_BRKPT 3 // breakpoint #define T_BRKPT 3 // breakpoint
#define T_OFLOW 4 // overflow #define T_OFLOW 4 // overflow
#define T_BOUND 5 // bounds check #define T_BOUND 5 // bounds check
#define T_ILLOP 6 // illegal opcode #define T_ILLOP 6 // illegal opcode
#define T_DEVICE 7 // device not available #define T_DEVICE 7 // device not available
#define T_DBLFLT 8 // double fault #define T_DBLFLT 8 // double fault
/* #define T_COPROC 9 */ // reserved (not generated by recent processors) /* #define T_COPROC 9 */ // reserved (not generated by recent processors)
#define T_TSS 10 // invalid task switch segment #define T_TSS 10 // invalid task switch segment
#define T_SEGNP 11 // segment not present #define T_SEGNP 11 // segment not present
#define T_STACK 12 // stack exception #define T_STACK 12 // stack exception
#define T_GPFLT 13 // genernal protection fault #define T_GPFLT 13 // genernal protection fault
#define T_PGFLT 14 // page fault #define T_PGFLT 14 // page fault
/* #define T_RES 15 */ // reserved /* #define T_RES 15 */ // reserved
#define T_FPERR 16 // floating point error #define T_FPERR 16 // floating point error
#define T_ALIGN 17 // aligment check #define T_ALIGN 17 // aligment check
#define T_MCHK 18 // machine check #define T_MCHK 18 // machine check
#define T_SIMDERR 19 // SIMD floating point error #define T_SIMDERR 19 // SIMD floating point error
// These are arbitrarily chosen, but with care not to overlap // These are arbitrarily chosen, but with care not to overlap
// processor defined exceptions or interrupt vectors. // processor defined exceptions or interrupt vectors.
#define T_SYSCALL 48 // system call #define T_SYSCALL 48 // system call
#define T_DEFAULT 500 // catchall #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_KBD 1
#define IRQ_IDE 14 #define IRQ_IDE 14
#define IRQ_TIMER 18 #define IRQ_TIMER 18
#define IRQ_ERROR 19 #define IRQ_ERROR 19

30
ulib.c
View file

@ -12,20 +12,20 @@ puts(char *s)
char* char*
strcpy(char *s, char *t) strcpy(char *s, char *t)
{ {
char *os; char *os;
os = s; os = s;
while((*s++ = *t++) != 0) while((*s++ = *t++) != 0)
; ;
return os; return os;
} }
int int
strcmp(const char *p, const char *q) strcmp(const char *p, const char *q)
{ {
while (*p && *p == *q) while (*p && *p == *q)
p++, q++; p++, q++;
return (int) ((unsigned char) *p - (unsigned char) *q); return (int) ((unsigned char) *p - (unsigned char) *q);
} }
unsigned int unsigned int
@ -37,7 +37,7 @@ strlen(char *s)
return n; return n;
} }
void * void*
memset(void *dst, int c, unsigned int n) memset(void *dst, int c, unsigned int n)
{ {
char *d = (char *) dst; char *d = (char *) dst;
@ -48,16 +48,16 @@ memset(void *dst, int c, unsigned int n)
return dst; return dst;
} }
char * char*
strchr(const char *s, char c) strchr(const char *s, char c)
{ {
for (; *s; s++) for (; *s; s++)
if (*s == c) if (*s == c)
return (char *) s; return (char *) s;
return 0; return 0;
} }
char * char*
gets(char *buf, int max) gets(char *buf, int max)
{ {
int i = 0, cc; int i = 0, cc;

View file

@ -74,17 +74,17 @@ malloc(uint nbytes)
for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) { for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) {
if (p->s.size >= nunits) { if (p->s.size >= nunits) {
if (p->s.size == nunits) if (p->s.size == nunits)
prevp->s.ptr = p->s.ptr; prevp->s.ptr = p->s.ptr;
else { else {
p->s.size -= nunits; p->s.size -= nunits;
p += p->s.size; p += p->s.size;
p->s.size = nunits; p->s.size = nunits;
} }
freep = prevp; freep = prevp;
return (void *) (p + 1); return (void *) (p + 1);
} }
if (p == freep) if (p == freep)
if ((p = morecore(nunits)) == 0) if ((p = morecore(nunits)) == 0)
return 0; return 0;
} }
} }

View file

@ -115,8 +115,8 @@ writetest1(void)
i = read(fd, buf, 512); i = read(fd, buf, 512);
if (i == 0) { if (i == 0) {
if (n == MAXFILE - 1) { if (n == MAXFILE - 1) {
printf(stdout, "read only %d blocks from big", n); printf(stdout, "read only %d blocks from big", n);
exit(); exit();
} }
break; break;
} else if (i != 512) { } else if (i != 512) {

10
usys.S
View file

@ -2,11 +2,11 @@
#include "traps.h" #include "traps.h"
#define STUB(name) \ #define STUB(name) \
.globl name; \ .globl name; \
name: \ name: \
movl $SYS_ ## name, %eax; \ movl $SYS_ ## name, %eax; \
int $T_SYSCALL; \ int $T_SYSCALL; \
ret ret
STUB(fork) STUB(fork)
STUB(exit) STUB(exit)

View file

@ -13,10 +13,10 @@ for(my $i = 0; $i < 256; $i++){
print ".globl vector$i\n"; print ".globl vector$i\n";
print "vector$i:\n"; print "vector$i:\n";
if(($i < 8 || $i > 14) && $i != 17){ if(($i < 8 || $i > 14) && $i != 17){
print "\tpushl \$0\n"; print " pushl \$0\n";
} }
print "\tpushl \$$i\n"; print " pushl \$$i\n";
print "\tjmp alltraps\n"; print " jmp alltraps\n";
} }
print "\n/* vector table */\n"; print "\n/* vector table */\n";
@ -24,5 +24,5 @@ print ".data\n";
print ".globl vectors\n"; print ".globl vectors\n";
print "vectors:\n"; print "vectors:\n";
for(my $i = 0; $i < 256; $i++){ for(my $i = 0; $i < 256; $i++){
print "\t.long vector$i\n"; print " .long vector$i\n";
} }

142
x86.h
View file

@ -1,39 +1,39 @@
static __inline uchar static __inline uchar
inb(int port) inb(int port)
{ {
uchar data; uchar data;
__asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port)); __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
return data; return data;
} }
static __inline void static __inline void
insl(int port, void *addr, int cnt) insl(int port, void *addr, int cnt)
{ {
__asm __volatile("cld\n\trepne\n\tinsl" : __asm __volatile("cld\n\trepne\n\tinsl" :
"=D" (addr), "=c" (cnt) : "=D" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) : "d" (port), "0" (addr), "1" (cnt) :
"memory", "cc"); "memory", "cc");
} }
static __inline void static __inline void
outb(int port, uchar data) outb(int port, uchar data)
{ {
__asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
} }
static __inline void static __inline void
outw(int port, ushort data) outw(int port, ushort data)
{ {
__asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
} }
static __inline void static __inline void
outsl(int port, const void *addr, int cnt) outsl(int port, const void *addr, int cnt)
{ {
__asm __volatile("cld\n\trepne\n\toutsl" : __asm __volatile("cld\n\trepne\n\toutsl" :
"=S" (addr), "=c" (cnt) : "=S" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) : "d" (port), "0" (addr), "1" (cnt) :
"cc"); "cc");
} }
struct segdesc; struct segdesc;
@ -41,13 +41,13 @@ struct segdesc;
static __inline void static __inline void
lgdt(struct segdesc *p, int size) lgdt(struct segdesc *p, int size)
{ {
volatile ushort pd[3]; volatile ushort pd[3];
pd[0] = size-1; pd[0] = size-1;
pd[1] = (uint)p; pd[1] = (uint)p;
pd[2] = (uint)p >> 16; pd[2] = (uint)p >> 16;
asm volatile("lgdt (%0)" : : "g" (pd)); asm volatile("lgdt (%0)" : : "g" (pd));
} }
struct gatedesc; struct gatedesc;
@ -55,99 +55,99 @@ struct gatedesc;
static __inline void static __inline void
lidt(struct gatedesc *p, int size) lidt(struct gatedesc *p, int size)
{ {
volatile ushort pd[3]; volatile ushort pd[3];
pd[0] = size-1; pd[0] = size-1;
pd[1] = (uint)p; pd[1] = (uint)p;
pd[2] = (uint)p >> 16; pd[2] = (uint)p >> 16;
asm volatile("lidt (%0)" : : "g" (pd)); asm volatile("lidt (%0)" : : "g" (pd));
} }
static __inline void static __inline void
ltr(ushort sel) ltr(ushort sel)
{ {
__asm __volatile("ltr %0" : : "r" (sel)); __asm __volatile("ltr %0" : : "r" (sel));
} }
static __inline uint static __inline uint
read_eflags(void) read_eflags(void)
{ {
uint eflags; uint eflags;
__asm __volatile("pushfl; popl %0" : "=r" (eflags)); __asm __volatile("pushfl; popl %0" : "=r" (eflags));
return eflags; return eflags;
} }
static __inline void static __inline void
write_eflags(uint eflags) write_eflags(uint eflags)
{ {
__asm __volatile("pushl %0; popfl" : : "r" (eflags)); __asm __volatile("pushl %0; popfl" : : "r" (eflags));
} }
static __inline void static __inline void
cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp) cpuid(uint info, uint *eaxp, uint *ebxp, uint *ecxp, uint *edxp)
{ {
uint eax, ebx, ecx, edx; uint eax, ebx, ecx, edx;
asm volatile("cpuid" asm volatile("cpuid" :
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) :
: "a" (info)); "a" (info));
if (eaxp) if (eaxp)
*eaxp = eax; *eaxp = eax;
if (ebxp) if (ebxp)
*ebxp = ebx; *ebxp = ebx;
if (ecxp) if (ecxp)
*ecxp = ecx; *ecxp = ecx;
if (edxp) if (edxp)
*edxp = edx; *edxp = edx;
} }
static __inline uint static __inline uint
cmpxchg(uint oldval, uint newval, volatile uint* lock_addr) cmpxchg(uint oldval, uint newval, volatile uint* lock_addr)
{ {
uint result; uint result;
__asm__ __volatile__( __asm__ __volatile__("lock; cmpxchgl %2, %0" :
"lock; cmpxchgl %2, %0" "+m" (*lock_addr), "=a" (result) :
:"+m" (*lock_addr), "=a" (result) : "r"(newval), "1"(oldval) : "cc" "r"(newval), "1"(oldval) :
); "cc");
return result; return result;
} }
static __inline void static __inline void
cli(void) cli(void)
{ {
__asm__ volatile("cli"); __asm__ volatile("cli");
} }
static __inline void static __inline void
sti(void) sti(void)
{ {
__asm__ volatile("sti"); __asm__ volatile("sti");
} }
struct trapframe { struct trapframe {
/* registers as pushed by pusha */ /* registers as pushed by pusha */
uint edi; uint edi;
uint esi; uint esi;
uint ebp; uint ebp;
uint oesp; /* Useless */ uint oesp; /* Useless */
uint ebx; uint ebx;
uint edx; uint edx;
uint ecx; uint ecx;
uint eax; uint eax;
/* rest of trap frame */ /* rest of trap frame */
ushort es; ushort es;
ushort padding1; ushort padding1;
ushort ds; ushort ds;
ushort padding2; ushort padding2;
uint trapno; uint trapno;
/* below here defined by x86 hardware */ /* below here defined by x86 hardware */
uint err; uint err;
uint eip; uint eip;
ushort cs; ushort cs;
ushort padding3; ushort padding3;
uint eflags; uint eflags;
/* below here only when crossing rings, such as from user to kernel */ /* below here only when crossing rings, such as from user to kernel */
uint esp; uint esp;
ushort ss; ushort ss;
ushort padding4; ushort padding4;
}; };