diff --git a/Notes b/Notes index 2291621..1140f9d 100644 --- a/Notes +++ b/Notes @@ -241,3 +241,41 @@ maybe a race; acquire does cpu = cpu() what if another acquire calls holding w/ locked = 1 but before cpu is set? + +if I type a lot (kbd), i get a panic +cpu1 in scheduler: panic "holding locks in scheduler" +cpu0 also in the same panic! +recursive interrupt? + FL_IF is probably set during interrupt... is that correct? +again: + olding locks in scheduler + trap v 33 eip 100ED3 c (that is, interrupt while holding a lock) + 100ed3 is in lapic_write +again: + trap v 33 eip 102A3C cpu 1 nlock 1 (in acquire) + panic: interrupt while holding a lock +again: + trap v 33 eip 102A3C cpu 1 nlock 1 + panic: interrupt while holding a lock +OR is it the cprintf("kbd overflow")? + no, get panic even w/o that cprintf +OR a release() at interrupt time turns interrupts back on? + of course i don't think they were off... +OK, fixing trap.c to make interrupts turn off FL_IF + that makes it take longer, but still panics + (maybe b/c release sets FL_IF) + +shouldn't something (PIC?) prevent recursive interrupts of same IRQ? + or should FL_IF be clear during all interrupts? + +maybe acquire should remember old FL_IF value, release should restore + if acquire did cli() + +DUH the increment of nlock in acquire() happens before the cli! + so the panic is probably not a real problem + test nlock, cli(), then increment? + +BUT now userfs doesn't do the final cat README + +AND w/ cprintf("kbd overflow"), panic holding locks in scheduler + maybe also simulataneous panic("interrupt while holding a lock") diff --git a/console.c b/console.c index eca0225..726aa0a 100644 --- a/console.c +++ b/console.c @@ -174,8 +174,186 @@ console_write (int minor, void *buf, int n) return n; } + +/* This is i8042reg.h + kbdreg.h from NetBSD. */ +#define KBSTATP 0x64 /* kbd controller status port(I) */ +#define KBS_DIB 0x01 /* kbd data in buffer */ +#define KBDATAP 0x60 /* kbd data port(I) */ + +#define NO 0 + +#define SHIFT (1<<0) +#define CTL (1<<1) +#define ALT (1<<2) + +#define CAPSLOCK (1<<3) +#define NUMLOCK (1<<4) +#define SCROLLLOCK (1<<5) + +#define E0ESC (1<<6) + +// Special keycodes +#define KEY_HOME 0xE0 +#define KEY_END 0xE1 +#define KEY_UP 0xE2 +#define KEY_DN 0xE3 +#define KEY_LF 0xE4 +#define KEY_RT 0xE5 +#define KEY_PGUP 0xE6 +#define KEY_PGDN 0xE7 +#define KEY_INS 0xE8 +#define KEY_DEL 0xE9 + +static uchar shiftcode[256] = +{ + [0x1D] CTL, + [0x2A] SHIFT, + [0x36] SHIFT, + [0x38] ALT, + [0x9D] CTL, + [0xB8] ALT +}; + +static uchar togglecode[256] = +{ + [0x3A] CAPSLOCK, + [0x45] NUMLOCK, + [0x46] SCROLLLOCK +}; + +static uchar normalmap[256] = +{ + NO, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00 + '7', '8', '9', '0', '-', '=', '\b', '\t', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10 + 'o', 'p', '[', ']', '\n', NO, 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20 + '\'', '`', NO, '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', NO, '*', // 0x30 + NO, ' ', NO, NO, NO, NO, NO, NO, + NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 + '8', '9', '-', '4', '5', '6', '+', '1', + '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 + [0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/, + [0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP, + [0xC9] KEY_PGUP, [0xCB] KEY_LF, + [0xCD] KEY_RT, [0xCF] KEY_END, + [0xD0] KEY_DN, [0xD1] KEY_PGDN, + [0xD2] KEY_INS, [0xD3] KEY_DEL +}; + +static uchar shiftmap[256] = +{ + NO, 033, '!', '@', '#', '$', '%', '^', // 0x00 + '&', '*', '(', ')', '_', '+', '\b', '\t', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10 + 'O', 'P', '{', '}', '\n', NO, 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20 + '"', '~', NO, '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', NO, '*', // 0x30 + NO, ' ', NO, NO, NO, NO, NO, NO, + NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 + '8', '9', '-', '4', '5', '6', '+', '1', + '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 + [0x97] KEY_HOME, [0x9C] '\n' /*KP_Enter*/, + [0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP, + [0xC9] KEY_PGUP, [0xCB] KEY_LF, + [0xCD] KEY_RT, [0xCF] KEY_END, + [0xD0] KEY_DN, [0xD1] KEY_PGDN, + [0xD2] KEY_INS, [0xD3] KEY_DEL +}; + +#define C(x) (x - '@') + +static uchar ctlmap[256] = +{ + 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('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, + NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'), + C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO, + [0x97] KEY_HOME, + [0xB5] C('/'), [0xC8] KEY_UP, + [0xC9] KEY_PGUP, [0xCB] KEY_LF, + [0xCD] KEY_RT, [0xCF] KEY_END, + [0xD0] KEY_DN, [0xD1] KEY_PGDN, + [0xD2] KEY_INS, [0xD3] KEY_DEL +}; + +static uchar *charcode[4] = { + normalmap, + shiftmap, + ctlmap, + ctlmap +}; + +#define KBD_BUF 64 +char kbd_buf[KBD_BUF]; +int kbd_r; +int kbd_w; +struct spinlock kbd_lock = { "kbd_lock" }; + void -console_init () +kbd_intr() +{ + uint st, data, c; + static uint shift; + + st = inb(KBSTATP); + if ((st & KBS_DIB) == 0){ + lapic_eoi(); + return; + } + data = inb(KBDATAP); + + if (data == 0xE0) { + shift |= E0ESC; + lapic_eoi(); + return; + } else if (data & 0x80) { + // Key released + data = (shift & E0ESC ? data : data & 0x7F); + shift &= ~(shiftcode[data] | E0ESC); + lapic_eoi(); + return; + } else if (shift & E0ESC) { + // Last character was an E0 escape; or with 0x80 + data |= 0x80; + shift &= ~E0ESC; + } + + shift |= shiftcode[data]; + shift ^= togglecode[data]; + + c = charcode[shift & (CTL | SHIFT)][data]; + if (shift & CAPSLOCK) { + if ('a' <= c && c <= 'z') + c += 'A' - 'a'; + else if ('A' <= c && c <= 'Z') + c += 'a' - 'A'; + } + + acquire(&kbd_lock); + + if(((kbd_w + 1) % KBD_BUF) != kbd_r){ + kbd_buf[kbd_w++] = c; + if(kbd_w >= KBD_BUF) + kbd_w = 0; + } else { + cprintf("kbd overflow\n"); + } + + release(&kbd_lock); + + lapic_eoi(); +} + +void +console_init() { devsw[CONSOLE].d_write = console_write; + + ioapic_enable (IRQ_KBD, 1); } diff --git a/defs.h b/defs.h index 99a3119..de11401 100644 --- a/defs.h +++ b/defs.h @@ -4,8 +4,10 @@ void kfree(char *cp, int len); void kinit(void); // console.c +void console_init(void); void cprintf(char *fmt, ...); void panic(char *s); +void kbd_intr(void); // proc.c struct proc; diff --git a/fcntl.h b/fcntl.h new file mode 100644 index 0000000..baa5c0e --- /dev/null +++ b/fcntl.h @@ -0,0 +1,4 @@ +#define O_CREATE 0x200 +#define O_RDONLY 0x000 +#define O_WRONLY 0x001 +#define O_RDWR 0x002 diff --git a/fs.c b/fs.c index 7e54876..126c18f 100644 --- a/fs.c +++ b/fs.c @@ -329,6 +329,7 @@ writei(struct inode *ip, void *addr, uint off, uint n) return r; } else { panic ("writei: unknown type\n"); + return 0; } } diff --git a/fs.h b/fs.h index c3f4e5f..6e83373 100644 --- a/fs.h +++ b/fs.h @@ -36,8 +36,3 @@ struct dirent { ushort inum; char name[DIRSIZ]; }; - -#define O_CREATE 0x200 -#define O_RDONLY 0x000 -#define O_WRONLY 0x001 -#define O_RDWR 0x002 diff --git a/ide.c b/ide.c index 400b726..67fb613 100644 --- a/ide.c +++ b/ide.c @@ -49,7 +49,7 @@ ide_init(void) if (ncpu < 2) { panic ("ide_init: disk interrupt is going to the second cpu\n"); } - ioapic_enable (14, 1); // 14 is IRQ # for IDE + ioapic_enable (IRQ_IDE, 1); ide_wait_ready(0); cprintf ("cpu%d: ide_init:done\n", cpu()); } diff --git a/main.c b/main.c index f0ca80e..b558e41 100644 --- a/main.c +++ b/main.c @@ -71,7 +71,7 @@ main0(void) p->tf->eflags = FL_IF; setupsegs(p); - // init disk device + // initialize I/O devices, let them enable interrupts console_init(); ide_init(); diff --git a/mkfs.c b/mkfs.c index fbf78b0..b048e10 100644 --- a/mkfs.c +++ b/mkfs.c @@ -75,7 +75,7 @@ main(int argc, char *argv[]) sb.nblocks = xint(nblocks); // so whole disk is size sectors sb.ninodes = xint(ninodes); - bitblocks = sb.size/(512*8) + 1; + bitblocks = size/(512*8) + 1; usedblocks = ninodes / IPB + 3 + bitblocks; freeblock = usedblocks; diff --git a/spinlock.c b/spinlock.c index 5a0fd23..b1b4079 100644 --- a/spinlock.c +++ b/spinlock.c @@ -30,8 +30,10 @@ acquire(struct spinlock * lock) if(holding(lock)) panic("acquire"); - if(cpus[cpu()].nlock++ == 0) - cli(); + if(cpus[cpu()].nlock == 0) + cli(); + cpus[cpu()].nlock++; + while(cmpxchg(0, 1, &lock->locked) == 1) ; cpuid(0, 0, 0, 0, 0); // memory barrier @@ -53,6 +55,8 @@ release(struct spinlock * lock) lock->locked = 0; if(--cpus[cpu()].nlock == 0) sti(); + // xxx we may have just turned interrupts on during + // an interrupt, is that ok? } int diff --git a/syscall.c b/syscall.c index 685fa46..c53c447 100644 --- a/syscall.c +++ b/syscall.c @@ -12,6 +12,7 @@ #include "fsvar.h" #include "elf.h" #include "fd.h" +#include "fcntl.h" /* * User code makes a system call with INT T_SYSCALL. diff --git a/trap.c b/trap.c index 7031223..b172a77 100644 --- a/trap.c +++ b/trap.c @@ -21,7 +21,7 @@ tvinit(void) for(i = 0; i < 256; i++){ SETGATE(idt[i], 1, SEG_KCODE << 3, vectors[i], 0); } - SETGATE(idt[T_SYSCALL], T_SYSCALL, SEG_KCODE << 3, vectors[48], 3); + SETGATE(idt[T_SYSCALL], 1, SEG_KCODE << 3, vectors[48], 3); } void @@ -40,12 +40,12 @@ trap(struct trapframe *tf) v, tf->eip, cpu(), cpus[cpu()].nlock); panic("interrupt while holding a lock"); } - if((read_eflags() & FL_IF) == 0) - panic("interrupt but interrupts now disabled"); if(v == T_SYSCALL){ struct proc *cp = curproc[cpu()]; int num = cp->tf->eax; + if((read_eflags() & FL_IF) == 0) + panic("syscall but interrupts now disabled"); if(cp == 0) panic("syscall with no proc"); if(cp->killed) @@ -73,6 +73,9 @@ trap(struct trapframe *tf) return; } + //if(read_eflags() & FL_IF) + //panic("interrupt but interrupts enabled"); + if(v == (IRQ_OFFSET + IRQ_TIMER)){ struct proc *cp = curproc[cpu()]; lapic_timerintr(); @@ -97,5 +100,12 @@ trap(struct trapframe *tf) return; } + if(v == (IRQ_OFFSET + IRQ_KBD)){ + kbd_intr(); + return; + } + + cprintf("trap %d\n", v); + return; } diff --git a/userfs.c b/userfs.c index 516a7c9..af87561 100644 --- a/userfs.c +++ b/userfs.c @@ -1,6 +1,7 @@ #include "user.h" #include "types.h" #include "fs.h" +#include "fcntl.h" // file system tests diff --git a/x86.h b/x86.h index 41a6e9a..ea60064 100644 --- a/x86.h +++ b/x86.h @@ -362,6 +362,7 @@ struct trapframe { #define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET +#define IRQ_KBD 1 #define IRQ_IDE 14 #define IRQ_ERROR 19 #define IRQ_SPURIOUS 31