shuffle and tweak for formatting.
pdf has very good page breaks now. would be a good copy for fall 2009.
This commit is contained in:
parent
b3bebfce8a
commit
0aef891495
24 changed files with 6869 additions and 6672 deletions
1
Makefile
1
Makefile
|
@ -128,6 +128,7 @@ PRINT = runoff.list $(FILES)
|
||||||
|
|
||||||
xv6.pdf: $(PRINT)
|
xv6.pdf: $(PRINT)
|
||||||
./runoff
|
./runoff
|
||||||
|
ls -l xv6.pdf
|
||||||
|
|
||||||
print: xv6.pdf
|
print: xv6.pdf
|
||||||
|
|
||||||
|
|
14
bootother.S
14
bootother.S
|
@ -38,7 +38,7 @@ start:
|
||||||
//PAGEBREAK!
|
//PAGEBREAK!
|
||||||
# Switch from real to protected mode, using a bootstrap GDT
|
# Switch from real to protected mode, using a bootstrap GDT
|
||||||
# and segment translation that makes virtual addresses
|
# and segment translation that makes virtual addresses
|
||||||
# identical to their physical addresses, so that the
|
# identical to physical addresses, so that the
|
||||||
# effective memory map does not change during the switch.
|
# effective memory map does not change during the switch.
|
||||||
lgdt gdtdesc
|
lgdt gdtdesc
|
||||||
movl %cr0, %eax
|
movl %cr0, %eax
|
||||||
|
@ -47,10 +47,10 @@ start:
|
||||||
|
|
||||||
# Jump to next instruction, but in 32-bit code segment.
|
# Jump to next instruction, but in 32-bit code segment.
|
||||||
# Switches processor into 32-bit mode.
|
# Switches processor into 32-bit mode.
|
||||||
ljmp $(SEG_KCODE<<3), $protcseg
|
ljmp $(SEG_KCODE<<3), $start32
|
||||||
|
|
||||||
.code32 # Assemble for 32-bit mode
|
.code32 # Assemble for 32-bit mode
|
||||||
protcseg:
|
start32:
|
||||||
# Set up the protected-mode data segment registers
|
# Set up the protected-mode data segment registers
|
||||||
movw $(SEG_KDATA<<3), %ax # Our data segment selector
|
movw $(SEG_KDATA<<3), %ax # Our data segment selector
|
||||||
movw %ax, %ds # -> DS: Data Segment
|
movw %ax, %ds # -> DS: Data Segment
|
||||||
|
@ -60,11 +60,11 @@ protcseg:
|
||||||
movw %ax, %fs # -> FS
|
movw %ax, %fs # -> FS
|
||||||
movw %ax, %gs # -> GS
|
movw %ax, %gs # -> GS
|
||||||
|
|
||||||
|
# Set up the stack pointer and call into C.
|
||||||
movl start-4, %esp
|
movl start-4, %esp
|
||||||
movl start-8, %eax
|
call *(start-8)
|
||||||
call *%eax
|
|
||||||
|
|
||||||
# If bootmain returns (it shouldn't), trigger a Bochs
|
# If the call returns (it shouldn't), trigger a Bochs
|
||||||
# breakpoint if running under Bochs, then loop.
|
# breakpoint if running under Bochs, then loop.
|
||||||
movw $0x8a00, %ax # 0x8a00 -> port 0x8a00
|
movw $0x8a00, %ax # 0x8a00 -> port 0x8a00
|
||||||
movw %ax, %dx
|
movw %ax, %dx
|
||||||
|
|
241
console.c
241
console.c
|
@ -7,22 +7,120 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "traps.h"
|
#include "traps.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "dev.h"
|
#include "fs.h"
|
||||||
|
#include "file.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
|
||||||
#define CRTPORT 0x3d4
|
static void consputc(int);
|
||||||
#define BACKSPACE 0x100
|
|
||||||
|
|
||||||
static ushort *crt = (ushort*)0xb8000; // CGA memory
|
static int panicked = 0;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct spinlock lock;
|
struct spinlock lock;
|
||||||
int locking;
|
int locking;
|
||||||
} cons;
|
} cons;
|
||||||
|
|
||||||
static int panicked = 0;
|
static void
|
||||||
|
printint(int xx, int base, int sgn)
|
||||||
|
{
|
||||||
|
static char digits[] = "0123456789abcdef";
|
||||||
|
char buf[16];
|
||||||
|
int i = 0, neg = 0;
|
||||||
|
uint x;
|
||||||
|
|
||||||
|
if(sgn && xx < 0){
|
||||||
|
neg = 1;
|
||||||
|
x = -xx;
|
||||||
|
} else
|
||||||
|
x = xx;
|
||||||
|
|
||||||
|
do{
|
||||||
|
buf[i++] = digits[x % base];
|
||||||
|
}while((x /= base) != 0);
|
||||||
|
if(neg)
|
||||||
|
buf[i++] = '-';
|
||||||
|
|
||||||
|
while(--i >= 0)
|
||||||
|
consputc(buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//PAGEBREAK: 50
|
||||||
|
// Print to the console. only understands %d, %x, %p, %s.
|
||||||
|
void
|
||||||
|
cprintf(char *fmt, ...)
|
||||||
|
{
|
||||||
|
int i, c, state, locking;
|
||||||
|
uint *argp;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
locking = cons.locking;
|
||||||
|
if(locking)
|
||||||
|
acquire(&cons.lock);
|
||||||
|
|
||||||
|
argp = (uint*)(void*)&fmt + 1;
|
||||||
|
state = 0;
|
||||||
|
for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
|
||||||
|
if(c != '%'){
|
||||||
|
consputc(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
c = fmt[++i] & 0xff;
|
||||||
|
if(c == 0)
|
||||||
|
break;
|
||||||
|
switch(c){
|
||||||
|
case 'd':
|
||||||
|
printint(*argp++, 10, 1);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'p':
|
||||||
|
printint(*argp++, 16, 0);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if((s = (char*)*argp++) == 0)
|
||||||
|
s = "(null)";
|
||||||
|
for(; *s; s++)
|
||||||
|
consputc(*s);
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
consputc('%');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Print unknown % sequence to draw attention.
|
||||||
|
consputc('%');
|
||||||
|
consputc(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(locking)
|
||||||
|
release(&cons.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
panic(char *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint pcs[10];
|
||||||
|
|
||||||
|
cli();
|
||||||
|
cons.locking = 0;
|
||||||
|
cprintf("cpu%d: panic: ", cpu());
|
||||||
|
cprintf(s);
|
||||||
|
cprintf("\n");
|
||||||
|
getcallerpcs(&s, pcs);
|
||||||
|
for(i=0; i<10; i++)
|
||||||
|
cprintf(" %p", pcs[i]);
|
||||||
|
panicked = 1; // freeze other CPU
|
||||||
|
for(;;)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PAGEBREAK: 50
|
||||||
|
#define BACKSPACE 0x100
|
||||||
|
#define CRTPORT 0x3d4
|
||||||
|
static ushort *crt = (ushort*)0xb8000; // CGA memory
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cgaputc(int c)
|
cgaputc(int c)
|
||||||
|
@ -69,104 +167,7 @@ consputc(int c)
|
||||||
cgaputc(c);
|
cgaputc(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
//PAGEBREAK: 50
|
||||||
printint(int xx, int base, int sgn)
|
|
||||||
{
|
|
||||||
static char digits[] = "0123456789abcdef";
|
|
||||||
char buf[16];
|
|
||||||
int i = 0, neg = 0;
|
|
||||||
uint x;
|
|
||||||
|
|
||||||
if(sgn && xx < 0){
|
|
||||||
neg = 1;
|
|
||||||
x = 0 - xx;
|
|
||||||
} else {
|
|
||||||
x = xx;
|
|
||||||
}
|
|
||||||
|
|
||||||
do{
|
|
||||||
buf[i++] = digits[x % base];
|
|
||||||
}while((x /= base) != 0);
|
|
||||||
if(neg)
|
|
||||||
buf[i++] = '-';
|
|
||||||
|
|
||||||
while(--i >= 0)
|
|
||||||
consputc(buf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print to the console. only understands %d, %x, %p, %s.
|
|
||||||
void
|
|
||||||
cprintf(char *fmt, ...)
|
|
||||||
{
|
|
||||||
int i, c, state, locking;
|
|
||||||
uint *argp;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
locking = cons.locking;
|
|
||||||
if(locking)
|
|
||||||
acquire(&cons.lock);
|
|
||||||
|
|
||||||
argp = (uint*)(void*)&fmt + 1;
|
|
||||||
state = 0;
|
|
||||||
for(i = 0; fmt[i]; i++){
|
|
||||||
c = fmt[i] & 0xff;
|
|
||||||
switch(state){
|
|
||||||
case 0:
|
|
||||||
if(c == '%')
|
|
||||||
state = '%';
|
|
||||||
else
|
|
||||||
consputc(c);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '%':
|
|
||||||
switch(c){
|
|
||||||
case 'd':
|
|
||||||
printint(*argp++, 10, 1);
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
case 'p':
|
|
||||||
printint(*argp++, 16, 0);
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
s = (char*)*argp++;
|
|
||||||
if(s == 0)
|
|
||||||
s = "(null)";
|
|
||||||
for(; *s; s++)
|
|
||||||
consputc(*s);
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
consputc('%');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Print unknown % sequence to draw attention.
|
|
||||||
consputc('%');
|
|
||||||
consputc(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(locking)
|
|
||||||
release(&cons.lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
consolewrite(struct inode *ip, char *buf, int n)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
iunlock(ip);
|
|
||||||
acquire(&cons.lock);
|
|
||||||
for(i = 0; i < n; i++)
|
|
||||||
consputc(buf[i] & 0xff);
|
|
||||||
release(&cons.lock);
|
|
||||||
ilock(ip);
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INPUT_BUF 128
|
#define INPUT_BUF 128
|
||||||
struct {
|
struct {
|
||||||
struct spinlock lock;
|
struct spinlock lock;
|
||||||
|
@ -255,6 +256,21 @@ consoleread(struct inode *ip, char *dst, int n)
|
||||||
return target - n;
|
return target - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
consolewrite(struct inode *ip, char *buf, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
iunlock(ip);
|
||||||
|
acquire(&cons.lock);
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
consputc(buf[i] & 0xff);
|
||||||
|
release(&cons.lock);
|
||||||
|
ilock(ip);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
consoleinit(void)
|
consoleinit(void)
|
||||||
{
|
{
|
||||||
|
@ -269,22 +285,3 @@ consoleinit(void)
|
||||||
ioapicenable(IRQ_KBD, 0);
|
ioapicenable(IRQ_KBD, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
panic(char *s)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint pcs[10];
|
|
||||||
|
|
||||||
cli();
|
|
||||||
cons.locking = 0;
|
|
||||||
cprintf("cpu%d: panic: ", cpu());
|
|
||||||
cprintf(s);
|
|
||||||
cprintf("\n");
|
|
||||||
getcallerpcs(&s, pcs);
|
|
||||||
for(i=0; i<10; i++)
|
|
||||||
cprintf(" %p", pcs[i]);
|
|
||||||
panicked = 1; // freeze other CPU
|
|
||||||
for(;;)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
1
defs.h
1
defs.h
|
@ -91,6 +91,7 @@ void pipeclose(struct pipe*, int);
|
||||||
int piperead(struct pipe*, char*, int);
|
int piperead(struct pipe*, char*, int);
|
||||||
int pipewrite(struct pipe*, char*, int);
|
int pipewrite(struct pipe*, char*, int);
|
||||||
|
|
||||||
|
//PAGEBREAK: 16
|
||||||
// proc.c
|
// proc.c
|
||||||
struct proc* copyproc(struct proc*);
|
struct proc* copyproc(struct proc*);
|
||||||
void exit(void);
|
void exit(void);
|
||||||
|
|
8
dev.h
8
dev.h
|
@ -1,8 +0,0 @@
|
||||||
struct devsw {
|
|
||||||
int (*read)(struct inode*, char*, int);
|
|
||||||
int (*write)(struct inode*, char*, int);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct devsw devsw[];
|
|
||||||
|
|
||||||
#define CONSOLE 1
|
|
18
elf.h
18
elf.h
|
@ -40,21 +40,3 @@ struct proghdr {
|
||||||
#define ELF_PROG_FLAG_EXEC 1
|
#define ELF_PROG_FLAG_EXEC 1
|
||||||
#define ELF_PROG_FLAG_WRITE 2
|
#define ELF_PROG_FLAG_WRITE 2
|
||||||
#define ELF_PROG_FLAG_READ 4
|
#define ELF_PROG_FLAG_READ 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Blank page.
|
|
||||||
|
|
6
exec.c
6
exec.c
|
@ -11,7 +11,7 @@ exec(char *path, char **argv)
|
||||||
{
|
{
|
||||||
char *mem, *s, *last;
|
char *mem, *s, *last;
|
||||||
int i, argc, arglen, len, off;
|
int i, argc, arglen, len, off;
|
||||||
uint sz, sp, argp;
|
uint sz, sp, argp, x;
|
||||||
struct elfhdr elf;
|
struct elfhdr elf;
|
||||||
struct inode *ip;
|
struct inode *ip;
|
||||||
struct proghdr ph;
|
struct proghdr ph;
|
||||||
|
@ -67,7 +67,9 @@ exec(char *path, char **argv)
|
||||||
goto bad;
|
goto bad;
|
||||||
if(ph.type != ELF_PROG_LOAD)
|
if(ph.type != ELF_PROG_LOAD)
|
||||||
continue;
|
continue;
|
||||||
if(ph.va + ph.memsz < ph.va || ph.va + ph.memsz > sz || ph.memsz < ph.filesz)
|
if(ph.va + ph.memsz < ph.va || ph.va + ph.memsz > sz)
|
||||||
|
goto bad;
|
||||||
|
if(ph.memsz < ph.filesz)
|
||||||
goto bad;
|
goto bad;
|
||||||
if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
|
if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
2
file.c
2
file.c
|
@ -1,9 +1,9 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
|
#include "fs.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "dev.h"
|
|
||||||
|
|
||||||
struct devsw devsw[NDEV];
|
struct devsw devsw[NDEV];
|
||||||
struct {
|
struct {
|
||||||
|
|
32
file.h
32
file.h
|
@ -7,3 +7,35 @@ struct file {
|
||||||
struct inode *ip;
|
struct inode *ip;
|
||||||
uint off;
|
uint off;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// in-core file system types
|
||||||
|
|
||||||
|
struct inode {
|
||||||
|
uint dev; // Device number
|
||||||
|
uint inum; // Inode number
|
||||||
|
int ref; // Reference count
|
||||||
|
int flags; // I_BUSY, I_VALID
|
||||||
|
|
||||||
|
short type; // copy of disk inode
|
||||||
|
short major;
|
||||||
|
short minor;
|
||||||
|
short nlink;
|
||||||
|
uint size;
|
||||||
|
uint addrs[NDIRECT+1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define I_BUSY 0x1
|
||||||
|
#define I_VALID 0x2
|
||||||
|
|
||||||
|
|
||||||
|
// device implementations
|
||||||
|
|
||||||
|
struct devsw {
|
||||||
|
int (*read)(struct inode*, char*, int);
|
||||||
|
int (*write)(struct inode*, char*, int);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct devsw devsw[];
|
||||||
|
|
||||||
|
#define CONSOLE 1
|
||||||
|
|
3
fs.c
3
fs.c
|
@ -19,8 +19,7 @@
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "fsvar.h"
|
#include "file.h"
|
||||||
#include "dev.h"
|
|
||||||
|
|
||||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
static void itrunc(struct inode*);
|
static void itrunc(struct inode*);
|
||||||
|
|
18
fsvar.h
18
fsvar.h
|
@ -1,18 +0,0 @@
|
||||||
// in-core file system types
|
|
||||||
|
|
||||||
struct inode {
|
|
||||||
uint dev; // Device number
|
|
||||||
uint inum; // Inode number
|
|
||||||
int ref; // Reference count
|
|
||||||
int flags; // I_BUSY, I_VALID
|
|
||||||
|
|
||||||
short type; // copy of disk inode
|
|
||||||
short major;
|
|
||||||
short minor;
|
|
||||||
short nlink;
|
|
||||||
uint size;
|
|
||||||
uint addrs[NDIRECT+1];
|
|
||||||
};
|
|
||||||
|
|
||||||
#define I_BUSY 0x1
|
|
||||||
#define I_VALID 0x2
|
|
29
picirq.c
29
picirq.c
|
@ -82,3 +82,32 @@ picinit(void)
|
||||||
if(irqmask != 0xFFFF)
|
if(irqmask != 0xFFFF)
|
||||||
picsetmask(irqmask);
|
picsetmask(irqmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Blank page.
|
||||||
|
|
3
pipe.c
3
pipe.c
|
@ -3,6 +3,7 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
|
#include "fs.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ pipeclose(struct pipe *p, int writable)
|
||||||
release(&p->lock);
|
release(&p->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//PAGEBREAK: 30
|
//PAGEBREAK: 40
|
||||||
int
|
int
|
||||||
pipewrite(struct pipe *p, char *addr, int n)
|
pipewrite(struct pipe *p, char *addr, int n)
|
||||||
{
|
{
|
||||||
|
|
206
proc.c
206
proc.c
|
@ -23,6 +23,79 @@ pinit(void)
|
||||||
initlock(&ptable.lock, "ptable");
|
initlock(&ptable.lock, "ptable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//PAGEBREAK: 36
|
||||||
|
// Print a process listing to console. For debugging.
|
||||||
|
// Runs when user types ^P on console.
|
||||||
|
// No lock to avoid wedging a stuck machine further.
|
||||||
|
void
|
||||||
|
procdump(void)
|
||||||
|
{
|
||||||
|
static char *states[] = {
|
||||||
|
[UNUSED] "unused",
|
||||||
|
[EMBRYO] "embryo",
|
||||||
|
[SLEEPING] "sleep ",
|
||||||
|
[RUNNABLE] "runble",
|
||||||
|
[RUNNING] "run ",
|
||||||
|
[ZOMBIE] "zombie"
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
struct proc *p;
|
||||||
|
char *state;
|
||||||
|
uint pc[10];
|
||||||
|
|
||||||
|
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
||||||
|
if(p->state == UNUSED)
|
||||||
|
continue;
|
||||||
|
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
|
||||||
|
state = states[p->state];
|
||||||
|
else
|
||||||
|
state = "???";
|
||||||
|
cprintf("%d %s %s", p->pid, state, p->name);
|
||||||
|
if(p->state == SLEEPING){
|
||||||
|
getcallerpcs((uint*)p->context->ebp+2, pc);
|
||||||
|
for(i=0; i<10 && pc[i] != 0; i++)
|
||||||
|
cprintf(" %p", pc[i]);
|
||||||
|
}
|
||||||
|
cprintf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up CPU's kernel segment descriptors.
|
||||||
|
// Run once at boot time on each CPU.
|
||||||
|
void
|
||||||
|
ksegment(void)
|
||||||
|
{
|
||||||
|
struct cpu *c1;
|
||||||
|
|
||||||
|
c1 = &cpus[cpu()];
|
||||||
|
c1->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0);
|
||||||
|
c1->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
|
||||||
|
c1->gdt[SEG_KCPU] = SEG(STA_W, (uint)(&c1->tls+1), 0xffffffff, 0);
|
||||||
|
lgdt(c1->gdt, sizeof(c1->gdt));
|
||||||
|
loadfsgs(SEG_KCPU << 3);
|
||||||
|
|
||||||
|
// Initialize cpu-local variables.
|
||||||
|
c = c1;
|
||||||
|
cp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up CPU's segment descriptors and current process task state.
|
||||||
|
// If cp==0, set up for "idle" state for when scheduler() is running.
|
||||||
|
void
|
||||||
|
usegment(void)
|
||||||
|
{
|
||||||
|
pushcli();
|
||||||
|
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER);
|
||||||
|
c->gdt[SEG_UDATA] = SEG(STA_W, (uint)cp->mem, cp->sz-1, DPL_USER);
|
||||||
|
c->gdt[SEG_TSS] = SEG16(STS_T32A, (uint)&c->ts, sizeof(c->ts)-1, 0);
|
||||||
|
c->gdt[SEG_TSS].s = 0;
|
||||||
|
c->ts.ss0 = SEG_KDATA << 3;
|
||||||
|
c->ts.esp0 = (uint)cp->kstack + KSTACKSIZE;
|
||||||
|
ltr(SEG_TSS << 3);
|
||||||
|
popcli();
|
||||||
|
}
|
||||||
|
|
||||||
|
//PAGEBREAK: 15
|
||||||
// Look in the process table for an UNUSED proc.
|
// Look in the process table for an UNUSED proc.
|
||||||
// If found, change state to EMBRYO and return it.
|
// If found, change state to EMBRYO and return it.
|
||||||
// Otherwise return 0.
|
// Otherwise return 0.
|
||||||
|
@ -67,6 +140,37 @@ found:
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up first user process.
|
||||||
|
void
|
||||||
|
userinit(void)
|
||||||
|
{
|
||||||
|
struct proc *p;
|
||||||
|
extern char _binary_initcode_start[], _binary_initcode_size[];
|
||||||
|
|
||||||
|
p = allocproc();
|
||||||
|
initproc = p;
|
||||||
|
|
||||||
|
// Initialize memory from initcode.S
|
||||||
|
p->sz = PAGE;
|
||||||
|
p->mem = kalloc(p->sz);
|
||||||
|
memset(p->mem, 0, p->sz);
|
||||||
|
memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
|
||||||
|
|
||||||
|
memset(p->tf, 0, sizeof(*p->tf));
|
||||||
|
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
|
||||||
|
p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
|
||||||
|
p->tf->es = p->tf->ds;
|
||||||
|
p->tf->ss = p->tf->ds;
|
||||||
|
p->tf->eflags = FL_IF;
|
||||||
|
p->tf->esp = p->sz;
|
||||||
|
p->tf->eip = 0; // beginning of initcode.S
|
||||||
|
|
||||||
|
safestrcpy(p->name, "initcode", sizeof(p->name));
|
||||||
|
p->cwd = namei("/");
|
||||||
|
|
||||||
|
p->state = RUNNABLE;
|
||||||
|
}
|
||||||
|
|
||||||
// Grow current process's memory by n bytes.
|
// Grow current process's memory by n bytes.
|
||||||
// Return 0 on success, -1 on failure.
|
// Return 0 on success, -1 on failure.
|
||||||
int
|
int
|
||||||
|
@ -86,41 +190,6 @@ growproc(int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up CPU's kernel segment descriptors.
|
|
||||||
// Run once at boot time on each CPU.
|
|
||||||
void
|
|
||||||
ksegment(void)
|
|
||||||
{
|
|
||||||
struct cpu *c1;
|
|
||||||
|
|
||||||
c1 = &cpus[cpu()];
|
|
||||||
c1->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0);
|
|
||||||
c1->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
|
|
||||||
c1->gdt[SEG_KCPU] = SEG(STA_W, (uint)(&c1->tls+1), 0xffffffff, 0);
|
|
||||||
lgdt(c1->gdt, sizeof(c1->gdt));
|
|
||||||
loadfsgs(SEG_KCPU << 3);
|
|
||||||
|
|
||||||
// Initialize cpu-local variables.
|
|
||||||
c = c1;
|
|
||||||
cp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up CPU's segment descriptors and task state for the current process.
|
|
||||||
// If cp==0, set up for "idle" state for when scheduler() is running.
|
|
||||||
void
|
|
||||||
usegment(void)
|
|
||||||
{
|
|
||||||
pushcli();
|
|
||||||
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER);
|
|
||||||
c->gdt[SEG_UDATA] = SEG(STA_W, (uint)cp->mem, cp->sz-1, DPL_USER);
|
|
||||||
c->gdt[SEG_TSS] = SEG16(STS_T32A, (uint)&c->ts, sizeof(c->ts)-1, 0);
|
|
||||||
c->gdt[SEG_TSS].s = 0;
|
|
||||||
c->ts.ss0 = SEG_KDATA << 3;
|
|
||||||
c->ts.esp0 = (uint)cp->kstack + KSTACKSIZE;
|
|
||||||
ltr(SEG_TSS << 3);
|
|
||||||
popcli();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new process copying p as the parent.
|
// Create a new process copying p as the parent.
|
||||||
// Sets up stack to return as if from system call.
|
// Sets up stack to return as if from system call.
|
||||||
// Caller must set state of returned proc to RUNNABLE.
|
// Caller must set state of returned proc to RUNNABLE.
|
||||||
|
@ -160,37 +229,6 @@ fork(void)
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up first user process.
|
|
||||||
void
|
|
||||||
userinit(void)
|
|
||||||
{
|
|
||||||
struct proc *p;
|
|
||||||
extern char _binary_initcode_start[], _binary_initcode_size[];
|
|
||||||
|
|
||||||
p = allocproc();
|
|
||||||
initproc = p;
|
|
||||||
|
|
||||||
// Initialize memory from initcode.S
|
|
||||||
p->sz = PAGE;
|
|
||||||
p->mem = kalloc(p->sz);
|
|
||||||
memset(p->mem, 0, p->sz);
|
|
||||||
memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
|
|
||||||
|
|
||||||
memset(p->tf, 0, sizeof(*p->tf));
|
|
||||||
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
|
|
||||||
p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
|
|
||||||
p->tf->es = p->tf->ds;
|
|
||||||
p->tf->ss = p->tf->ds;
|
|
||||||
p->tf->eflags = FL_IF;
|
|
||||||
p->tf->esp = p->sz;
|
|
||||||
p->tf->eip = 0; // beginning of initcode.S
|
|
||||||
|
|
||||||
safestrcpy(p->name, "initcode", sizeof(p->name));
|
|
||||||
p->cwd = namei("/");
|
|
||||||
|
|
||||||
p->state = RUNNABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//PAGEBREAK: 42
|
//PAGEBREAK: 42
|
||||||
// Per-CPU process scheduler.
|
// Per-CPU process scheduler.
|
||||||
// Each CPU calls scheduler() after setting itself up.
|
// Each CPU calls scheduler() after setting itself up.
|
||||||
|
@ -440,39 +478,3 @@ wait(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a process listing to console. For debugging.
|
|
||||||
// Runs when user types ^P on console.
|
|
||||||
// No lock to avoid wedging a stuck machine further.
|
|
||||||
void
|
|
||||||
procdump(void)
|
|
||||||
{
|
|
||||||
static char *states[] = {
|
|
||||||
[UNUSED] "unused",
|
|
||||||
[EMBRYO] "embryo",
|
|
||||||
[SLEEPING] "sleep ",
|
|
||||||
[RUNNABLE] "runble",
|
|
||||||
[RUNNING] "run ",
|
|
||||||
[ZOMBIE] "zombie"
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
struct proc *p;
|
|
||||||
char *state;
|
|
||||||
uint pc[10];
|
|
||||||
|
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
|
||||||
if(p->state == UNUSED)
|
|
||||||
continue;
|
|
||||||
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
|
|
||||||
state = states[p->state];
|
|
||||||
else
|
|
||||||
state = "???";
|
|
||||||
cprintf("%d %s %s", p->pid, state, p->name);
|
|
||||||
if(p->state == SLEEPING){
|
|
||||||
getcallerpcs((uint*)p->context->ebp+2, pc);
|
|
||||||
for(i=0; i<10 && pc[i] != 0; i++)
|
|
||||||
cprintf(" %p", pc[i]);
|
|
||||||
}
|
|
||||||
cprintf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
26
runoff
26
runoff
|
@ -45,6 +45,7 @@ cat toc.ftr >>fmt/toc
|
||||||
|
|
||||||
# check for bad alignments
|
# check for bad alignments
|
||||||
perl -e '
|
perl -e '
|
||||||
|
$leftwarn = 0;
|
||||||
while(<>){
|
while(<>){
|
||||||
chomp;
|
chomp;
|
||||||
s!#.*!!;
|
s!#.*!!;
|
||||||
|
@ -75,12 +76,35 @@ perl -e '
|
||||||
print STDERR "Have no toc for $file\n";
|
print STDERR "Have no toc for $file\n";
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if($toc{$file} =~ /^\d\d[^5]/){
|
if($toc{$file} !~ /^\d\d5/){
|
||||||
print STDERR "$file does not start on a second half page.\n";
|
print STDERR "$file does not start on a second half page.\n";
|
||||||
}
|
}
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(/(left|right): (.*)/){
|
||||||
|
$what = $1;
|
||||||
|
$file = $2;
|
||||||
|
if(!defined($toc{$file})){
|
||||||
|
print STDERR "Have no toc for $file\n";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
# this assumes that sheet 1 of code is a left page
|
||||||
|
# double-check the PDF
|
||||||
|
if(!$leftwarn++) {
|
||||||
|
print STDERR "assuming that sheet 1 is a left page. double-check!\n";
|
||||||
|
}
|
||||||
|
if($what eq "left" && !($toc{$file} =~ /^\d[13579]0/)){
|
||||||
|
print STDERR "$file does not start on a fresh left page [$toc{$file}]\n";
|
||||||
|
}
|
||||||
|
# why does this not work if I inline $x in the if?
|
||||||
|
$x = ($toc{$file} =~ /^\d[02468]0/);
|
||||||
|
if($what eq "right" && !$x){
|
||||||
|
print STDERR "$file does not start on a fresh right page [$toc{$file}] [$x]\n";
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
print STDERR "Unknown spec: $_\n";
|
print STDERR "Unknown spec: $_\n";
|
||||||
}
|
}
|
||||||
' fmt/tocdata runoff.spec
|
' fmt/tocdata runoff.spec
|
||||||
|
|
|
@ -34,12 +34,10 @@ sysproc.c
|
||||||
|
|
||||||
# file system
|
# file system
|
||||||
buf.h
|
buf.h
|
||||||
dev.h
|
|
||||||
fcntl.h
|
fcntl.h
|
||||||
stat.h
|
stat.h
|
||||||
file.h
|
|
||||||
fs.h
|
fs.h
|
||||||
fsvar.h
|
file.h
|
||||||
ide.c
|
ide.c
|
||||||
bio.c
|
bio.c
|
||||||
fs.c
|
fs.c
|
||||||
|
|
18
runoff.spec
18
runoff.spec
|
@ -12,20 +12,27 @@ even: bootother.S # mild preference
|
||||||
# bootmain.c either
|
# bootmain.c either
|
||||||
even: main.c
|
even: main.c
|
||||||
# mp.c don't care at all
|
# mp.c don't care at all
|
||||||
even: initcode.S
|
# even: initcode.S
|
||||||
odd: init.c
|
# odd: init.c
|
||||||
|
|
||||||
# spinlock.h either
|
# spinlock.h either
|
||||||
# spinlock.c either
|
# spinlock.c either
|
||||||
even: proc.h # mild preference
|
even: proc.h # mild preference
|
||||||
even: proc.c # VERY important
|
|
||||||
|
# goal is to have two action-packed 2-page spreads,
|
||||||
|
# one with
|
||||||
|
# ksegment usegment allocproc userinit growproc fork
|
||||||
|
# and another with
|
||||||
|
# scheduler sched yield forkret sleep wakeup1 wakeup
|
||||||
|
right: proc.c # VERY important
|
||||||
|
|
||||||
# setjmp.S either
|
# setjmp.S either
|
||||||
# kalloc.c either
|
# kalloc.c either
|
||||||
|
|
||||||
# syscall.h either
|
# syscall.h either
|
||||||
# trapasm.S either
|
# trapasm.S either
|
||||||
# traps.h either
|
# traps.h either
|
||||||
even: trap.c # important
|
# even: trap.c
|
||||||
# vectors.pl either
|
# vectors.pl either
|
||||||
# syscall.c either
|
# syscall.c either
|
||||||
# sysproc.c either
|
# sysproc.c either
|
||||||
|
@ -37,7 +44,7 @@ even: trap.c # important
|
||||||
# file.h either
|
# file.h either
|
||||||
# fs.h either
|
# fs.h either
|
||||||
# fsvar.h either
|
# fsvar.h either
|
||||||
# even: ide.c
|
left: ide.c
|
||||||
# odd: bio.c
|
# odd: bio.c
|
||||||
odd: fs.c # VERY important
|
odd: fs.c # VERY important
|
||||||
# file.c either
|
# file.c either
|
||||||
|
@ -46,5 +53,6 @@ odd: fs.c # VERY important
|
||||||
|
|
||||||
# even: pipe.c # mild preference
|
# even: pipe.c # mild preference
|
||||||
# string.c either
|
# string.c either
|
||||||
|
left: kbd.h
|
||||||
even: console.c
|
even: console.c
|
||||||
odd: sh.c
|
odd: sh.c
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "fsvar.h"
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "fcntl.h"
|
#include "fcntl.h"
|
||||||
|
|
||||||
|
|
33
timer.c
33
timer.c
|
@ -30,36 +30,3 @@ timerinit(void)
|
||||||
outb(IO_TIMER1, TIMER_DIV(100) / 256);
|
outb(IO_TIMER1, TIMER_DIV(100) / 256);
|
||||||
picenable(IRQ_TIMER);
|
picenable(IRQ_TIMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Blank page
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1
trap.c
1
trap.c
|
@ -31,6 +31,7 @@ idtinit(void)
|
||||||
lidt(idt, sizeof(idt));
|
lidt(idt, sizeof(idt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//PAGEBREAK: 41
|
||||||
void
|
void
|
||||||
trap(struct trapframe *tf)
|
trap(struct trapframe *tf)
|
||||||
{
|
{
|
||||||
|
|
3
uart.c
3
uart.c
|
@ -5,7 +5,8 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "traps.h"
|
#include "traps.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "dev.h"
|
#include "fs.h"
|
||||||
|
#include "file.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
|
1
x86.h
1
x86.h
|
@ -122,6 +122,7 @@ sti(void)
|
||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//PAGEBREAK: 36
|
||||||
// Layout of the trap frame built on the stack by the
|
// Layout of the trap frame built on the stack by the
|
||||||
// hardware and by trapasm.S, and passed to trap().
|
// hardware and by trapasm.S, and passed to trap().
|
||||||
struct trapframe {
|
struct trapframe {
|
||||||
|
|
BIN
xv6.pdf
BIN
xv6.pdf
Binary file not shown.
Loading…
Reference in a new issue