]> Devi Nivas Git - cs3210-lab1.git/commitdiff
Cmake builds and runs!
authorDavid Devecsery <ddevec@gatech.edu>
Thu, 14 May 2020 13:37:42 +0000 (09:37 -0400)
committerDavid Devecsery <ddevec@gatech.edu>
Thu, 14 May 2020 13:38:18 +0000 (09:38 -0400)
138 files changed:
CMakeLists.txt [new file with mode: 0644]
asm.h [deleted file]
bio.c [deleted file]
bootasm.S [deleted file]
bootmain.c [deleted file]
buf.h [deleted file]
cat.c [deleted file]
console.c [deleted file]
cuth [deleted file]
date.h [deleted file]
defs.h [deleted file]
dot-bochsrc [deleted file]
echo.c [deleted file]
elf.h [deleted file]
entry.S [deleted file]
entryother.S [deleted file]
exec.c [deleted file]
fcntl.h [deleted file]
file.c [deleted file]
file.h [deleted file]
forktest.c [deleted file]
fs.c [deleted file]
fs.h [deleted file]
grep.c [deleted file]
ide.c [deleted file]
include/asm/asm.h [new file with mode: 0644]
include/asm/x86.h [new file with mode: 0644]
include/elf.h [new file with mode: 0644]
include/fcntl.h [new file with mode: 0644]
include/fs.h [new file with mode: 0644]
include/memlayout.h [new file with mode: 0644]
include/mmu.h [new file with mode: 0644]
include/param.h [new file with mode: 0644]
include/stat.h [new file with mode: 0644]
include/syscall.h [new file with mode: 0644]
include/traps.h [new file with mode: 0644]
include/types.h [new file with mode: 0644]
init.c [deleted file]
initcode.S [deleted file]
ioapic.c [deleted file]
kalloc.c [deleted file]
kbd.c [deleted file]
kbd.h [deleted file]
kernel.ld [deleted file]
kill.c [deleted file]
lapic.c [deleted file]
ln.c [deleted file]
log.c [deleted file]
ls.c [deleted file]
main.c [deleted file]
memide.c [deleted file]
memlayout.h [deleted file]
mkdir.c [deleted file]
mkfs.c [deleted file]
mmu.h [deleted file]
mp.c [deleted file]
mp.h [deleted file]
param.h [deleted file]
picirq.c [deleted file]
pipe.c [deleted file]
pr.pl [deleted file]
printf.c [deleted file]
printpcs [deleted file]
proc.c [deleted file]
proc.h [deleted file]
rm.c [deleted file]
runoff [deleted file]
runoff.list [deleted file]
runoff.spec [deleted file]
runoff1 [deleted file]
sh.c [deleted file]
show1 [deleted file]
sign.pl [deleted file]
sleep1.p [deleted file]
sleeplock.c [deleted file]
sleeplock.h [deleted file]
spinlock.c [deleted file]
spinlock.h [deleted file]
spinp [deleted file]
stat.h [deleted file]
stressfs.c [deleted file]
string.c [deleted file]
swtch.S [deleted file]
syscall.c [deleted file]
syscall.h [deleted file]
sysfile.c [deleted file]
sysproc.c [deleted file]
toc.ftr [deleted file]
toc.hdr [deleted file]
tools/CMakeLists.txt [new file with mode: 0644]
tools/cuth [new file with mode: 0755]
tools/mkfs.c [new file with mode: 0644]
tools/pr.pl [new file with mode: 0755]
tools/printpcs [new file with mode: 0755]
tools/runoff [new file with mode: 0755]
tools/runoff.list [new file with mode: 0644]
tools/runoff.spec [new file with mode: 0644]
tools/runoff1 [new file with mode: 0755]
tools/show1 [new file with mode: 0755]
tools/spinp [new file with mode: 0755]
tools/toc.ftr [new file with mode: 0644]
tools/toc.hdr [new file with mode: 0644]
trap.c [deleted file]
trapasm.S [deleted file]
traps.h [deleted file]
types.h [deleted file]
uart.c [deleted file]
ulib.c [deleted file]
umalloc.c [deleted file]
user.h [deleted file]
user/CMakeLists.txt [new file with mode: 0644]
user/asm/usys.S [new file with mode: 0644]
user/include/user.h [new file with mode: 0644]
user/src/cat.c [new file with mode: 0644]
user/src/echo.c [new file with mode: 0644]
user/src/forktest.c [new file with mode: 0644]
user/src/grep.c [new file with mode: 0644]
user/src/init.c [new file with mode: 0644]
user/src/kill.c [new file with mode: 0644]
user/src/ln.c [new file with mode: 0644]
user/src/ls.c [new file with mode: 0644]
user/src/mkdir.c [new file with mode: 0644]
user/src/printf.c [new file with mode: 0644]
user/src/rm.c [new file with mode: 0644]
user/src/sh.c [new file with mode: 0644]
user/src/stressfs.c [new file with mode: 0644]
user/src/ulib.c [new file with mode: 0644]
user/src/umalloc.c [new file with mode: 0644]
user/src/usertests.c [new file with mode: 0644]
user/src/wc.c [new file with mode: 0644]
user/src/zombie.c [new file with mode: 0644]
usertests.c [deleted file]
usys.S [deleted file]
vectors.pl [deleted file]
vm.c [deleted file]
wc.c [deleted file]
x86.h [deleted file]
zombie.c [deleted file]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e3d975d
--- /dev/null
@@ -0,0 +1,51 @@
+cmake_minimum_required(VERSION 3.10)
+
+if (NOT CMAKE_BUILD_TYPE)
+  set(CMAKE_BUILD_TYPE Release)
+endif()
+
+project(xv6)
+
+#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -Werror -fno-omit-frame-pointer -fno-stack-protector")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing -Wall -ggdb -Werror -fno-omit-frame-pointer -fno-stack-protector")
+
+set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
+set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb3")
+
+set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
+
+function(add_prefix_suffix var prefix suffix)
+  set(listVar "")
+  foreach(f ${ARGN})
+    list(APPEND listVar "${prefix}${f}${suffix}")
+  endforeach(f)
+  set(${var} "${listVar}" PARENT_SCOPE)
+endfunction(add_prefix_suffix)
+
+# Build the tools!
+add_subdirectory(tools)
+
+include_directories(include)
+
+# Kernel and bootblock
+add_subdirectory(bootblock)
+add_subdirectory(kernel)
+
+# User-space applications
+add_subdirectory(user)
+
+# Whoo boy, lets build the actual boot image
+add_custom_command(
+  OUTPUT xv6.img
+  COMMAND dd if=/dev/zero of=xv6.img count=10000
+  COMMAND dd if=${CMAKE_CURRENT_BINARY_DIR}/bootblock/bootblock of=xv6.img conv=notrunc
+  COMMAND dd if=${CMAKE_CURRENT_BINARY_DIR}/kernel/kernel of=xv6.img seek=1 conv=notrunc
+  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bootblock/bootblock ${CMAKE_CURRENT_BINARY_DIR}/kernel/kernel
+)
+
+add_custom_target(
+  image ALL
+  DEPENDS buildkern buildboot xv6.img makeuserfs
+  #DEPENDS buildkern buildboot xv6.img
+)
+
diff --git a/asm.h b/asm.h
deleted file mode 100644 (file)
index b8a7353..0000000
--- a/asm.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// assembler macros to create x86 segments
-//
-
-#define SEG_NULLASM                                             \
-        .word 0, 0;                                             \
-        .byte 0, 0, 0, 0
-
-// The 0xC0 means the limit is in 4096-byte units
-// and (for executable segments) 32-bit mode.
-#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 STA_W     0x2       // Writeable (non-executable segments)
-#define STA_R     0x2       // Readable (executable segments)
diff --git a/bio.c b/bio.c
deleted file mode 100644 (file)
index a45ff3e..0000000
--- a/bio.c
+++ /dev/null
@@ -1,144 +0,0 @@
-// Buffer cache.
-//
-// The buffer cache is a linked list of buf structures holding
-// cached copies of disk block contents.  Caching disk blocks
-// in memory reduces the number of disk reads and also provides
-// a synchronization point for disk blocks used by multiple processes.
-//
-// Interface:
-// * To get a buffer for a particular disk block, call bread.
-// * After changing buffer data, call bwrite to write it to disk.
-// * When done with the buffer, call brelse.
-// * Do not use the buffer after calling brelse.
-// * Only one process at a time can use a buffer,
-//     so do not keep them longer than necessary.
-//
-// The implementation uses two state flags internally:
-// * B_VALID: the buffer data has been read from the disk.
-// * B_DIRTY: the buffer data has been modified
-//     and needs to be written to disk.
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "fs.h"
-#include "buf.h"
-
-struct {
-  struct spinlock lock;
-  struct buf buf[NBUF];
-
-  // Linked list of all buffers, through prev/next.
-  // head.next is most recently used.
-  struct buf head;
-} bcache;
-
-void
-binit(void)
-{
-  struct buf *b;
-
-  initlock(&bcache.lock, "bcache");
-
-//PAGEBREAK!
-  // Create linked list of buffers
-  bcache.head.prev = &bcache.head;
-  bcache.head.next = &bcache.head;
-  for(b = bcache.buf; b < bcache.buf+NBUF; b++){
-    b->next = bcache.head.next;
-    b->prev = &bcache.head;
-    initsleeplock(&b->lock, "buffer");
-    bcache.head.next->prev = b;
-    bcache.head.next = b;
-  }
-}
-
-// Look through buffer cache for block on device dev.
-// If not found, allocate a buffer.
-// In either case, return locked buffer.
-static struct buf*
-bget(uint dev, uint blockno)
-{
-  struct buf *b;
-
-  acquire(&bcache.lock);
-
-  // Is the block already cached?
-  for(b = bcache.head.next; b != &bcache.head; b = b->next){
-    if(b->dev == dev && b->blockno == blockno){
-      b->refcnt++;
-      release(&bcache.lock);
-      acquiresleep(&b->lock);
-      return b;
-    }
-  }
-
-  // Not cached; recycle an unused buffer.
-  // Even if refcnt==0, B_DIRTY indicates a buffer is in use
-  // because log.c has modified it but not yet committed it.
-  for(b = bcache.head.prev; b != &bcache.head; b = b->prev){
-    if(b->refcnt == 0 && (b->flags & B_DIRTY) == 0) {
-      b->dev = dev;
-      b->blockno = blockno;
-      b->flags = 0;
-      b->refcnt = 1;
-      release(&bcache.lock);
-      acquiresleep(&b->lock);
-      return b;
-    }
-  }
-  panic("bget: no buffers");
-}
-
-// Return a locked buf with the contents of the indicated block.
-struct buf*
-bread(uint dev, uint blockno)
-{
-  struct buf *b;
-
-  b = bget(dev, blockno);
-  if((b->flags & B_VALID) == 0) {
-    iderw(b);
-  }
-  return b;
-}
-
-// Write b's contents to disk.  Must be locked.
-void
-bwrite(struct buf *b)
-{
-  if(!holdingsleep(&b->lock))
-    panic("bwrite");
-  b->flags |= B_DIRTY;
-  iderw(b);
-}
-
-// Release a locked buffer.
-// Move to the head of the MRU list.
-void
-brelse(struct buf *b)
-{
-  if(!holdingsleep(&b->lock))
-    panic("brelse");
-
-  releasesleep(&b->lock);
-
-  acquire(&bcache.lock);
-  b->refcnt--;
-  if (b->refcnt == 0) {
-    // no one is waiting for it.
-    b->next->prev = b->prev;
-    b->prev->next = b->next;
-    b->next = bcache.head.next;
-    b->prev = &bcache.head;
-    bcache.head.next->prev = b;
-    bcache.head.next = b;
-  }
-  
-  release(&bcache.lock);
-}
-//PAGEBREAK!
-// Blank page.
-
diff --git a/bootasm.S b/bootasm.S
deleted file mode 100644 (file)
index 257867c..0000000
--- a/bootasm.S
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "asm.h"
-#include "memlayout.h"
-#include "mmu.h"
-
-# Start the first CPU: switch to 32-bit protected mode, jump into C.
-# The BIOS loads this code from the first sector of the hard disk into
-# memory at physical address 0x7c00 and starts executing in real mode
-# with %cs=0 %ip=7c00.
-
-.code16                       # Assemble for 16-bit mode
-.globl start
-start:
-  cli                         # BIOS enabled interrupts; disable
-
-  # Zero data segment registers DS, ES, and SS.
-  xorw    %ax,%ax             # Set %ax to zero
-  movw    %ax,%ds             # -> Data Segment
-  movw    %ax,%es             # -> Extra Segment
-  movw    %ax,%ss             # -> Stack Segment
-
-  # Physical address line A20 is tied to zero so that the first PCs 
-  # with 2 MB would run software that assumed 1 MB.  Undo that.
-seta20.1:
-  inb     $0x64,%al               # Wait for not busy
-  testb   $0x2,%al
-  jnz     seta20.1
-
-  movb    $0xd1,%al               # 0xd1 -> port 0x64
-  outb    %al,$0x64
-
-seta20.2:
-  inb     $0x64,%al               # Wait for not busy
-  testb   $0x2,%al
-  jnz     seta20.2
-
-  movb    $0xdf,%al               # 0xdf -> port 0x60
-  outb    %al,$0x60
-
-  # Switch from real to protected mode.  Use a bootstrap GDT that makes
-  # virtual addresses map directly to physical addresses so that the
-  # effective memory map doesn't change during the transition.
-  lgdt    gdtdesc
-  movl    %cr0, %eax
-  orl     $CR0_PE, %eax
-  movl    %eax, %cr0
-
-//PAGEBREAK!
-  # Complete the transition to 32-bit protected mode by using a long jmp
-  # to reload %cs and %eip.  The segment descriptors are set up with no
-  # translation, so that the mapping is still the identity mapping.
-  ljmp    $(SEG_KCODE<<3), $start32
-
-.code32  # Tell assembler to generate 32-bit code now.
-start32:
-  # Set up the protected-mode data segment registers
-  movw    $(SEG_KDATA<<3), %ax    # Our data segment selector
-  movw    %ax, %ds                # -> DS: Data Segment
-  movw    %ax, %es                # -> ES: Extra Segment
-  movw    %ax, %ss                # -> SS: Stack Segment
-  movw    $0, %ax                 # Zero segments not ready for use
-  movw    %ax, %fs                # -> FS
-  movw    %ax, %gs                # -> GS
-
-  # Set up the stack pointer and call into C.
-  movl    $start, %esp
-  call    bootmain
-
-  # If bootmain returns (it shouldn't), trigger a Bochs
-  # breakpoint if running under Bochs, then loop.
-  movw    $0x8a00, %ax            # 0x8a00 -> port 0x8a00
-  movw    %ax, %dx
-  outw    %ax, %dx
-  movw    $0x8ae0, %ax            # 0x8ae0 -> port 0x8a00
-  outw    %ax, %dx
-spin:
-  jmp     spin
-
-# Bootstrap GDT
-.p2align 2                                # force 4 byte alignment
-gdt:
-  SEG_NULLASM                             # null seg
-  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg
-  SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg
-
-gdtdesc:
-  .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
-  .long   gdt                             # address gdt
-
diff --git a/bootmain.c b/bootmain.c
deleted file mode 100644 (file)
index 1f20e5b..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// Boot loader.
-//
-// Part of the boot block, along with bootasm.S, which calls bootmain().
-// bootasm.S has put the processor into protected 32-bit mode.
-// bootmain() loads an ELF kernel image from the disk starting at
-// sector 1 and then jumps to the kernel entry routine.
-
-#include "types.h"
-#include "elf.h"
-#include "x86.h"
-#include "memlayout.h"
-
-#define SECTSIZE  512
-
-void readseg(uchar*, uint, uint);
-
-void
-bootmain(void)
-{
-  struct elfhdr *elf;
-  struct proghdr *ph, *eph;
-  void (*entry)(void);
-  uchar* pa;
-
-  elf = (struct elfhdr*)0x10000;  // scratch space
-
-  // Read 1st page off disk
-  readseg((uchar*)elf, 4096, 0);
-
-  // Is this an ELF executable?
-  if(elf->magic != ELF_MAGIC)
-    return;  // let bootasm.S handle error
-
-  // Load each program segment (ignores ph flags).
-  ph = (struct proghdr*)((uchar*)elf + elf->phoff);
-  eph = ph + elf->phnum;
-  for(; ph < eph; ph++){
-    pa = (uchar*)ph->paddr;
-    readseg(pa, ph->filesz, ph->off);
-    if(ph->memsz > ph->filesz)
-      stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz);
-  }
-
-  // Call the entry point from the ELF header.
-  // Does not return!
-  entry = (void(*)(void))(elf->entry);
-  entry();
-}
-
-void
-waitdisk(void)
-{
-  // Wait for disk ready.
-  while((inb(0x1F7) & 0xC0) != 0x40)
-    ;
-}
-
-// Read a single sector at offset into dst.
-void
-readsect(void *dst, uint offset)
-{
-  // Issue command.
-  waitdisk();
-  outb(0x1F2, 1);   // count = 1
-  outb(0x1F3, offset);
-  outb(0x1F4, offset >> 8);
-  outb(0x1F5, offset >> 16);
-  outb(0x1F6, (offset >> 24) | 0xE0);
-  outb(0x1F7, 0x20);  // cmd 0x20 - read sectors
-
-  // Read data.
-  waitdisk();
-  insl(0x1F0, dst, SECTSIZE/4);
-}
-
-// Read 'count' bytes at 'offset' from kernel into physical address 'pa'.
-// Might copy more than asked.
-void
-readseg(uchar* pa, uint count, uint offset)
-{
-  uchar* epa;
-
-  epa = pa + count;
-
-  // Round down to sector boundary.
-  pa -= offset % SECTSIZE;
-
-  // Translate from bytes to sectors; kernel starts at sector 1.
-  offset = (offset / SECTSIZE) + 1;
-
-  // 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 load in increasing order.
-  for(; pa < epa; pa += SECTSIZE, offset++)
-    readsect(pa, offset);
-}
diff --git a/buf.h b/buf.h
deleted file mode 100644 (file)
index 3266495..0000000
--- a/buf.h
+++ /dev/null
@@ -1,14 +0,0 @@
-struct buf {
-  int flags;
-  uint dev;
-  uint blockno;
-  struct sleeplock lock;
-  uint refcnt;
-  struct buf *prev; // LRU cache list
-  struct buf *next;
-  struct buf *qnext; // disk queue
-  uchar data[BSIZE];
-};
-#define B_VALID 0x2  // buffer has been read from disk
-#define B_DIRTY 0x4  // buffer needs to be written to disk
-
diff --git a/cat.c b/cat.c
deleted file mode 100644 (file)
index 5ddc820..0000000
--- a/cat.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-char buf[512];
-
-void
-cat(int fd)
-{
-  int n;
-
-  while((n = read(fd, buf, sizeof(buf))) > 0) {
-    if (write(1, buf, n) != n) {
-      printf(1, "cat: write error\n");
-      exit();
-    }
-  }
-  if(n < 0){
-    printf(1, "cat: read error\n");
-    exit();
-  }
-}
-
-int
-main(int argc, char *argv[])
-{
-  int fd, i;
-
-  if(argc <= 1){
-    cat(0);
-    exit();
-  }
-
-  for(i = 1; i < argc; i++){
-    if((fd = open(argv[i], 0)) < 0){
-      printf(1, "cat: cannot open %s\n", argv[i]);
-      exit();
-    }
-    cat(fd);
-    close(fd);
-  }
-  exit();
-}
diff --git a/console.c b/console.c
deleted file mode 100644 (file)
index a280d2b..0000000
--- a/console.c
+++ /dev/null
@@ -1,299 +0,0 @@
-// Console input and output.
-// Input is from the keyboard or serial port.
-// Output is written to the screen and serial port.
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "traps.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "fs.h"
-#include "file.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "x86.h"
-
-static void consputc(int);
-
-static int panicked = 0;
-
-static struct {
-  struct spinlock lock;
-  int locking;
-} cons;
-
-static void
-printint(int xx, int base, int sign)
-{
-  static char digits[] = "0123456789abcdef";
-  char buf[16];
-  int i;
-  uint x;
-
-  if(sign && (sign = xx < 0))
-    x = -xx;
-  else
-    x = xx;
-
-  i = 0;
-  do{
-    buf[i++] = digits[x % base];
-  }while((x /= base) != 0);
-
-  if(sign)
-    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, locking;
-  uint *argp;
-  char *s;
-
-  locking = cons.locking;
-  if(locking)
-    acquire(&cons.lock);
-
-  if (fmt == 0)
-    panic("null fmt");
-
-  argp = (uint*)(void*)(&fmt + 1);
-  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;
-  // use lapiccpunum so that we can call panic from mycpu()
-  cprintf("lapicid %d: panic: ", lapicid());
-  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*)P2V(0xb8000);  // CGA memory
-
-static void
-cgaputc(int c)
-{
-  int pos;
-
-  // Cursor position: col + 80*row.
-  outb(CRTPORT, 14);
-  pos = inb(CRTPORT+1) << 8;
-  outb(CRTPORT, 15);
-  pos |= inb(CRTPORT+1);
-
-  if(c == '\n')
-    pos += 80 - pos%80;
-  else if(c == BACKSPACE){
-    if(pos > 0) --pos;
-  } else
-    crt[pos++] = (c&0xff) | 0x0700;  // black on white
-
-  if(pos < 0 || pos > 25*80)
-    panic("pos under/overflow");
-
-  if((pos/80) >= 24){  // Scroll up.
-    memmove(crt, crt+80, sizeof(crt[0])*23*80);
-    pos -= 80;
-    memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
-  }
-
-  outb(CRTPORT, 14);
-  outb(CRTPORT+1, pos>>8);
-  outb(CRTPORT, 15);
-  outb(CRTPORT+1, pos);
-  crt[pos] = ' ' | 0x0700;
-}
-
-void
-consputc(int c)
-{
-  if(panicked){
-    cli();
-    for(;;)
-      ;
-  }
-
-  if(c == BACKSPACE){
-    uartputc('\b'); uartputc(' '); uartputc('\b');
-  } else
-    uartputc(c);
-  cgaputc(c);
-}
-
-#define INPUT_BUF 128
-struct {
-  char buf[INPUT_BUF];
-  uint r;  // Read index
-  uint w;  // Write index
-  uint e;  // Edit index
-} input;
-
-#define C(x)  ((x)-'@')  // Control-x
-
-void
-consoleintr(int (*getc)(void))
-{
-  int c, doprocdump = 0;
-
-  acquire(&cons.lock);
-  while((c = getc()) >= 0){
-    switch(c){
-    case C('P'):  // Process listing.
-      // procdump() locks cons.lock indirectly; invoke later
-      doprocdump = 1;
-      break;
-    case C('U'):  // Kill line.
-      while(input.e != input.w &&
-            input.buf[(input.e-1) % INPUT_BUF] != '\n'){
-        input.e--;
-        consputc(BACKSPACE);
-      }
-      break;
-    case C('H'): case '\x7f':  // Backspace
-      if(input.e != input.w){
-        input.e--;
-        consputc(BACKSPACE);
-      }
-      break;
-    default:
-      if(c != 0 && input.e-input.r < INPUT_BUF){
-        c = (c == '\r') ? '\n' : c;
-        input.buf[input.e++ % INPUT_BUF] = c;
-        consputc(c);
-        if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
-          input.w = input.e;
-          wakeup(&input.r);
-        }
-      }
-      break;
-    }
-  }
-  release(&cons.lock);
-  if(doprocdump) {
-    procdump();  // now call procdump() wo. cons.lock held
-  }
-}
-
-int
-consoleread(struct inode *ip, char *dst, int n)
-{
-  uint target;
-  int c;
-
-  iunlock(ip);
-  target = n;
-  acquire(&cons.lock);
-  while(n > 0){
-    while(input.r == input.w){
-      if(myproc()->killed){
-        release(&cons.lock);
-        ilock(ip);
-        return -1;
-      }
-      sleep(&input.r, &cons.lock);
-    }
-    c = input.buf[input.r++ % INPUT_BUF];
-    if(c == C('D')){  // EOF
-      if(n < target){
-        // Save ^D for next time, to make sure
-        // caller gets a 0-byte result.
-        input.r--;
-      }
-      break;
-    }
-    *dst++ = c;
-    --n;
-    if(c == '\n')
-      break;
-  }
-  release(&cons.lock);
-  ilock(ip);
-
-  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
-consoleinit(void)
-{
-  initlock(&cons.lock, "console");
-
-  devsw[CONSOLE].write = consolewrite;
-  devsw[CONSOLE].read = consoleread;
-  cons.locking = 1;
-
-  ioapicenable(IRQ_KBD, 0);
-}
-
diff --git a/cuth b/cuth
deleted file mode 100755 (executable)
index cce8c0c..0000000
--- a/cuth
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/perl
-
-$| = 1;
-
-sub writefile($@){
-       my ($file, @lines) = @_;
-       
-       sleep(1);
-       open(F, ">$file") || die "open >$file: $!";
-       print F @lines;
-       close(F);
-}
-
-# Cut out #include lines that don't contribute anything.
-for($i=0; $i<@ARGV; $i++){
-       $file = $ARGV[$i];
-       if(!open(F, $file)){
-               print STDERR "open $file: $!\n";
-               next;
-       }
-       @lines = <F>;
-       close(F);
-       
-       $obj = "$file.o";
-       $obj =~ s/\.c\.o$/.o/;
-       system("touch $file");
-
-       if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){
-               print STDERR "make $obj failed: $rv\n";
-               next;
-       }
-
-       system("cp $file =$file");
-       for($j=@lines-1; $j>=0; $j--){
-               if($lines[$j] =~ /^#include/){
-                       $old = $lines[$j];
-                       $lines[$j] = "/* CUT-H */\n";
-                       writefile($file, @lines);
-                       if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){
-                               $lines[$j] = $old;
-                       }else{
-                               print STDERR "$file $old";
-                       }
-               }
-       }
-       writefile($file, grep {!/CUT-H/} @lines);
-       system("rm =$file");
-}
diff --git a/date.h b/date.h
deleted file mode 100644 (file)
index 94aec4b..0000000
--- a/date.h
+++ /dev/null
@@ -1,8 +0,0 @@
-struct rtcdate {
-  uint second;
-  uint minute;
-  uint hour;
-  uint day;
-  uint month;
-  uint year;
-};
diff --git a/defs.h b/defs.h
deleted file mode 100644 (file)
index 82fb982..0000000
--- a/defs.h
+++ /dev/null
@@ -1,190 +0,0 @@
-struct buf;
-struct context;
-struct file;
-struct inode;
-struct pipe;
-struct proc;
-struct rtcdate;
-struct spinlock;
-struct sleeplock;
-struct stat;
-struct superblock;
-
-// bio.c
-void            binit(void);
-struct buf*     bread(uint, uint);
-void            brelse(struct buf*);
-void            bwrite(struct buf*);
-
-// console.c
-void            consoleinit(void);
-void            cprintf(char*, ...);
-void            consoleintr(int(*)(void));
-void            panic(char*) __attribute__((noreturn));
-
-// exec.c
-int             exec(char*, char**);
-
-// file.c
-struct file*    filealloc(void);
-void            fileclose(struct file*);
-struct file*    filedup(struct file*);
-void            fileinit(void);
-int             fileread(struct file*, char*, int n);
-int             filestat(struct file*, struct stat*);
-int             filewrite(struct file*, char*, int n);
-
-// fs.c
-void            readsb(int dev, struct superblock *sb);
-int             dirlink(struct inode*, char*, uint);
-struct inode*   dirlookup(struct inode*, char*, uint*);
-struct inode*   ialloc(uint, short);
-struct inode*   idup(struct inode*);
-void            iinit(int dev);
-void            ilock(struct inode*);
-void            iput(struct inode*);
-void            iunlock(struct inode*);
-void            iunlockput(struct inode*);
-void            iupdate(struct inode*);
-int             namecmp(const char*, const char*);
-struct inode*   namei(char*);
-struct inode*   nameiparent(char*, char*);
-int             readi(struct inode*, char*, uint, uint);
-void            stati(struct inode*, struct stat*);
-int             writei(struct inode*, char*, uint, uint);
-
-// ide.c
-void            ideinit(void);
-void            ideintr(void);
-void            iderw(struct buf*);
-
-// ioapic.c
-void            ioapicenable(int irq, int cpu);
-extern uchar    ioapicid;
-void            ioapicinit(void);
-
-// kalloc.c
-char*           kalloc(void);
-void            kfree(char*);
-void            kinit1(void*, void*);
-void            kinit2(void*, void*);
-
-// kbd.c
-void            kbdintr(void);
-
-// lapic.c
-void            cmostime(struct rtcdate *r);
-int             lapicid(void);
-extern volatile uint*    lapic;
-void            lapiceoi(void);
-void            lapicinit(void);
-void            lapicstartap(uchar, uint);
-void            microdelay(int);
-
-// log.c
-void            initlog(int dev);
-void            log_write(struct buf*);
-void            begin_op();
-void            end_op();
-
-// mp.c
-extern int      ismp;
-void            mpinit(void);
-
-// picirq.c
-void            picenable(int);
-void            picinit(void);
-
-// pipe.c
-int             pipealloc(struct file**, struct file**);
-void            pipeclose(struct pipe*, int);
-int             piperead(struct pipe*, char*, int);
-int             pipewrite(struct pipe*, char*, int);
-
-//PAGEBREAK: 16
-// proc.c
-int             cpuid(void);
-void            exit(void);
-int             fork(void);
-int             growproc(int);
-int             kill(int);
-struct cpu*     mycpu(void);
-struct proc*    myproc();
-void            pinit(void);
-void            procdump(void);
-void            scheduler(void) __attribute__((noreturn));
-void            sched(void);
-void            setproc(struct proc*);
-void            sleep(void*, struct spinlock*);
-void            userinit(void);
-int             wait(void);
-void            wakeup(void*);
-void            yield(void);
-
-// swtch.S
-void            swtch(struct context**, struct context*);
-
-// spinlock.c
-void            acquire(struct spinlock*);
-void            getcallerpcs(void*, uint*);
-int             holding(struct spinlock*);
-void            initlock(struct spinlock*, char*);
-void            release(struct spinlock*);
-void            pushcli(void);
-void            popcli(void);
-
-// sleeplock.c
-void            acquiresleep(struct sleeplock*);
-void            releasesleep(struct sleeplock*);
-int             holdingsleep(struct sleeplock*);
-void            initsleeplock(struct sleeplock*, char*);
-
-// string.c
-int             memcmp(const void*, const void*, uint);
-void*           memmove(void*, const void*, uint);
-void*           memset(void*, int, uint);
-char*           safestrcpy(char*, const char*, int);
-int             strlen(const char*);
-int             strncmp(const char*, const char*, uint);
-char*           strncpy(char*, const char*, int);
-
-// syscall.c
-int             argint(int, int*);
-int             argptr(int, char**, int);
-int             argstr(int, char**);
-int             fetchint(uint, int*);
-int             fetchstr(uint, char**);
-void            syscall(void);
-
-// timer.c
-void            timerinit(void);
-
-// trap.c
-void            idtinit(void);
-extern uint     ticks;
-void            tvinit(void);
-extern struct spinlock tickslock;
-
-// uart.c
-void            uartinit(void);
-void            uartintr(void);
-void            uartputc(int);
-
-// vm.c
-void            seginit(void);
-void            kvmalloc(void);
-pde_t*          setupkvm(void);
-char*           uva2ka(pde_t*, char*);
-int             allocuvm(pde_t*, uint, uint);
-int             deallocuvm(pde_t*, uint, uint);
-void            freevm(pde_t*);
-void            inituvm(pde_t*, char*, uint);
-int             loaduvm(pde_t*, char*, struct inode*, uint, uint);
-pde_t*          copyuvm(pde_t*, uint);
-void            switchuvm(struct proc*);
-void            switchkvm(void);
-int             copyout(pde_t*, uint, void*, uint);
-void            clearpteu(pde_t *pgdir, char *uva);
-
-// number of elements in fixed-size array
-#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
diff --git a/dot-bochsrc b/dot-bochsrc
deleted file mode 100755 (executable)
index ba13db7..0000000
+++ /dev/null
@@ -1,738 +0,0 @@
-# You may now use double quotes around pathnames, in case
-# your pathname includes spaces.
-
-#=======================================================================
-# CONFIG_INTERFACE
-#
-# The configuration interface is a series of menus or dialog boxes that
-# allows you to change all the settings that control Bochs's behavior.
-# There are two choices of configuration interface: a text mode version
-# called "textconfig" and a graphical version called "wx".  The text
-# mode version uses stdin/stdout and is always compiled in.  The graphical
-# version is only available when you use "--with-wx" on the configure 
-# command.  If you do not write a config_interface line, Bochs will 
-# choose a default for you.
-#
-# NOTE: if you use the "wx" configuration interface, you must also use
-# the "wx" display library.
-#=======================================================================
-#config_interface: textconfig
-#config_interface: wx
-
-#=======================================================================
-# DISPLAY_LIBRARY
-#
-# The display library is the code that displays the Bochs VGA screen.  Bochs 
-# has a selection of about 10 different display library implementations for 
-# different platforms.  If you run configure with multiple --with-* options, 
-# the display_library command lets you choose which one you want to run with.
-# If you do not write a display_library line, Bochs will choose a default for
-# you.
-#
-# The choices are: 
-#   x              use X windows interface, cross platform
-#   win32          use native win32 libraries
-#   carbon         use Carbon library (for MacOS X)
-#   beos           use native BeOS libraries
-#   macintosh      use MacOS pre-10
-#   amigaos        use native AmigaOS libraries
-#   sdl            use SDL library, cross platform
-#   svga           use SVGALIB library for Linux, allows graphics without X11
-#   term           text only, uses curses/ncurses library, cross platform
-#   rfb            provides an interface to AT&T's VNC viewer, cross platform
-#   wx             use wxWidgets library, cross platform
-#   nogui          no display at all
-#
-# NOTE: if you use the "wx" configuration interface, you must also use
-# the "wx" display library.
-#
-# Specific options:
-# Some display libraries now support specific option to control their
-# behaviour. See the examples below for currently supported options.
-#=======================================================================
-#display_library: amigaos
-#display_library: beos
-#display_library: carbon
-#display_library: macintosh
-#display_library: nogui
-#display_library: rfb, options="timeout=60" # time to wait for client
-#display_library: sdl, options="fullscreen" # startup in fullscreen mode
-#display_library: term
-#display_library: win32, options="legacyF12" # use F12 to toggle mouse
-#display_library: wx
-#display_library: x
-
-#=======================================================================
-# ROMIMAGE:
-# The ROM BIOS controls what the PC does when it first powers on.
-# Normally, you can use a precompiled BIOS in the source or binary
-# distribution called BIOS-bochs-latest. The ROM BIOS is usually loaded
-# starting at address 0xf0000, and it is exactly 64k long.
-# You can also use the environment variable $BXSHARE to specify the
-# location of the BIOS.
-# The usage of external large BIOS images (up to 512k) at memory top is
-# now supported, but we still recommend to use the BIOS distributed with
-# Bochs. Now the start address can be calculated from image size.
-#=======================================================================
-romimage: file=$BXSHARE/BIOS-bochs-latest
-#romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top
-#romimage: file=mybios.bin # calculate start address from image size
-
-#=======================================================================
-# CPU:
-# This defines cpu-related parameters inside Bochs:
-#
-#  COUNT:
-#  Set the number of processors when Bochs is compiled for SMP emulation.
-#  Bochs currently supports up to 8 processors. If Bochs is compiled
-#  without SMP support, it won't accept values different from 1.
-#
-#  IPS:
-#  Emulated Instructions Per Second.  This is the number of IPS that bochs
-#  is capable of running on your machine. You can recompile Bochs with
-#  --enable-show-ips option enabled, to find your workstation's capability.
-#  Measured IPS value will then be logged into your log file or status bar
-#  (if supported by the gui).
-#
-#  IPS is used to calibrate many time-dependent events within the bochs 
-#  simulation.  For example, changing IPS affects the frequency of VGA
-#  updates, the duration of time before a key starts to autorepeat, and
-#  the measurement of BogoMips and other benchmarks.
-#
-#  Examples:
-#  Machine                                         Mips
-# ________________________________________________________________
-#  2.1Ghz Athlon XP with Linux 2.6/g++ 3.4         12 to 15 Mips
-#  1.6Ghz Intel P4 with Win2000/g++ 3.3             5 to  7 Mips
-#  650Mhz Athlon K-7 with Linux 2.4.4/egcs-2.91.66  2 to  2.5 Mips
-#  400Mhz Pentium II with Linux 2.0.36/egcs-1.0.3   1 to  1.8 Mips
-#=======================================================================
-cpu: count=2, ips=10000000
-
-#=======================================================================
-# MEGS
-# Set the number of Megabytes of physical memory you want to emulate. 
-# The default is 32MB, most OS's won't need more than that.
-# The maximum amount of memory supported is 2048Mb.
-#=======================================================================
-#megs: 256
-#megs: 128
-#megs: 64
-megs: 32
-#megs: 16
-#megs: 8
-
-#=======================================================================
-# OPTROMIMAGE[1-4]:
-# You may now load up to 4 optional ROM images. Be sure to use a 
-# read-only area, typically between C8000 and EFFFF. These optional
-# ROM images should not overwrite the rombios (located at
-# F0000-FFFFF) and the videobios (located at C0000-C7FFF).
-# Those ROM images will be initialized by the bios if they contain 
-# the right signature (0x55AA) and a valid checksum.
-# It can also be a convenient way to upload some arbitrary code/data
-# in the simulation, that can be retrieved by the boot loader
-#=======================================================================
-#optromimage1: file=optionalrom.bin, address=0xd0000
-#optromimage2: file=optionalrom.bin, address=0xd1000
-#optromimage3: file=optionalrom.bin, address=0xd2000
-#optromimage4: file=optionalrom.bin, address=0xd3000
-
-#optramimage1: file=/path/file1.img, address=0x0010000
-#optramimage2: file=/path/file2.img, address=0x0020000
-#optramimage3: file=/path/file3.img, address=0x0030000
-#optramimage4: file=/path/file4.img, address=0x0040000
-
-#=======================================================================
-# VGAROMIMAGE
-# You now need to load a VGA ROM BIOS into C0000.
-#=======================================================================
-#vgaromimage: file=bios/VGABIOS-elpin-2.40
-vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
-#vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus
-
-#=======================================================================
-# VGA:
-# Here you can specify the display extension to be used. With the value
-# 'none' you can use standard VGA with no extension. Other supported
-# values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support.
-#=======================================================================
-#vga: extension=cirrus
-#vga: extension=vbe
-vga: extension=none
-
-#=======================================================================
-# FLOPPYA:
-# Point this to pathname of floppy image file or device
-# This should be of a bootable floppy(image/device) if you're
-# booting from 'a' (or 'floppy').
-#
-# You can set the initial status of the media to 'ejected' or 'inserted'.
-#   floppya: 2_88=path, status=ejected             (2.88M 3.5" floppy)
-#   floppya: 1_44=path, status=inserted            (1.44M 3.5" floppy)
-#   floppya: 1_2=path, status=ejected              (1.2M  5.25" floppy)
-#   floppya: 720k=path, status=inserted            (720K  3.5" floppy)
-#   floppya: 360k=path, status=inserted            (360K  5.25" floppy)
-#   floppya: 320k=path, status=inserted            (320K  5.25" floppy)
-#   floppya: 180k=path, status=inserted            (180K  5.25" floppy)
-#   floppya: 160k=path, status=inserted            (160K  5.25" floppy)
-#   floppya: image=path, status=inserted           (guess type from image size)
-#
-# The path should be the name of a disk image file.  On Unix, you can use a raw
-# device name such as /dev/fd0 on Linux.  On win32 platforms, use drive letters
-# such as a: or b: as the path.  The parameter 'image' works with image files
-# only. In that case the size must match one of the supported types.
-#=======================================================================
-floppya: 1_44=/dev/fd0, status=inserted
-#floppya: image=../1.44, status=inserted
-#floppya: 1_44=/dev/fd0H1440, status=inserted
-#floppya: 1_2=../1_2, status=inserted
-#floppya: 1_44=a:, status=inserted
-#floppya: 1_44=a.img, status=inserted
-#floppya: 1_44=/dev/rfd0a, status=inserted
-
-#=======================================================================
-# FLOPPYB:
-# See FLOPPYA above for syntax
-#=======================================================================
-#floppyb: 1_44=b:, status=inserted
-floppyb: 1_44=b.img, status=inserted
-
-#=======================================================================
-# ATA0, ATA1, ATA2, ATA3
-# ATA controller for hard disks and cdroms
-#
-# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number
-# 
-# These options enables up to 4 ata channels. For each channel
-# the two base io addresses and the irq must be specified.
-# 
-# ata0 and ata1 are enabled by default with the values shown below
-#
-# Examples:
-#   ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
-#   ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
-#   ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
-#   ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9
-#=======================================================================
-ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
-ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
-ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
-ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
-
-#=======================================================================
-# ATA[0-3]-MASTER, ATA[0-3]-SLAVE
-#
-# This defines the type and characteristics of all attached ata devices:
-#   type=       type of attached device [disk|cdrom] 
-#   mode=       only valid for disks [flat|concat|external|dll|sparse|vmware3]
-#   mode=       only valid for disks [undoable|growing|volatile]
-#   path=       path of the image
-#   cylinders=  only valid for disks
-#   heads=      only valid for disks
-#   spt=        only valid for disks
-#   status=     only valid for cdroms [inserted|ejected]
-#   biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos]
-#   translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto]
-#   model=      string returned by identify device command
-#   journal=    optional filename of the redolog for undoable and volatile disks
-#   
-# Point this at a hard disk image file, cdrom iso file, or physical cdrom
-# device.  To create a hard disk image, try running bximage.  It will help you
-# choose the size and then suggest a line that works with it.
-#
-# In UNIX it may be possible to use a raw device as a Bochs hard disk, 
-# but WE DON'T RECOMMEND IT.  In Windows there is no easy way.
-#
-# In windows, the drive letter + colon notation should be used for cdroms.
-# Depending on versions of windows and drivers, you may only be able to 
-# access the "first" cdrom in the system.  On MacOSX, use path="drive"
-# to access the physical drive.
-#
-# The path is always mandatory. For flat hard disk images created with
-# bximage geometry autodetection can be used (cylinders=0 -> cylinders are
-# calculated using heads=16 and spt=63). For other hard disk images and modes
-# the cylinders, heads, and spt are mandatory.
-#
-# Default values are:
-#   mode=flat, biosdetect=auto, translation=auto, model="Generic 1234"
-#
-# The biosdetect option has currently no effect on the bios
-#
-# Examples:
-#   ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17
-#   ata0-slave:  type=disk, mode=flat, path=20M.sample, cylinders=615, heads=4, spt=17
-#   ata1-master: type=disk, mode=flat, path=30M.sample, cylinders=615, heads=6, spt=17
-#   ata1-slave:  type=disk, mode=flat, path=46M.sample, cylinders=940, heads=6, spt=17
-#   ata2-master: type=disk, mode=flat, path=62M.sample, cylinders=940, heads=8, spt=17
-#   ata2-slave:  type=disk, mode=flat, path=112M.sample, cylinders=900, heads=15, spt=17
-#   ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63
-#   ata3-slave:  type=cdrom, path=iso.sample, status=inserted
-#=======================================================================
-ata0-master: type=disk, mode=flat, path="xv6.img", cylinders=100, heads=10, spt=10
-ata0-slave: type=disk, mode=flat, path="fs.img", cylinders=1024, heads=1, spt=1
-#ata0-slave: type=cdrom, path=D:, status=inserted
-#ata0-slave: type=cdrom, path=/dev/cdrom, status=inserted
-#ata0-slave: type=cdrom, path="drive", status=inserted
-#ata0-slave: type=cdrom, path=/dev/rcd0d, status=inserted 
-
-#=======================================================================
-# BOOT:
-# This defines the boot sequence. Now you can specify up to 3 boot drives.
-# You can either boot from 'floppy', 'disk' or 'cdrom'
-# legacy 'a' and 'c' are also supported
-# Examples:
-#   boot: floppy
-#   boot: disk
-#   boot: cdrom
-#   boot: c
-#   boot: a
-#   boot: cdrom, floppy, disk
-#=======================================================================
-#boot: floppy
-boot: disk
-
-#=======================================================================
-# CLOCK:
-# This defines the parameters of the clock inside Bochs:
-#
-#  SYNC:
-#  TO BE COMPLETED (see Greg explanation in feature request #536329)
-#
-#  TIME0:
-#  Specifies the start (boot) time of the virtual machine. Use a time 
-#  value as returned by the time(2) system call. If no time0 value is 
-#  set or if time0 equal to 1 (special case) or if time0 equal 'local', 
-#  the simulation will be started at the current local host time.
-#  If time0 equal to 2 (special case) or if time0 equal 'utc',
-#  the simulation will be started at the current utc time.
-#
-# Syntax:
-#  clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc]
-#
-# Example:
-#   clock: sync=none,     time0=local       # Now (localtime)
-#   clock: sync=slowdown, time0=315529200   # Tue Jan  1 00:00:00 1980
-#   clock: sync=none,     time0=631148400   # Mon Jan  1 00:00:00 1990
-#   clock: sync=realtime, time0=938581955   # Wed Sep 29 07:12:35 1999
-#   clock: sync=realtime, time0=946681200   # Sat Jan  1 00:00:00 2000
-#   clock: sync=none,     time0=1           # Now (localtime)
-#   clock: sync=none,     time0=utc         # Now (utc/gmt)
-# 
-# Default value are sync=none, time0=local
-#=======================================================================
-#clock: sync=none, time0=local
-
-
-#=======================================================================
-# FLOPPY_BOOTSIG_CHECK: disabled=[0|1]
-# Enables or disables the 0xaa55 signature check on boot floppies
-# Defaults to disabled=0
-# Examples:
-#   floppy_bootsig_check: disabled=0
-#   floppy_bootsig_check: disabled=1
-#=======================================================================
-#floppy_bootsig_check: disabled=1
-floppy_bootsig_check: disabled=0
-
-#=======================================================================
-# LOG:
-# Give the path of the log file you'd like Bochs debug and misc. verbiage
-# to be written to. If you don't use this option or set the filename to
-# '-' the output is written to the console. If you really don't want it,
-# make it "/dev/null" (Unix) or "nul" (win32). :^(
-#
-# Examples:
-#   log: ./bochs.out
-#   log: /dev/tty
-#=======================================================================
-#log: /dev/null
-log: bochsout.txt
-
-#=======================================================================
-# LOGPREFIX:
-# This handles the format of the string prepended to each log line.
-# You may use those special tokens :
-#   %t : 11 decimal digits timer tick
-#   %i : 8 hexadecimal digits of cpu current eip (ignored in SMP configuration)
-#   %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror)
-#   %d : 5 characters string of the device, between brackets
-# 
-# Default : %t%e%d
-# Examples:
-#   logprefix: %t-%e-@%i-%d
-#   logprefix: %i%e%d
-#=======================================================================
-#logprefix: %t%e%d
-
-#=======================================================================
-# LOG CONTROLS
-#
-# Bochs now has four severity levels for event logging.
-#   panic: cannot proceed.  If you choose to continue after a panic, 
-#          don't be surprised if you get strange behavior or crashes.
-#   error: something went wrong, but it is probably safe to continue the
-#          simulation.
-#   info: interesting or useful messages.
-#   debug: messages useful only when debugging the code.  This may
-#          spit out thousands per second.
-#
-# For events of each level, you can choose to crash, report, or ignore.
-# TODO: allow choice based on the facility: e.g. crash on panics from
-#       everything except the cdrom, and only report those.
-#
-# If you are experiencing many panics, it can be helpful to change
-# the panic action to report instead of fatal.  However, be aware
-# that anything executed after a panic is uncharted territory and can 
-# cause bochs to become unstable.  The panic is a "graceful exit," so
-# if you disable it you may get a spectacular disaster instead.
-#=======================================================================
-panic: action=ask
-error: action=report
-info: action=report
-debug: action=ignore
-#pass: action=fatal
-
-#=======================================================================
-# DEBUGGER_LOG:
-# Give the path of the log file you'd like Bochs to log debugger output.
-# If you really don't want it, make it /dev/null or '-'. :^(
-#
-# Examples:
-#   debugger_log: ./debugger.out
-#=======================================================================
-#debugger_log: /dev/null
-#debugger_log: debugger.out
-debugger_log: -
-
-#=======================================================================
-# COM1, COM2, COM3, COM4:
-# This defines a serial port (UART type 16550A). In the 'term' you can specify
-# a device to use as com1. This can be a real serial line, or a pty.  To use
-# a pty (under X/Unix), create two windows (xterms, usually).  One of them will
-# run bochs, and the other will act as com1. Find out the tty the com1
-# window using the `tty' command, and use that as the `dev' parameter.
-# Then do `sleep 1000000' in the com1 window to keep the shell from
-# messing with things, and run bochs in the other window.  Serial I/O to
-# com1 (port 0x3f8) will all go to the other window.
-# Other serial modes are 'null' (no input/output), 'file' (output to a file
-# specified as the 'dev' parameter), 'raw' (use the real serial port - under
-# construction for win32), 'mouse' (standard serial mouse - requires
-# mouse option setting 'type=serial' or 'type=serial_wheel') and 'socket'
-# (connect a networking socket).
-#
-# Examples:
-#   com1: enabled=1, mode=null
-#   com1: enabled=1, mode=mouse
-#   com2: enabled=1, mode=file, dev=serial.out
-#   com3: enabled=1, mode=raw, dev=com1
-#   com3: enabled=1, mode=socket, dev=localhost:8888
-#=======================================================================
-#com1: enabled=1, mode=term, dev=/dev/ttyp9
-
-
-#=======================================================================
-# PARPORT1, PARPORT2:
-# This defines a parallel (printer) port. When turned on and an output file is
-# defined the emulated printer port sends characters printed by the guest OS
-# into the output file. On some platforms a device filename can be used to
-# send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on
-# win32 platforms).
-#
-# Examples:
-#   parport1: enabled=1, file="parport.out"
-#   parport2: enabled=1, file="/dev/lp0"
-#   parport1: enabled=0
-#=======================================================================
-parport1: enabled=1, file="/dev/stdout"
-
-#=======================================================================
-# SB16:
-# This defines the SB16 sound emulation. It can have several of the
-# following properties.
-# All properties are in the format sb16: property=value
-# midi: The filename is where the midi data is sent. This can be a
-#       device or just a file if you want to record the midi data.
-# midimode:
-#      0=no data
-#      1=output to device (system dependent. midi denotes the device driver)
-#      2=SMF file output, including headers
-#      3=output the midi data stream to the file (no midi headers and no
-#        delta times, just command and data bytes)
-# wave: This is the device/file where wave output is stored
-# wavemode:
-#      0=no data
-#      1=output to device (system dependent. wave denotes the device driver)
-#      2=VOC file output, incl. headers
-#      3=output the raw wave stream to the file
-# log:  The file to write the sb16 emulator messages to.
-# loglevel:
-#      0=no log
-#      1=resource changes, midi program and bank changes
-#      2=severe errors
-#      3=all errors
-#      4=all errors plus all port accesses
-#      5=all errors and port accesses plus a lot of extra info
-# dmatimer:
-#      microseconds per second for a DMA cycle.  Make it smaller to fix
-#      non-continuous sound.  750000 is usually a good value.  This needs a
-#      reasonably correct setting for the IPS parameter of the CPU option.
-#
-# For an example look at the next line:
-#=======================================================================
-
-#sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000
-
-#=======================================================================
-# VGA_UPDATE_INTERVAL:
-# Video memory is scanned for updates and screen updated every so many
-# virtual seconds.  The default is 40000, about 25Hz. Keep in mind that
-# you must tweak the 'cpu: ips=N' directive to be as close to the number
-# of emulated instructions-per-second your workstation can do, for this
-# to be accurate.
-#
-# Examples:
-#   vga_update_interval: 250000
-#=======================================================================
-vga_update_interval: 300000
-
-# using for Winstone '98 tests
-#vga_update_interval:  100000
-
-#=======================================================================
-# KEYBOARD_SERIAL_DELAY:
-# Approximate time in microseconds that it takes one character to
-# be transfered from the keyboard to controller over the serial path.
-# Examples:
-#   keyboard_serial_delay: 200
-#=======================================================================
-keyboard_serial_delay: 250
-
-#=======================================================================
-# KEYBOARD_PASTE_DELAY:
-# Approximate time in microseconds between attempts to paste
-# characters to the keyboard controller. This leaves time for the
-# guest os to deal with the flow of characters.  The ideal setting
-# depends on how your operating system processes characters.  The
-# default of 100000 usec (.1 seconds) was chosen because it works 
-# consistently in Windows.
-#
-# If your OS is losing characters during a paste, increase the paste
-# delay until it stops losing characters.
-#
-# Examples:
-#   keyboard_paste_delay: 100000
-#=======================================================================
-keyboard_paste_delay: 100000
-
-#=======================================================================
-# MOUSE: 
-# This option prevents Bochs from creating mouse "events" unless a mouse
-# is  enabled. The hardware emulation itself is not disabled by this.
-# You can turn the mouse on by setting enabled to 1, or turn it off by
-# setting enabled to 0. Unless you have a particular reason for enabling
-# the mouse by default, it is recommended that you leave it off.
-# You can also toggle the mouse usage at runtime (control key + middle
-# mouse button on X11, SDL, wxWidgets and Win32).
-# With the mouse type option you can select the type of mouse to emulate.
-# The default value is 'ps2'. The other choices are 'imps2' (wheel mouse
-# on PS/2), 'serial', 'serial_wheel' (one com port requires setting
-# 'mode=mouse') and 'usb' (3-button mouse - one of the USB ports must be
-# connected with the 'mouse' device - requires PCI and USB support).
-#
-# Examples:
-#   mouse: enabled=1
-#   mouse: enabled=1, type=imps2
-#   mouse: enabled=1, type=serial
-#   mouse: enabled=0
-#=======================================================================
-mouse: enabled=0
-
-#=======================================================================
-# private_colormap: Request that the GUI create and use it's own
-#                   non-shared colormap.  This colormap will be used
-#                   when in the bochs window.  If not enabled, a
-#                   shared colormap scheme may be used.  Not implemented
-#                   on all GUI's.
-#
-# Examples:
-#   private_colormap: enabled=1
-#   private_colormap: enabled=0
-#=======================================================================
-private_colormap: enabled=0
-
-#=======================================================================
-# fullscreen: ONLY IMPLEMENTED ON AMIGA
-#             Request that Bochs occupy the entire screen instead of a 
-#             window.
-#
-# Examples:
-#   fullscreen: enabled=0
-#   fullscreen: enabled=1
-#=======================================================================
-#fullscreen: enabled=0
-#screenmode: name="sample"
-
-#=======================================================================
-# ne2k: NE2000 compatible ethernet adapter
-#
-# Examples:
-# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT
-#
-# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there
-# are IRQ conflicts.
-#
-# mac: The MAC address MUST NOT match the address of any machine on the net.
-# Also, the first byte must be an even number (bit 0 set means a multicast
-# address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast
-# address.  For the ethertap module, you must use fe:fd:00:00:00:01.  There may
-# be other restrictions too.  To be safe, just use the b0:c4... address.
-#
-# ethdev: The ethdev value is the name of the network interface on your host
-# platform.  On UNIX machines, you can get the name by running ifconfig.  On
-# Windows machines, you must run niclist to get the name of the ethdev.
-# Niclist source code is in misc/niclist.c and it is included in Windows 
-# binary releases.
-#
-# script: The script value is optional, and is the name of a script that 
-# is executed after bochs initialize the network interface. You can use 
-# this script to configure this network interface, or enable masquerading.
-# This is mainly useful for the tun/tap devices that only exist during
-# Bochs execution. The network interface name is supplied to the script
-# as first parameter
-#
-# If you don't want to make connections to any physical networks,
-# you can use the following 'ethmod's to simulate a virtual network.
-#   null: All packets are discarded, but logged to a few files.
-#   arpback: ARP is simulated. Disabled by default.
-#   vde:  Virtual Distributed Ethernet
-#   vnet: ARP, ICMP-echo(ping), DHCP and read/write TFTP are simulated.
-#         The virtual host uses 192.168.10.1.
-#         DHCP assigns 192.168.10.2 to the guest.
-#         TFTP uses the ethdev value for the root directory and doesn't
-#         overwrite files.
-#
-#=======================================================================
-# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=fbsd, ethdev=en0 #macosx
-# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0
-# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0
-# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD
-# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0
-# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig
-# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0
-# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl"
-# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp"
-
-#=======================================================================
-# KEYBOARD_MAPPING:
-# This enables a remap of a physical localized keyboard to a 
-# virtualized us keyboard, as the PC architecture expects.
-# If enabled, the keymap file must be specified.
-# 
-# Examples:
-#   keyboard_mapping: enabled=1, map=gui/keymaps/x11-pc-de.map
-#=======================================================================
-keyboard_mapping: enabled=0, map=
-
-#=======================================================================
-# KEYBOARD_TYPE:
-# Type of keyboard return by a "identify keyboard" command to the
-# keyboard controler. It must be one of "xt", "at" or "mf".
-# Defaults to "mf". It should be ok for almost everybody. A known
-# exception is french macs, that do have a "at"-like keyboard.
-#
-# Examples:
-#   keyboard_type: mf
-#=======================================================================
-#keyboard_type: mf
-
-#=======================================================================
-# USER_SHORTCUT:
-# This defines the keyboard shortcut to be sent when you press the "user"
-# button in the headerbar. The shortcut string is a combination of maximum
-# 3 key names (listed below) separated with a '-' character. The old-style
-# syntax (without the '-') still works for the key combinations supported
-# in Bochs 2.2.1.
-# Valid key names:
-# "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc",
-# "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup",
-# "plus", "right", "shift", "space", "tab", "up", and "win".
-#
-# Example:
-#   user_shortcut: keys=ctrl-alt-del
-#=======================================================================
-#user_shortcut: keys=ctrl-alt-del
-
-#=======================================================================
-# I440FXSUPPORT:
-# This option controls the presence of the i440FX PCI chipset. You can
-# also specify the devices connected to PCI slots. Up to 5 slots are
-# available now. These devices are currently supported: ne2k, pcivga,
-# pcidev and pcipnic. If Bochs is compiled with Cirrus SVGA support
-# you'll have the additional choice 'cirrus'.
-#
-# Example:
-#   i440fxsupport: enabled=1, slot1=pcivga, slot2=ne2k
-#=======================================================================
-#i440fxsupport: enabled=1
-
-#=======================================================================
-# USB1:
-# This option controls the presence of the USB root hub which is a part
-# of the i440FX PCI chipset. With the portX option you can connect devices
-# to the hub (currently supported: 'mouse' and 'keypad'). If you connect
-# the mouse to one of the ports and use the mouse option 'type=usb' you'll
-# have a 3-button USB mouse.
-#
-# Example:
-#   usb1: enabled=1, port1=mouse, port2=keypad
-#=======================================================================
-#usb1: enabled=1
-
-#=======================================================================
-# CMOSIMAGE:
-# This defines image file that can be loaded into the CMOS RAM at startup.
-# The rtc_init parameter controls whether initialize the RTC with values stored
-# in the image. By default the time0 argument given to the clock option is used.
-# With 'rtc_init=image' the image is the source for the initial time.
-#
-# Example:
-#   cmosimage: file=cmos.img, rtc_init=image
-#=======================================================================
-#cmosimage: file=cmos.img, rtc_init=time0
-
-#=======================================================================
-# other stuff
-#=======================================================================
-#magic_break: enabled=1
-#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log
-#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img
-#text_snapshot_check: enable
-
-#-------------------------
-# PCI host device mapping
-#-------------------------
-#pcidev: vendor=0x1234, device=0x5678
-
-#=======================================================================
-# GDBSTUB:
-# Enable GDB stub. See user documentation for details.
-# Default value is enabled=0.
-#=======================================================================
-#gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0
-
-#=======================================================================
-# IPS:
-# The IPS directive is DEPRECATED. Use the parameter IPS of the CPU
-# directive instead.
-#=======================================================================
-#ips: 10000000
-
-#=======================================================================
-# for Macintosh, use the style of pathnames in the following
-# examples.
-#
-# vgaromimage: :bios:VGABIOS-elpin-2.40
-# romimage: file=:bios:BIOS-bochs-latest, address=0xf0000
-# floppya: 1_44=[fd:], status=inserted
-#=======================================================================
diff --git a/echo.c b/echo.c
deleted file mode 100644 (file)
index 806dee0..0000000
--- a/echo.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-int
-main(int argc, char *argv[])
-{
-  int i;
-
-  for(i = 1; i < argc; i++)
-    printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n");
-  exit();
-}
diff --git a/elf.h b/elf.h
deleted file mode 100644 (file)
index d16c967..0000000
--- a/elf.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Format of an ELF executable file
-
-#define ELF_MAGIC 0x464C457FU  // "\x7FELF" in little endian
-
-// File header
-struct elfhdr {
-  uint magic;  // must equal ELF_MAGIC
-  uchar elf[12];
-  ushort type;
-  ushort machine;
-  uint version;
-  uint entry;
-  uint phoff;
-  uint shoff;
-  uint flags;
-  ushort ehsize;
-  ushort phentsize;
-  ushort phnum;
-  ushort shentsize;
-  ushort shnum;
-  ushort shstrndx;
-};
-
-// Program section header
-struct proghdr {
-  uint type;
-  uint off;
-  uint vaddr;
-  uint paddr;
-  uint filesz;
-  uint memsz;
-  uint flags;
-  uint align;
-};
-
-// Values for Proghdr type
-#define ELF_PROG_LOAD           1
-
-// Flag bits for Proghdr flags
-#define ELF_PROG_FLAG_EXEC      1
-#define ELF_PROG_FLAG_WRITE     2
-#define ELF_PROG_FLAG_READ      4
diff --git a/entry.S b/entry.S
deleted file mode 100644 (file)
index bc79bab..0000000
--- a/entry.S
+++ /dev/null
@@ -1,68 +0,0 @@
-# The xv6 kernel starts executing in this file. This file is linked with
-# the kernel C code, so it can refer to kernel symbols such as main().
-# The boot block (bootasm.S and bootmain.c) jumps to entry below.
-        
-# Multiboot header, for multiboot boot loaders like GNU Grub.
-# http://www.gnu.org/software/grub/manual/multiboot/multiboot.html
-#
-# Using GRUB 2, you can boot xv6 from a file stored in a
-# Linux file system by copying kernel or kernelmemfs to /boot
-# and then adding this menu entry:
-#
-# menuentry "xv6" {
-#      insmod ext2
-#      set root='(hd0,msdos1)'
-#      set kernel='/boot/kernel'
-#      echo "Loading ${kernel}..."
-#      multiboot ${kernel} ${kernel}
-#      boot
-# }
-
-#include "asm.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "param.h"
-
-# Multiboot header.  Data to direct multiboot loader.
-.p2align 2
-.text
-.globl multiboot_header
-multiboot_header:
-  #define magic 0x1badb002
-  #define flags 0
-  .long magic
-  .long flags
-  .long (-magic-flags)
-
-# By convention, the _start symbol specifies the ELF entry point.
-# Since we haven't set up virtual memory yet, our entry point is
-# the physical address of 'entry'.
-.globl _start
-_start = V2P_WO(entry)
-
-# Entering xv6 on boot processor, with paging off.
-.globl entry
-entry:
-  # Turn on page size extension for 4Mbyte pages
-  movl    %cr4, %eax
-  orl     $(CR4_PSE), %eax
-  movl    %eax, %cr4
-  # Set page directory
-  movl    $(V2P_WO(entrypgdir)), %eax
-  movl    %eax, %cr3
-  # Turn on paging.
-  movl    %cr0, %eax
-  orl     $(CR0_PG|CR0_WP), %eax
-  movl    %eax, %cr0
-
-  # Set up the stack pointer.
-  movl $(stack + KSTACKSIZE), %esp
-
-  # Jump to main(), and switch to executing at
-  # high addresses. The indirect call is needed because
-  # the assembler produces a PC-relative instruction
-  # for a direct jump.
-  mov $main, %eax
-  jmp *%eax
-
-.comm stack, KSTACKSIZE
diff --git a/entryother.S b/entryother.S
deleted file mode 100644 (file)
index a3b6dc2..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "asm.h"
-#include "memlayout.h"
-#include "mmu.h"
-       
-# Each non-boot CPU ("AP") is started up in response to a STARTUP
-# IPI from the boot CPU.  Section B.4.2 of the Multi-Processor
-# Specification says that the AP will start in real mode with CS:IP
-# set to XY00:0000, where XY is an 8-bit value sent with the
-# STARTUP. Thus this code must start at a 4096-byte boundary.
-#
-# Because this code sets DS to zero, it must sit
-# at an address in the low 2^16 bytes.
-#
-# Startothers (in main.c) sends the STARTUPs one at a time.
-# It copies this code (start) at 0x7000.  It puts the address of
-# a newly allocated per-core stack in start-4,the address of the
-# place to jump to (mpenter) in start-8, and the physical address
-# of entrypgdir in start-12.
-#
-# This code combines elements of bootasm.S and entry.S.
-
-.code16           
-.globl start
-start:
-  cli            
-
-  # Zero data segment registers DS, ES, and SS.
-  xorw    %ax,%ax
-  movw    %ax,%ds
-  movw    %ax,%es
-  movw    %ax,%ss
-
-  # Switch from real to protected mode.  Use a bootstrap GDT that makes
-  # virtual addresses map directly to physical addresses so that the
-  # effective memory map doesn't change during the transition.
-  lgdt    gdtdesc
-  movl    %cr0, %eax
-  orl     $CR0_PE, %eax
-  movl    %eax, %cr0
-
-  # Complete the transition to 32-bit protected mode by using a long jmp
-  # to reload %cs and %eip.  The segment descriptors are set up with no
-  # translation, so that the mapping is still the identity mapping.
-  ljmpl    $(SEG_KCODE<<3), $(start32)
-
-//PAGEBREAK!
-.code32  # Tell assembler to generate 32-bit code now.
-start32:
-  # Set up the protected-mode data segment registers
-  movw    $(SEG_KDATA<<3), %ax    # Our data segment selector
-  movw    %ax, %ds                # -> DS: Data Segment
-  movw    %ax, %es                # -> ES: Extra Segment
-  movw    %ax, %ss                # -> SS: Stack Segment
-  movw    $0, %ax                 # Zero segments not ready for use
-  movw    %ax, %fs                # -> FS
-  movw    %ax, %gs                # -> GS
-
-  # Turn on page size extension for 4Mbyte pages
-  movl    %cr4, %eax
-  orl     $(CR4_PSE), %eax
-  movl    %eax, %cr4
-  # Use entrypgdir as our initial page table
-  movl    (start-12), %eax
-  movl    %eax, %cr3
-  # Turn on paging.
-  movl    %cr0, %eax
-  orl     $(CR0_PE|CR0_PG|CR0_WP), %eax
-  movl    %eax, %cr0
-
-  # Switch to the stack allocated by startothers()
-  movl    (start-4), %esp
-  # Call mpenter()
-  call  *(start-8)
-
-  movw    $0x8a00, %ax
-  movw    %ax, %dx
-  outw    %ax, %dx
-  movw    $0x8ae0, %ax
-  outw    %ax, %dx
-spin:
-  jmp     spin
-
-.p2align 2
-gdt:
-  SEG_NULLASM
-  SEG_ASM(STA_X|STA_R, 0, 0xffffffff)
-  SEG_ASM(STA_W, 0, 0xffffffff)
-
-
-gdtdesc:
-  .word   (gdtdesc - gdt - 1)
-  .long   gdt
-
diff --git a/exec.c b/exec.c
deleted file mode 100644 (file)
index b40134f..0000000
--- a/exec.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include "types.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "defs.h"
-#include "x86.h"
-#include "elf.h"
-
-int
-exec(char *path, char **argv)
-{
-  char *s, *last;
-  int i, off;
-  uint argc, sz, sp, ustack[3+MAXARG+1];
-  struct elfhdr elf;
-  struct inode *ip;
-  struct proghdr ph;
-  pde_t *pgdir, *oldpgdir;
-  struct proc *curproc = myproc();
-
-  begin_op();
-
-  if((ip = namei(path)) == 0){
-    end_op();
-    cprintf("exec: fail\n");
-    return -1;
-  }
-  ilock(ip);
-  pgdir = 0;
-
-  // Check ELF header
-  if(readi(ip, (char*)&elf, 0, sizeof(elf)) != sizeof(elf))
-    goto bad;
-  if(elf.magic != ELF_MAGIC)
-    goto bad;
-
-  if((pgdir = setupkvm()) == 0)
-    goto bad;
-
-  // Load program into memory.
-  sz = 0;
-  for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
-    if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
-      goto bad;
-    if(ph.type != ELF_PROG_LOAD)
-      continue;
-    if(ph.memsz < ph.filesz)
-      goto bad;
-    if(ph.vaddr + ph.memsz < ph.vaddr)
-      goto bad;
-    if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
-      goto bad;
-    if(ph.vaddr % PGSIZE != 0)
-      goto bad;
-    if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
-      goto bad;
-  }
-  iunlockput(ip);
-  end_op();
-  ip = 0;
-
-  // Allocate two pages at the next page boundary.
-  // Make the first inaccessible.  Use the second as the user stack.
-  sz = PGROUNDUP(sz);
-  if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
-    goto bad;
-  clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
-  sp = sz;
-
-  // Push argument strings, prepare rest of stack in ustack.
-  for(argc = 0; argv[argc]; argc++) {
-    if(argc >= MAXARG)
-      goto bad;
-    sp = (sp - (strlen(argv[argc]) + 1)) & ~3;
-    if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
-      goto bad;
-    ustack[3+argc] = sp;
-  }
-  ustack[3+argc] = 0;
-
-  ustack[0] = 0xffffffff;  // fake return PC
-  ustack[1] = argc;
-  ustack[2] = sp - (argc+1)*4;  // argv pointer
-
-  sp -= (3+argc+1) * 4;
-  if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
-    goto bad;
-
-  // Save program name for debugging.
-  for(last=s=path; *s; s++)
-    if(*s == '/')
-      last = s+1;
-  safestrcpy(curproc->name, last, sizeof(curproc->name));
-
-  // Commit to the user image.
-  oldpgdir = curproc->pgdir;
-  curproc->pgdir = pgdir;
-  curproc->sz = sz;
-  curproc->tf->eip = elf.entry;  // main
-  curproc->tf->esp = sp;
-  switchuvm(curproc);
-  freevm(oldpgdir);
-  return 0;
-
- bad:
-  if(pgdir)
-    freevm(pgdir);
-  if(ip){
-    iunlockput(ip);
-    end_op();
-  }
-  return -1;
-}
diff --git a/fcntl.h b/fcntl.h
deleted file mode 100644 (file)
index d565483..0000000
--- a/fcntl.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#define O_RDONLY  0x000
-#define O_WRONLY  0x001
-#define O_RDWR    0x002
-#define O_CREATE  0x200
diff --git a/file.c b/file.c
deleted file mode 100644 (file)
index 24b32c2..0000000
--- a/file.c
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// File descriptors
-//
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "fs.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "file.h"
-
-struct devsw devsw[NDEV];
-struct {
-  struct spinlock lock;
-  struct file file[NFILE];
-} ftable;
-
-void
-fileinit(void)
-{
-  initlock(&ftable.lock, "ftable");
-}
-
-// Allocate a file structure.
-struct file*
-filealloc(void)
-{
-  struct file *f;
-
-  acquire(&ftable.lock);
-  for(f = ftable.file; f < ftable.file + NFILE; f++){
-    if(f->ref == 0){
-      f->ref = 1;
-      release(&ftable.lock);
-      return f;
-    }
-  }
-  release(&ftable.lock);
-  return 0;
-}
-
-// Increment ref count for file f.
-struct file*
-filedup(struct file *f)
-{
-  acquire(&ftable.lock);
-  if(f->ref < 1)
-    panic("filedup");
-  f->ref++;
-  release(&ftable.lock);
-  return f;
-}
-
-// Close file f.  (Decrement ref count, close when reaches 0.)
-void
-fileclose(struct file *f)
-{
-  struct file ff;
-
-  acquire(&ftable.lock);
-  if(f->ref < 1)
-    panic("fileclose");
-  if(--f->ref > 0){
-    release(&ftable.lock);
-    return;
-  }
-  ff = *f;
-  f->ref = 0;
-  f->type = FD_NONE;
-  release(&ftable.lock);
-
-  if(ff.type == FD_PIPE)
-    pipeclose(ff.pipe, ff.writable);
-  else if(ff.type == FD_INODE){
-    begin_op();
-    iput(ff.ip);
-    end_op();
-  }
-}
-
-// Get metadata about file f.
-int
-filestat(struct file *f, struct stat *st)
-{
-  if(f->type == FD_INODE){
-    ilock(f->ip);
-    stati(f->ip, st);
-    iunlock(f->ip);
-    return 0;
-  }
-  return -1;
-}
-
-// Read from file f.
-int
-fileread(struct file *f, char *addr, int n)
-{
-  int r;
-
-  if(f->readable == 0)
-    return -1;
-  if(f->type == FD_PIPE)
-    return piperead(f->pipe, addr, n);
-  if(f->type == FD_INODE){
-    ilock(f->ip);
-    if((r = readi(f->ip, addr, f->off, n)) > 0)
-      f->off += r;
-    iunlock(f->ip);
-    return r;
-  }
-  panic("fileread");
-}
-
-//PAGEBREAK!
-// Write to file f.
-int
-filewrite(struct file *f, char *addr, int n)
-{
-  int r;
-
-  if(f->writable == 0)
-    return -1;
-  if(f->type == FD_PIPE)
-    return pipewrite(f->pipe, addr, n);
-  if(f->type == FD_INODE){
-    // write a few blocks at a time to avoid exceeding
-    // the maximum log transaction size, including
-    // i-node, indirect block, allocation blocks,
-    // and 2 blocks of slop for non-aligned writes.
-    // this really belongs lower down, since writei()
-    // might be writing a device like the console.
-    int max = ((MAXOPBLOCKS-1-1-2) / 2) * 512;
-    int i = 0;
-    while(i < n){
-      int n1 = n - i;
-      if(n1 > max)
-        n1 = max;
-
-      begin_op();
-      ilock(f->ip);
-      if ((r = writei(f->ip, addr + i, f->off, n1)) > 0)
-        f->off += r;
-      iunlock(f->ip);
-      end_op();
-
-      if(r < 0)
-        break;
-      if(r != n1)
-        panic("short filewrite");
-      i += r;
-    }
-    return i == n ? n : -1;
-  }
-  panic("filewrite");
-}
-
diff --git a/file.h b/file.h
deleted file mode 100644 (file)
index 0990c82..0000000
--- a/file.h
+++ /dev/null
@@ -1,37 +0,0 @@
-struct file {
-  enum { FD_NONE, FD_PIPE, FD_INODE } type;
-  int ref; // reference count
-  char readable;
-  char writable;
-  struct pipe *pipe;
-  struct inode *ip;
-  uint off;
-};
-
-
-// in-memory copy of an inode
-struct inode {
-  uint dev;           // Device number
-  uint inum;          // Inode number
-  int ref;            // Reference count
-  struct sleeplock lock; // protects everything below here
-  int valid;          // inode has been read from disk?
-
-  short type;         // copy of disk inode
-  short major;
-  short minor;
-  short nlink;
-  uint size;
-  uint addrs[NDIRECT+1];
-};
-
-// table mapping major device number to
-// device functions
-struct devsw {
-  int (*read)(struct inode*, char*, int);
-  int (*write)(struct inode*, char*, int);
-};
-
-extern struct devsw devsw[];
-
-#define CONSOLE 1
diff --git a/forktest.c b/forktest.c
deleted file mode 100644 (file)
index 8bc984d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// Test that fork fails gracefully.
-// Tiny executable so that the limit can be filling the proc table.
-
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-#define N  1000
-
-void
-printf(int fd, const char *s, ...)
-{
-  write(fd, s, strlen(s));
-}
-
-void
-forktest(void)
-{
-  int n, pid;
-
-  printf(1, "fork test\n");
-
-  for(n=0; n<N; n++){
-    pid = fork();
-    if(pid < 0)
-      break;
-    if(pid == 0)
-      exit();
-  }
-
-  if(n == N){
-    printf(1, "fork claimed to work N times!\n", N);
-    exit();
-  }
-
-  for(; n > 0; n--){
-    if(wait() < 0){
-      printf(1, "wait stopped early\n");
-      exit();
-    }
-  }
-
-  if(wait() != -1){
-    printf(1, "wait got too many\n");
-    exit();
-  }
-
-  printf(1, "fork test OK\n");
-}
-
-int
-main(void)
-{
-  forktest();
-  exit();
-}
diff --git a/fs.c b/fs.c
deleted file mode 100644 (file)
index f77275f..0000000
--- a/fs.c
+++ /dev/null
@@ -1,670 +0,0 @@
-// File system implementation.  Five layers:
-//   + Blocks: allocator for raw disk blocks.
-//   + Log: crash recovery for multi-step updates.
-//   + Files: inode allocator, reading, writing, metadata.
-//   + Directories: inode with special contents (list of other inodes!)
-//   + Names: paths like /usr/rtm/xv6/fs.c for convenient naming.
-//
-// This file contains the low-level file system manipulation
-// routines.  The (higher-level) system call implementations
-// are in sysfile.c.
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "stat.h"
-#include "mmu.h"
-#include "proc.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "fs.h"
-#include "buf.h"
-#include "file.h"
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-static void itrunc(struct inode*);
-// there should be one superblock per disk device, but we run with
-// only one device
-struct superblock sb; 
-
-// Read the super block.
-void
-readsb(int dev, struct superblock *sb)
-{
-  struct buf *bp;
-
-  bp = bread(dev, 1);
-  memmove(sb, bp->data, sizeof(*sb));
-  brelse(bp);
-}
-
-// Zero a block.
-static void
-bzero(int dev, int bno)
-{
-  struct buf *bp;
-
-  bp = bread(dev, bno);
-  memset(bp->data, 0, BSIZE);
-  log_write(bp);
-  brelse(bp);
-}
-
-// Blocks.
-
-// Allocate a zeroed disk block.
-static uint
-balloc(uint dev)
-{
-  int b, bi, m;
-  struct buf *bp;
-
-  bp = 0;
-  for(b = 0; b < sb.size; b += BPB){
-    bp = bread(dev, BBLOCK(b, sb));
-    for(bi = 0; bi < BPB && b + bi < sb.size; bi++){
-      m = 1 << (bi % 8);
-      if((bp->data[bi/8] & m) == 0){  // Is block free?
-        bp->data[bi/8] |= m;  // Mark block in use.
-        log_write(bp);
-        brelse(bp);
-        bzero(dev, b + bi);
-        return b + bi;
-      }
-    }
-    brelse(bp);
-  }
-  panic("balloc: out of blocks");
-}
-
-// Free a disk block.
-static void
-bfree(int dev, uint b)
-{
-  struct buf *bp;
-  int bi, m;
-
-  bp = bread(dev, BBLOCK(b, sb));
-  bi = b % BPB;
-  m = 1 << (bi % 8);
-  if((bp->data[bi/8] & m) == 0)
-    panic("freeing free block");
-  bp->data[bi/8] &= ~m;
-  log_write(bp);
-  brelse(bp);
-}
-
-// Inodes.
-//
-// An inode describes a single unnamed file.
-// The inode disk structure holds metadata: the file's type,
-// its size, the number of links referring to it, and the
-// list of blocks holding the file's content.
-//
-// The inodes are laid out sequentially on disk at
-// sb.startinode. Each inode has a number, indicating its
-// position on the disk.
-//
-// The kernel keeps a cache of in-use inodes in memory
-// to provide a place for synchronizing access
-// to inodes used by multiple processes. The cached
-// inodes include book-keeping information that is
-// not stored on disk: ip->ref and ip->valid.
-//
-// An inode and its in-memory representation go through a
-// sequence of states before they can be used by the
-// rest of the file system code.
-//
-// * Allocation: an inode is allocated if its type (on disk)
-//   is non-zero. ialloc() allocates, and iput() frees if
-//   the reference and link counts have fallen to zero.
-//
-// * Referencing in cache: an entry in the inode cache
-//   is free if ip->ref is zero. Otherwise ip->ref tracks
-//   the number of in-memory pointers to the entry (open
-//   files and current directories). iget() finds or
-//   creates a cache entry and increments its ref; iput()
-//   decrements ref.
-//
-// * Valid: the information (type, size, &c) in an inode
-//   cache entry is only correct when ip->valid is 1.
-//   ilock() reads the inode from
-//   the disk and sets ip->valid, while iput() clears
-//   ip->valid if ip->ref has fallen to zero.
-//
-// * Locked: file system code may only examine and modify
-//   the information in an inode and its content if it
-//   has first locked the inode.
-//
-// Thus a typical sequence is:
-//   ip = iget(dev, inum)
-//   ilock(ip)
-//   ... examine and modify ip->xxx ...
-//   iunlock(ip)
-//   iput(ip)
-//
-// ilock() is separate from iget() so that system calls can
-// get a long-term reference to an inode (as for an open file)
-// and only lock it for short periods (e.g., in read()).
-// The separation also helps avoid deadlock and races during
-// pathname lookup. iget() increments ip->ref so that the inode
-// stays cached and pointers to it remain valid.
-//
-// Many internal file system functions expect the caller to
-// have locked the inodes involved; this lets callers create
-// multi-step atomic operations.
-//
-// The icache.lock spin-lock protects the allocation of icache
-// entries. Since ip->ref indicates whether an entry is free,
-// and ip->dev and ip->inum indicate which i-node an entry
-// holds, one must hold icache.lock while using any of those fields.
-//
-// An ip->lock sleep-lock protects all ip-> fields other than ref,
-// dev, and inum.  One must hold ip->lock in order to
-// read or write that inode's ip->valid, ip->size, ip->type, &c.
-
-struct {
-  struct spinlock lock;
-  struct inode inode[NINODE];
-} icache;
-
-void
-iinit(int dev)
-{
-  int i = 0;
-  
-  initlock(&icache.lock, "icache");
-  for(i = 0; i < NINODE; i++) {
-    initsleeplock(&icache.inode[i].lock, "inode");
-  }
-
-  readsb(dev, &sb);
-  cprintf("sb: size %d nblocks %d ninodes %d nlog %d logstart %d\
- inodestart %d bmap start %d\n", sb.size, sb.nblocks,
-          sb.ninodes, sb.nlog, sb.logstart, sb.inodestart,
-          sb.bmapstart);
-}
-
-static struct inode* iget(uint dev, uint inum);
-
-//PAGEBREAK!
-// Allocate an inode on device dev.
-// Mark it as allocated by  giving it type type.
-// Returns an unlocked but allocated and referenced inode.
-struct inode*
-ialloc(uint dev, short type)
-{
-  int inum;
-  struct buf *bp;
-  struct dinode *dip;
-
-  for(inum = 1; inum < sb.ninodes; inum++){
-    bp = bread(dev, IBLOCK(inum, sb));
-    dip = (struct dinode*)bp->data + inum%IPB;
-    if(dip->type == 0){  // a free inode
-      memset(dip, 0, sizeof(*dip));
-      dip->type = type;
-      log_write(bp);   // mark it allocated on the disk
-      brelse(bp);
-      return iget(dev, inum);
-    }
-    brelse(bp);
-  }
-  panic("ialloc: no inodes");
-}
-
-// Copy a modified in-memory inode to disk.
-// Must be called after every change to an ip->xxx field
-// that lives on disk, since i-node cache is write-through.
-// Caller must hold ip->lock.
-void
-iupdate(struct inode *ip)
-{
-  struct buf *bp;
-  struct dinode *dip;
-
-  bp = bread(ip->dev, IBLOCK(ip->inum, sb));
-  dip = (struct dinode*)bp->data + ip->inum%IPB;
-  dip->type = ip->type;
-  dip->major = ip->major;
-  dip->minor = ip->minor;
-  dip->nlink = ip->nlink;
-  dip->size = ip->size;
-  memmove(dip->addrs, ip->addrs, sizeof(ip->addrs));
-  log_write(bp);
-  brelse(bp);
-}
-
-// Find the inode with number inum on device dev
-// and return the in-memory copy. Does not lock
-// the inode and does not read it from disk.
-static struct inode*
-iget(uint dev, uint inum)
-{
-  struct inode *ip, *empty;
-
-  acquire(&icache.lock);
-
-  // Is the inode already cached?
-  empty = 0;
-  for(ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++){
-    if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){
-      ip->ref++;
-      release(&icache.lock);
-      return ip;
-    }
-    if(empty == 0 && ip->ref == 0)    // Remember empty slot.
-      empty = ip;
-  }
-
-  // Recycle an inode cache entry.
-  if(empty == 0)
-    panic("iget: no inodes");
-
-  ip = empty;
-  ip->dev = dev;
-  ip->inum = inum;
-  ip->ref = 1;
-  ip->valid = 0;
-  release(&icache.lock);
-
-  return ip;
-}
-
-// Increment reference count for ip.
-// Returns ip to enable ip = idup(ip1) idiom.
-struct inode*
-idup(struct inode *ip)
-{
-  acquire(&icache.lock);
-  ip->ref++;
-  release(&icache.lock);
-  return ip;
-}
-
-// Lock the given inode.
-// Reads the inode from disk if necessary.
-void
-ilock(struct inode *ip)
-{
-  struct buf *bp;
-  struct dinode *dip;
-
-  if(ip == 0 || ip->ref < 1)
-    panic("ilock");
-
-  acquiresleep(&ip->lock);
-
-  if(ip->valid == 0){
-    bp = bread(ip->dev, IBLOCK(ip->inum, sb));
-    dip = (struct dinode*)bp->data + ip->inum%IPB;
-    ip->type = dip->type;
-    ip->major = dip->major;
-    ip->minor = dip->minor;
-    ip->nlink = dip->nlink;
-    ip->size = dip->size;
-    memmove(ip->addrs, dip->addrs, sizeof(ip->addrs));
-    brelse(bp);
-    ip->valid = 1;
-    if(ip->type == 0)
-      panic("ilock: no type");
-  }
-}
-
-// Unlock the given inode.
-void
-iunlock(struct inode *ip)
-{
-  if(ip == 0 || !holdingsleep(&ip->lock) || ip->ref < 1)
-    panic("iunlock");
-
-  releasesleep(&ip->lock);
-}
-
-// Drop a reference to an in-memory inode.
-// If that was the last reference, the inode cache entry can
-// be recycled.
-// If that was the last reference and the inode has no links
-// to it, free the inode (and its content) on disk.
-// All calls to iput() must be inside a transaction in
-// case it has to free the inode.
-void
-iput(struct inode *ip)
-{
-  acquiresleep(&ip->lock);
-  if(ip->valid && ip->nlink == 0){
-    acquire(&icache.lock);
-    int r = ip->ref;
-    release(&icache.lock);
-    if(r == 1){
-      // inode has no links and no other references: truncate and free.
-      itrunc(ip);
-      ip->type = 0;
-      iupdate(ip);
-      ip->valid = 0;
-    }
-  }
-  releasesleep(&ip->lock);
-
-  acquire(&icache.lock);
-  ip->ref--;
-  release(&icache.lock);
-}
-
-// Common idiom: unlock, then put.
-void
-iunlockput(struct inode *ip)
-{
-  iunlock(ip);
-  iput(ip);
-}
-
-//PAGEBREAK!
-// Inode content
-//
-// The content (data) associated with each inode is stored
-// in blocks on the disk. The first NDIRECT block numbers
-// are listed in ip->addrs[].  The next NINDIRECT blocks are
-// listed in block ip->addrs[NDIRECT].
-
-// Return the disk block address of the nth block in inode ip.
-// If there is no such block, bmap allocates one.
-static uint
-bmap(struct inode *ip, uint bn)
-{
-  uint addr, *a;
-  struct buf *bp;
-
-  if(bn < NDIRECT){
-    if((addr = ip->addrs[bn]) == 0)
-      ip->addrs[bn] = addr = balloc(ip->dev);
-    return addr;
-  }
-  bn -= NDIRECT;
-
-  if(bn < NINDIRECT){
-    // Load indirect block, allocating if necessary.
-    if((addr = ip->addrs[NDIRECT]) == 0)
-      ip->addrs[NDIRECT] = addr = balloc(ip->dev);
-    bp = bread(ip->dev, addr);
-    a = (uint*)bp->data;
-    if((addr = a[bn]) == 0){
-      a[bn] = addr = balloc(ip->dev);
-      log_write(bp);
-    }
-    brelse(bp);
-    return addr;
-  }
-
-  panic("bmap: out of range");
-}
-
-// Truncate inode (discard contents).
-// Only called when the inode has no links
-// to it (no directory entries referring to it)
-// and has no in-memory reference to it (is
-// not an open file or current directory).
-static void
-itrunc(struct inode *ip)
-{
-  int i, j;
-  struct buf *bp;
-  uint *a;
-
-  for(i = 0; i < NDIRECT; i++){
-    if(ip->addrs[i]){
-      bfree(ip->dev, ip->addrs[i]);
-      ip->addrs[i] = 0;
-    }
-  }
-
-  if(ip->addrs[NDIRECT]){
-    bp = bread(ip->dev, ip->addrs[NDIRECT]);
-    a = (uint*)bp->data;
-    for(j = 0; j < NINDIRECT; j++){
-      if(a[j])
-        bfree(ip->dev, a[j]);
-    }
-    brelse(bp);
-    bfree(ip->dev, ip->addrs[NDIRECT]);
-    ip->addrs[NDIRECT] = 0;
-  }
-
-  ip->size = 0;
-  iupdate(ip);
-}
-
-// Copy stat information from inode.
-// Caller must hold ip->lock.
-void
-stati(struct inode *ip, struct stat *st)
-{
-  st->dev = ip->dev;
-  st->ino = ip->inum;
-  st->type = ip->type;
-  st->nlink = ip->nlink;
-  st->size = ip->size;
-}
-
-//PAGEBREAK!
-// Read data from inode.
-// Caller must hold ip->lock.
-int
-readi(struct inode *ip, char *dst, uint off, uint n)
-{
-  uint tot, m;
-  struct buf *bp;
-
-  if(ip->type == T_DEV){
-    if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].read)
-      return -1;
-    return devsw[ip->major].read(ip, dst, n);
-  }
-
-  if(off > ip->size || off + n < off)
-    return -1;
-  if(off + n > ip->size)
-    n = ip->size - off;
-
-  for(tot=0; tot<n; tot+=m, off+=m, dst+=m){
-    bp = bread(ip->dev, bmap(ip, off/BSIZE));
-    m = min(n - tot, BSIZE - off%BSIZE);
-    memmove(dst, bp->data + off%BSIZE, m);
-    brelse(bp);
-  }
-  return n;
-}
-
-// PAGEBREAK!
-// Write data to inode.
-// Caller must hold ip->lock.
-int
-writei(struct inode *ip, char *src, uint off, uint n)
-{
-  uint tot, m;
-  struct buf *bp;
-
-  if(ip->type == T_DEV){
-    if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].write)
-      return -1;
-    return devsw[ip->major].write(ip, src, n);
-  }
-
-  if(off > ip->size || off + n < off)
-    return -1;
-  if(off + n > MAXFILE*BSIZE)
-    return -1;
-
-  for(tot=0; tot<n; tot+=m, off+=m, src+=m){
-    bp = bread(ip->dev, bmap(ip, off/BSIZE));
-    m = min(n - tot, BSIZE - off%BSIZE);
-    memmove(bp->data + off%BSIZE, src, m);
-    log_write(bp);
-    brelse(bp);
-  }
-
-  if(n > 0 && off > ip->size){
-    ip->size = off;
-    iupdate(ip);
-  }
-  return n;
-}
-
-//PAGEBREAK!
-// Directories
-
-int
-namecmp(const char *s, const char *t)
-{
-  return strncmp(s, t, DIRSIZ);
-}
-
-// Look for a directory entry in a directory.
-// If found, set *poff to byte offset of entry.
-struct inode*
-dirlookup(struct inode *dp, char *name, uint *poff)
-{
-  uint off, inum;
-  struct dirent de;
-
-  if(dp->type != T_DIR)
-    panic("dirlookup not DIR");
-
-  for(off = 0; off < dp->size; off += sizeof(de)){
-    if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
-      panic("dirlookup read");
-    if(de.inum == 0)
-      continue;
-    if(namecmp(name, de.name) == 0){
-      // entry matches path element
-      if(poff)
-        *poff = off;
-      inum = de.inum;
-      return iget(dp->dev, inum);
-    }
-  }
-
-  return 0;
-}
-
-// Write a new directory entry (name, inum) into the directory dp.
-int
-dirlink(struct inode *dp, char *name, uint inum)
-{
-  int off;
-  struct dirent de;
-  struct inode *ip;
-
-  // Check that name is not present.
-  if((ip = dirlookup(dp, name, 0)) != 0){
-    iput(ip);
-    return -1;
-  }
-
-  // Look for an empty dirent.
-  for(off = 0; off < dp->size; off += sizeof(de)){
-    if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
-      panic("dirlink read");
-    if(de.inum == 0)
-      break;
-  }
-
-  strncpy(de.name, name, DIRSIZ);
-  de.inum = inum;
-  if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
-    panic("dirlink");
-
-  return 0;
-}
-
-//PAGEBREAK!
-// Paths
-
-// Copy the next path element from path into name.
-// Return a pointer to the element following the copied one.
-// The returned path has no leading slashes,
-// so the caller can check *path=='\0' to see if the name is the last one.
-// If no name to remove, return 0.
-//
-// Examples:
-//   skipelem("a/bb/c", name) = "bb/c", setting name = "a"
-//   skipelem("///a//bb", name) = "bb", setting name = "a"
-//   skipelem("a", name) = "", setting name = "a"
-//   skipelem("", name) = skipelem("////", name) = 0
-//
-static char*
-skipelem(char *path, char *name)
-{
-  char *s;
-  int len;
-
-  while(*path == '/')
-    path++;
-  if(*path == 0)
-    return 0;
-  s = path;
-  while(*path != '/' && *path != 0)
-    path++;
-  len = path - s;
-  if(len >= DIRSIZ)
-    memmove(name, s, DIRSIZ);
-  else {
-    memmove(name, s, len);
-    name[len] = 0;
-  }
-  while(*path == '/')
-    path++;
-  return path;
-}
-
-// Look up and return the inode for a path name.
-// If parent != 0, return the inode for the parent and copy the final
-// path element into name, which must have room for DIRSIZ bytes.
-// Must be called inside a transaction since it calls iput().
-static struct inode*
-namex(char *path, int nameiparent, char *name)
-{
-  struct inode *ip, *next;
-
-  if(*path == '/')
-    ip = iget(ROOTDEV, ROOTINO);
-  else
-    ip = idup(myproc()->cwd);
-
-  while((path = skipelem(path, name)) != 0){
-    ilock(ip);
-    if(ip->type != T_DIR){
-      iunlockput(ip);
-      return 0;
-    }
-    if(nameiparent && *path == '\0'){
-      // Stop one level early.
-      iunlock(ip);
-      return ip;
-    }
-    if((next = dirlookup(ip, name, 0)) == 0){
-      iunlockput(ip);
-      return 0;
-    }
-    iunlockput(ip);
-    ip = next;
-  }
-  if(nameiparent){
-    iput(ip);
-    return 0;
-  }
-  return ip;
-}
-
-struct inode*
-namei(char *path)
-{
-  char name[DIRSIZ];
-  return namex(path, 0, name);
-}
-
-struct inode*
-nameiparent(char *path, char *name)
-{
-  return namex(path, 1, name);
-}
diff --git a/fs.h b/fs.h
deleted file mode 100644 (file)
index 3214f1d..0000000
--- a/fs.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// On-disk file system format.
-// Both the kernel and user programs use this header file.
-
-
-#define ROOTINO 1  // root i-number
-#define BSIZE 512  // block size
-
-// Disk layout:
-// [ boot block | super block | log | inode blocks |
-//                                          free bit map | data blocks]
-//
-// mkfs computes the super block and builds an initial file system. The
-// super block describes the disk layout:
-struct superblock {
-  uint size;         // Size of file system image (blocks)
-  uint nblocks;      // Number of data blocks
-  uint ninodes;      // Number of inodes.
-  uint nlog;         // Number of log blocks
-  uint logstart;     // Block number of first log block
-  uint inodestart;   // Block number of first inode block
-  uint bmapstart;    // Block number of first free map block
-};
-
-#define NDIRECT 12
-#define NINDIRECT (BSIZE / sizeof(uint))
-#define MAXFILE (NDIRECT + NINDIRECT)
-
-// On-disk inode structure
-struct dinode {
-  short type;           // File type
-  short major;          // Major device number (T_DEV only)
-  short minor;          // Minor device number (T_DEV only)
-  short nlink;          // Number of links to inode in file system
-  uint size;            // Size of file (bytes)
-  uint addrs[NDIRECT+1];   // Data block addresses
-};
-
-// Inodes per block.
-#define IPB           (BSIZE / sizeof(struct dinode))
-
-// Block containing inode i
-#define IBLOCK(i, sb)     ((i) / IPB + sb.inodestart)
-
-// Bitmap bits per block
-#define BPB           (BSIZE*8)
-
-// Block of free map containing bit for block b
-#define BBLOCK(b, sb) (b/BPB + sb.bmapstart)
-
-// Directory is a file containing a sequence of dirent structures.
-#define DIRSIZ 14
-
-struct dirent {
-  ushort inum;
-  char name[DIRSIZ];
-};
-
diff --git a/grep.c b/grep.c
deleted file mode 100644 (file)
index adc4835..0000000
--- a/grep.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// Simple grep.  Only supports ^ . * $ operators.
-
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-char buf[1024];
-int match(char*, char*);
-
-void
-grep(char *pattern, int fd)
-{
-  int n, m;
-  char *p, *q;
-
-  m = 0;
-  while((n = read(fd, buf+m, sizeof(buf)-m-1)) > 0){
-    m += n;
-    buf[m] = '\0';
-    p = buf;
-    while((q = strchr(p, '\n')) != 0){
-      *q = 0;
-      if(match(pattern, p)){
-        *q = '\n';
-        write(1, p, q+1 - p);
-      }
-      p = q+1;
-    }
-    if(p == buf)
-      m = 0;
-    if(m > 0){
-      m -= p - buf;
-      memmove(buf, p, m);
-    }
-  }
-}
-
-int
-main(int argc, char *argv[])
-{
-  int fd, i;
-  char *pattern;
-
-  if(argc <= 1){
-    printf(2, "usage: grep pattern [file ...]\n");
-    exit();
-  }
-  pattern = argv[1];
-
-  if(argc <= 2){
-    grep(pattern, 0);
-    exit();
-  }
-
-  for(i = 2; i < argc; i++){
-    if((fd = open(argv[i], 0)) < 0){
-      printf(1, "grep: cannot open %s\n", argv[i]);
-      exit();
-    }
-    grep(pattern, fd);
-    close(fd);
-  }
-  exit();
-}
-
-// Regexp matcher from Kernighan & Pike,
-// The Practice of Programming, Chapter 9.
-
-int matchhere(char*, char*);
-int matchstar(int, char*, char*);
-
-int
-match(char *re, char *text)
-{
-  if(re[0] == '^')
-    return matchhere(re+1, text);
-  do{  // must look at empty string
-    if(matchhere(re, text))
-      return 1;
-  }while(*text++ != '\0');
-  return 0;
-}
-
-// matchhere: search for re at beginning of text
-int matchhere(char *re, char *text)
-{
-  if(re[0] == '\0')
-    return 1;
-  if(re[1] == '*')
-    return matchstar(re[0], re+2, text);
-  if(re[0] == '$' && re[1] == '\0')
-    return *text == '\0';
-  if(*text!='\0' && (re[0]=='.' || re[0]==*text))
-    return matchhere(re+1, text+1);
-  return 0;
-}
-
-// matchstar: search for c*re at beginning of text
-int matchstar(int c, char *re, char *text)
-{
-  do{  // a * matches zero or more instances
-    if(matchhere(re, text))
-      return 1;
-  }while(*text!='\0' && (*text++==c || c=='.'));
-  return 0;
-}
-
diff --git a/ide.c b/ide.c
deleted file mode 100644 (file)
index b4c0b1f..0000000
--- a/ide.c
+++ /dev/null
@@ -1,168 +0,0 @@
-// Simple PIO-based (non-DMA) IDE driver code.
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "x86.h"
-#include "traps.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "fs.h"
-#include "buf.h"
-
-#define SECTOR_SIZE   512
-#define IDE_BSY       0x80
-#define IDE_DRDY      0x40
-#define IDE_DF        0x20
-#define IDE_ERR       0x01
-
-#define IDE_CMD_READ  0x20
-#define IDE_CMD_WRITE 0x30
-#define IDE_CMD_RDMUL 0xc4
-#define IDE_CMD_WRMUL 0xc5
-
-// idequeue points to the buf now being read/written to the disk.
-// idequeue->qnext points to the next buf to be processed.
-// You must hold idelock while manipulating queue.
-
-static struct spinlock idelock;
-static struct buf *idequeue;
-
-static int havedisk1;
-static void idestart(struct buf*);
-
-// Wait for IDE disk to become ready.
-static int
-idewait(int checkerr)
-{
-  int r;
-
-  while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
-    ;
-  if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0)
-    return -1;
-  return 0;
-}
-
-void
-ideinit(void)
-{
-  int i;
-
-  initlock(&idelock, "ide");
-  ioapicenable(IRQ_IDE, ncpu - 1);
-  idewait(0);
-
-  // Check if disk 1 is present
-  outb(0x1f6, 0xe0 | (1<<4));
-  for(i=0; i<1000; i++){
-    if(inb(0x1f7) != 0){
-      havedisk1 = 1;
-      break;
-    }
-  }
-
-  // Switch back to disk 0.
-  outb(0x1f6, 0xe0 | (0<<4));
-}
-
-// Start the request for b.  Caller must hold idelock.
-static void
-idestart(struct buf *b)
-{
-  if(b == 0)
-    panic("idestart");
-  if(b->blockno >= FSSIZE)
-    panic("incorrect blockno");
-  int sector_per_block =  BSIZE/SECTOR_SIZE;
-  int sector = b->blockno * sector_per_block;
-  int read_cmd = (sector_per_block == 1) ? IDE_CMD_READ :  IDE_CMD_RDMUL;
-  int write_cmd = (sector_per_block == 1) ? IDE_CMD_WRITE : IDE_CMD_WRMUL;
-
-  if (sector_per_block > 7) panic("idestart");
-
-  idewait(0);
-  outb(0x3f6, 0);  // generate interrupt
-  outb(0x1f2, sector_per_block);  // number of sectors
-  outb(0x1f3, sector & 0xff);
-  outb(0x1f4, (sector >> 8) & 0xff);
-  outb(0x1f5, (sector >> 16) & 0xff);
-  outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((sector>>24)&0x0f));
-  if(b->flags & B_DIRTY){
-    outb(0x1f7, write_cmd);
-    outsl(0x1f0, b->data, BSIZE/4);
-  } else {
-    outb(0x1f7, read_cmd);
-  }
-}
-
-// Interrupt handler.
-void
-ideintr(void)
-{
-  struct buf *b;
-
-  // First queued buffer is the active request.
-  acquire(&idelock);
-
-  if((b = idequeue) == 0){
-    release(&idelock);
-    return;
-  }
-  idequeue = b->qnext;
-
-  // Read data if needed.
-  if(!(b->flags & B_DIRTY) && idewait(1) >= 0)
-    insl(0x1f0, b->data, BSIZE/4);
-
-  // Wake process waiting for this buf.
-  b->flags |= B_VALID;
-  b->flags &= ~B_DIRTY;
-  wakeup(b);
-
-  // Start disk on next buf in queue.
-  if(idequeue != 0)
-    idestart(idequeue);
-
-  release(&idelock);
-}
-
-//PAGEBREAK!
-// Sync buf with disk.
-// If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID.
-// Else if B_VALID is not set, read buf from disk, set B_VALID.
-void
-iderw(struct buf *b)
-{
-  struct buf **pp;
-
-  if(!holdingsleep(&b->lock))
-    panic("iderw: buf not locked");
-  if((b->flags & (B_VALID|B_DIRTY)) == B_VALID)
-    panic("iderw: nothing to do");
-  if(b->dev != 0 && !havedisk1)
-    panic("iderw: ide disk 1 not present");
-
-  acquire(&idelock);  //DOC:acquire-lock
-
-  // Append b to idequeue.
-  b->qnext = 0;
-  for(pp=&idequeue; *pp; pp=&(*pp)->qnext)  //DOC:insert-queue
-    ;
-  *pp = b;
-
-  // Start disk if necessary.
-  if(idequeue == b)
-    idestart(b);
-
-  // Wait for request to finish.
-  while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){
-    sleep(b, &idelock);
-  }
-
-
-  release(&idelock);
-}
diff --git a/include/asm/asm.h b/include/asm/asm.h
new file mode 100644 (file)
index 0000000..7b582b3
--- /dev/null
@@ -0,0 +1,22 @@
+//
+// assembler macros to create x86 segments
+//
+#ifndef INCLUDE_ASM_ASM_h_
+#define INCLUDE_ASM_ASM_h_
+
+#define SEG_NULLASM                                             \
+        .word 0, 0;                                             \
+        .byte 0, 0, 0, 0
+
+// The 0xC0 means the limit is in 4096-byte units
+// and (for executable segments) 32-bit mode.
+#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 STA_W     0x2       // Writeable (non-executable segments)
+#define STA_R     0x2       // Readable (executable segments)
+
+#endif  // INCLUDE_ASM_ASM_h_
diff --git a/include/asm/x86.h b/include/asm/x86.h
new file mode 100644 (file)
index 0000000..12ff7d2
--- /dev/null
@@ -0,0 +1,176 @@
+// Routines to let C code use special x86 instructions.
+#ifndef INCLUDE_ASM_X86_h_
+#define INCLUDE_ASM_X86_h_
+
+#include "types.h"
+
+static inline uchar
+inb(ushort port)
+{
+  uchar data;
+
+  __asm__ volatile("in %1,%0" : "=a" (data) : "d" (port));
+  return data;
+}
+
+static inline void
+insl(int port, void *addr, int cnt)
+{
+  __asm__ volatile("cld; rep insl" :
+               "=D" (addr), "=c" (cnt) :
+               "d" (port), "0" (addr), "1" (cnt) :
+               "memory", "cc");
+}
+
+static inline void
+outb(ushort port, uchar data)
+{
+  __asm__ volatile("out %0,%1" : : "a" (data), "d" (port));
+}
+
+static inline void
+outw(ushort port, ushort data)
+{
+  __asm__ volatile("out %0,%1" : : "a" (data), "d" (port));
+}
+
+static inline void
+outsl(int port, const void *addr, int cnt)
+{
+  __asm__ volatile("cld; rep outsl" :
+               "=S" (addr), "=c" (cnt) :
+               "d" (port), "0" (addr), "1" (cnt) :
+               "cc");
+}
+
+static inline void
+stosb(void *addr, int data, int cnt)
+{
+  __asm__ volatile("cld; rep stosb" :
+               "=D" (addr), "=c" (cnt) :
+               "0" (addr), "1" (cnt), "a" (data) :
+               "memory", "cc");
+}
+
+static inline void
+stosl(void *addr, int data, int cnt)
+{
+  __asm__ volatile("cld; rep stosl" :
+               "=D" (addr), "=c" (cnt) :
+               "0" (addr), "1" (cnt), "a" (data) :
+               "memory", "cc");
+}
+
+struct segdesc;
+
+static inline void
+lgdt(struct segdesc *p, int size)
+{
+  volatile ushort pd[3];
+
+  pd[0] = size-1;
+  pd[1] = (uint)p;
+  pd[2] = (uint)p >> 16;
+
+  __asm__ volatile("lgdt (%0)" : : "r" (pd));
+}
+
+struct gatedesc;
+
+static inline void
+lidt(struct gatedesc *p, int size)
+{
+  volatile ushort pd[3];
+
+  pd[0] = size-1;
+  pd[1] = (uint)p;
+  pd[2] = (uint)p >> 16;
+
+  __asm__ volatile("lidt (%0)" : : "r" (pd));
+}
+
+static inline void
+ltr(ushort sel)
+{
+  __asm__ volatile("ltr %0" : : "r" (sel));
+}
+
+static inline uint
+readeflags(void)
+{
+  uint eflags;
+  __asm__ volatile("pushfl; popl %0" : "=r" (eflags));
+  return eflags;
+}
+
+static inline void
+loadgs(ushort v)
+{
+  __asm__ volatile("movw %0, %%gs" : : "r" (v));
+}
+
+static inline void
+cli(void)
+{
+  __asm__ volatile("cli");
+}
+
+static inline void
+sti(void)
+{
+  __asm__ volatile("sti");
+}
+
+static inline uint
+rcr2(void)
+{
+  uint val;
+  __asm__ volatile("movl %%cr2,%0" : "=r" (val));
+  return val;
+}
+
+static inline void
+lcr3(uint val)
+{
+  __asm__ volatile("movl %0,%%cr3" : : "r" (val));
+}
+
+//PAGEBREAK: 36
+// Layout of the trap frame built on the stack by the
+// hardware and by trapasm.S, and passed to trap().
+struct trapframe {
+  // registers as pushed by pusha
+  uint edi;
+  uint esi;
+  uint ebp;
+  uint oesp;      // useless & ignored
+  uint ebx;
+  uint edx;
+  uint ecx;
+  uint eax;
+
+  // rest of trap frame
+  ushort gs;
+  ushort padding1;
+  ushort fs;
+  ushort padding2;
+  ushort es;
+  ushort padding3;
+  ushort ds;
+  ushort padding4;
+  uint trapno;
+
+  // below here defined by x86 hardware
+  uint err;
+  uint eip;
+  ushort cs;
+  ushort padding5;
+  uint eflags;
+
+  // below here only when crossing rings, such as from user to kernel
+  uint esp;
+  ushort ss;
+  ushort padding6;
+};
+
+#endif  // INCLUDE_ASM_X86_h_
diff --git a/include/elf.h b/include/elf.h
new file mode 100644 (file)
index 0000000..3047821
--- /dev/null
@@ -0,0 +1,46 @@
+// Format of an ELF executable file
+#ifndef INCLUDE_ELF_h_
+#define INCLUDE_ELF_h_
+
+#define ELF_MAGIC 0x464C457FU  // "\x7FELF" in little endian
+
+// File header
+struct elfhdr {
+  uint magic;  // must equal ELF_MAGIC
+  uchar elf[12];
+  ushort type;
+  ushort machine;
+  uint version;
+  uint entry;
+  uint phoff;
+  uint shoff;
+  uint flags;
+  ushort ehsize;
+  ushort phentsize;
+  ushort phnum;
+  ushort shentsize;
+  ushort shnum;
+  ushort shstrndx;
+};
+
+// Program section header
+struct proghdr {
+  uint type;
+  uint off;
+  uint vaddr;
+  uint paddr;
+  uint filesz;
+  uint memsz;
+  uint flags;
+  uint align;
+};
+
+// Values for Proghdr type
+#define ELF_PROG_LOAD           1
+
+// Flag bits for Proghdr flags
+#define ELF_PROG_FLAG_EXEC      1
+#define ELF_PROG_FLAG_WRITE     2
+#define ELF_PROG_FLAG_READ      4
+
+#endif  // INCLUDE_ELF_h_
diff --git a/include/fcntl.h b/include/fcntl.h
new file mode 100644 (file)
index 0000000..2f2f5b6
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef INCLUDE_FCNTL_h_
+#define INCLUDE_FCNTL_h_
+
+#define O_RDONLY  0x000
+#define O_WRONLY  0x001
+#define O_RDWR    0x002
+#define O_CREATE  0x200
+
+#endif  // INCLUDE_FCNTL_h_
diff --git a/include/fs.h b/include/fs.h
new file mode 100644 (file)
index 0000000..3214f1d
--- /dev/null
@@ -0,0 +1,57 @@
+// On-disk file system format.
+// Both the kernel and user programs use this header file.
+
+
+#define ROOTINO 1  // root i-number
+#define BSIZE 512  // block size
+
+// Disk layout:
+// [ boot block | super block | log | inode blocks |
+//                                          free bit map | data blocks]
+//
+// mkfs computes the super block and builds an initial file system. The
+// super block describes the disk layout:
+struct superblock {
+  uint size;         // Size of file system image (blocks)
+  uint nblocks;      // Number of data blocks
+  uint ninodes;      // Number of inodes.
+  uint nlog;         // Number of log blocks
+  uint logstart;     // Block number of first log block
+  uint inodestart;   // Block number of first inode block
+  uint bmapstart;    // Block number of first free map block
+};
+
+#define NDIRECT 12
+#define NINDIRECT (BSIZE / sizeof(uint))
+#define MAXFILE (NDIRECT + NINDIRECT)
+
+// On-disk inode structure
+struct dinode {
+  short type;           // File type
+  short major;          // Major device number (T_DEV only)
+  short minor;          // Minor device number (T_DEV only)
+  short nlink;          // Number of links to inode in file system
+  uint size;            // Size of file (bytes)
+  uint addrs[NDIRECT+1];   // Data block addresses
+};
+
+// Inodes per block.
+#define IPB           (BSIZE / sizeof(struct dinode))
+
+// Block containing inode i
+#define IBLOCK(i, sb)     ((i) / IPB + sb.inodestart)
+
+// Bitmap bits per block
+#define BPB           (BSIZE*8)
+
+// Block of free map containing bit for block b
+#define BBLOCK(b, sb) (b/BPB + sb.bmapstart)
+
+// Directory is a file containing a sequence of dirent structures.
+#define DIRSIZ 14
+
+struct dirent {
+  ushort inum;
+  char name[DIRSIZ];
+};
+
diff --git a/include/memlayout.h b/include/memlayout.h
new file mode 100644 (file)
index 0000000..bd57410
--- /dev/null
@@ -0,0 +1,19 @@
+// Memory layout
+#ifndef INCLUDE_MEMLAYOUT_h_
+#define INCLUDE_MEMLAYOUT_h_
+
+#define EXTMEM  0x100000            // Start of extended memory
+#define PHYSTOP 0xE000000           // Top physical memory
+#define DEVSPACE 0xFE000000         // Other devices are at high addresses
+
+// Key addresses for address space layout (see kmap in vm.c for layout)
+#define KERNBASE 0x80000000         // First kernel virtual address
+#define KERNLINK (KERNBASE+EXTMEM)  // Address where kernel is linked
+
+#define V2P(a) (((uint) (a)) - KERNBASE)
+#define P2V(a) ((void *)(((char *) (a)) + KERNBASE))
+
+#define V2P_WO(x) ((x) - KERNBASE)    // same as V2P, but without casts
+#define P2V_WO(x) ((x) + KERNBASE)    // same as P2V, but without casts
+
+#endif  // INCLUDE_MEMLAYOUT_h_
diff --git a/include/mmu.h b/include/mmu.h
new file mode 100644 (file)
index 0000000..96900aa
--- /dev/null
@@ -0,0 +1,185 @@
+// This file contains definitions for the
+// x86 memory management unit (MMU).
+#ifndef INCLUDE_MMU_h_
+#define INCLUDE_MMU_h_
+
+// Eflags register
+#define FL_IF           0x00000200      // Interrupt Enable
+
+// Control Register flags
+#define CR0_PE          0x00000001      // Protection Enable
+#define CR0_WP          0x00010000      // Write Protect
+#define CR0_PG          0x80000000      // Paging
+
+#define CR4_PSE         0x00000010      // Page size extension
+
+// various segment selectors.
+#define SEG_KCODE 1  // kernel code
+#define SEG_KDATA 2  // kernel data+stack
+#define SEG_UCODE 3  // user code
+#define SEG_UDATA 4  // user data+stack
+#define SEG_TSS   5  // this process's task state
+
+// cpu->gdt[NSEGS] holds the above segments.
+#define NSEGS     6
+
+#ifndef __ASSEMBLER__
+// Segment Descriptor
+struct segdesc {
+  uint lim_15_0 : 16;  // Low bits of segment limit
+  uint base_15_0 : 16; // Low 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 s : 1;          // 0 = system, 1 = application
+  uint dpl : 2;        // Descriptor Privilege Level
+  uint p : 1;          // Present
+  uint lim_19_16 : 4;  // High bits of segment limit
+  uint avl : 1;        // Unused (available for software use)
+  uint rsv1 : 1;       // Reserved
+  uint db : 1;         // 0 = 16-bit segment, 1 = 32-bit segment
+  uint g : 1;          // Granularity: limit scaled by 4K when set
+  uint base_31_24 : 8; // High bits of segment base address
+};
+
+// Normal segment
+#define SEG(type, base, lim, dpl) (struct segdesc)    \
+{ ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff,      \
+  ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1,       \
+  (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 }
+#define SEG16(type, base, lim, dpl) (struct segdesc)  \
+{ (lim) & 0xffff, (uint)(base) & 0xffff,              \
+  ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1,       \
+  (uint)(lim) >> 16, 0, 0, 1, 0, (uint)(base) >> 24 }
+#endif
+
+#define DPL_USER    0x3     // User DPL
+
+// Application segment type bits
+#define STA_X       0x8     // Executable segment
+#define STA_W       0x2     // Writeable (non-executable segments)
+#define STA_R       0x2     // Readable (executable segments)
+
+// System segment type bits
+#define STS_T32A    0x9     // Available 32-bit TSS
+#define STS_IG32    0xE     // 32-bit Interrupt Gate
+#define STS_TG32    0xF     // 32-bit Trap Gate
+
+// A virtual address 'la' has a three-part structure as follows:
+//
+// +--------10------+-------10-------+---------12----------+
+// | Page Directory |   Page Table   | Offset within Page  |
+// |      Index     |      Index     |                     |
+// +----------------+----------------+---------------------+
+//  \--- PDX(va) --/ \--- PTX(va) --/
+
+// page directory index
+#define PDX(va)         (((uint)(va) >> PDXSHIFT) & 0x3FF)
+
+// page table index
+#define PTX(va)         (((uint)(va) >> PTXSHIFT) & 0x3FF)
+
+// construct virtual address from indexes and offset
+#define PGADDR(d, t, o) ((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))
+
+// Page directory and page table constants.
+#define NPDENTRIES      1024    // # directory entries per page directory
+#define NPTENTRIES      1024    // # PTEs per page table
+#define PGSIZE          4096    // bytes mapped by a page
+
+#define PTXSHIFT        12      // offset of PTX in a linear address
+#define PDXSHIFT        22      // offset of PDX in a linear address
+
+#define PGROUNDUP(sz)  (((sz)+PGSIZE-1) & ~(PGSIZE-1))
+#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))
+
+// Page table/directory entry flags.
+#define PTE_P           0x001   // Present
+#define PTE_W           0x002   // Writeable
+#define PTE_U           0x004   // User
+#define PTE_PS          0x080   // Page Size
+
+// Address in page table or page directory entry
+#define PTE_ADDR(pte)   ((uint)(pte) & ~0xFFF)
+#define PTE_FLAGS(pte)  ((uint)(pte) &  0xFFF)
+
+#ifndef __ASSEMBLER__
+typedef uint pte_t;
+
+// Task state segment format
+struct taskstate {
+  uint link;         // Old ts selector
+  uint esp0;         // Stack pointers and segment selectors
+  ushort ss0;        //   after an increase in privilege level
+  ushort padding1;
+  uint *esp1;
+  ushort ss1;
+  ushort padding2;
+  uint *esp2;
+  ushort ss2;
+  ushort padding3;
+  void *cr3;         // Page directory base
+  uint *eip;         // Saved state from last task switch
+  uint eflags;
+  uint eax;          // More saved state (registers)
+  uint ecx;
+  uint edx;
+  uint ebx;
+  uint *esp;
+  uint *ebp;
+  uint esi;
+  uint edi;
+  ushort es;         // Even more saved state (segment selectors)
+  ushort padding4;
+  ushort cs;
+  ushort padding5;
+  ushort ss;
+  ushort padding6;
+  ushort ds;
+  ushort padding7;
+  ushort fs;
+  ushort padding8;
+  ushort gs;
+  ushort padding9;
+  ushort ldt;
+  ushort padding10;
+  ushort t;          // Trap on task switch
+  ushort iomb;       // I/O map base address
+};
+
+// Gate descriptors for interrupts and traps
+struct gatedesc {
+  uint off_15_0 : 16;   // low 16 bits of offset in segment
+  uint cs : 16;         // code segment selector
+  uint args : 5;        // # args, 0 for interrupt/trap gates
+  uint rsv1 : 3;        // reserved(should be zero I guess)
+  uint type : 4;        // type(STS_{IG32,TG32})
+  uint s : 1;           // must be 0 (system)
+  uint dpl : 2;         // descriptor(meaning new) privilege level
+  uint p : 1;           // Present
+  uint off_31_16 : 16;  // high bits of offset in segment
+};
+
+// Set up a normal interrupt/trap gate descriptor.
+// - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
+//   interrupt gate clears FL_IF, trap gate leaves FL_IF alone
+// - sel: Code segment selector for interrupt/trap handler
+// - off: Offset in code segment for interrupt/trap handler
+// - dpl: Descriptor Privilege Level -
+//        the privilege level required for software to invoke
+//        this interrupt/trap gate explicitly using an int instruction.
+#define SETGATE(gate, istrap, sel, off, d)                \
+{                                                         \
+  (gate).off_15_0 = (uint)(off) & 0xffff;                \
+  (gate).cs = (sel);                                      \
+  (gate).args = 0;                                        \
+  (gate).rsv1 = 0;                                        \
+  (gate).type = (istrap) ? STS_TG32 : STS_IG32;           \
+  (gate).s = 0;                                           \
+  (gate).dpl = (d);                                       \
+  (gate).p = 1;                                           \
+  (gate).off_31_16 = (uint)(off) >> 16;                  \
+}
+
+#endif
+
+#endif  // INCLUDE_MMU_h_
diff --git a/include/param.h b/include/param.h
new file mode 100644 (file)
index 0000000..4502792
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef INCLUDE_PARAM_h_
+#define INCLUDE_PARAM_h_
+
+#define NPROC        64  // maximum number of processes
+#define KSTACKSIZE 4096  // size of per-process kernel stack
+#define NCPU          8  // maximum number of CPUs
+#define NOFILE       16  // open files per process
+#define NFILE       100  // open files per system
+#define NINODE       50  // maximum number of active i-nodes
+#define NDEV         10  // maximum major device number
+#define ROOTDEV       1  // device number of file system root disk
+#define MAXARG       32  // max exec arguments
+#define MAXOPBLOCKS  10  // max # of blocks any FS op writes
+#define LOGSIZE      (MAXOPBLOCKS*3)  // max data blocks in on-disk log
+#define NBUF         (MAXOPBLOCKS*3)  // size of disk block cache
+#define FSSIZE       1000  // size of file system in blocks
+
+#endif  // INCLUDE_PARAM_h_
diff --git a/include/stat.h b/include/stat.h
new file mode 100644 (file)
index 0000000..2bee692
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef INCLUDE_STAT_h_
+#define INCLUDE_STAT_h_
+
+#define T_DIR  1   // Directory
+#define T_FILE 2   // File
+#define T_DEV  3   // Device
+
+struct stat {
+  short type;  // Type of file
+  int dev;     // File system's disk device
+  uint ino;    // Inode number
+  short nlink; // Number of links to file
+  uint size;   // Size of file in bytes
+};
+
+#endif  // INCLUDE_STAT_h_
diff --git a/include/syscall.h b/include/syscall.h
new file mode 100644 (file)
index 0000000..bc5f356
--- /dev/null
@@ -0,0 +1,22 @@
+// System call numbers
+#define SYS_fork    1
+#define SYS_exit    2
+#define SYS_wait    3
+#define SYS_pipe    4
+#define SYS_read    5
+#define SYS_kill    6
+#define SYS_exec    7
+#define SYS_fstat   8
+#define SYS_chdir   9
+#define SYS_dup    10
+#define SYS_getpid 11
+#define SYS_sbrk   12
+#define SYS_sleep  13
+#define SYS_uptime 14
+#define SYS_open   15
+#define SYS_write  16
+#define SYS_mknod  17
+#define SYS_unlink 18
+#define SYS_link   19
+#define SYS_mkdir  20
+#define SYS_close  21
diff --git a/include/traps.h b/include/traps.h
new file mode 100644 (file)
index 0000000..0bd1fd8
--- /dev/null
@@ -0,0 +1,38 @@
+// x86 trap and interrupt constants.
+
+// Processor-defined:
+#define T_DIVIDE         0      // divide error
+#define T_DEBUG          1      // debug exception
+#define T_NMI            2      // non-maskable interrupt
+#define T_BRKPT          3      // breakpoint
+#define T_OFLOW          4      // overflow
+#define T_BOUND          5      // bounds check
+#define T_ILLOP          6      // illegal opcode
+#define T_DEVICE         7      // device not available
+#define T_DBLFLT         8      // double fault
+// #define T_COPROC      9      // reserved (not used since 486)
+#define T_TSS           10      // invalid task switch segment
+#define T_SEGNP         11      // segment not present
+#define T_STACK         12      // stack exception
+#define T_GPFLT         13      // general protection fault
+#define T_PGFLT         14      // page fault
+// #define T_RES        15      // reserved
+#define T_FPERR         16      // floating point error
+#define T_ALIGN         17      // aligment check
+#define T_MCHK          18      // machine check
+#define T_SIMDERR       19      // SIMD floating point error
+
+// These are arbitrarily chosen, but with care not to overlap
+// processor defined exceptions or interrupt vectors.
+#define T_SYSCALL       64      // system call
+#define T_DEFAULT      500      // catchall
+
+#define T_IRQ0          32      // IRQ 0 corresponds to int T_IRQ
+
+#define IRQ_TIMER        0
+#define IRQ_KBD          1
+#define IRQ_COM1         4
+#define IRQ_IDE         14
+#define IRQ_ERROR       19
+#define IRQ_SPURIOUS    31
+
diff --git a/include/types.h b/include/types.h
new file mode 100644 (file)
index 0000000..97bff57
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef INCLUDE_TYPES_h_
+#define INCLUDE_TYPES_h_
+
+typedef unsigned int   uint;
+typedef unsigned short ushort;
+typedef unsigned char  uchar;
+typedef uint pde_t;
+
+#endif  //INCLUDE_TYPES_h_
diff --git a/init.c b/init.c
deleted file mode 100644 (file)
index 046b551..0000000
--- a/init.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// init: The initial user-level program
-
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-#include "fcntl.h"
-
-char *argv[] = { "sh", 0 };
-
-int
-main(void)
-{
-  int pid, wpid;
-
-  if(open("console", O_RDWR) < 0){
-    mknod("console", 1, 1);
-    open("console", O_RDWR);
-  }
-  dup(0);  // stdout
-  dup(0);  // stderr
-
-  for(;;){
-    printf(1, "init: starting sh\n");
-    pid = fork();
-    if(pid < 0){
-      printf(1, "init: fork failed\n");
-      exit();
-    }
-    if(pid == 0){
-      exec("sh", argv);
-      printf(1, "init: exec sh failed\n");
-      exit();
-    }
-    while((wpid=wait()) >= 0 && wpid != pid)
-      printf(1, "zombie!\n");
-  }
-}
diff --git a/initcode.S b/initcode.S
deleted file mode 100644 (file)
index 80ac5d8..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# Initial process execs /init.
-# This code runs in user space.
-
-#include "syscall.h"
-#include "traps.h"
-
-
-# exec(init, argv)
-.globl start
-start:
-  pushl $argv
-  pushl $init
-  pushl $0  // where caller pc would be
-  movl $SYS_exec, %eax
-  int $T_SYSCALL
-
-# for(;;) exit();
-exit:
-  movl $SYS_exit, %eax
-  int $T_SYSCALL
-  jmp exit
-
-# char init[] = "/init\0";
-init:
-  .string "/init\0"
-
-# char *argv[] = { init, 0 };
-.p2align 2
-argv:
-  .long init
-  .long 0
-
diff --git a/ioapic.c b/ioapic.c
deleted file mode 100644 (file)
index cb0f015..0000000
--- a/ioapic.c
+++ /dev/null
@@ -1,75 +0,0 @@
-// The I/O APIC manages hardware interrupts for an SMP system.
-// http://www.intel.com/design/chipsets/datashts/29056601.pdf
-// See also picirq.c.
-
-#include "types.h"
-#include "defs.h"
-#include "traps.h"
-
-#define IOAPIC  0xFEC00000   // Default physical address of IO APIC
-
-#define REG_ID     0x00  // Register index: ID
-#define REG_VER    0x01  // Register index: version
-#define REG_TABLE  0x10  // Redirection table base
-
-// The redirection table starts at REG_TABLE and uses
-// two registers to configure each interrupt.
-// The first (low) register in a pair contains configuration bits.
-// The second (high) register contains a bitmask telling which
-// CPUs can serve that interrupt.
-#define INT_DISABLED   0x00010000  // Interrupt disabled
-#define INT_LEVEL      0x00008000  // Level-triggered (vs edge-)
-#define INT_ACTIVELOW  0x00002000  // Active low (vs high)
-#define INT_LOGICAL    0x00000800  // Destination is CPU id (vs APIC ID)
-
-volatile struct ioapic *ioapic;
-
-// IO APIC MMIO structure: write reg, then read or write data.
-struct ioapic {
-  uint reg;
-  uint pad[3];
-  uint data;
-};
-
-static uint
-ioapicread(int reg)
-{
-  ioapic->reg = reg;
-  return ioapic->data;
-}
-
-static void
-ioapicwrite(int reg, uint data)
-{
-  ioapic->reg = reg;
-  ioapic->data = data;
-}
-
-void
-ioapicinit(void)
-{
-  int i, id, maxintr;
-
-  ioapic = (volatile struct ioapic*)IOAPIC;
-  maxintr = (ioapicread(REG_VER) >> 16) & 0xFF;
-  id = ioapicread(REG_ID) >> 24;
-  if(id != ioapicid)
-    cprintf("ioapicinit: id isn't equal to ioapicid; not a MP\n");
-
-  // Mark all interrupts edge-triggered, active high, disabled,
-  // and not routed to any CPUs.
-  for(i = 0; i <= maxintr; i++){
-    ioapicwrite(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i));
-    ioapicwrite(REG_TABLE+2*i+1, 0);
-  }
-}
-
-void
-ioapicenable(int irq, int cpunum)
-{
-  // Mark interrupt edge-triggered, active high,
-  // enabled, and routed to the given cpunum,
-  // which happens to be that cpu's APIC ID.
-  ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq);
-  ioapicwrite(REG_TABLE+2*irq+1, cpunum << 24);
-}
diff --git a/kalloc.c b/kalloc.c
deleted file mode 100644 (file)
index 14cd4f4..0000000
--- a/kalloc.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// Physical memory allocator, intended to allocate
-// memory for user processes, kernel stacks, page table pages,
-// and pipe buffers. Allocates 4096-byte pages.
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "spinlock.h"
-
-void freerange(void *vstart, void *vend);
-extern char end[]; // first address after kernel loaded from ELF file
-                   // defined by the kernel linker script in kernel.ld
-
-struct run {
-  struct run *next;
-};
-
-struct {
-  struct spinlock lock;
-  int use_lock;
-  struct run *freelist;
-} kmem;
-
-// Initialization happens in two phases.
-// 1. main() calls kinit1() while still using entrypgdir to place just
-// the pages mapped by entrypgdir on free list.
-// 2. main() calls kinit2() with the rest of the physical pages
-// after installing a full page table that maps them on all cores.
-void
-kinit1(void *vstart, void *vend)
-{
-  initlock(&kmem.lock, "kmem");
-  kmem.use_lock = 0;
-  freerange(vstart, vend);
-}
-
-void
-kinit2(void *vstart, void *vend)
-{
-  freerange(vstart, vend);
-  kmem.use_lock = 1;
-}
-
-void
-freerange(void *vstart, void *vend)
-{
-  char *p;
-  p = (char*)PGROUNDUP((uint)vstart);
-  for(; p + PGSIZE <= (char*)vend; p += PGSIZE)
-    kfree(p);
-}
-//PAGEBREAK: 21
-// Free the page of physical memory pointed at by v,
-// which normally should have been returned by a
-// call to kalloc().  (The exception is when
-// initializing the allocator; see kinit above.)
-void
-kfree(char *v)
-{
-  struct run *r;
-
-  if((uint)v % PGSIZE || v < end || V2P(v) >= PHYSTOP)
-    panic("kfree");
-
-  // Fill with junk to catch dangling refs.
-  memset(v, 1, PGSIZE);
-
-  if(kmem.use_lock)
-    acquire(&kmem.lock);
-  r = (struct run*)v;
-  r->next = kmem.freelist;
-  kmem.freelist = r;
-  if(kmem.use_lock)
-    release(&kmem.lock);
-}
-
-// Allocate one 4096-byte page of physical memory.
-// Returns a pointer that the kernel can use.
-// Returns 0 if the memory cannot be allocated.
-char*
-kalloc(void)
-{
-  struct run *r;
-
-  if(kmem.use_lock)
-    acquire(&kmem.lock);
-  r = kmem.freelist;
-  if(r)
-    kmem.freelist = r->next;
-  if(kmem.use_lock)
-    release(&kmem.lock);
-  return (char*)r;
-}
-
diff --git a/kbd.c b/kbd.c
deleted file mode 100644 (file)
index 32c1463..0000000
--- a/kbd.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "types.h"
-#include "x86.h"
-#include "defs.h"
-#include "kbd.h"
-
-int
-kbdgetc(void)
-{
-  static uint shift;
-  static uchar *charcode[4] = {
-    normalmap, shiftmap, ctlmap, ctlmap
-  };
-  uint st, data, c;
-
-  st = inb(KBSTATP);
-  if((st & KBS_DIB) == 0)
-    return -1;
-  data = inb(KBDATAP);
-
-  if(data == 0xE0){
-    shift |= E0ESC;
-    return 0;
-  } else if(data & 0x80){
-    // Key released
-    data = (shift & E0ESC ? data : data & 0x7F);
-    shift &= ~(shiftcode[data] | E0ESC);
-    return 0;
-  } 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';
-  }
-  return c;
-}
-
-void
-kbdintr(void)
-{
-  consoleintr(kbdgetc);
-}
diff --git a/kbd.h b/kbd.h
deleted file mode 100644 (file)
index babbd6e..0000000
--- a/kbd.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// PC keyboard interface constants
-
-#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
-
-// C('A') == Control-A
-#define C(x) (x - '@')
-
-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
-  [0x9C] '\n',      // KP_Enter
-  [0xB5] '/',       // KP_Div
-  [0xC8] KEY_UP,    [0xD0] KEY_DN,
-  [0xC9] KEY_PGUP,  [0xD1] KEY_PGDN,
-  [0xCB] KEY_LF,    [0xCD] KEY_RT,
-  [0x97] KEY_HOME,  [0xCF] KEY_END,
-  [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
-  [0x9C] '\n',      // KP_Enter
-  [0xB5] '/',       // KP_Div
-  [0xC8] KEY_UP,    [0xD0] KEY_DN,
-  [0xC9] KEY_PGUP,  [0xD1] KEY_PGDN,
-  [0xCB] KEY_LF,    [0xCD] KEY_RT,
-  [0x97] KEY_HOME,  [0xCF] KEY_END,
-  [0xD2] KEY_INS,   [0xD3] KEY_DEL
-};
-
-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,
-  [0x9C] '\r',      // KP_Enter
-  [0xB5] C('/'),    // KP_Div
-  [0xC8] KEY_UP,    [0xD0] KEY_DN,
-  [0xC9] KEY_PGUP,  [0xD1] KEY_PGDN,
-  [0xCB] KEY_LF,    [0xCD] KEY_RT,
-  [0x97] KEY_HOME,  [0xCF] KEY_END,
-  [0xD2] KEY_INS,   [0xD3] KEY_DEL
-};
-
diff --git a/kernel.ld b/kernel.ld
deleted file mode 100644 (file)
index e24c860..0000000
--- a/kernel.ld
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Simple linker script for the JOS kernel.
-   See the GNU ld 'info' manual ("info ld") to learn the syntax. */
-
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-
-SECTIONS
-{
-       /* Link the kernel at this address: "." means the current address */
-        /* Must be equal to KERNLINK */
-       . = 0x80100000;
-
-       .text : AT(0x100000) {
-               *(.text .stub .text.* .gnu.linkonce.t.*)
-       }
-
-       PROVIDE(etext = .);     /* Define the 'etext' symbol to this value */
-
-       .rodata : {
-               *(.rodata .rodata.* .gnu.linkonce.r.*)
-       }
-
-       /* Include debugging information in kernel memory */
-       .stab : {
-               PROVIDE(__STAB_BEGIN__ = .);
-               *(.stab);
-               PROVIDE(__STAB_END__ = .);
-               BYTE(0)         /* Force the linker to allocate space
-                                  for this section */
-       }
-
-       .stabstr : {
-               PROVIDE(__STABSTR_BEGIN__ = .);
-               *(.stabstr);
-               PROVIDE(__STABSTR_END__ = .);
-               BYTE(0)         /* Force the linker to allocate space
-                                  for this section */
-       }
-
-       /* Adjust the address for the data segment to the next page */
-       . = ALIGN(0x1000);
-
-       /* Conventionally, Unix linkers provide pseudo-symbols
-        * etext, edata, and end, at the end of the text, data, and bss.
-        * For the kernel mapping, we need the address at the beginning
-        * of the data section, but that's not one of the conventional
-        * symbols, because the convention started before there was a
-        * read-only rodata section between text and data. */
-       PROVIDE(data = .);
-
-       /* The data segment */
-       .data : {
-               *(.data)
-       }
-
-       PROVIDE(edata = .);
-
-       .bss : {
-               *(.bss)
-       }
-
-       PROVIDE(end = .);
-
-       /DISCARD/ : {
-               *(.eh_frame .note.GNU-stack)
-       }
-}
diff --git a/kill.c b/kill.c
deleted file mode 100644 (file)
index 364f6af..0000000
--- a/kill.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-int
-main(int argc, char **argv)
-{
-  int i;
-
-  if(argc < 2){
-    printf(2, "usage: kill pid...\n");
-    exit();
-  }
-  for(i=1; i<argc; i++)
-    kill(atoi(argv[i]));
-  exit();
-}
diff --git a/lapic.c b/lapic.c
deleted file mode 100644 (file)
index b22bbd7..0000000
--- a/lapic.c
+++ /dev/null
@@ -1,229 +0,0 @@
-// The local APIC manages internal (non-I/O) interrupts.
-// See Chapter 8 & Appendix C of Intel processor manual volume 3.
-
-#include "param.h"
-#include "types.h"
-#include "defs.h"
-#include "date.h"
-#include "memlayout.h"
-#include "traps.h"
-#include "mmu.h"
-#include "x86.h"
-
-// Local APIC registers, divided by 4 for use as uint[] indices.
-#define ID      (0x0020/4)   // ID
-#define VER     (0x0030/4)   // Version
-#define TPR     (0x0080/4)   // Task Priority
-#define EOI     (0x00B0/4)   // EOI
-#define SVR     (0x00F0/4)   // Spurious Interrupt Vector
-  #define ENABLE     0x00000100   // Unit Enable
-#define ESR     (0x0280/4)   // Error Status
-#define ICRLO   (0x0300/4)   // Interrupt Command
-  #define INIT       0x00000500   // INIT/RESET
-  #define STARTUP    0x00000600   // Startup IPI
-  #define DELIVS     0x00001000   // Delivery status
-  #define ASSERT     0x00004000   // Assert interrupt (vs deassert)
-  #define DEASSERT   0x00000000
-  #define LEVEL      0x00008000   // Level triggered
-  #define BCAST      0x00080000   // Send to all APICs, including self.
-  #define BUSY       0x00001000
-  #define FIXED      0x00000000
-#define ICRHI   (0x0310/4)   // Interrupt Command [63:32]
-#define TIMER   (0x0320/4)   // Local Vector Table 0 (TIMER)
-  #define X1         0x0000000B   // divide counts by 1
-  #define PERIODIC   0x00020000   // Periodic
-#define PCINT   (0x0340/4)   // Performance Counter LVT
-#define LINT0   (0x0350/4)   // Local Vector Table 1 (LINT0)
-#define LINT1   (0x0360/4)   // Local Vector Table 2 (LINT1)
-#define ERROR   (0x0370/4)   // Local Vector Table 3 (ERROR)
-  #define MASKED     0x00010000   // Interrupt masked
-#define TICR    (0x0380/4)   // Timer Initial Count
-#define TCCR    (0x0390/4)   // Timer Current Count
-#define TDCR    (0x03E0/4)   // Timer Divide Configuration
-
-volatile uint *lapic;  // Initialized in mp.c
-
-//PAGEBREAK!
-static void
-lapicw(int index, int value)
-{
-  lapic[index] = value;
-  lapic[ID];  // wait for write to finish, by reading
-}
-
-void
-lapicinit(void)
-{
-  if(!lapic)
-    return;
-
-  // Enable local APIC; set spurious interrupt vector.
-  lapicw(SVR, ENABLE | (T_IRQ0 + IRQ_SPURIOUS));
-
-  // The timer repeatedly counts down at bus frequency
-  // from lapic[TICR] and then issues an interrupt.
-  // If xv6 cared more about precise timekeeping,
-  // TICR would be calibrated using an external time source.
-  lapicw(TDCR, X1);
-  lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
-  lapicw(TICR, 10000000);
-
-  // Disable logical interrupt lines.
-  lapicw(LINT0, MASKED);
-  lapicw(LINT1, MASKED);
-
-  // Disable performance counter overflow interrupts
-  // on machines that provide that interrupt entry.
-  if(((lapic[VER]>>16) & 0xFF) >= 4)
-    lapicw(PCINT, MASKED);
-
-  // Map error interrupt to IRQ_ERROR.
-  lapicw(ERROR, T_IRQ0 + IRQ_ERROR);
-
-  // Clear error status register (requires back-to-back writes).
-  lapicw(ESR, 0);
-  lapicw(ESR, 0);
-
-  // Ack any outstanding interrupts.
-  lapicw(EOI, 0);
-
-  // Send an Init Level De-Assert to synchronise arbitration ID's.
-  lapicw(ICRHI, 0);
-  lapicw(ICRLO, BCAST | INIT | LEVEL);
-  while(lapic[ICRLO] & DELIVS)
-    ;
-
-  // Enable interrupts on the APIC (but not on the processor).
-  lapicw(TPR, 0);
-}
-
-int
-lapicid(void)
-{
-  if (!lapic)
-    return 0;
-  return lapic[ID] >> 24;
-}
-
-// Acknowledge interrupt.
-void
-lapiceoi(void)
-{
-  if(lapic)
-    lapicw(EOI, 0);
-}
-
-// Spin for a given number of microseconds.
-// On real hardware would want to tune this dynamically.
-void
-microdelay(int us)
-{
-}
-
-#define CMOS_PORT    0x70
-#define CMOS_RETURN  0x71
-
-// Start additional processor running entry code at addr.
-// See Appendix B of MultiProcessor Specification.
-void
-lapicstartap(uchar apicid, uint addr)
-{
-  int i;
-  ushort *wrv;
-
-  // "The BSP must initialize CMOS shutdown code to 0AH
-  // and the warm reset vector (DWORD based at 40:67) to point at
-  // the AP startup code prior to the [universal startup algorithm]."
-  outb(CMOS_PORT, 0xF);  // offset 0xF is shutdown code
-  outb(CMOS_PORT+1, 0x0A);
-  wrv = (ushort*)P2V((0x40<<4 | 0x67));  // Warm reset vector
-  wrv[0] = 0;
-  wrv[1] = addr >> 4;
-
-  // "Universal startup algorithm."
-  // Send INIT (level-triggered) interrupt to reset other CPU.
-  lapicw(ICRHI, apicid<<24);
-  lapicw(ICRLO, INIT | LEVEL | ASSERT);
-  microdelay(200);
-  lapicw(ICRLO, INIT | LEVEL);
-  microdelay(100);    // should be 10ms, but too slow in Bochs!
-
-  // Send startup IPI (twice!) to enter code.
-  // Regular hardware is supposed to only accept a STARTUP
-  // when it is in the halted state due to an INIT.  So the second
-  // should be ignored, but it is part of the official Intel algorithm.
-  // Bochs complains about the second one.  Too bad for Bochs.
-  for(i = 0; i < 2; i++){
-    lapicw(ICRHI, apicid<<24);
-    lapicw(ICRLO, STARTUP | (addr>>12));
-    microdelay(200);
-  }
-}
-
-#define CMOS_STATA   0x0a
-#define CMOS_STATB   0x0b
-#define CMOS_UIP    (1 << 7)        // RTC update in progress
-
-#define SECS    0x00
-#define MINS    0x02
-#define HOURS   0x04
-#define DAY     0x07
-#define MONTH   0x08
-#define YEAR    0x09
-
-static uint
-cmos_read(uint reg)
-{
-  outb(CMOS_PORT,  reg);
-  microdelay(200);
-
-  return inb(CMOS_RETURN);
-}
-
-static void
-fill_rtcdate(struct rtcdate *r)
-{
-  r->second = cmos_read(SECS);
-  r->minute = cmos_read(MINS);
-  r->hour   = cmos_read(HOURS);
-  r->day    = cmos_read(DAY);
-  r->month  = cmos_read(MONTH);
-  r->year   = cmos_read(YEAR);
-}
-
-// qemu seems to use 24-hour GWT and the values are BCD encoded
-void
-cmostime(struct rtcdate *r)
-{
-  struct rtcdate t1, t2;
-  int sb, bcd;
-
-  sb = cmos_read(CMOS_STATB);
-
-  bcd = (sb & (1 << 2)) == 0;
-
-  // make sure CMOS doesn't modify time while we read it
-  for(;;) {
-    fill_rtcdate(&t1);
-    if(cmos_read(CMOS_STATA) & CMOS_UIP)
-        continue;
-    fill_rtcdate(&t2);
-    if(memcmp(&t1, &t2, sizeof(t1)) == 0)
-      break;
-  }
-
-  // convert
-  if(bcd) {
-#define    CONV(x)     (t1.x = ((t1.x >> 4) * 10) + (t1.x & 0xf))
-    CONV(second);
-    CONV(minute);
-    CONV(hour  );
-    CONV(day   );
-    CONV(month );
-    CONV(year  );
-#undef     CONV
-  }
-
-  *r = t1;
-  r->year += 2000;
-}
diff --git a/ln.c b/ln.c
deleted file mode 100644 (file)
index cf8a64e..0000000
--- a/ln.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-int
-main(int argc, char *argv[])
-{
-  if(argc != 3){
-    printf(2, "Usage: ln old new\n");
-    exit();
-  }
-  if(link(argv[1], argv[2]) < 0)
-    printf(2, "link %s %s: failed\n", argv[1], argv[2]);
-  exit();
-}
diff --git a/log.c b/log.c
deleted file mode 100644 (file)
index a64c0f6..0000000
--- a/log.c
+++ /dev/null
@@ -1,234 +0,0 @@
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "fs.h"
-#include "buf.h"
-
-// Simple logging that allows concurrent FS system calls.
-//
-// A log transaction contains the updates of multiple FS system
-// calls. The logging system only commits when there are
-// no FS system calls active. Thus there is never
-// any reasoning required about whether a commit might
-// write an uncommitted system call's updates to disk.
-//
-// A system call should call begin_op()/end_op() to mark
-// its start and end. Usually begin_op() just increments
-// the count of in-progress FS system calls and returns.
-// But if it thinks the log is close to running out, it
-// sleeps until the last outstanding end_op() commits.
-//
-// The log is a physical re-do log containing disk blocks.
-// The on-disk log format:
-//   header block, containing block #s for block A, B, C, ...
-//   block A
-//   block B
-//   block C
-//   ...
-// Log appends are synchronous.
-
-// Contents of the header block, used for both the on-disk header block
-// and to keep track in memory of logged block# before commit.
-struct logheader {
-  int n;
-  int block[LOGSIZE];
-};
-
-struct log {
-  struct spinlock lock;
-  int start;
-  int size;
-  int outstanding; // how many FS sys calls are executing.
-  int committing;  // in commit(), please wait.
-  int dev;
-  struct logheader lh;
-};
-struct log log;
-
-static void recover_from_log(void);
-static void commit();
-
-void
-initlog(int dev)
-{
-  if (sizeof(struct logheader) >= BSIZE)
-    panic("initlog: too big logheader");
-
-  struct superblock sb;
-  initlock(&log.lock, "log");
-  readsb(dev, &sb);
-  log.start = sb.logstart;
-  log.size = sb.nlog;
-  log.dev = dev;
-  recover_from_log();
-}
-
-// Copy committed blocks from log to their home location
-static void
-install_trans(void)
-{
-  int tail;
-
-  for (tail = 0; tail < log.lh.n; tail++) {
-    struct buf *lbuf = bread(log.dev, log.start+tail+1); // read log block
-    struct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst
-    memmove(dbuf->data, lbuf->data, BSIZE);  // copy block to dst
-    bwrite(dbuf);  // write dst to disk
-    brelse(lbuf);
-    brelse(dbuf);
-  }
-}
-
-// Read the log header from disk into the in-memory log header
-static void
-read_head(void)
-{
-  struct buf *buf = bread(log.dev, log.start);
-  struct logheader *lh = (struct logheader *) (buf->data);
-  int i;
-  log.lh.n = lh->n;
-  for (i = 0; i < log.lh.n; i++) {
-    log.lh.block[i] = lh->block[i];
-  }
-  brelse(buf);
-}
-
-// Write in-memory log header to disk.
-// This is the true point at which the
-// current transaction commits.
-static void
-write_head(void)
-{
-  struct buf *buf = bread(log.dev, log.start);
-  struct logheader *hb = (struct logheader *) (buf->data);
-  int i;
-  hb->n = log.lh.n;
-  for (i = 0; i < log.lh.n; i++) {
-    hb->block[i] = log.lh.block[i];
-  }
-  bwrite(buf);
-  brelse(buf);
-}
-
-static void
-recover_from_log(void)
-{
-  read_head();
-  install_trans(); // if committed, copy from log to disk
-  log.lh.n = 0;
-  write_head(); // clear the log
-}
-
-// called at the start of each FS system call.
-void
-begin_op(void)
-{
-  acquire(&log.lock);
-  while(1){
-    if(log.committing){
-      sleep(&log, &log.lock);
-    } else if(log.lh.n + (log.outstanding+1)*MAXOPBLOCKS > LOGSIZE){
-      // this op might exhaust log space; wait for commit.
-      sleep(&log, &log.lock);
-    } else {
-      log.outstanding += 1;
-      release(&log.lock);
-      break;
-    }
-  }
-}
-
-// called at the end of each FS system call.
-// commits if this was the last outstanding operation.
-void
-end_op(void)
-{
-  int do_commit = 0;
-
-  acquire(&log.lock);
-  log.outstanding -= 1;
-  if(log.committing)
-    panic("log.committing");
-  if(log.outstanding == 0){
-    do_commit = 1;
-    log.committing = 1;
-  } else {
-    // begin_op() may be waiting for log space,
-    // and decrementing log.outstanding has decreased
-    // the amount of reserved space.
-    wakeup(&log);
-  }
-  release(&log.lock);
-
-  if(do_commit){
-    // call commit w/o holding locks, since not allowed
-    // to sleep with locks.
-    commit();
-    acquire(&log.lock);
-    log.committing = 0;
-    wakeup(&log);
-    release(&log.lock);
-  }
-}
-
-// Copy modified blocks from cache to log.
-static void
-write_log(void)
-{
-  int tail;
-
-  for (tail = 0; tail < log.lh.n; tail++) {
-    struct buf *to = bread(log.dev, log.start+tail+1); // log block
-    struct buf *from = bread(log.dev, log.lh.block[tail]); // cache block
-    memmove(to->data, from->data, BSIZE);
-    bwrite(to);  // write the log
-    brelse(from);
-    brelse(to);
-  }
-}
-
-static void
-commit()
-{
-  if (log.lh.n > 0) {
-    write_log();     // Write modified blocks from cache to log
-    write_head();    // Write header to disk -- the real commit
-    install_trans(); // Now install writes to home locations
-    log.lh.n = 0;
-    write_head();    // Erase the transaction from the log
-  }
-}
-
-// Caller has modified b->data and is done with the buffer.
-// Record the block number and pin in the cache with B_DIRTY.
-// commit()/write_log() will do the disk write.
-//
-// log_write() replaces bwrite(); a typical use is:
-//   bp = bread(...)
-//   modify bp->data[]
-//   log_write(bp)
-//   brelse(bp)
-void
-log_write(struct buf *b)
-{
-  int i;
-
-  if (log.lh.n >= LOGSIZE || log.lh.n >= log.size - 1)
-    panic("too big a transaction");
-  if (log.outstanding < 1)
-    panic("log_write outside of trans");
-
-  acquire(&log.lock);
-  for (i = 0; i < log.lh.n; i++) {
-    if (log.lh.block[i] == b->blockno)   // log absorbtion
-      break;
-  }
-  log.lh.block[i] = b->blockno;
-  if (i == log.lh.n)
-    log.lh.n++;
-  b->flags |= B_DIRTY; // prevent eviction
-  release(&log.lock);
-}
-
diff --git a/ls.c b/ls.c
deleted file mode 100644 (file)
index 2862913..0000000
--- a/ls.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-#include "fs.h"
-
-char*
-fmtname(char *path)
-{
-  static char buf[DIRSIZ+1];
-  char *p;
-
-  // Find first character after last slash.
-  for(p=path+strlen(path); p >= path && *p != '/'; p--)
-    ;
-  p++;
-
-  // Return blank-padded name.
-  if(strlen(p) >= DIRSIZ)
-    return p;
-  memmove(buf, p, strlen(p));
-  memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
-  return buf;
-}
-
-void
-ls(char *path)
-{
-  char buf[512], *p;
-  int fd;
-  struct dirent de;
-  struct stat st;
-
-  if((fd = open(path, 0)) < 0){
-    printf(2, "ls: cannot open %s\n", path);
-    return;
-  }
-
-  if(fstat(fd, &st) < 0){
-    printf(2, "ls: cannot stat %s\n", path);
-    close(fd);
-    return;
-  }
-
-  switch(st.type){
-  case T_FILE:
-    printf(1, "%s %d %d %d\n", fmtname(path), st.type, st.ino, st.size);
-    break;
-
-  case T_DIR:
-    if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
-      printf(1, "ls: path too long\n");
-      break;
-    }
-    strcpy(buf, path);
-    p = buf+strlen(buf);
-    *p++ = '/';
-    while(read(fd, &de, sizeof(de)) == sizeof(de)){
-      if(de.inum == 0)
-        continue;
-      memmove(p, de.name, DIRSIZ);
-      p[DIRSIZ] = 0;
-      if(stat(buf, &st) < 0){
-        printf(1, "ls: cannot stat %s\n", buf);
-        continue;
-      }
-      printf(1, "%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
-    }
-    break;
-  }
-  close(fd);
-}
-
-int
-main(int argc, char *argv[])
-{
-  int i;
-
-  if(argc < 2){
-    ls(".");
-    exit();
-  }
-  for(i=1; i<argc; i++)
-    ls(argv[i]);
-  exit();
-}
diff --git a/main.c b/main.c
deleted file mode 100644 (file)
index d7045a9..0000000
--- a/main.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#include <stdatomic.h>
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "x86.h"
-
-static void startothers(void);
-static void mpmain(void)  __attribute__((noreturn));
-extern pde_t *kpgdir;
-extern char end[]; // first address after kernel loaded from ELF file
-
-// Bootstrap processor starts running C code here.
-// Allocate a real stack and switch to it, first
-// doing some setup required for memory allocator to work.
-int
-main(void)
-{
-  kinit1(end, P2V(4*1024*1024)); // phys page allocator
-  kvmalloc();      // kernel page table
-  mpinit();        // detect other processors
-  lapicinit();     // interrupt controller
-  seginit();       // segment descriptors
-  picinit();       // disable pic
-  ioapicinit();    // another interrupt controller
-  consoleinit();   // console hardware
-  uartinit();      // serial port
-  pinit();         // process table
-  tvinit();        // trap vectors
-  binit();         // buffer cache
-  fileinit();      // file table
-  ideinit();       // disk 
-  startothers();   // start other processors
-  kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
-  userinit();      // first user process
-  mpmain();        // finish this processor's setup
-}
-
-// Other CPUs jump here from entryother.S.
-static void
-mpenter(void)
-{
-  switchkvm();
-  seginit();
-  lapicinit();
-  mpmain();
-}
-
-// Common CPU setup code.
-static void
-mpmain(void)
-{
-  cprintf("cpu%d: starting %d\n", cpuid(), cpuid());
-  idtinit();       // load idt register
-  atomic_store(&mycpu()->started, 1); // tell startothers() we're up -- atomically
-  scheduler();     // start running processes
-}
-
-pde_t entrypgdir[];  // For entry.S
-
-// Start the non-boot (AP) processors.
-static void
-startothers(void)
-{
-  extern uchar _binary_entryother_start[], _binary_entryother_size[];
-  uchar *code;
-  struct cpu *c;
-  char *stack;
-
-  // Write entry code to unused memory at 0x7000.
-  // The linker has placed the image of entryother.S in
-  // _binary_entryother_start.
-  code = P2V(0x7000);
-  memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
-
-  for(c = cpus; c < cpus+ncpu; c++){
-    if(c == mycpu())  // We've started already.
-      continue;
-
-    // Tell entryother.S what stack to use, where to enter, and what
-    // pgdir to use. We cannot use kpgdir yet, because the AP processor
-    // is running in low  memory, so we use entrypgdir for the APs too.
-    stack = kalloc();
-    *(void**)(code-4) = stack + KSTACKSIZE;
-    *(void(**)(void))(code-8) = mpenter;
-    *(int**)(code-12) = (void *) V2P(entrypgdir);
-
-    lapicstartap(c->apicid, V2P(code));
-
-    // wait for cpu to finish mpmain()
-    while(atomic_load(&c->started) == 0)
-      ;
-  }
-}
-
-// The boot page table used in entry.S and entryother.S.
-// Page directories (and page tables) must start on page boundaries,
-// hence the __aligned__ attribute.
-// PTE_PS in a page directory entry enables 4Mbyte pages.
-
-__attribute__((__aligned__(PGSIZE)))
-pde_t entrypgdir[NPDENTRIES] = {
-  // Map VA's [0, 4MB) to PA's [0, 4MB)
-  [0] = (0) | PTE_P | PTE_W | PTE_PS,
-  // Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB)
-  [KERNBASE>>PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS,
-};
-
-//PAGEBREAK!
-// Blank page.
-//PAGEBREAK!
-// Blank page.
-//PAGEBREAK!
-// Blank page.
-
diff --git a/memide.c b/memide.c
deleted file mode 100644 (file)
index ba267ac..0000000
--- a/memide.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// Fake IDE disk; stores blocks in memory.
-// Useful for running kernel without scratch disk.
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "mmu.h"
-#include "proc.h"
-#include "x86.h"
-#include "traps.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "fs.h"
-#include "buf.h"
-
-extern uchar _binary_fs_img_start[], _binary_fs_img_size[];
-
-static int disksize;
-static uchar *memdisk;
-
-void
-ideinit(void)
-{
-  memdisk = _binary_fs_img_start;
-  disksize = (uint)_binary_fs_img_size/BSIZE;
-}
-
-// Interrupt handler.
-void
-ideintr(void)
-{
-  // no-op
-}
-
-// Sync buf with disk.
-// If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID.
-// Else if B_VALID is not set, read buf from disk, set B_VALID.
-void
-iderw(struct buf *b)
-{
-  uchar *p;
-
-  if(!holdingsleep(&b->lock))
-    panic("iderw: buf not locked");
-  if((b->flags & (B_VALID|B_DIRTY)) == B_VALID)
-    panic("iderw: nothing to do");
-  if(b->dev != 1)
-    panic("iderw: request not for disk 1");
-  if(b->blockno >= disksize)
-    panic("iderw: block out of range");
-
-  p = memdisk + b->blockno*BSIZE;
-
-  if(b->flags & B_DIRTY){
-    b->flags &= ~B_DIRTY;
-    memmove(p, b->data, BSIZE);
-  } else
-    memmove(b->data, p, BSIZE);
-  b->flags |= B_VALID;
-}
diff --git a/memlayout.h b/memlayout.h
deleted file mode 100644 (file)
index d1615f7..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Memory layout
-
-#define EXTMEM  0x100000            // Start of extended memory
-#define PHYSTOP 0xE000000           // Top physical memory
-#define DEVSPACE 0xFE000000         // Other devices are at high addresses
-
-// Key addresses for address space layout (see kmap in vm.c for layout)
-#define KERNBASE 0x80000000         // First kernel virtual address
-#define KERNLINK (KERNBASE+EXTMEM)  // Address where kernel is linked
-
-#define V2P(a) (((uint) (a)) - KERNBASE)
-#define P2V(a) ((void *)(((char *) (a)) + KERNBASE))
-
-#define V2P_WO(x) ((x) - KERNBASE)    // same as V2P, but without casts
-#define P2V_WO(x) ((x) + KERNBASE)    // same as P2V, but without casts
diff --git a/mkdir.c b/mkdir.c
deleted file mode 100644 (file)
index 6e4c954..0000000
--- a/mkdir.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-int
-main(int argc, char *argv[])
-{
-  int i;
-
-  if(argc < 2){
-    printf(2, "Usage: mkdir files...\n");
-    exit();
-  }
-
-  for(i = 1; i < argc; i++){
-    if(mkdir(argv[i]) < 0){
-      printf(2, "mkdir: %s failed to create\n", argv[i]);
-      break;
-    }
-  }
-
-  exit();
-}
diff --git a/mkfs.c b/mkfs.c
deleted file mode 100644 (file)
index 8e011a7..0000000
--- a/mkfs.c
+++ /dev/null
@@ -1,297 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#define stat xv6_stat  // avoid clash with host struct stat
-#include "types.h"
-#include "fs.h"
-#include "stat.h"
-#include "param.h"
-
-#ifndef static_assert
-#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
-#endif
-
-#define NINODES 200
-
-// Disk layout:
-// [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
-
-int nbitmap = FSSIZE/(BSIZE*8) + 1;
-int ninodeblocks = NINODES / IPB + 1;
-int nlog = LOGSIZE;
-int nmeta;    // Number of meta blocks (boot, sb, nlog, inode, bitmap)
-int nblocks;  // Number of data blocks
-
-int fsfd;
-struct superblock sb;
-char zeroes[BSIZE];
-uint freeinode = 1;
-uint freeblock;
-
-
-void balloc(int);
-void wsect(uint, void*);
-void winode(uint, struct dinode*);
-void rinode(uint inum, struct dinode *ip);
-void rsect(uint sec, void *buf);
-uint ialloc(ushort type);
-void iappend(uint inum, void *p, int n);
-
-// convert to intel byte order
-ushort
-xshort(ushort x)
-{
-  ushort y;
-  uchar *a = (uchar*)&y;
-  a[0] = x;
-  a[1] = x >> 8;
-  return y;
-}
-
-uint
-xint(uint x)
-{
-  uint y;
-  uchar *a = (uchar*)&y;
-  a[0] = x;
-  a[1] = x >> 8;
-  a[2] = x >> 16;
-  a[3] = x >> 24;
-  return y;
-}
-
-int
-main(int argc, char *argv[])
-{
-  int i, cc, fd;
-  uint rootino, inum, off;
-  struct dirent de;
-  char buf[BSIZE];
-  struct dinode din;
-
-
-  static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
-
-  if(argc < 2){
-    fprintf(stderr, "Usage: mkfs fs.img files...\n");
-    exit(1);
-  }
-
-  assert((BSIZE % sizeof(struct dinode)) == 0);
-  assert((BSIZE % sizeof(struct dirent)) == 0);
-
-  fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
-  if(fsfd < 0){
-    perror(argv[1]);
-    exit(1);
-  }
-
-  // 1 fs block = 1 disk sector
-  nmeta = 2 + nlog + ninodeblocks + nbitmap;
-  nblocks = FSSIZE - nmeta;
-
-  sb.size = xint(FSSIZE);
-  sb.nblocks = xint(nblocks);
-  sb.ninodes = xint(NINODES);
-  sb.nlog = xint(nlog);
-  sb.logstart = xint(2);
-  sb.inodestart = xint(2+nlog);
-  sb.bmapstart = xint(2+nlog+ninodeblocks);
-
-  printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
-         nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
-
-  freeblock = nmeta;     // the first free block that we can allocate
-
-  for(i = 0; i < FSSIZE; i++)
-    wsect(i, zeroes);
-
-  memset(buf, 0, sizeof(buf));
-  memmove(buf, &sb, sizeof(sb));
-  wsect(1, buf);
-
-  rootino = ialloc(T_DIR);
-  assert(rootino == ROOTINO);
-
-  bzero(&de, sizeof(de));
-  de.inum = xshort(rootino);
-  strcpy(de.name, ".");
-  iappend(rootino, &de, sizeof(de));
-
-  bzero(&de, sizeof(de));
-  de.inum = xshort(rootino);
-  strcpy(de.name, "..");
-  iappend(rootino, &de, sizeof(de));
-
-  for(i = 2; i < argc; i++){
-    assert(index(argv[i], '/') == 0);
-
-    if((fd = open(argv[i], 0)) < 0){
-      perror(argv[i]);
-      exit(1);
-    }
-
-    // Skip leading _ in name when writing to file system.
-    // The binaries are named _rm, _cat, etc. to keep the
-    // build operating system from trying to execute them
-    // in place of system binaries like rm and cat.
-    if(argv[i][0] == '_')
-      ++argv[i];
-
-    inum = ialloc(T_FILE);
-
-    bzero(&de, sizeof(de));
-    de.inum = xshort(inum);
-    strncpy(de.name, argv[i], DIRSIZ);
-    iappend(rootino, &de, sizeof(de));
-
-    while((cc = read(fd, buf, sizeof(buf))) > 0)
-      iappend(inum, buf, cc);
-
-    close(fd);
-  }
-
-  // fix size of root inode dir
-  rinode(rootino, &din);
-  off = xint(din.size);
-  off = ((off/BSIZE) + 1) * BSIZE;
-  din.size = xint(off);
-  winode(rootino, &din);
-
-  balloc(freeblock);
-
-  exit(0);
-}
-
-void
-wsect(uint sec, void *buf)
-{
-  if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
-    perror("lseek");
-    exit(1);
-  }
-  if(write(fsfd, buf, BSIZE) != BSIZE){
-    perror("write");
-    exit(1);
-  }
-}
-
-void
-winode(uint inum, struct dinode *ip)
-{
-  char buf[BSIZE];
-  uint bn;
-  struct dinode *dip;
-
-  bn = IBLOCK(inum, sb);
-  rsect(bn, buf);
-  dip = ((struct dinode*)buf) + (inum % IPB);
-  *dip = *ip;
-  wsect(bn, buf);
-}
-
-void
-rinode(uint inum, struct dinode *ip)
-{
-  char buf[BSIZE];
-  uint bn;
-  struct dinode *dip;
-
-  bn = IBLOCK(inum, sb);
-  rsect(bn, buf);
-  dip = ((struct dinode*)buf) + (inum % IPB);
-  *ip = *dip;
-}
-
-void
-rsect(uint sec, void *buf)
-{
-  if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
-    perror("lseek");
-    exit(1);
-  }
-  if(read(fsfd, buf, BSIZE) != BSIZE){
-    perror("read");
-    exit(1);
-  }
-}
-
-uint
-ialloc(ushort type)
-{
-  uint inum = freeinode++;
-  struct dinode din;
-
-  bzero(&din, sizeof(din));
-  din.type = xshort(type);
-  din.nlink = xshort(1);
-  din.size = xint(0);
-  winode(inum, &din);
-  return inum;
-}
-
-void
-balloc(int used)
-{
-  uchar buf[BSIZE];
-  int i;
-
-  printf("balloc: first %d blocks have been allocated\n", used);
-  assert(used < BSIZE*8);
-  bzero(buf, BSIZE);
-  for(i = 0; i < used; i++){
-    buf[i/8] = buf[i/8] | (0x1 << (i%8));
-  }
-  printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
-  wsect(sb.bmapstart, buf);
-}
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-void
-iappend(uint inum, void *xp, int n)
-{
-  char *p = (char*)xp;
-  uint fbn, off, n1;
-  struct dinode din;
-  char buf[BSIZE];
-  uint indirect[NINDIRECT];
-  uint x;
-
-  rinode(inum, &din);
-  off = xint(din.size);
-  // printf("append inum %d at off %d sz %d\n", inum, off, n);
-  while(n > 0){
-    fbn = off / BSIZE;
-    assert(fbn < MAXFILE);
-    if(fbn < NDIRECT){
-      if(xint(din.addrs[fbn]) == 0){
-        din.addrs[fbn] = xint(freeblock++);
-      }
-      x = xint(din.addrs[fbn]);
-    } else {
-      if(xint(din.addrs[NDIRECT]) == 0){
-        din.addrs[NDIRECT] = xint(freeblock++);
-      }
-      rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
-      if(indirect[fbn - NDIRECT] == 0){
-        indirect[fbn - NDIRECT] = xint(freeblock++);
-        wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
-      }
-      x = xint(indirect[fbn-NDIRECT]);
-    }
-    n1 = min(n, (fbn + 1) * BSIZE - off);
-    rsect(x, buf);
-    bcopy(p, buf + off - (fbn * BSIZE), n1);
-    wsect(x, buf);
-    n -= n1;
-    off += n1;
-    p += n1;
-  }
-  din.size = xint(off);
-  winode(inum, &din);
-}
diff --git a/mmu.h b/mmu.h
deleted file mode 100644 (file)
index a82d8e2..0000000
--- a/mmu.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// This file contains definitions for the
-// x86 memory management unit (MMU).
-
-// Eflags register
-#define FL_IF           0x00000200      // Interrupt Enable
-
-// Control Register flags
-#define CR0_PE          0x00000001      // Protection Enable
-#define CR0_WP          0x00010000      // Write Protect
-#define CR0_PG          0x80000000      // Paging
-
-#define CR4_PSE         0x00000010      // Page size extension
-
-// various segment selectors.
-#define SEG_KCODE 1  // kernel code
-#define SEG_KDATA 2  // kernel data+stack
-#define SEG_UCODE 3  // user code
-#define SEG_UDATA 4  // user data+stack
-#define SEG_TSS   5  // this process's task state
-
-// cpu->gdt[NSEGS] holds the above segments.
-#define NSEGS     6
-
-#ifndef __ASSEMBLER__
-// Segment Descriptor
-struct segdesc {
-  uint lim_15_0 : 16;  // Low bits of segment limit
-  uint base_15_0 : 16; // Low 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 s : 1;          // 0 = system, 1 = application
-  uint dpl : 2;        // Descriptor Privilege Level
-  uint p : 1;          // Present
-  uint lim_19_16 : 4;  // High bits of segment limit
-  uint avl : 1;        // Unused (available for software use)
-  uint rsv1 : 1;       // Reserved
-  uint db : 1;         // 0 = 16-bit segment, 1 = 32-bit segment
-  uint g : 1;          // Granularity: limit scaled by 4K when set
-  uint base_31_24 : 8; // High bits of segment base address
-};
-
-// Normal segment
-#define SEG(type, base, lim, dpl) (struct segdesc)    \
-{ ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff,      \
-  ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1,       \
-  (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 }
-#define SEG16(type, base, lim, dpl) (struct segdesc)  \
-{ (lim) & 0xffff, (uint)(base) & 0xffff,              \
-  ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1,       \
-  (uint)(lim) >> 16, 0, 0, 1, 0, (uint)(base) >> 24 }
-#endif
-
-#define DPL_USER    0x3     // User DPL
-
-// Application segment type bits
-#define STA_X       0x8     // Executable segment
-#define STA_W       0x2     // Writeable (non-executable segments)
-#define STA_R       0x2     // Readable (executable segments)
-
-// System segment type bits
-#define STS_T32A    0x9     // Available 32-bit TSS
-#define STS_IG32    0xE     // 32-bit Interrupt Gate
-#define STS_TG32    0xF     // 32-bit Trap Gate
-
-// A virtual address 'la' has a three-part structure as follows:
-//
-// +--------10------+-------10-------+---------12----------+
-// | Page Directory |   Page Table   | Offset within Page  |
-// |      Index     |      Index     |                     |
-// +----------------+----------------+---------------------+
-//  \--- PDX(va) --/ \--- PTX(va) --/
-
-// page directory index
-#define PDX(va)         (((uint)(va) >> PDXSHIFT) & 0x3FF)
-
-// page table index
-#define PTX(va)         (((uint)(va) >> PTXSHIFT) & 0x3FF)
-
-// construct virtual address from indexes and offset
-#define PGADDR(d, t, o) ((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))
-
-// Page directory and page table constants.
-#define NPDENTRIES      1024    // # directory entries per page directory
-#define NPTENTRIES      1024    // # PTEs per page table
-#define PGSIZE          4096    // bytes mapped by a page
-
-#define PTXSHIFT        12      // offset of PTX in a linear address
-#define PDXSHIFT        22      // offset of PDX in a linear address
-
-#define PGROUNDUP(sz)  (((sz)+PGSIZE-1) & ~(PGSIZE-1))
-#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))
-
-// Page table/directory entry flags.
-#define PTE_P           0x001   // Present
-#define PTE_W           0x002   // Writeable
-#define PTE_U           0x004   // User
-#define PTE_PS          0x080   // Page Size
-
-// Address in page table or page directory entry
-#define PTE_ADDR(pte)   ((uint)(pte) & ~0xFFF)
-#define PTE_FLAGS(pte)  ((uint)(pte) &  0xFFF)
-
-#ifndef __ASSEMBLER__
-typedef uint pte_t;
-
-// Task state segment format
-struct taskstate {
-  uint link;         // Old ts selector
-  uint esp0;         // Stack pointers and segment selectors
-  ushort ss0;        //   after an increase in privilege level
-  ushort padding1;
-  uint *esp1;
-  ushort ss1;
-  ushort padding2;
-  uint *esp2;
-  ushort ss2;
-  ushort padding3;
-  void *cr3;         // Page directory base
-  uint *eip;         // Saved state from last task switch
-  uint eflags;
-  uint eax;          // More saved state (registers)
-  uint ecx;
-  uint edx;
-  uint ebx;
-  uint *esp;
-  uint *ebp;
-  uint esi;
-  uint edi;
-  ushort es;         // Even more saved state (segment selectors)
-  ushort padding4;
-  ushort cs;
-  ushort padding5;
-  ushort ss;
-  ushort padding6;
-  ushort ds;
-  ushort padding7;
-  ushort fs;
-  ushort padding8;
-  ushort gs;
-  ushort padding9;
-  ushort ldt;
-  ushort padding10;
-  ushort t;          // Trap on task switch
-  ushort iomb;       // I/O map base address
-};
-
-// Gate descriptors for interrupts and traps
-struct gatedesc {
-  uint off_15_0 : 16;   // low 16 bits of offset in segment
-  uint cs : 16;         // code segment selector
-  uint args : 5;        // # args, 0 for interrupt/trap gates
-  uint rsv1 : 3;        // reserved(should be zero I guess)
-  uint type : 4;        // type(STS_{IG32,TG32})
-  uint s : 1;           // must be 0 (system)
-  uint dpl : 2;         // descriptor(meaning new) privilege level
-  uint p : 1;           // Present
-  uint off_31_16 : 16;  // high bits of offset in segment
-};
-
-// Set up a normal interrupt/trap gate descriptor.
-// - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
-//   interrupt gate clears FL_IF, trap gate leaves FL_IF alone
-// - sel: Code segment selector for interrupt/trap handler
-// - off: Offset in code segment for interrupt/trap handler
-// - dpl: Descriptor Privilege Level -
-//        the privilege level required for software to invoke
-//        this interrupt/trap gate explicitly using an int instruction.
-#define SETGATE(gate, istrap, sel, off, d)                \
-{                                                         \
-  (gate).off_15_0 = (uint)(off) & 0xffff;                \
-  (gate).cs = (sel);                                      \
-  (gate).args = 0;                                        \
-  (gate).rsv1 = 0;                                        \
-  (gate).type = (istrap) ? STS_TG32 : STS_IG32;           \
-  (gate).s = 0;                                           \
-  (gate).dpl = (d);                                       \
-  (gate).p = 1;                                           \
-  (gate).off_31_16 = (uint)(off) >> 16;                  \
-}
-
-#endif
diff --git a/mp.c b/mp.c
deleted file mode 100644 (file)
index 79bb0ad..0000000
--- a/mp.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// Multiprocessor support
-// Search memory for MP description structures.
-// http://developer.intel.com/design/pentium/datashts/24201606.pdf
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mp.h"
-#include "x86.h"
-#include "mmu.h"
-#include "proc.h"
-
-struct cpu cpus[NCPU];
-int ncpu;
-uchar ioapicid;
-
-static uchar
-sum(uchar *addr, int len)
-{
-  int i, sum;
-
-  sum = 0;
-  for(i=0; i<len; i++)
-    sum += addr[i];
-  return sum;
-}
-
-// Look for an MP structure in the len bytes at addr.
-static struct mp*
-mpsearch1(uint a, int len)
-{
-  uchar *e, *p, *addr;
-
-  addr = P2V(a);
-  e = addr+len;
-  for(p = addr; p < e; p += sizeof(struct mp))
-    if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
-      return (struct mp*)p;
-  return 0;
-}
-
-// Search for the MP Floating Pointer Structure, which according to the
-// spec is in one of the following three locations:
-// 1) in the first KB of the EBDA;
-// 2) in the last KB of system base memory;
-// 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
-static struct mp*
-mpsearch(void)
-{
-  uchar *bda;
-  uint p;
-  struct mp *mp;
-
-  bda = (uchar *) P2V(0x400);
-  if((p = ((bda[0x0F]<<8)| bda[0x0E]) << 4)){
-    if((mp = mpsearch1(p, 1024)))
-      return mp;
-  } else {
-    p = ((bda[0x14]<<8)|bda[0x13])*1024;
-    if((mp = mpsearch1(p-1024, 1024)))
-      return mp;
-  }
-  return mpsearch1(0xF0000, 0x10000);
-}
-
-// Search for an MP configuration table.  For now,
-// don't accept the default configurations (physaddr == 0).
-// Check for correct signature, calculate the checksum and,
-// if correct, check the version.
-// To do: check extended table checksum.
-static struct mpconf*
-mpconfig(struct mp **pmp)
-{
-  struct mpconf *conf;
-  struct mp *mp;
-
-  if((mp = mpsearch()) == 0 || mp->physaddr == 0)
-    return 0;
-  conf = (struct mpconf*) P2V((uint) mp->physaddr);
-  if(memcmp(conf, "PCMP", 4) != 0)
-    return 0;
-  if(conf->version != 1 && conf->version != 4)
-    return 0;
-  if(sum((uchar*)conf, conf->length) != 0)
-    return 0;
-  *pmp = mp;
-  return conf;
-}
-
-void
-mpinit(void)
-{
-  uchar *p, *e;
-  int ismp;
-  struct mp *mp;
-  struct mpconf *conf;
-  struct mpproc *proc;
-  struct mpioapic *ioapic;
-
-  if((conf = mpconfig(&mp)) == 0)
-    panic("Expect to run on an SMP");
-  ismp = 1;
-  lapic = (uint*)conf->lapicaddr;
-  for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; p<e; ){
-    switch(*p){
-    case MPPROC:
-      proc = (struct mpproc*)p;
-      if(ncpu < NCPU) {
-        cpus[ncpu].apicid = proc->apicid;  // apicid may differ from ncpu
-        ncpu++;
-      }
-      p += sizeof(struct mpproc);
-      continue;
-    case MPIOAPIC:
-      ioapic = (struct mpioapic*)p;
-      ioapicid = ioapic->apicno;
-      p += sizeof(struct mpioapic);
-      continue;
-    case MPBUS:
-    case MPIOINTR:
-    case MPLINTR:
-      p += 8;
-      continue;
-    default:
-      ismp = 0;
-      break;
-    }
-  }
-  if(!ismp)
-    panic("Didn't find a suitable machine");
-
-  if(mp->imcrp){
-    // Bochs doesn't support IMCR, so this doesn't run on Bochs.
-    // But it would on real hardware.
-    outb(0x22, 0x70);   // Select IMCR
-    outb(0x23, inb(0x23) | 1);  // Mask external interrupts.
-  }
-}
diff --git a/mp.h b/mp.h
deleted file mode 100644 (file)
index 4d17283..0000000
--- a/mp.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// See MultiProcessor Specification Version 1.[14]
-
-struct mp {             // floating pointer
-  uchar signature[4];           // "_MP_"
-  void *physaddr;               // phys addr of MP config table
-  uchar length;                 // 1
-  uchar specrev;                // [14]
-  uchar checksum;               // all bytes must add up to 0
-  uchar type;                   // MP system config type
-  uchar imcrp;
-  uchar reserved[3];
-};
-
-struct mpconf {         // configuration table header
-  uchar signature[4];           // "PCMP"
-  ushort length;                // total table length
-  uchar version;                // [14]
-  uchar checksum;               // all bytes must add up to 0
-  uchar product[20];            // product id
-  uint *oemtable;               // OEM table pointer
-  ushort oemlength;             // OEM table length
-  ushort entry;                 // entry count
-  uint *lapicaddr;              // address of local APIC
-  ushort xlength;               // extended table length
-  uchar xchecksum;              // extended table checksum
-  uchar reserved;
-};
-
-struct mpproc {         // processor table entry
-  uchar type;                   // entry type (0)
-  uchar apicid;                 // local APIC id
-  uchar version;                // local APIC verison
-  uchar flags;                  // CPU flags
-    #define MPBOOT 0x02           // This proc is the bootstrap processor.
-  uchar signature[4];           // CPU signature
-  uint feature;                 // feature flags from CPUID instruction
-  uchar reserved[8];
-};
-
-struct mpioapic {       // I/O APIC table entry
-  uchar type;                   // entry type (2)
-  uchar apicno;                 // I/O APIC id
-  uchar version;                // I/O APIC version
-  uchar flags;                  // I/O APIC flags
-  uint *addr;                  // I/O APIC address
-};
-
-// Table entry types
-#define MPPROC    0x00  // One per processor
-#define MPBUS     0x01  // One per bus
-#define MPIOAPIC  0x02  // One per I/O APIC
-#define MPIOINTR  0x03  // One per bus interrupt source
-#define MPLINTR   0x04  // One per system interrupt source
-
-//PAGEBREAK!
-// Blank page.
diff --git a/param.h b/param.h
deleted file mode 100644 (file)
index a7e90ef..0000000
--- a/param.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#define NPROC        64  // maximum number of processes
-#define KSTACKSIZE 4096  // size of per-process kernel stack
-#define NCPU          8  // maximum number of CPUs
-#define NOFILE       16  // open files per process
-#define NFILE       100  // open files per system
-#define NINODE       50  // maximum number of active i-nodes
-#define NDEV         10  // maximum major device number
-#define ROOTDEV       1  // device number of file system root disk
-#define MAXARG       32  // max exec arguments
-#define MAXOPBLOCKS  10  // max # of blocks any FS op writes
-#define LOGSIZE      (MAXOPBLOCKS*3)  // max data blocks in on-disk log
-#define NBUF         (MAXOPBLOCKS*3)  // size of disk block cache
-#define FSSIZE       1000  // size of file system in blocks
-
diff --git a/picirq.c b/picirq.c
deleted file mode 100644 (file)
index e26957f..0000000
--- a/picirq.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "types.h"
-#include "x86.h"
-#include "traps.h"
-
-// I/O Addresses of the two programmable interrupt controllers
-#define IO_PIC1         0x20    // Master (IRQs 0-7)
-#define IO_PIC2         0xA0    // Slave (IRQs 8-15)
-
-// Don't use the 8259A interrupt controllers.  Xv6 assumes SMP hardware.
-void
-picinit(void)
-{
-  // mask all interrupts
-  outb(IO_PIC1+1, 0xFF);
-  outb(IO_PIC2+1, 0xFF);
-}
-
-//PAGEBREAK!
-// Blank page.
diff --git a/pipe.c b/pipe.c
deleted file mode 100644 (file)
index e9abe7f..0000000
--- a/pipe.c
+++ /dev/null
@@ -1,121 +0,0 @@
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "mmu.h"
-#include "proc.h"
-#include "fs.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "file.h"
-
-#define PIPESIZE 512
-
-struct pipe {
-  struct spinlock lock;
-  char data[PIPESIZE];
-  uint nread;     // number of bytes read
-  uint nwrite;    // number of bytes written
-  int readopen;   // read fd is still open
-  int writeopen;  // write fd is still open
-};
-
-int
-pipealloc(struct file **f0, struct file **f1)
-{
-  struct pipe *p;
-
-  p = 0;
-  *f0 = *f1 = 0;
-  if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
-    goto bad;
-  if((p = (struct pipe*)kalloc()) == 0)
-    goto bad;
-  p->readopen = 1;
-  p->writeopen = 1;
-  p->nwrite = 0;
-  p->nread = 0;
-  initlock(&p->lock, "pipe");
-  (*f0)->type = FD_PIPE;
-  (*f0)->readable = 1;
-  (*f0)->writable = 0;
-  (*f0)->pipe = p;
-  (*f1)->type = FD_PIPE;
-  (*f1)->readable = 0;
-  (*f1)->writable = 1;
-  (*f1)->pipe = p;
-  return 0;
-
-//PAGEBREAK: 20
- bad:
-  if(p)
-    kfree((char*)p);
-  if(*f0)
-    fileclose(*f0);
-  if(*f1)
-    fileclose(*f1);
-  return -1;
-}
-
-void
-pipeclose(struct pipe *p, int writable)
-{
-  acquire(&p->lock);
-  if(writable){
-    p->writeopen = 0;
-    wakeup(&p->nread);
-  } else {
-    p->readopen = 0;
-    wakeup(&p->nwrite);
-  }
-  if(p->readopen == 0 && p->writeopen == 0){
-    release(&p->lock);
-    kfree((char*)p);
-  } else
-    release(&p->lock);
-}
-
-//PAGEBREAK: 40
-int
-pipewrite(struct pipe *p, char *addr, int n)
-{
-  int i;
-
-  acquire(&p->lock);
-  for(i = 0; i < n; i++){
-    while(p->nwrite == p->nread + PIPESIZE){  //DOC: pipewrite-full
-      if(p->readopen == 0 || myproc()->killed){
-        release(&p->lock);
-        return -1;
-      }
-      wakeup(&p->nread);
-      sleep(&p->nwrite, &p->lock);  //DOC: pipewrite-sleep
-    }
-    p->data[p->nwrite++ % PIPESIZE] = addr[i];
-  }
-  wakeup(&p->nread);  //DOC: pipewrite-wakeup1
-  release(&p->lock);
-  return n;
-}
-
-int
-piperead(struct pipe *p, char *addr, int n)
-{
-  int i;
-
-  acquire(&p->lock);
-  while(p->nread == p->nwrite && p->writeopen){  //DOC: pipe-empty
-    if(myproc()->killed){
-      release(&p->lock);
-      return -1;
-    }
-    sleep(&p->nread, &p->lock); //DOC: piperead-sleep
-  }
-  for(i = 0; i < n; i++){  //DOC: piperead-copy
-    if(p->nread == p->nwrite)
-      break;
-    addr[i] = p->data[p->nread++ % PIPESIZE];
-  }
-  wakeup(&p->nwrite);  //DOC: piperead-wakeup
-  release(&p->lock);
-  return i;
-}
diff --git a/pr.pl b/pr.pl
deleted file mode 100755 (executable)
index 46905bd..0000000
--- a/pr.pl
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/perl
-
-use POSIX qw(strftime);
-
-if($ARGV[0] eq "-h"){
-       shift @ARGV;
-       $h = $ARGV[0];
-       shift @ARGV;
-}else{
-       $h = $ARGV[0];
-}
-
-$page = 0;
-$now = strftime "%b %e %H:%M %Y", localtime;
-
-@lines = <>;
-for($i=0; $i<@lines; $i+=50){
-       print "\n\n";
-       ++$page;
-       print "$now  $h  Page $page\n";
-       print "\n\n";
-       for($j=$i; $j<@lines && $j<$i +50; $j++){
-               $lines[$j] =~ s!//DOC.*!!;
-               print $lines[$j];
-       }
-       for(; $j<$i+50; $j++){
-               print "\n";
-       }
-       $sheet = "";
-       if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){
-               $sheet = "Sheet $1";
-       }
-       print "\n\n";
-       print "$sheet\n";
-       print "\n\n";
-}
diff --git a/printf.c b/printf.c
deleted file mode 100644 (file)
index b3298aa..0000000
--- a/printf.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-static void
-putc(int fd, char c)
-{
-  write(fd, &c, 1);
-}
-
-static void
-printint(int fd, int xx, int base, int sgn)
-{
-  static char digits[] = "0123456789ABCDEF";
-  char buf[16];
-  int i, neg;
-  uint x;
-
-  neg = 0;
-  if(sgn && xx < 0){
-    neg = 1;
-    x = -xx;
-  } else {
-    x = xx;
-  }
-
-  i = 0;
-  do{
-    buf[i++] = digits[x % base];
-  }while((x /= base) != 0);
-  if(neg)
-    buf[i++] = '-';
-
-  while(--i >= 0)
-    putc(fd, buf[i]);
-}
-
-// Print to the given fd. Only understands %d, %x, %p, %s.
-void
-printf(int fd, const char *fmt, ...)
-{
-  char *s;
-  int c, i, state;
-  uint *ap;
-
-  state = 0;
-  ap = (uint*)(void*)&fmt + 1;
-  for(i = 0; fmt[i]; i++){
-    c = fmt[i] & 0xff;
-    if(state == 0){
-      if(c == '%'){
-        state = '%';
-      } else {
-        putc(fd, c);
-      }
-    } else if(state == '%'){
-      if(c == 'd'){
-        printint(fd, *ap, 10, 1);
-        ap++;
-      } else if(c == 'x' || c == 'p'){
-        printint(fd, *ap, 16, 0);
-        ap++;
-      } else if(c == 's'){
-        s = (char*)*ap;
-        ap++;
-        if(s == 0)
-          s = "(null)";
-        while(*s != 0){
-          putc(fd, *s);
-          s++;
-        }
-      } else if(c == 'c'){
-        putc(fd, *ap);
-        ap++;
-      } else if(c == '%'){
-        putc(fd, c);
-      } else {
-        // Unknown % sequence.  Print it to draw attention.
-        putc(fd, '%');
-        putc(fd, c);
-      }
-      state = 0;
-    }
-  }
-}
diff --git a/printpcs b/printpcs
deleted file mode 100755 (executable)
index 81d039b..0000000
--- a/printpcs
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-# Decode the symbols from a panic EIP list
-
-# Find a working addr2line
-for p in i386-jos-elf-addr2line addr2line; do
-    if which $p 2>&1 >/dev/null && \
-       $p -h 2>&1 | grep -q '\belf32-i386\b'; then
-        break
-    fi
-done
-
-# Enable as much pretty-printing as this addr2line can do
-$p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@"
diff --git a/proc.c b/proc.c
deleted file mode 100644 (file)
index 806b1b1..0000000
--- a/proc.c
+++ /dev/null
@@ -1,534 +0,0 @@
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "x86.h"
-#include "proc.h"
-#include "spinlock.h"
-
-struct {
-  struct spinlock lock;
-  struct proc proc[NPROC];
-} ptable;
-
-static struct proc *initproc;
-
-int nextpid = 1;
-extern void forkret(void);
-extern void trapret(void);
-
-static void wakeup1(void *chan);
-
-void
-pinit(void)
-{
-  initlock(&ptable.lock, "ptable");
-}
-
-// Must be called with interrupts disabled
-int
-cpuid() {
-  return mycpu()-cpus;
-}
-
-// Must be called with interrupts disabled to avoid the caller being
-// rescheduled between reading lapicid and running through the loop.
-struct cpu*
-mycpu(void)
-{
-  int apicid, i;
-  
-  if(readeflags()&FL_IF)
-    panic("mycpu called with interrupts enabled\n");
-  
-  apicid = lapicid();
-  // APIC IDs are not guaranteed to be contiguous. Maybe we should have
-  // a reverse map, or reserve a register to store &cpus[i].
-  for (i = 0; i < ncpu; ++i) {
-    if (cpus[i].apicid == apicid)
-      return &cpus[i];
-  }
-  panic("unknown apicid\n");
-}
-
-// Disable interrupts so that we are not rescheduled
-// while reading proc from the cpu structure
-struct proc*
-myproc(void) {
-  struct cpu *c;
-  struct proc *p;
-  pushcli();
-  c = mycpu();
-  p = c->proc;
-  popcli();
-  return p;
-}
-
-//PAGEBREAK: 32
-// Look in the process table for an UNUSED proc.
-// If found, change state to EMBRYO and initialize
-// state required to run in the kernel.
-// Otherwise return 0.
-static struct proc*
-allocproc(void)
-{
-  struct proc *p;
-  char *sp;
-
-  acquire(&ptable.lock);
-
-  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
-    if(p->state == UNUSED)
-      goto found;
-
-  release(&ptable.lock);
-  return 0;
-
-found:
-  p->state = EMBRYO;
-  p->pid = nextpid++;
-
-  release(&ptable.lock);
-
-  // Allocate kernel stack.
-  if((p->kstack = kalloc()) == 0){
-    p->state = UNUSED;
-    return 0;
-  }
-  sp = p->kstack + KSTACKSIZE;
-
-  // Leave room for trap frame.
-  sp -= sizeof *p->tf;
-  p->tf = (struct trapframe*)sp;
-
-  // Set up new context to start executing at forkret,
-  // which returns to trapret.
-  sp -= 4;
-  *(uint*)sp = (uint)trapret;
-
-  sp -= sizeof *p->context;
-  p->context = (struct context*)sp;
-  memset(p->context, 0, sizeof *p->context);
-  p->context->eip = (uint)forkret;
-
-  return p;
-}
-
-//PAGEBREAK: 32
-// Set up first user process.
-void
-userinit(void)
-{
-  struct proc *p;
-  extern char _binary_initcode_start[], _binary_initcode_size[];
-
-  p = allocproc();
-  
-  initproc = p;
-  if((p->pgdir = setupkvm()) == 0)
-    panic("userinit: out of memory?");
-  inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
-  p->sz = PGSIZE;
-  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 = PGSIZE;
-  p->tf->eip = 0;  // beginning of initcode.S
-
-  safestrcpy(p->name, "initcode", sizeof(p->name));
-  p->cwd = namei("/");
-
-  // this assignment to p->state lets other cores
-  // run this process. the acquire forces the above
-  // writes to be visible, and the lock is also needed
-  // because the assignment might not be atomic.
-  acquire(&ptable.lock);
-
-  p->state = RUNNABLE;
-
-  release(&ptable.lock);
-}
-
-// Grow current process's memory by n bytes.
-// Return 0 on success, -1 on failure.
-int
-growproc(int n)
-{
-  uint sz;
-  struct proc *curproc = myproc();
-
-  sz = curproc->sz;
-  if(n > 0){
-    if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
-      return -1;
-  } else if(n < 0){
-    if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)
-      return -1;
-  }
-  curproc->sz = sz;
-  switchuvm(curproc);
-  return 0;
-}
-
-// Create a new process copying p as the parent.
-// Sets up stack to return as if from system call.
-// Caller must set state of returned proc to RUNNABLE.
-int
-fork(void)
-{
-  int i, pid;
-  struct proc *np;
-  struct proc *curproc = myproc();
-
-  // Allocate process.
-  if((np = allocproc()) == 0){
-    return -1;
-  }
-
-  // Copy process state from proc.
-  if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
-    kfree(np->kstack);
-    np->kstack = 0;
-    np->state = UNUSED;
-    return -1;
-  }
-  np->sz = curproc->sz;
-  np->parent = curproc;
-  *np->tf = *curproc->tf;
-
-  // Clear %eax so that fork returns 0 in the child.
-  np->tf->eax = 0;
-
-  for(i = 0; i < NOFILE; i++)
-    if(curproc->ofile[i])
-      np->ofile[i] = filedup(curproc->ofile[i]);
-  np->cwd = idup(curproc->cwd);
-
-  safestrcpy(np->name, curproc->name, sizeof(curproc->name));
-
-  pid = np->pid;
-
-  acquire(&ptable.lock);
-
-  np->state = RUNNABLE;
-
-  release(&ptable.lock);
-
-  return pid;
-}
-
-// Exit the current process.  Does not return.
-// An exited process remains in the zombie state
-// until its parent calls wait() to find out it exited.
-void
-exit(void)
-{
-  struct proc *curproc = myproc();
-  struct proc *p;
-  int fd;
-
-  if(curproc == initproc)
-    panic("init exiting");
-
-  // Close all open files.
-  for(fd = 0; fd < NOFILE; fd++){
-    if(curproc->ofile[fd]){
-      fileclose(curproc->ofile[fd]);
-      curproc->ofile[fd] = 0;
-    }
-  }
-
-  begin_op();
-  iput(curproc->cwd);
-  end_op();
-  curproc->cwd = 0;
-
-  acquire(&ptable.lock);
-
-  // Parent might be sleeping in wait().
-  wakeup1(curproc->parent);
-
-  // Pass abandoned children to init.
-  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
-    if(p->parent == curproc){
-      p->parent = initproc;
-      if(p->state == ZOMBIE)
-        wakeup1(initproc);
-    }
-  }
-
-  // Jump into the scheduler, never to return.
-  curproc->state = ZOMBIE;
-  sched();
-  panic("zombie exit");
-}
-
-// Wait for a child process to exit and return its pid.
-// Return -1 if this process has no children.
-int
-wait(void)
-{
-  struct proc *p;
-  int havekids, pid;
-  struct proc *curproc = myproc();
-  
-  acquire(&ptable.lock);
-  for(;;){
-    // Scan through table looking for exited children.
-    havekids = 0;
-    for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
-      if(p->parent != curproc)
-        continue;
-      havekids = 1;
-      if(p->state == ZOMBIE){
-        // Found one.
-        pid = p->pid;
-        kfree(p->kstack);
-        p->kstack = 0;
-        freevm(p->pgdir);
-        p->pid = 0;
-        p->parent = 0;
-        p->name[0] = 0;
-        p->killed = 0;
-        p->state = UNUSED;
-        release(&ptable.lock);
-        return pid;
-      }
-    }
-
-    // No point waiting if we don't have any children.
-    if(!havekids || curproc->killed){
-      release(&ptable.lock);
-      return -1;
-    }
-
-    // Wait for children to exit.  (See wakeup1 call in proc_exit.)
-    sleep(curproc, &ptable.lock);  //DOC: wait-sleep
-  }
-}
-
-//PAGEBREAK: 42
-// Per-CPU process scheduler.
-// Each CPU calls scheduler() after setting itself up.
-// Scheduler never returns.  It loops, doing:
-//  - choose a process to run
-//  - swtch to start running that process
-//  - eventually that process transfers control
-//      via swtch back to the scheduler.
-void
-scheduler(void)
-{
-  struct proc *p;
-  struct cpu *c = mycpu();
-  c->proc = 0;
-  
-  for(;;){
-    // Enable interrupts on this processor.
-    sti();
-
-    // Loop over process table looking for process to run.
-    acquire(&ptable.lock);
-    for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
-      if(p->state != RUNNABLE)
-        continue;
-
-      // Switch to chosen process.  It is the process's job
-      // to release ptable.lock and then reacquire it
-      // before jumping back to us.
-      c->proc = p;
-      switchuvm(p);
-      p->state = RUNNING;
-
-      swtch(&(c->scheduler), p->context);
-      switchkvm();
-
-      // Process is done running for now.
-      // It should have changed its p->state before coming back.
-      c->proc = 0;
-    }
-    release(&ptable.lock);
-
-  }
-}
-
-// Enter scheduler.  Must hold only ptable.lock
-// and have changed proc->state. Saves and restores
-// intena because intena is a property of this
-// kernel thread, not this CPU. It should
-// be proc->intena and proc->ncli, but that would
-// break in the few places where a lock is held but
-// there's no process.
-void
-sched(void)
-{
-  int intena;
-  struct proc *p = myproc();
-
-  if(!holding(&ptable.lock))
-    panic("sched ptable.lock");
-  if(mycpu()->ncli != 1)
-    panic("sched locks");
-  if(p->state == RUNNING)
-    panic("sched running");
-  if(readeflags()&FL_IF)
-    panic("sched interruptible");
-  intena = mycpu()->intena;
-  swtch(&p->context, mycpu()->scheduler);
-  mycpu()->intena = intena;
-}
-
-// Give up the CPU for one scheduling round.
-void
-yield(void)
-{
-  acquire(&ptable.lock);  //DOC: yieldlock
-  myproc()->state = RUNNABLE;
-  sched();
-  release(&ptable.lock);
-}
-
-// A fork child's very first scheduling by scheduler()
-// will swtch here.  "Return" to user space.
-void
-forkret(void)
-{
-  static int first = 1;
-  // Still holding ptable.lock from scheduler.
-  release(&ptable.lock);
-
-  if (first) {
-    // Some initialization functions must be run in the context
-    // of a regular process (e.g., they call sleep), and thus cannot
-    // be run from main().
-    first = 0;
-    iinit(ROOTDEV);
-    initlog(ROOTDEV);
-  }
-
-  // Return to "caller", actually trapret (see allocproc).
-}
-
-// Atomically release lock and sleep on chan.
-// Reacquires lock when awakened.
-void
-sleep(void *chan, struct spinlock *lk)
-{
-  struct proc *p = myproc();
-  
-  if(p == 0)
-    panic("sleep");
-
-  if(lk == 0)
-    panic("sleep without lk");
-
-  // Must acquire ptable.lock in order to
-  // change p->state and then call sched.
-  // Once we hold ptable.lock, we can be
-  // guaranteed that we won't miss any wakeup
-  // (wakeup runs with ptable.lock locked),
-  // so it's okay to release lk.
-  if(lk != &ptable.lock){  //DOC: sleeplock0
-    acquire(&ptable.lock);  //DOC: sleeplock1
-    release(lk);
-  }
-  // Go to sleep.
-  p->chan = chan;
-  p->state = SLEEPING;
-
-  sched();
-
-  // Tidy up.
-  p->chan = 0;
-
-  // Reacquire original lock.
-  if(lk != &ptable.lock){  //DOC: sleeplock2
-    release(&ptable.lock);
-    acquire(lk);
-  }
-}
-
-//PAGEBREAK!
-// Wake up all processes sleeping on chan.
-// The ptable lock must be held.
-static void
-wakeup1(void *chan)
-{
-  struct proc *p;
-
-  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
-    if(p->state == SLEEPING && p->chan == chan)
-      p->state = RUNNABLE;
-}
-
-// Wake up all processes sleeping on chan.
-void
-wakeup(void *chan)
-{
-  acquire(&ptable.lock);
-  wakeup1(chan);
-  release(&ptable.lock);
-}
-
-// Kill the process with the given pid.
-// Process won't exit until it returns
-// to user space (see trap in trap.c).
-int
-kill(int pid)
-{
-  struct proc *p;
-
-  acquire(&ptable.lock);
-  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
-    if(p->pid == pid){
-      p->killed = 1;
-      // Wake process from sleep if necessary.
-      if(p->state == SLEEPING)
-        p->state = RUNNABLE;
-      release(&ptable.lock);
-      return 0;
-    }
-  }
-  release(&ptable.lock);
-  return -1;
-}
-
-//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");
-  }
-}
diff --git a/proc.h b/proc.h
deleted file mode 100644 (file)
index 0c574b9..0000000
--- a/proc.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <stdatomic.h>
-
-// Per-CPU state
-struct cpu {
-  uchar apicid;                // Local APIC ID
-  struct context *scheduler;   // swtch() here to enter scheduler
-  struct taskstate ts;         // Used by x86 to find stack for interrupt
-  struct segdesc gdt[NSEGS];   // x86 global descriptor table
-  atomic_uint started;       // Has the CPU started?
-  int ncli;                    // Depth of pushcli nesting.
-  int intena;                  // Were interrupts enabled before pushcli?
-  struct proc *proc;           // The process running on this cpu or null
-};
-
-extern struct cpu cpus[NCPU];
-extern int ncpu;
-
-//PAGEBREAK: 17
-// Saved registers for kernel context switches.
-// Don't need to save all the segment registers (%cs, etc),
-// because they are constant across kernel contexts.
-// Don't need to save %eax, %ecx, %edx, because the
-// x86 convention is that the caller has saved them.
-// Contexts are stored at the bottom of the stack they
-// describe; the stack pointer is the address of the context.
-// The layout of the context matches the layout of the stack in swtch.S
-// at the "Switch stacks" comment. Switch doesn't save eip explicitly,
-// but it is on the stack and allocproc() manipulates it.
-struct context {
-  uint edi;
-  uint esi;
-  uint ebx;
-  uint ebp;
-  uint eip;
-};
-
-enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
-
-// Per-process state
-struct proc {
-  uint sz;                     // Size of process memory (bytes)
-  pde_t* pgdir;                // Page table
-  char *kstack;                // Bottom of kernel stack for this process
-  enum procstate state;        // Process state
-  int pid;                     // Process ID
-  struct proc *parent;         // Parent process
-  struct trapframe *tf;        // Trap frame for current syscall
-  struct context *context;     // swtch() here to run process
-  void *chan;                  // If non-zero, sleeping on chan
-  int killed;                  // If non-zero, have been killed
-  struct file *ofile[NOFILE];  // Open files
-  struct inode *cwd;           // Current directory
-  char name[16];               // Process name (debugging)
-};
-
-// Process memory is laid out contiguously, low addresses first:
-//   text
-//   original data and bss
-//   fixed-size stack
-//   expandable heap
diff --git a/rm.c b/rm.c
deleted file mode 100644 (file)
index 4fd33c8..0000000
--- a/rm.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-int
-main(int argc, char *argv[])
-{
-  int i;
-
-  if(argc < 2){
-    printf(2, "Usage: rm files...\n");
-    exit();
-  }
-
-  for(i = 1; i < argc; i++){
-    if(unlink(argv[i]) < 0){
-      printf(2, "rm: %s failed to delete\n", argv[i]);
-      break;
-    }
-  }
-
-  exit();
-}
diff --git a/runoff b/runoff
deleted file mode 100755 (executable)
index be362d0..0000000
--- a/runoff
+++ /dev/null
@@ -1,246 +0,0 @@
-#!/bin/sh
-
-echo This script takes a minute to run.  Be patient. 1>&2
-
-LC_CTYPE=C export LC_CTYPE
-
-# pad stdin to multiple of 120 lines
-pad()
-{
-       awk '{print} END{for(; NR%120!=0; NR++) print ""}'
-}
-
-# create formatted (numbered) files
-mkdir -p fmt
-rm -f fmt/*
-cp README fmt
-echo > fmt/blank
-files=`grep -v '^#' runoff.list | awk '{print $1}'`
-n=99
-for i in $files
-do
-       ./runoff1 -n $n $i >fmt/$i
-       nn=`tail -1 fmt/$i | sed 's/ .*//; s/^0*//'`
-       if [ "x$nn" != x ]; then
-               n=$nn
-       fi
-done
-
-# create table of contents
-cat toc.hdr >fmt/toc
-pr -e8 -t runoff.list | awk '
-/^[a-z0-9]/ {
-       s=$0
-       f="fmt/"$1
-       getline<f
-       close(f)
-       n=$1
-       printf("%02d %s\n", n/100, s);
-       printf("TOC: %04d %s\n", n, s) >"fmt/tocdata"
-       next
-}
-{
-       print
-}' | pr -3 -t >>fmt/toc
-cat toc.ftr >>fmt/toc
-
-# check for bad alignments
-perl -e '
-       $leftwarn = 0;
-       while(<>){
-               chomp;
-               s!#.*!!;
-               s!\s+! !g;
-               s! +$!!;
-               next if /^$/;
-               
-               if(/TOC: (\d+) (.*)/){
-                       $toc{$2} = $1;
-                       next;
-               }
-               
-               if(/sheet1: (left|right)$/){
-                       print STDERR "assuming that sheet 1 is a $1 page.  double-check!\n";
-                       $left = $1 eq "left" ? "13579" : "02468";
-                       $right = $1 eq "left" ? "02468" : "13579";
-                       next;
-               }
-               
-               if(/even: (.*)/){
-                       $file = $1;
-                       if(!defined($toc{$file})){
-                               print STDERR "Have no toc for $file\n";
-                               next;
-                       }
-                       if($toc{$file} =~ /^\d\d[^0]/){
-                               print STDERR "$file does not start on a fresh page.\n";
-                       }
-                       next;
-               }
-               
-               if(/odd: (.*)/){
-                       $file = $1;
-                       if(!defined($toc{$file})){
-                               print STDERR "Have no toc for $file\n";
-                               next;
-                       }
-                       if($toc{$file} !~ /^\d\d5/){
-                               print STDERR "$file does not start on a second half page.\n";
-                       }
-                       next;
-               }
-               
-               if(/(left|right): (.*)/){
-                       $what = $1;
-                       $file = $2;
-                       if(!defined($toc{$file})){
-                               print STDERR "Have no toc for $file\n";
-                               next;
-                       }
-                       if($what eq "left" && !($toc{$file} =~ /^\d[$left][05]/)){
-                               print STDERR "$file does not start on a left page [$toc{$file}]\n";
-                       }
-                       # why does this not work if I inline $x in the if?
-                       $x = ($toc{$file} =~ /^\d[$right][05]/);
-                       if($what eq "right" && !$x){
-                               print STDERR "$file does not start on a right page [$toc{$file}] [$x]\n";
-                       }
-                       next;
-               }
-               
-               print STDERR "Unknown spec: $_\n";
-       }
-' fmt/tocdata runoff.spec
-
-# make definition list
-cd fmt
-perl -e '
-       while(<>) {
-               chomp;
-
-               s!//.*!!;
-               s!/\*([^*]|[*][^/])*\*/!!g;
-               s!\s! !g;
-               s! +$!!;
-
-               # look for declarations like char* x;
-               if (/^[0-9]+ typedef .* u(int|short|long|char);/) {
-                       next;
-               }
-               if (/^[0-9]+ extern/) {
-                       next;
-               }
-               if (/^[0-9]+ struct [a-zA-Z0-9_]+;/) {
-                       next;
-               }
-               if (/^([0-9]+) #define +([A-za-z0-9_]+) +?\(.*/) {
-                       print "$1 $2\n"
-               }
-               elsif (/^([0-9]+) #define +([A-Za-z0-9_]+) +([^ ]+)/) {
-                       print "$1 $2 $3\n";
-               }
-               elsif (/^([0-9]+) #define +([A-Za-z0-9_]+)/) {
-                       print "$1 $2\n";
-               }
-               
-               if(/^^([0-9]+) \.globl ([a-zA-Z0-9_]+)/){
-                       $isglobl{$2} = 1;
-               }
-               if(/^^([0-9]+) ([a-zA-Z0-9_]+):$/ && $isglobl{$2}){
-                       print "$1 $2\n";
-               }
-               
-               if (/\(/) {
-                       next;
-               }
-
-               if (/^([0-9]+) (((static|struct|extern|union|enum) +)*([A-Za-z0-9_]+))( .*)? +([A-Za-z_][A-Za-z0-9_]*)(,|;|=| =)/) {
-                       print "$1 $7\n";
-               }
-               
-               elsif(/^([0-9]+) (enum|struct|union) +([A-Za-z0-9_]+) +{/){ 
-                       print "$1 $3\n";
-               }
-               # TODO: enum members
-       }
-' $files >defs
-
-(for i in $files
-do
-       case "$i" in
-       *.S)
-               cat $i | sed 's;#.*;;; s;//.*;;;'
-               ;;
-       *)
-               cat $i | sed 's;//.*;;; s;"([^"\\]|\\.)*";;;'
-       esac
-done
-) >alltext
-
-perl -n -e 'print if s/^([0-9]+ [a-zA-Z0-9_]+)\(.*$/\1/;' alltext |
-       egrep -v ' (STUB|usage|main|if|for)$' >>defs
-#perl -n -e 'print if s/^([0-9]+) STUB\(([a-zA-Z0-9_]+)\)$/\1 \2/;' alltext \
-#      >>defs
-(
->s.defs
-
-# make reference list
-for i in `awk '{print $2}' defs | sort -f | uniq`
-do
-       defs=`egrep '^[0-9]+ '$i'( |$)' defs | awk '{print $1}'`
-       echo $i $defs >>s.defs
-       uses=`egrep -h '([^a-zA-Z_0-9])'$i'($|[^a-zA-Z_0-9])' alltext | awk '{print $1}'`
-       if [ "x$defs" != "x$uses" ]; then
-               echo $i $defs
-               echo $uses |fmt -29 | sed 's/^/    /'
-#      else
-#              echo $i defined but not used >&2
-       fi
-done
-) >refs
-
-# build defs list
-awk '
-{
-       printf("%04d %s\n", $2, $1);
-       for(i=3; i<=NF; i++)
-               printf("%04d    \" \n", $i);
-}
-' s.defs > t.defs
-
-# format the whole thing
-(
-       ../pr.pl README
-       ../pr.pl -h "table of contents" toc
-       # pr -t -2 t.defs | ../pr.pl -h "definitions" | pad
-       pr -t -l50 -2 refs | ../pr.pl -h "cross-references" | pad
-       # pr.pl -h "definitions" -2 t.defs | pad
-       # pr.pl -h "cross-references" -2 refs | pad
-       ../pr.pl blank  # make sheet 1 start on left page
-       ../pr.pl blank
-       for i in $files
-       do
-               ../pr.pl -h "xv6/$i" $i
-       done
-) | mpage -m50t50b -o -bLetter -T -t -2 -FCourier -L60 >all.ps
-grep Pages: all.ps
-
-# if we have the nice font, use it
-nicefont=LucidaSans-Typewriter83
-if [ ! -f ../$nicefont ]
-then
-       if git cat-file blob font:$nicefont > ../$nicefont~; then
-               mv ../$nicefont~ ../$nicefont
-       fi
-fi
-if [ -f ../$nicefont ]
-then
-       echo nicefont
-       (sed 1q all.ps; cat ../$nicefont; sed "1d; s/Courier/$nicefont/" all.ps) >allf.ps
-else
-       echo ugly font!
-       cp all.ps allf.ps
-fi
-ps2pdf allf.ps ../xv6.pdf
-# cd ..
-# pdftops xv6.pdf xv6.ps
diff --git a/runoff.list b/runoff.list
deleted file mode 100644 (file)
index 2df9b81..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-# basic headers
-types.h
-param.h
-memlayout.h
-defs.h
-x86.h
-asm.h
-mmu.h
-elf.h
-date.h
-
-# entering xv6
-entry.S
-entryother.S
-main.c
-
-# locks
-spinlock.h
-spinlock.c
-
-# processes
-vm.c
-proc.h
-proc.c
-swtch.S
-kalloc.c
-
-# system calls
-traps.h
-vectors.pl
-trapasm.S
-trap.c
-syscall.h
-syscall.c
-sysproc.c
-
-# file system
-buf.h
-sleeplock.h
-fcntl.h
-stat.h
-fs.h
-file.h
-ide.c
-bio.c
-sleeplock.c
-log.c
-fs.c
-file.c
-sysfile.c
-exec.c
-
-# pipes
-pipe.c
-
-# string operations
-string.c
-
-# low-level hardware
-mp.h
-mp.c
-lapic.c
-ioapic.c
-kbd.h
-kbd.c
-console.c
-uart.c
-
-# user-level
-initcode.S
-usys.S
-init.c
-sh.c
-
-# bootloader
-bootasm.S
-bootmain.c
-
-# link
-kernel.ld
diff --git a/runoff.spec b/runoff.spec
deleted file mode 100644 (file)
index 9247948..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-# Is sheet 01 (after the TOC) a left sheet or a right sheet?
-sheet1: left
-
-# "left" and "right" specify which page of a two-page spread a file
-# must start on.  "left" means that a file must start on the first of
-# the two pages.  "right" means it must start on the second of the two
-# pages.  The file may start in either column.
-#
-# "even" and "odd" specify which column a file must start on.  "even"
-# means it must start in the left of the two columns (00).  "odd" means it
-# must start in the right of the two columns (50).
-#
-# You'd think these would be the other way around.
-
-# types.h either
-# param.h either
-# defs.h either
-# x86.h either
-# asm.h either
-# mmu.h either
-# elf.h either
-# mp.h either
-
-even: entry.S  # mild preference
-even: entryother.S  # mild preference
-even: main.c
-# mp.c don't care at all
-# even: initcode.S
-# odd: init.c
-
-left: spinlock.h
-even: spinlock.h
-
-# This gets struct proc and allocproc on the same spread
-left: proc.h
-even: proc.h
-
-# goal is to have two action-packed 2-page spreads,
-# one with
-#     userinit growproc fork exit wait
-# and another with
-#     scheduler sched yield forkret sleep wakeup1 wakeup
-right: proc.c   # VERY important
-even: proc.c   # VERY important
-
-# A few more action packed spreads
-# page table creation and process loading
-#     walkpgdir mappages setupkvm switch[ku]vm inituvm (loaduvm)
-# process memory management
-#     allocuvm deallocuvm freevm
-left: vm.c
-
-even: kalloc.c  # mild preference
-
-# syscall.h either
-# trapasm.S either
-# traps.h either
-# even: trap.c
-# vectors.pl either
-# syscall.c either
-# sysproc.c either
-
-# buf.h either
-# dev.h either
-# fcntl.h either
-# stat.h either
-# file.h either
-# fs.h either
-# fsvar.h either
-# left: ide.c # mild preference
-even: ide.c
-# odd: bio.c
-
-# log.c fits nicely in a spread
-even: log.c
-left: log.c
-
-# with fs.c starting on 2nd column of a left page, we get these 2-page spreads:
-#      ialloc iupdate iget idup ilock iunlock iput iunlockput
-#      bmap itrunc stati readi writei
-#      namecmp dirlookup dirlink skipelem namex namei
-#      fileinit filealloc filedup fileclose filestat fileread filewrite
-# starting on 2nd column of a right page is not terrible either
-odd: fs.c   # VERY important
-left: fs.c  # mild preference
-# file.c either
-# exec.c either
-# sysfile.c either
-
-# Mild preference, but makes spreads of mp.c, lapic.c, and ioapic.c+picirq.c
-even: mp.c
-left: mp.c
-
-# even: pipe.c  # mild preference
-# string.c either
-# left: kbd.h  # mild preference
-even: kbd.h
-even: console.c
-odd: sh.c
-
-even: bootasm.S   # mild preference
-even: bootmain.c  # mild preference
diff --git a/runoff1 b/runoff1
deleted file mode 100755 (executable)
index 532f844..0000000
--- a/runoff1
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/perl
-
-$n = 0;
-$v = 0;
-if($ARGV[0] eq "-v") {
-       $v = 1;
-       shift @ARGV;
-}
-if($ARGV[0] eq "-n") {
-       $n = $ARGV[1];
-       shift @ARGV;
-       shift @ARGV;
-}
-$n = int(($n+49)/50)*50 - 1;
-
-$file = $ARGV[0];
-@lines = <>;
-$linenum = 0;
-foreach (@lines) {
-       $linenum++;
-       chomp;
-       s/\s+$//;
-       if(length() >= 75){
-               print STDERR "$file:$linenum: line too long\n";
-       }
-}
-@outlines = ();
-$nextout = 0;
-
-for($i=0; $i<@lines; ){
-       # Skip leading blank lines.
-       $i++ while $i<@lines && $lines[$i] =~ /^$/;
-       last if $i>=@lines;
-
-       # If the rest of the file fits, use the whole thing.
-       if(@lines <= $i+50 && !grep { /PAGEBREAK/ } @lines){
-               $breakbefore = @lines;
-       }else{
-               # Find a good next page break;
-               # Hope for end of function.
-               # but settle for a blank line (but not first blank line
-               # in function, which comes after variable declarations).
-               $breakbefore = $i;
-               $lastblank = $i;
-               $sawbrace = 0;
-               $breaksize = 15;  # 15 lines to get to function
-               for($j=$i; $j<$i+50 && $j < @lines; $j++){
-                       if($lines[$j] =~ /PAGEBREAK!/){
-                               $lines[$j] = "";
-                               $breakbefore = $j;
-                               $breaksize = 100;
-                               last;
-                       }
-                       if($lines[$j] =~ /PAGEBREAK:\s*([0-9]+)/){
-                               $breaksize = $1;
-                               $breakbefore = $j;
-                               $lines[$j] = "";
-                       }
-                       if($lines[$j] =~ /^};?$/){
-                               $breakbefore = $j+1;
-                               $breaksize = 15;
-                       }
-                       if($lines[$j] =~ /^{$/){
-                               $sawbrace = 1;
-                       }
-                       if($lines[$j] =~ /^$/){
-                               if($sawbrace){
-                                       $sawbrace = 0;
-                               }else{
-                                       $lastblank = $j;
-                               }
-                       }
-               }
-               if($j<@lines && $lines[$j] =~ /^$/){
-                       $lastblank = $j;
-               }
-
-               # If we are not putting enough on a page, try a blank line.
-               if($breakbefore - $i < 50 - $breaksize && $lastblank > $breakbefore && $lastblank >= $i+50 - 5){
-                       if($v){
-                               print STDERR "breakbefore $breakbefore i $i breaksize $breaksize\n";
-                       }
-                       $breakbefore = $lastblank;
-                       $breaksize = 5;  # only 5 lines to get to blank line
-               }
-
-               # If we are not putting enough on a page, force a full page.
-               if($breakbefore - $i < 50 - $breaksize && $breakbefore != @lines){
-                       $breakbefore = $i + 50;
-                       $breakbefore = @lines if @lines < $breakbefore;
-               }
-
-               if($breakbefore < $i+2){
-                       $breakbefore = $i+2;
-               }
-       }
-
-       # Emit the page.
-       $i50 = $i + 50;
-       for(; $i<$breakbefore; $i++){
-               printf "%04d %s\n", ++$n, $lines[$i];
-       }
-
-       # Finish page
-       for($j=$i; $j<$i50; $j++){
-               printf "%04d \n", ++$n;
-       }
-}
diff --git a/sh.c b/sh.c
deleted file mode 100644 (file)
index 054bab9..0000000
--- a/sh.c
+++ /dev/null
@@ -1,493 +0,0 @@
-// Shell.
-
-#include "types.h"
-#include "user.h"
-#include "fcntl.h"
-
-// Parsed command representation
-#define EXEC  1
-#define REDIR 2
-#define PIPE  3
-#define LIST  4
-#define BACK  5
-
-#define MAXARGS 10
-
-struct cmd {
-  int type;
-};
-
-struct execcmd {
-  int type;
-  char *argv[MAXARGS];
-  char *eargv[MAXARGS];
-};
-
-struct redircmd {
-  int type;
-  struct cmd *cmd;
-  char *file;
-  char *efile;
-  int mode;
-  int fd;
-};
-
-struct pipecmd {
-  int type;
-  struct cmd *left;
-  struct cmd *right;
-};
-
-struct listcmd {
-  int type;
-  struct cmd *left;
-  struct cmd *right;
-};
-
-struct backcmd {
-  int type;
-  struct cmd *cmd;
-};
-
-int fork1(void);  // Fork but panics on failure.
-void panic(char*);
-struct cmd *parsecmd(char*);
-
-// Execute cmd.  Never returns.
-void
-runcmd(struct cmd *cmd)
-{
-  int p[2];
-  struct backcmd *bcmd;
-  struct execcmd *ecmd;
-  struct listcmd *lcmd;
-  struct pipecmd *pcmd;
-  struct redircmd *rcmd;
-
-  if(cmd == 0)
-    exit();
-
-  switch(cmd->type){
-  default:
-    panic("runcmd");
-
-  case EXEC:
-    ecmd = (struct execcmd*)cmd;
-    if(ecmd->argv[0] == 0)
-      exit();
-    exec(ecmd->argv[0], ecmd->argv);
-    printf(2, "exec %s failed\n", ecmd->argv[0]);
-    break;
-
-  case REDIR:
-    rcmd = (struct redircmd*)cmd;
-    close(rcmd->fd);
-    if(open(rcmd->file, rcmd->mode) < 0){
-      printf(2, "open %s failed\n", rcmd->file);
-      exit();
-    }
-    runcmd(rcmd->cmd);
-    break;
-
-  case LIST:
-    lcmd = (struct listcmd*)cmd;
-    if(fork1() == 0)
-      runcmd(lcmd->left);
-    wait();
-    runcmd(lcmd->right);
-    break;
-
-  case PIPE:
-    pcmd = (struct pipecmd*)cmd;
-    if(pipe(p) < 0)
-      panic("pipe");
-    if(fork1() == 0){
-      close(1);
-      dup(p[1]);
-      close(p[0]);
-      close(p[1]);
-      runcmd(pcmd->left);
-    }
-    if(fork1() == 0){
-      close(0);
-      dup(p[0]);
-      close(p[0]);
-      close(p[1]);
-      runcmd(pcmd->right);
-    }
-    close(p[0]);
-    close(p[1]);
-    wait();
-    wait();
-    break;
-
-  case BACK:
-    bcmd = (struct backcmd*)cmd;
-    if(fork1() == 0)
-      runcmd(bcmd->cmd);
-    break;
-  }
-  exit();
-}
-
-int
-getcmd(char *buf, int nbuf)
-{
-  printf(2, "$ ");
-  memset(buf, 0, nbuf);
-  gets(buf, nbuf);
-  if(buf[0] == 0) // EOF
-    return -1;
-  return 0;
-}
-
-int
-main(void)
-{
-  static char buf[100];
-  int fd;
-
-  // Ensure that three file descriptors are open.
-  while((fd = open("console", O_RDWR)) >= 0){
-    if(fd >= 3){
-      close(fd);
-      break;
-    }
-  }
-
-  // Read and run input commands.
-  while(getcmd(buf, sizeof(buf)) >= 0){
-    if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
-      // Chdir must be called by the parent, not the child.
-      buf[strlen(buf)-1] = 0;  // chop \n
-      if(chdir(buf+3) < 0)
-        printf(2, "cannot cd %s\n", buf+3);
-      continue;
-    }
-    if(fork1() == 0)
-      runcmd(parsecmd(buf));
-    wait();
-  }
-  exit();
-}
-
-void
-panic(char *s)
-{
-  printf(2, "%s\n", s);
-  exit();
-}
-
-int
-fork1(void)
-{
-  int pid;
-
-  pid = fork();
-  if(pid == -1)
-    panic("fork");
-  return pid;
-}
-
-//PAGEBREAK!
-// Constructors
-
-struct cmd*
-execcmd(void)
-{
-  struct execcmd *cmd;
-
-  cmd = malloc(sizeof(*cmd));
-  memset(cmd, 0, sizeof(*cmd));
-  cmd->type = EXEC;
-  return (struct cmd*)cmd;
-}
-
-struct cmd*
-redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)
-{
-  struct redircmd *cmd;
-
-  cmd = malloc(sizeof(*cmd));
-  memset(cmd, 0, sizeof(*cmd));
-  cmd->type = REDIR;
-  cmd->cmd = subcmd;
-  cmd->file = file;
-  cmd->efile = efile;
-  cmd->mode = mode;
-  cmd->fd = fd;
-  return (struct cmd*)cmd;
-}
-
-struct cmd*
-pipecmd(struct cmd *left, struct cmd *right)
-{
-  struct pipecmd *cmd;
-
-  cmd = malloc(sizeof(*cmd));
-  memset(cmd, 0, sizeof(*cmd));
-  cmd->type = PIPE;
-  cmd->left = left;
-  cmd->right = right;
-  return (struct cmd*)cmd;
-}
-
-struct cmd*
-listcmd(struct cmd *left, struct cmd *right)
-{
-  struct listcmd *cmd;
-
-  cmd = malloc(sizeof(*cmd));
-  memset(cmd, 0, sizeof(*cmd));
-  cmd->type = LIST;
-  cmd->left = left;
-  cmd->right = right;
-  return (struct cmd*)cmd;
-}
-
-struct cmd*
-backcmd(struct cmd *subcmd)
-{
-  struct backcmd *cmd;
-
-  cmd = malloc(sizeof(*cmd));
-  memset(cmd, 0, sizeof(*cmd));
-  cmd->type = BACK;
-  cmd->cmd = subcmd;
-  return (struct cmd*)cmd;
-}
-//PAGEBREAK!
-// Parsing
-
-char whitespace[] = " \t\r\n\v";
-char symbols[] = "<|>&;()";
-
-int
-gettoken(char **ps, char *es, char **q, char **eq)
-{
-  char *s;
-  int ret;
-
-  s = *ps;
-  while(s < es && strchr(whitespace, *s))
-    s++;
-  if(q)
-    *q = s;
-  ret = *s;
-  switch(*s){
-  case 0:
-    break;
-  case '|':
-  case '(':
-  case ')':
-  case ';':
-  case '&':
-  case '<':
-    s++;
-    break;
-  case '>':
-    s++;
-    if(*s == '>'){
-      ret = '+';
-      s++;
-    }
-    break;
-  default:
-    ret = 'a';
-    while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
-      s++;
-    break;
-  }
-  if(eq)
-    *eq = s;
-
-  while(s < es && strchr(whitespace, *s))
-    s++;
-  *ps = s;
-  return ret;
-}
-
-int
-peek(char **ps, char *es, char *toks)
-{
-  char *s;
-
-  s = *ps;
-  while(s < es && strchr(whitespace, *s))
-    s++;
-  *ps = s;
-  return *s && strchr(toks, *s);
-}
-
-struct cmd *parseline(char**, char*);
-struct cmd *parsepipe(char**, char*);
-struct cmd *parseexec(char**, char*);
-struct cmd *nulterminate(struct cmd*);
-
-struct cmd*
-parsecmd(char *s)
-{
-  char *es;
-  struct cmd *cmd;
-
-  es = s + strlen(s);
-  cmd = parseline(&s, es);
-  peek(&s, es, "");
-  if(s != es){
-    printf(2, "leftovers: %s\n", s);
-    panic("syntax");
-  }
-  nulterminate(cmd);
-  return cmd;
-}
-
-struct cmd*
-parseline(char **ps, char *es)
-{
-  struct cmd *cmd;
-
-  cmd = parsepipe(ps, es);
-  while(peek(ps, es, "&")){
-    gettoken(ps, es, 0, 0);
-    cmd = backcmd(cmd);
-  }
-  if(peek(ps, es, ";")){
-    gettoken(ps, es, 0, 0);
-    cmd = listcmd(cmd, parseline(ps, es));
-  }
-  return cmd;
-}
-
-struct cmd*
-parsepipe(char **ps, char *es)
-{
-  struct cmd *cmd;
-
-  cmd = parseexec(ps, es);
-  if(peek(ps, es, "|")){
-    gettoken(ps, es, 0, 0);
-    cmd = pipecmd(cmd, parsepipe(ps, es));
-  }
-  return cmd;
-}
-
-struct cmd*
-parseredirs(struct cmd *cmd, char **ps, char *es)
-{
-  int tok;
-  char *q, *eq;
-
-  while(peek(ps, es, "<>")){
-    tok = gettoken(ps, es, 0, 0);
-    if(gettoken(ps, es, &q, &eq) != 'a')
-      panic("missing file for redirection");
-    switch(tok){
-    case '<':
-      cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
-      break;
-    case '>':
-      cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
-      break;
-    case '+':  // >>
-      cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
-      break;
-    }
-  }
-  return cmd;
-}
-
-struct cmd*
-parseblock(char **ps, char *es)
-{
-  struct cmd *cmd;
-
-  if(!peek(ps, es, "("))
-    panic("parseblock");
-  gettoken(ps, es, 0, 0);
-  cmd = parseline(ps, es);
-  if(!peek(ps, es, ")"))
-    panic("syntax - missing )");
-  gettoken(ps, es, 0, 0);
-  cmd = parseredirs(cmd, ps, es);
-  return cmd;
-}
-
-struct cmd*
-parseexec(char **ps, char *es)
-{
-  char *q, *eq;
-  int tok, argc;
-  struct execcmd *cmd;
-  struct cmd *ret;
-
-  if(peek(ps, es, "("))
-    return parseblock(ps, es);
-
-  ret = execcmd();
-  cmd = (struct execcmd*)ret;
-
-  argc = 0;
-  ret = parseredirs(ret, ps, es);
-  while(!peek(ps, es, "|)&;")){
-    if((tok=gettoken(ps, es, &q, &eq)) == 0)
-      break;
-    if(tok != 'a')
-      panic("syntax");
-    cmd->argv[argc] = q;
-    cmd->eargv[argc] = eq;
-    argc++;
-    if(argc >= MAXARGS)
-      panic("too many args");
-    ret = parseredirs(ret, ps, es);
-  }
-  cmd->argv[argc] = 0;
-  cmd->eargv[argc] = 0;
-  return ret;
-}
-
-// NUL-terminate all the counted strings.
-struct cmd*
-nulterminate(struct cmd *cmd)
-{
-  int i;
-  struct backcmd *bcmd;
-  struct execcmd *ecmd;
-  struct listcmd *lcmd;
-  struct pipecmd *pcmd;
-  struct redircmd *rcmd;
-
-  if(cmd == 0)
-    return 0;
-
-  switch(cmd->type){
-  case EXEC:
-    ecmd = (struct execcmd*)cmd;
-    for(i=0; ecmd->argv[i]; i++)
-      *ecmd->eargv[i] = 0;
-    break;
-
-  case REDIR:
-    rcmd = (struct redircmd*)cmd;
-    nulterminate(rcmd->cmd);
-    *rcmd->efile = 0;
-    break;
-
-  case PIPE:
-    pcmd = (struct pipecmd*)cmd;
-    nulterminate(pcmd->left);
-    nulterminate(pcmd->right);
-    break;
-
-  case LIST:
-    lcmd = (struct listcmd*)cmd;
-    nulterminate(lcmd->left);
-    nulterminate(lcmd->right);
-    break;
-
-  case BACK:
-    bcmd = (struct backcmd*)cmd;
-    nulterminate(bcmd->cmd);
-    break;
-  }
-  return cmd;
-}
diff --git a/show1 b/show1
deleted file mode 100755 (executable)
index e0d3d83..0000000
--- a/show1
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps
diff --git a/sign.pl b/sign.pl
deleted file mode 100755 (executable)
index d793035..0000000
--- a/sign.pl
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/perl
-
-open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!";
-
-$n = sysread(SIG, $buf, 1000);
-
-if($n > 510){
-  print STDERR "boot block too large: $n bytes (max 510)\n";
-  exit 1;
-}
-
-print STDERR "boot block is $n bytes (max 510)\n";
-
-$buf .= "\0" x (510-$n);
-$buf .= "\x55\xAA";
-
-open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!";
-print SIG $buf;
-close SIG;
diff --git a/sleep1.p b/sleep1.p
deleted file mode 100644 (file)
index af69772..0000000
--- a/sleep1.p
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-This file defines a Promela model for xv6's
-acquire, release, sleep, and wakeup, along with
-a model of a simple producer/consumer queue.
-
-To run:
-       spinp sleep1.p
-
-(You may need to install Spin, available at http://spinroot.com/.)
-
-After a successful run spin prints something like:
-
-       unreached in proctype consumer
-               (0 of 37 states)
-       unreached in proctype producer
-               (0 of 23 states)
-
-After an unsuccessful run, the spinp script prints
-an execution trace that causes a deadlock.
-
-The safe body of producer reads:
-
-               acquire(lk);
-               x = value; value = x + 1; x = 0;
-               wakeup(0);
-               release(lk);
-               i = i + 1;
-
-If this is changed to:
-
-               x = value; value = x + 1; x = 0;
-               acquire(lk);
-               wakeup(0);
-               release(lk);
-               i = i + 1;
-
-then a deadlock can happen, because the non-atomic
-increment of value conflicts with the non-atomic 
-decrement in consumer, causing value to have a bad value.
-Try this.
-
-If it is changed to:
-
-               acquire(lk);
-               x = value; value = x + 1; x = 0;
-               release(lk);
-               wakeup(0);
-               i = i + 1;
-
-then nothing bad happens: it is okay to wakeup after release
-instead of before, although it seems morally wrong.
-*/
-
-#define ITER 4
-#define N 2
-
-bit lk;
-byte value;
-bit sleeping[N];
-
-inline acquire(x)
-{
-       atomic { x == 0; x = 1 }
-}
-
-inline release(x)
-{
-       assert x==1;
-       x = 0
-}
-
-inline sleep(cond, lk)
-{
-       assert !sleeping[_pid];
-       if
-       :: cond ->
-               skip
-       :: else ->
-               atomic { release(lk); sleeping[_pid] = 1 };
-               sleeping[_pid] == 0;
-               acquire(lk)
-       fi
-}
-
-inline wakeup()
-{
-       w = 0;
-       do
-       :: w < N ->
-               sleeping[w] = 0;
-               w = w + 1
-       :: else ->
-               break
-       od
-}
-
-active[N] proctype consumer()
-{
-       byte i, x;
-       
-       i = 0;
-       do
-       :: i < ITER ->
-               acquire(lk);
-               sleep(value > 0, lk);
-               x = value; value = x - 1; x = 0;
-               release(lk);
-               i = i + 1;
-       :: else ->
-               break
-       od;
-       i = 0;
-       skip
-}
-
-active[N] proctype producer()
-{
-       byte i, x, w;
-       
-       i = 0;
-       do
-       :: i < ITER ->
-               acquire(lk);
-               x = value; value = x + 1; x = 0;
-               release(lk);
-               wakeup();
-               i = i + 1;
-       :: else ->
-               break
-       od;
-       i = 0;
-       skip    
-}
-
diff --git a/sleeplock.c b/sleeplock.c
deleted file mode 100644 (file)
index e0750ea..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// Sleeping locks
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "x86.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-
-void
-initsleeplock(struct sleeplock *lk, char *name)
-{
-  initlock(&lk->lk, "sleep lock");
-  lk->name = name;
-  lk->locked = 0;
-  lk->pid = 0;
-}
-
-void
-acquiresleep(struct sleeplock *lk)
-{
-  acquire(&lk->lk);
-  while (lk->locked) {
-    sleep(lk, &lk->lk);
-  }
-  lk->locked = 1;
-  lk->pid = myproc()->pid;
-  release(&lk->lk);
-}
-
-void
-releasesleep(struct sleeplock *lk)
-{
-  acquire(&lk->lk);
-  lk->locked = 0;
-  lk->pid = 0;
-  wakeup(lk);
-  release(&lk->lk);
-}
-
-int
-holdingsleep(struct sleeplock *lk)
-{
-  int r;
-  
-  acquire(&lk->lk);
-  r = lk->locked && (lk->pid == myproc()->pid);
-  release(&lk->lk);
-  return r;
-}
-
-
-
diff --git a/sleeplock.h b/sleeplock.h
deleted file mode 100644 (file)
index 110e6f3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Long-term locks for processes
-struct sleeplock {
-  uint locked;       // Is the lock held?
-  struct spinlock lk; // spinlock protecting this sleep lock
-  
-  // For debugging:
-  char *name;        // Name of lock.
-  int pid;           // Process holding lock
-};
-
diff --git a/spinlock.c b/spinlock.c
deleted file mode 100644 (file)
index 78f2325..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// Mutual exclusion spin locks.
-#include <stdatomic.h>
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "x86.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "spinlock.h"
-
-void
-initlock(struct spinlock *lk, char *name)
-{
-  atomic_init(&lk->locked, 0);
-
-  lk->name = name;
-  lk->cpu = 0;
-}
-
-// Acquire the lock.
-// Loops (spins) until the lock is acquired.
-// Holding a lock for a long time may cause
-// other CPUs to waste time spinning to acquire it.
-void
-acquire(struct spinlock *lk)
-{
-  pushcli(); // disable interrupts to avoid deadlock.
-  if(holding(lk))
-    panic("acquire");
-
-  // Use c11 atomics to acquire the lock
-  //  Here we atomically exchange locked with 1.  If locked was 0, then we've
-  //    just acquired the lock!
-  //  We use the acquire release semantics (orderings).  We really only want
-  //    acquire semantics, but we are doing a read and modify operation at once
-  //    which requires acquire (write) and release (read) ordering semantics.
-  while (atomic_exchange_explicit(&lk->locked, 1, memory_order_acq_rel) != 0)
-    ;
-
-  // Record info about lock acquisition for debugging.
-  lk->cpu = mycpu();
-  getcallerpcs(&lk, lk->pcs);
-}
-
-// Release the lock.
-void
-release(struct spinlock *lk)
-{
-  if(!holding(lk))
-    panic("release");
-
-  lk->pcs[0] = 0;
-  lk->cpu = 0;
-
-  
-  // Use c11 atomics to release the lock.
-  //  Here we set the locked value to 0 atomically
-  //  We also give it "release" semantics, as we're doing an unlock 
-  //    (e.g. release) operation
-  atomic_store_explicit(&lk->locked, 0, memory_order_release);
-
-  popcli();
-}
-
-// Record the current call stack in pcs[] by following the %ebp chain.
-void
-getcallerpcs(void *v, uint pcs[])
-{
-  uint *ebp;
-  int i;
-
-  ebp = (uint*)v - 2;
-  for(i = 0; i < 10; i++){
-    if(ebp == 0 || ebp < (uint*)KERNBASE || ebp == (uint*)0xffffffff)
-      break;
-    pcs[i] = ebp[1];     // saved %eip
-    ebp = (uint*)ebp[0]; // saved %ebp
-  }
-  for(; i < 10; i++)
-    pcs[i] = 0;
-}
-
-// Check whether this cpu is holding the lock.
-int
-holding(struct spinlock *lock)
-{
-  int r;
-  pushcli();
-  r = lock->locked && lock->cpu == mycpu();
-  popcli();
-  return r;
-}
-
-
-// Pushcli/popcli are like cli/sti except that they are matched:
-// it takes two popcli to undo two pushcli.  Also, if interrupts
-// are off, then pushcli, popcli leaves them off.
-
-void
-pushcli(void)
-{
-  int eflags;
-
-  eflags = readeflags();
-  cli();
-  if(mycpu()->ncli == 0)
-    mycpu()->intena = eflags & FL_IF;
-  mycpu()->ncli += 1;
-}
-
-void
-popcli(void)
-{
-  if(readeflags()&FL_IF)
-    panic("popcli - interruptible");
-  if(--mycpu()->ncli < 0)
-    panic("popcli");
-  if(mycpu()->ncli == 0 && mycpu()->intena)
-    sti();
-}
-
diff --git a/spinlock.h b/spinlock.h
deleted file mode 100644 (file)
index 947aaee..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdatomic.h>
-
-// Mutual exclusion lock.
-struct spinlock {
-  atomic_uint locked;       // Is the lock held?
-
-  // For debugging:
-  char *name;        // Name of lock.
-  struct cpu *cpu;   // The cpu holding the lock.
-  uint pcs[10];      // The call stack (an array of program counters)
-                     // that locked the lock.
-};
-
diff --git a/spinp b/spinp
deleted file mode 100755 (executable)
index db9614b..0000000
--- a/spinp
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-if [ $# != 1 ] || [ ! -f "$1" ]; then
-       echo 'usage: spinp file.p' 1>&2
-       exit 1
-fi
-
-rm -f $1.trail
-spin -a $1 || exit 1
-cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c
-pan -i
-rm pan.* pan
-if [ -f $1.trail ]; then
-       spin -t -p $1
-fi
-
diff --git a/stat.h b/stat.h
deleted file mode 100644 (file)
index 8a80933..0000000
--- a/stat.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#define T_DIR  1   // Directory
-#define T_FILE 2   // File
-#define T_DEV  3   // Device
-
-struct stat {
-  short type;  // Type of file
-  int dev;     // File system's disk device
-  uint ino;    // Inode number
-  short nlink; // Number of links to file
-  uint size;   // Size of file in bytes
-};
diff --git a/stressfs.c b/stressfs.c
deleted file mode 100644 (file)
index c0a4743..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// Demonstrate that moving the "acquire" in iderw after the loop that
-// appends to the idequeue results in a race.
-
-// For this to work, you should also add a spin within iderw's
-// idequeue traversal loop.  Adding the following demonstrated a panic
-// after about 5 runs of stressfs in QEMU on a 2.1GHz CPU:
-//    for (i = 0; i < 40000; i++)
-//      asm volatile("");
-
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-#include "fs.h"
-#include "fcntl.h"
-
-int
-main(int argc, char *argv[])
-{
-  int fd, i;
-  char path[] = "stressfs0";
-  char data[512];
-
-  printf(1, "stressfs starting\n");
-  memset(data, 'a', sizeof(data));
-
-  for(i = 0; i < 4; i++)
-    if(fork() > 0)
-      break;
-
-  printf(1, "write %d\n", i);
-
-  path[8] += i;
-  fd = open(path, O_CREATE | O_RDWR);
-  for(i = 0; i < 20; i++)
-//    printf(fd, "%d\n", i);
-    write(fd, data, sizeof(data));
-  close(fd);
-
-  printf(1, "read\n");
-
-  fd = open(path, O_RDONLY);
-  for (i = 0; i < 20; i++)
-    read(fd, data, sizeof(data));
-  close(fd);
-
-  wait();
-
-  exit();
-}
diff --git a/string.c b/string.c
deleted file mode 100644 (file)
index a7cc61f..0000000
--- a/string.c
+++ /dev/null
@@ -1,105 +0,0 @@
-#include "types.h"
-#include "x86.h"
-
-void*
-memset(void *dst, int c, uint n)
-{
-  if ((int)dst%4 == 0 && n%4 == 0){
-    c &= 0xFF;
-    stosl(dst, (c<<24)|(c<<16)|(c<<8)|c, n/4);
-  } else
-    stosb(dst, c, n);
-  return dst;
-}
-
-int
-memcmp(const void *v1, const void *v2, uint n)
-{
-  const uchar *s1, *s2;
-
-  s1 = v1;
-  s2 = v2;
-  while(n-- > 0){
-    if(*s1 != *s2)
-      return *s1 - *s2;
-    s1++, s2++;
-  }
-
-  return 0;
-}
-
-void*
-memmove(void *dst, const void *src, uint n)
-{
-  const char *s;
-  char *d;
-
-  s = src;
-  d = dst;
-  if(s < d && s + n > d){
-    s += n;
-    d += n;
-    while(n-- > 0)
-      *--d = *--s;
-  } else
-    while(n-- > 0)
-      *d++ = *s++;
-
-  return dst;
-}
-
-// memcpy exists to placate GCC.  Use memmove.
-void*
-memcpy(void *dst, const void *src, uint n)
-{
-  return memmove(dst, src, n);
-}
-
-int
-strncmp(const char *p, const char *q, uint n)
-{
-  while(n > 0 && *p && *p == *q)
-    n--, p++, q++;
-  if(n == 0)
-    return 0;
-  return (uchar)*p - (uchar)*q;
-}
-
-char*
-strncpy(char *s, const char *t, int n)
-{
-  char *os;
-
-  os = s;
-  while(n-- > 0 && (*s++ = *t++) != 0)
-    ;
-  while(n-- > 0)
-    *s++ = 0;
-  return os;
-}
-
-// Like strncpy but guaranteed to NUL-terminate.
-char*
-safestrcpy(char *s, const char *t, int n)
-{
-  char *os;
-
-  os = s;
-  if(n <= 0)
-    return os;
-  while(--n > 0 && (*s++ = *t++) != 0)
-    ;
-  *s = 0;
-  return os;
-}
-
-int
-strlen(const char *s)
-{
-  int n;
-
-  for(n = 0; s[n]; n++)
-    ;
-  return n;
-}
-
diff --git a/swtch.S b/swtch.S
deleted file mode 100644 (file)
index 63a7dcc..0000000
--- a/swtch.S
+++ /dev/null
@@ -1,29 +0,0 @@
-# Context switch
-#
-#   void swtch(struct context **old, struct context *new);
-# 
-# Save the current registers on the stack, creating
-# a struct context, and save its address in *old.
-# Switch stacks to new and pop previously-saved registers.
-
-.globl swtch
-swtch:
-  movl 4(%esp), %eax
-  movl 8(%esp), %edx
-
-  # Save old callee-saved registers
-  pushl %ebp
-  pushl %ebx
-  pushl %esi
-  pushl %edi
-
-  # Switch stacks
-  movl %esp, (%eax)
-  movl %edx, %esp
-
-  # Load new callee-saved registers
-  popl %edi
-  popl %esi
-  popl %ebx
-  popl %ebp
-  ret
diff --git a/syscall.c b/syscall.c
deleted file mode 100644 (file)
index ee85261..0000000
--- a/syscall.c
+++ /dev/null
@@ -1,145 +0,0 @@
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "x86.h"
-#include "syscall.h"
-
-// User code makes a system call with INT T_SYSCALL.
-// System call number in %eax.
-// Arguments on the stack, from the user call to the C
-// library system call function. The saved user %esp points
-// to a saved program counter, and then the first argument.
-
-// Fetch the int at addr from the current process.
-int
-fetchint(uint addr, int *ip)
-{
-  struct proc *curproc = myproc();
-
-  if(addr >= curproc->sz || addr+4 > curproc->sz)
-    return -1;
-  *ip = *(int*)(addr);
-  return 0;
-}
-
-// Fetch the nul-terminated string at addr from the current process.
-// Doesn't actually copy the string - just sets *pp to point at it.
-// Returns length of string, not including nul.
-int
-fetchstr(uint addr, char **pp)
-{
-  char *s, *ep;
-  struct proc *curproc = myproc();
-
-  if(addr >= curproc->sz)
-    return -1;
-  *pp = (char*)addr;
-  ep = (char*)curproc->sz;
-  for(s = *pp; s < ep; s++){
-    if(*s == 0)
-      return s - *pp;
-  }
-  return -1;
-}
-
-// Fetch the nth 32-bit system call argument.
-int
-argint(int n, int *ip)
-{
-  return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
-}
-
-// Fetch the nth word-sized system call argument as a pointer
-// to a block of memory of size bytes.  Check that the pointer
-// lies within the process address space.
-int
-argptr(int n, char **pp, int size)
-{
-  int i;
-  struct proc *curproc = myproc();
-  if(argint(n, &i) < 0)
-    return -1;
-  if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)
-    return -1;
-  *pp = (char*)i;
-  return 0;
-}
-
-// Fetch the nth word-sized system call argument as a string pointer.
-// Check that the pointer is valid and the string is nul-terminated.
-// (There is no shared writable memory, so the string can't change
-// between this check and being used by the kernel.)
-int
-argstr(int n, char **pp)
-{
-  int addr;
-  if(argint(n, &addr) < 0)
-    return -1;
-  return fetchstr(addr, pp);
-}
-
-extern int sys_chdir(void);
-extern int sys_close(void);
-extern int sys_dup(void);
-extern int sys_exec(void);
-extern int sys_exit(void);
-extern int sys_fork(void);
-extern int sys_fstat(void);
-extern int sys_getpid(void);
-extern int sys_kill(void);
-extern int sys_link(void);
-extern int sys_mkdir(void);
-extern int sys_mknod(void);
-extern int sys_open(void);
-extern int sys_pipe(void);
-extern int sys_read(void);
-extern int sys_sbrk(void);
-extern int sys_sleep(void);
-extern int sys_unlink(void);
-extern int sys_wait(void);
-extern int sys_write(void);
-extern int sys_uptime(void);
-
-static int (*syscalls[])(void) = {
-[SYS_fork]    sys_fork,
-[SYS_exit]    sys_exit,
-[SYS_wait]    sys_wait,
-[SYS_pipe]    sys_pipe,
-[SYS_read]    sys_read,
-[SYS_kill]    sys_kill,
-[SYS_exec]    sys_exec,
-[SYS_fstat]   sys_fstat,
-[SYS_chdir]   sys_chdir,
-[SYS_dup]     sys_dup,
-[SYS_getpid]  sys_getpid,
-[SYS_sbrk]    sys_sbrk,
-[SYS_sleep]   sys_sleep,
-[SYS_uptime]  sys_uptime,
-[SYS_open]    sys_open,
-[SYS_write]   sys_write,
-[SYS_mknod]   sys_mknod,
-[SYS_unlink]  sys_unlink,
-[SYS_link]    sys_link,
-[SYS_mkdir]   sys_mkdir,
-[SYS_close]   sys_close,
-};
-
-void
-syscall(void)
-{
-  int num;
-  struct proc *curproc = myproc();
-
-  num = curproc->tf->eax;
-  if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
-    curproc->tf->eax = syscalls[num]();
-  } else {
-    cprintf("%d %s: unknown sys call %d\n",
-            curproc->pid, curproc->name, num);
-    curproc->tf->eax = -1;
-  }
-}
diff --git a/syscall.h b/syscall.h
deleted file mode 100644 (file)
index bc5f356..0000000
--- a/syscall.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// System call numbers
-#define SYS_fork    1
-#define SYS_exit    2
-#define SYS_wait    3
-#define SYS_pipe    4
-#define SYS_read    5
-#define SYS_kill    6
-#define SYS_exec    7
-#define SYS_fstat   8
-#define SYS_chdir   9
-#define SYS_dup    10
-#define SYS_getpid 11
-#define SYS_sbrk   12
-#define SYS_sleep  13
-#define SYS_uptime 14
-#define SYS_open   15
-#define SYS_write  16
-#define SYS_mknod  17
-#define SYS_unlink 18
-#define SYS_link   19
-#define SYS_mkdir  20
-#define SYS_close  21
diff --git a/sysfile.c b/sysfile.c
deleted file mode 100644 (file)
index bfe61b7..0000000
--- a/sysfile.c
+++ /dev/null
@@ -1,444 +0,0 @@
-//
-// File-system system calls.
-// Mostly argument checking, since we don't trust
-// user code, and calls into file.c and fs.c.
-//
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "stat.h"
-#include "mmu.h"
-#include "proc.h"
-#include "fs.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "file.h"
-#include "fcntl.h"
-
-// Fetch the nth word-sized system call argument as a file descriptor
-// and return both the descriptor and the corresponding struct file.
-static int
-argfd(int n, int *pfd, struct file **pf)
-{
-  int fd;
-  struct file *f;
-
-  if(argint(n, &fd) < 0)
-    return -1;
-  if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
-    return -1;
-  if(pfd)
-    *pfd = fd;
-  if(pf)
-    *pf = f;
-  return 0;
-}
-
-// Allocate a file descriptor for the given file.
-// Takes over file reference from caller on success.
-static int
-fdalloc(struct file *f)
-{
-  int fd;
-  struct proc *curproc = myproc();
-
-  for(fd = 0; fd < NOFILE; fd++){
-    if(curproc->ofile[fd] == 0){
-      curproc->ofile[fd] = f;
-      return fd;
-    }
-  }
-  return -1;
-}
-
-int
-sys_dup(void)
-{
-  struct file *f;
-  int fd;
-
-  if(argfd(0, 0, &f) < 0)
-    return -1;
-  if((fd=fdalloc(f)) < 0)
-    return -1;
-  filedup(f);
-  return fd;
-}
-
-int
-sys_read(void)
-{
-  struct file *f;
-  int n;
-  char *p;
-
-  if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
-    return -1;
-  return fileread(f, p, n);
-}
-
-int
-sys_write(void)
-{
-  struct file *f;
-  int n;
-  char *p;
-
-  if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
-    return -1;
-  return filewrite(f, p, n);
-}
-
-int
-sys_close(void)
-{
-  int fd;
-  struct file *f;
-
-  if(argfd(0, &fd, &f) < 0)
-    return -1;
-  myproc()->ofile[fd] = 0;
-  fileclose(f);
-  return 0;
-}
-
-int
-sys_fstat(void)
-{
-  struct file *f;
-  struct stat *st;
-
-  if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0)
-    return -1;
-  return filestat(f, st);
-}
-
-// Create the path new as a link to the same inode as old.
-int
-sys_link(void)
-{
-  char name[DIRSIZ], *new, *old;
-  struct inode *dp, *ip;
-
-  if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
-    return -1;
-
-  begin_op();
-  if((ip = namei(old)) == 0){
-    end_op();
-    return -1;
-  }
-
-  ilock(ip);
-  if(ip->type == T_DIR){
-    iunlockput(ip);
-    end_op();
-    return -1;
-  }
-
-  ip->nlink++;
-  iupdate(ip);
-  iunlock(ip);
-
-  if((dp = nameiparent(new, name)) == 0)
-    goto bad;
-  ilock(dp);
-  if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){
-    iunlockput(dp);
-    goto bad;
-  }
-  iunlockput(dp);
-  iput(ip);
-
-  end_op();
-
-  return 0;
-
-bad:
-  ilock(ip);
-  ip->nlink--;
-  iupdate(ip);
-  iunlockput(ip);
-  end_op();
-  return -1;
-}
-
-// Is the directory dp empty except for "." and ".." ?
-static int
-isdirempty(struct inode *dp)
-{
-  int off;
-  struct dirent de;
-
-  for(off=2*sizeof(de); off<dp->size; off+=sizeof(de)){
-    if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
-      panic("isdirempty: readi");
-    if(de.inum != 0)
-      return 0;
-  }
-  return 1;
-}
-
-//PAGEBREAK!
-int
-sys_unlink(void)
-{
-  struct inode *ip, *dp;
-  struct dirent de;
-  char name[DIRSIZ], *path;
-  uint off;
-
-  if(argstr(0, &path) < 0)
-    return -1;
-
-  begin_op();
-  if((dp = nameiparent(path, name)) == 0){
-    end_op();
-    return -1;
-  }
-
-  ilock(dp);
-
-  // Cannot unlink "." or "..".
-  if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0)
-    goto bad;
-
-  if((ip = dirlookup(dp, name, &off)) == 0)
-    goto bad;
-  ilock(ip);
-
-  if(ip->nlink < 1)
-    panic("unlink: nlink < 1");
-  if(ip->type == T_DIR && !isdirempty(ip)){
-    iunlockput(ip);
-    goto bad;
-  }
-
-  memset(&de, 0, sizeof(de));
-  if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
-    panic("unlink: writei");
-  if(ip->type == T_DIR){
-    dp->nlink--;
-    iupdate(dp);
-  }
-  iunlockput(dp);
-
-  ip->nlink--;
-  iupdate(ip);
-  iunlockput(ip);
-
-  end_op();
-
-  return 0;
-
-bad:
-  iunlockput(dp);
-  end_op();
-  return -1;
-}
-
-static struct inode*
-create(char *path, short type, short major, short minor)
-{
-  struct inode *ip, *dp;
-  char name[DIRSIZ];
-
-  if((dp = nameiparent(path, name)) == 0)
-    return 0;
-  ilock(dp);
-
-  if((ip = dirlookup(dp, name, 0)) != 0){
-    iunlockput(dp);
-    ilock(ip);
-    if(type == T_FILE && ip->type == T_FILE)
-      return ip;
-    iunlockput(ip);
-    return 0;
-  }
-
-  if((ip = ialloc(dp->dev, type)) == 0)
-    panic("create: ialloc");
-
-  ilock(ip);
-  ip->major = major;
-  ip->minor = minor;
-  ip->nlink = 1;
-  iupdate(ip);
-
-  if(type == T_DIR){  // Create . and .. entries.
-    dp->nlink++;  // for ".."
-    iupdate(dp);
-    // No ip->nlink++ for ".": avoid cyclic ref count.
-    if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
-      panic("create dots");
-  }
-
-  if(dirlink(dp, name, ip->inum) < 0)
-    panic("create: dirlink");
-
-  iunlockput(dp);
-
-  return ip;
-}
-
-int
-sys_open(void)
-{
-  char *path;
-  int fd, omode;
-  struct file *f;
-  struct inode *ip;
-
-  if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
-    return -1;
-
-  begin_op();
-
-  if(omode & O_CREATE){
-    ip = create(path, T_FILE, 0, 0);
-    if(ip == 0){
-      end_op();
-      return -1;
-    }
-  } else {
-    if((ip = namei(path)) == 0){
-      end_op();
-      return -1;
-    }
-    ilock(ip);
-    if(ip->type == T_DIR && omode != O_RDONLY){
-      iunlockput(ip);
-      end_op();
-      return -1;
-    }
-  }
-
-  if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
-    if(f)
-      fileclose(f);
-    iunlockput(ip);
-    end_op();
-    return -1;
-  }
-  iunlock(ip);
-  end_op();
-
-  f->type = FD_INODE;
-  f->ip = ip;
-  f->off = 0;
-  f->readable = !(omode & O_WRONLY);
-  f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
-  return fd;
-}
-
-int
-sys_mkdir(void)
-{
-  char *path;
-  struct inode *ip;
-
-  begin_op();
-  if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){
-    end_op();
-    return -1;
-  }
-  iunlockput(ip);
-  end_op();
-  return 0;
-}
-
-int
-sys_mknod(void)
-{
-  struct inode *ip;
-  char *path;
-  int major, minor;
-
-  begin_op();
-  if((argstr(0, &path)) < 0 ||
-     argint(1, &major) < 0 ||
-     argint(2, &minor) < 0 ||
-     (ip = create(path, T_DEV, major, minor)) == 0){
-    end_op();
-    return -1;
-  }
-  iunlockput(ip);
-  end_op();
-  return 0;
-}
-
-int
-sys_chdir(void)
-{
-  char *path;
-  struct inode *ip;
-  struct proc *curproc = myproc();
-  
-  begin_op();
-  if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){
-    end_op();
-    return -1;
-  }
-  ilock(ip);
-  if(ip->type != T_DIR){
-    iunlockput(ip);
-    end_op();
-    return -1;
-  }
-  iunlock(ip);
-  iput(curproc->cwd);
-  end_op();
-  curproc->cwd = ip;
-  return 0;
-}
-
-int
-sys_exec(void)
-{
-  char *path, *argv[MAXARG];
-  int i;
-  uint uargv, uarg;
-
-  if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){
-    return -1;
-  }
-  memset(argv, 0, sizeof(argv));
-  for(i=0;; i++){
-    if(i >= NELEM(argv))
-      return -1;
-    if(fetchint(uargv+4*i, (int*)&uarg) < 0)
-      return -1;
-    if(uarg == 0){
-      argv[i] = 0;
-      break;
-    }
-    if(fetchstr(uarg, &argv[i]) < 0)
-      return -1;
-  }
-  return exec(path, argv);
-}
-
-int
-sys_pipe(void)
-{
-  int *fd;
-  struct file *rf, *wf;
-  int fd0, fd1;
-
-  if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0)
-    return -1;
-  if(pipealloc(&rf, &wf) < 0)
-    return -1;
-  fd0 = -1;
-  if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
-    if(fd0 >= 0)
-      myproc()->ofile[fd0] = 0;
-    fileclose(rf);
-    fileclose(wf);
-    return -1;
-  }
-  fd[0] = fd0;
-  fd[1] = fd1;
-  return 0;
-}
diff --git a/sysproc.c b/sysproc.c
deleted file mode 100644 (file)
index 0686d29..0000000
--- a/sysproc.c
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "types.h"
-#include "x86.h"
-#include "defs.h"
-#include "date.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-
-int
-sys_fork(void)
-{
-  return fork();
-}
-
-int
-sys_exit(void)
-{
-  exit();
-  return 0;  // not reached
-}
-
-int
-sys_wait(void)
-{
-  return wait();
-}
-
-int
-sys_kill(void)
-{
-  int pid;
-
-  if(argint(0, &pid) < 0)
-    return -1;
-  return kill(pid);
-}
-
-int
-sys_getpid(void)
-{
-  return myproc()->pid;
-}
-
-int
-sys_sbrk(void)
-{
-  int addr;
-  int n;
-
-  if(argint(0, &n) < 0)
-    return -1;
-  addr = myproc()->sz;
-  if(growproc(n) < 0)
-    return -1;
-  return addr;
-}
-
-int
-sys_sleep(void)
-{
-  int n;
-  uint ticks0;
-
-  if(argint(0, &n) < 0)
-    return -1;
-  acquire(&tickslock);
-  ticks0 = ticks;
-  while(ticks - ticks0 < n){
-    if(myproc()->killed){
-      release(&tickslock);
-      return -1;
-    }
-    sleep(&ticks, &tickslock);
-  }
-  release(&tickslock);
-  return 0;
-}
-
-// return how many clock tick interrupts have occurred
-// since start.
-int
-sys_uptime(void)
-{
-  uint xticks;
-
-  acquire(&tickslock);
-  xticks = ticks;
-  release(&tickslock);
-  return xticks;
-}
diff --git a/toc.ftr b/toc.ftr
deleted file mode 100644 (file)
index 0061c1d..0000000
--- a/toc.ftr
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-The source listing is preceded by a cross-reference that lists every defined 
-constant, struct, global variable, and function in xv6.  Each entry gives,
-on the same line as the name, the line number (or, in a few cases, numbers)
-where the name is defined.  Successive lines in an entry list the line
-numbers where the name is used.  For example, this entry:
-
-    swtch 2658
-        0374 2428 2466 2657 2658
-
-indicates that swtch is defined on line 2658 and is mentioned on five lines
-on sheets 03, 24, and 26.
diff --git a/toc.hdr b/toc.hdr
deleted file mode 100644 (file)
index 3698d81..0000000
--- a/toc.hdr
+++ /dev/null
@@ -1,6 +0,0 @@
-The numbers to the left of the file names in the table are sheet numbers.
-The source code has been printed in a double column format with fifty
-lines per column, giving one hundred lines per sheet (or page).
-Thus there is a convenient relationship between line numbers and sheet numbers.
-
-
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a45860a
--- /dev/null
@@ -0,0 +1,4 @@
+project(mkfs)
+
+add_executable(mkfs mkfs.c)
+
diff --git a/tools/cuth b/tools/cuth
new file mode 100755 (executable)
index 0000000..cce8c0c
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+
+$| = 1;
+
+sub writefile($@){
+       my ($file, @lines) = @_;
+       
+       sleep(1);
+       open(F, ">$file") || die "open >$file: $!";
+       print F @lines;
+       close(F);
+}
+
+# Cut out #include lines that don't contribute anything.
+for($i=0; $i<@ARGV; $i++){
+       $file = $ARGV[$i];
+       if(!open(F, $file)){
+               print STDERR "open $file: $!\n";
+               next;
+       }
+       @lines = <F>;
+       close(F);
+       
+       $obj = "$file.o";
+       $obj =~ s/\.c\.o$/.o/;
+       system("touch $file");
+
+       if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){
+               print STDERR "make $obj failed: $rv\n";
+               next;
+       }
+
+       system("cp $file =$file");
+       for($j=@lines-1; $j>=0; $j--){
+               if($lines[$j] =~ /^#include/){
+                       $old = $lines[$j];
+                       $lines[$j] = "/* CUT-H */\n";
+                       writefile($file, @lines);
+                       if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){
+                               $lines[$j] = $old;
+                       }else{
+                               print STDERR "$file $old";
+                       }
+               }
+       }
+       writefile($file, grep {!/CUT-H/} @lines);
+       system("rm =$file");
+}
diff --git a/tools/mkfs.c b/tools/mkfs.c
new file mode 100644 (file)
index 0000000..753f49c
--- /dev/null
@@ -0,0 +1,304 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// This is a huge kludge and a hack.  This file was written to use XV6
+//   primitives that overlap with unix interfaces.  I have to directly include
+//   those shared headers, as including the whole directory (at compile time
+//   -I../include) would result in ../include/fcntl.h being read instead of the
+//   system fcntl (which we need for open).
+#define stat xv6_stat  // avoid clash with host struct stat
+#include "../include/types.h"
+#include "../include/fs.h"
+#include "../include/stat.h"
+#include "../include/param.h"
+
+#ifndef static_assert
+#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
+#endif
+
+#define NINODES 200
+
+// Disk layout:
+// [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
+
+int nbitmap = FSSIZE/(BSIZE*8) + 1;
+int ninodeblocks = NINODES / IPB + 1;
+int nlog = LOGSIZE;
+int nmeta;    // Number of meta blocks (boot, sb, nlog, inode, bitmap)
+int nblocks;  // Number of data blocks
+
+int fsfd;
+struct superblock sb;
+char zeroes[BSIZE];
+uint freeinode = 1;
+uint freeblock;
+
+
+void balloc(int);
+void wsect(uint, void*);
+void winode(uint, struct dinode*);
+void rinode(uint inum, struct dinode *ip);
+void rsect(uint sec, void *buf);
+uint ialloc(ushort type);
+void iappend(uint inum, void *p, int n);
+
+// convert to intel byte order
+ushort
+xshort(ushort x)
+{
+  ushort y;
+  uchar *a = (uchar*)&y;
+  a[0] = x;
+  a[1] = x >> 8;
+  return y;
+}
+
+uint
+xint(uint x)
+{
+  uint y;
+  uchar *a = (uchar*)&y;
+  a[0] = x;
+  a[1] = x >> 8;
+  a[2] = x >> 16;
+  a[3] = x >> 24;
+  return y;
+}
+
+int
+main(int argc, char *argv[])
+{
+  int i, cc, fd;
+  uint rootino, inum, off;
+  struct dirent de;
+  char buf[BSIZE];
+  struct dinode din;
+
+
+  static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
+
+  if(argc < 2){
+    fprintf(stderr, "Usage: mkfs fs.img files...\n");
+    exit(1);
+  }
+
+  assert((BSIZE % sizeof(struct dinode)) == 0);
+  assert((BSIZE % sizeof(struct dirent)) == 0);
+
+  fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
+  if(fsfd < 0){
+    perror(argv[1]);
+    exit(1);
+  }
+
+  // 1 fs block = 1 disk sector
+  nmeta = 2 + nlog + ninodeblocks + nbitmap;
+  nblocks = FSSIZE - nmeta;
+
+  sb.size = xint(FSSIZE);
+  sb.nblocks = xint(nblocks);
+  sb.ninodes = xint(NINODES);
+  sb.nlog = xint(nlog);
+  sb.logstart = xint(2);
+  sb.inodestart = xint(2+nlog);
+  sb.bmapstart = xint(2+nlog+ninodeblocks);
+
+  printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
+         nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
+
+  freeblock = nmeta;     // the first free block that we can allocate
+
+  for(i = 0; i < FSSIZE; i++)
+    wsect(i, zeroes);
+
+  memset(buf, 0, sizeof(buf));
+  memmove(buf, &sb, sizeof(sb));
+  wsect(1, buf);
+
+  rootino = ialloc(T_DIR);
+  assert(rootino == ROOTINO);
+
+  bzero(&de, sizeof(de));
+  de.inum = xshort(rootino);
+  strcpy(de.name, ".");
+  iappend(rootino, &de, sizeof(de));
+
+  bzero(&de, sizeof(de));
+  de.inum = xshort(rootino);
+  strcpy(de.name, "..");
+  iappend(rootino, &de, sizeof(de));
+
+  for(i = 2; i < argc; i++){
+    assert(index(argv[i], '/') == 0);
+
+    if((fd = open(argv[i], 0)) < 0){
+      perror(argv[i]);
+      exit(1);
+    }
+
+    // Skip leading _ in name when writing to file system.
+    // The binaries are named _rm, _cat, etc. to keep the
+    // build operating system from trying to execute them
+    // in place of system binaries like rm and cat.
+    if(argv[i][0] == '_')
+      ++argv[i];
+
+    inum = ialloc(T_FILE);
+
+    bzero(&de, sizeof(de));
+    de.inum = xshort(inum);
+    strncpy(de.name, argv[i], DIRSIZ);
+    iappend(rootino, &de, sizeof(de));
+
+    while((cc = read(fd, buf, sizeof(buf))) > 0)
+      iappend(inum, buf, cc);
+
+    close(fd);
+  }
+
+  // fix size of root inode dir
+  rinode(rootino, &din);
+  off = xint(din.size);
+  off = ((off/BSIZE) + 1) * BSIZE;
+  din.size = xint(off);
+  winode(rootino, &din);
+
+  balloc(freeblock);
+
+  exit(0);
+}
+
+void
+wsect(uint sec, void *buf)
+{
+  if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
+    perror("lseek");
+    exit(1);
+  }
+  if(write(fsfd, buf, BSIZE) != BSIZE){
+    perror("write");
+    exit(1);
+  }
+}
+
+void
+winode(uint inum, struct dinode *ip)
+{
+  char buf[BSIZE];
+  uint bn;
+  struct dinode *dip;
+
+  bn = IBLOCK(inum, sb);
+  rsect(bn, buf);
+  dip = ((struct dinode*)buf) + (inum % IPB);
+  *dip = *ip;
+  wsect(bn, buf);
+}
+
+void
+rinode(uint inum, struct dinode *ip)
+{
+  char buf[BSIZE];
+  uint bn;
+  struct dinode *dip;
+
+  bn = IBLOCK(inum, sb);
+  rsect(bn, buf);
+  dip = ((struct dinode*)buf) + (inum % IPB);
+  *ip = *dip;
+}
+
+void
+rsect(uint sec, void *buf)
+{
+  if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
+    perror("lseek");
+    exit(1);
+  }
+  if(read(fsfd, buf, BSIZE) != BSIZE){
+    perror("read");
+    exit(1);
+  }
+}
+
+uint
+ialloc(ushort type)
+{
+  uint inum = freeinode++;
+  struct dinode din;
+
+  bzero(&din, sizeof(din));
+  din.type = xshort(type);
+  din.nlink = xshort(1);
+  din.size = xint(0);
+  winode(inum, &din);
+  return inum;
+}
+
+void
+balloc(int used)
+{
+  uchar buf[BSIZE];
+  int i;
+
+  printf("balloc: first %d blocks have been allocated\n", used);
+  assert(used < BSIZE*8);
+  bzero(buf, BSIZE);
+  for(i = 0; i < used; i++){
+    buf[i/8] = buf[i/8] | (0x1 << (i%8));
+  }
+  printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
+  wsect(sb.bmapstart, buf);
+}
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+void
+iappend(uint inum, void *xp, int n)
+{
+  char *p = (char*)xp;
+  uint fbn, off, n1;
+  struct dinode din;
+  char buf[BSIZE];
+  uint indirect[NINDIRECT];
+  uint x;
+
+  rinode(inum, &din);
+  off = xint(din.size);
+  // printf("append inum %d at off %d sz %d\n", inum, off, n);
+  while(n > 0){
+    fbn = off / BSIZE;
+    assert(fbn < MAXFILE);
+    if(fbn < NDIRECT){
+      if(xint(din.addrs[fbn]) == 0){
+        din.addrs[fbn] = xint(freeblock++);
+      }
+      x = xint(din.addrs[fbn]);
+    } else {
+      if(xint(din.addrs[NDIRECT]) == 0){
+        din.addrs[NDIRECT] = xint(freeblock++);
+      }
+      rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
+      if(indirect[fbn - NDIRECT] == 0){
+        indirect[fbn - NDIRECT] = xint(freeblock++);
+        wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
+      }
+      x = xint(indirect[fbn-NDIRECT]);
+    }
+    n1 = min(n, (fbn + 1) * BSIZE - off);
+    rsect(x, buf);
+    bcopy(p, buf + off - (fbn * BSIZE), n1);
+    wsect(x, buf);
+    n -= n1;
+    off += n1;
+    p += n1;
+  }
+  din.size = xint(off);
+  winode(inum, &din);
+}
diff --git a/tools/pr.pl b/tools/pr.pl
new file mode 100755 (executable)
index 0000000..46905bd
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+
+use POSIX qw(strftime);
+
+if($ARGV[0] eq "-h"){
+       shift @ARGV;
+       $h = $ARGV[0];
+       shift @ARGV;
+}else{
+       $h = $ARGV[0];
+}
+
+$page = 0;
+$now = strftime "%b %e %H:%M %Y", localtime;
+
+@lines = <>;
+for($i=0; $i<@lines; $i+=50){
+       print "\n\n";
+       ++$page;
+       print "$now  $h  Page $page\n";
+       print "\n\n";
+       for($j=$i; $j<@lines && $j<$i +50; $j++){
+               $lines[$j] =~ s!//DOC.*!!;
+               print $lines[$j];
+       }
+       for(; $j<$i+50; $j++){
+               print "\n";
+       }
+       $sheet = "";
+       if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){
+               $sheet = "Sheet $1";
+       }
+       print "\n\n";
+       print "$sheet\n";
+       print "\n\n";
+}
diff --git a/tools/printpcs b/tools/printpcs
new file mode 100755 (executable)
index 0000000..81d039b
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Decode the symbols from a panic EIP list
+
+# Find a working addr2line
+for p in i386-jos-elf-addr2line addr2line; do
+    if which $p 2>&1 >/dev/null && \
+       $p -h 2>&1 | grep -q '\belf32-i386\b'; then
+        break
+    fi
+done
+
+# Enable as much pretty-printing as this addr2line can do
+$p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@"
diff --git a/tools/runoff b/tools/runoff
new file mode 100755 (executable)
index 0000000..be362d0
--- /dev/null
@@ -0,0 +1,246 @@
+#!/bin/sh
+
+echo This script takes a minute to run.  Be patient. 1>&2
+
+LC_CTYPE=C export LC_CTYPE
+
+# pad stdin to multiple of 120 lines
+pad()
+{
+       awk '{print} END{for(; NR%120!=0; NR++) print ""}'
+}
+
+# create formatted (numbered) files
+mkdir -p fmt
+rm -f fmt/*
+cp README fmt
+echo > fmt/blank
+files=`grep -v '^#' runoff.list | awk '{print $1}'`
+n=99
+for i in $files
+do
+       ./runoff1 -n $n $i >fmt/$i
+       nn=`tail -1 fmt/$i | sed 's/ .*//; s/^0*//'`
+       if [ "x$nn" != x ]; then
+               n=$nn
+       fi
+done
+
+# create table of contents
+cat toc.hdr >fmt/toc
+pr -e8 -t runoff.list | awk '
+/^[a-z0-9]/ {
+       s=$0
+       f="fmt/"$1
+       getline<f
+       close(f)
+       n=$1
+       printf("%02d %s\n", n/100, s);
+       printf("TOC: %04d %s\n", n, s) >"fmt/tocdata"
+       next
+}
+{
+       print
+}' | pr -3 -t >>fmt/toc
+cat toc.ftr >>fmt/toc
+
+# check for bad alignments
+perl -e '
+       $leftwarn = 0;
+       while(<>){
+               chomp;
+               s!#.*!!;
+               s!\s+! !g;
+               s! +$!!;
+               next if /^$/;
+               
+               if(/TOC: (\d+) (.*)/){
+                       $toc{$2} = $1;
+                       next;
+               }
+               
+               if(/sheet1: (left|right)$/){
+                       print STDERR "assuming that sheet 1 is a $1 page.  double-check!\n";
+                       $left = $1 eq "left" ? "13579" : "02468";
+                       $right = $1 eq "left" ? "02468" : "13579";
+                       next;
+               }
+               
+               if(/even: (.*)/){
+                       $file = $1;
+                       if(!defined($toc{$file})){
+                               print STDERR "Have no toc for $file\n";
+                               next;
+                       }
+                       if($toc{$file} =~ /^\d\d[^0]/){
+                               print STDERR "$file does not start on a fresh page.\n";
+                       }
+                       next;
+               }
+               
+               if(/odd: (.*)/){
+                       $file = $1;
+                       if(!defined($toc{$file})){
+                               print STDERR "Have no toc for $file\n";
+                               next;
+                       }
+                       if($toc{$file} !~ /^\d\d5/){
+                               print STDERR "$file does not start on a second half page.\n";
+                       }
+                       next;
+               }
+               
+               if(/(left|right): (.*)/){
+                       $what = $1;
+                       $file = $2;
+                       if(!defined($toc{$file})){
+                               print STDERR "Have no toc for $file\n";
+                               next;
+                       }
+                       if($what eq "left" && !($toc{$file} =~ /^\d[$left][05]/)){
+                               print STDERR "$file does not start on a left page [$toc{$file}]\n";
+                       }
+                       # why does this not work if I inline $x in the if?
+                       $x = ($toc{$file} =~ /^\d[$right][05]/);
+                       if($what eq "right" && !$x){
+                               print STDERR "$file does not start on a right page [$toc{$file}] [$x]\n";
+                       }
+                       next;
+               }
+               
+               print STDERR "Unknown spec: $_\n";
+       }
+' fmt/tocdata runoff.spec
+
+# make definition list
+cd fmt
+perl -e '
+       while(<>) {
+               chomp;
+
+               s!//.*!!;
+               s!/\*([^*]|[*][^/])*\*/!!g;
+               s!\s! !g;
+               s! +$!!;
+
+               # look for declarations like char* x;
+               if (/^[0-9]+ typedef .* u(int|short|long|char);/) {
+                       next;
+               }
+               if (/^[0-9]+ extern/) {
+                       next;
+               }
+               if (/^[0-9]+ struct [a-zA-Z0-9_]+;/) {
+                       next;
+               }
+               if (/^([0-9]+) #define +([A-za-z0-9_]+) +?\(.*/) {
+                       print "$1 $2\n"
+               }
+               elsif (/^([0-9]+) #define +([A-Za-z0-9_]+) +([^ ]+)/) {
+                       print "$1 $2 $3\n";
+               }
+               elsif (/^([0-9]+) #define +([A-Za-z0-9_]+)/) {
+                       print "$1 $2\n";
+               }
+               
+               if(/^^([0-9]+) \.globl ([a-zA-Z0-9_]+)/){
+                       $isglobl{$2} = 1;
+               }
+               if(/^^([0-9]+) ([a-zA-Z0-9_]+):$/ && $isglobl{$2}){
+                       print "$1 $2\n";
+               }
+               
+               if (/\(/) {
+                       next;
+               }
+
+               if (/^([0-9]+) (((static|struct|extern|union|enum) +)*([A-Za-z0-9_]+))( .*)? +([A-Za-z_][A-Za-z0-9_]*)(,|;|=| =)/) {
+                       print "$1 $7\n";
+               }
+               
+               elsif(/^([0-9]+) (enum|struct|union) +([A-Za-z0-9_]+) +{/){ 
+                       print "$1 $3\n";
+               }
+               # TODO: enum members
+       }
+' $files >defs
+
+(for i in $files
+do
+       case "$i" in
+       *.S)
+               cat $i | sed 's;#.*;;; s;//.*;;;'
+               ;;
+       *)
+               cat $i | sed 's;//.*;;; s;"([^"\\]|\\.)*";;;'
+       esac
+done
+) >alltext
+
+perl -n -e 'print if s/^([0-9]+ [a-zA-Z0-9_]+)\(.*$/\1/;' alltext |
+       egrep -v ' (STUB|usage|main|if|for)$' >>defs
+#perl -n -e 'print if s/^([0-9]+) STUB\(([a-zA-Z0-9_]+)\)$/\1 \2/;' alltext \
+#      >>defs
+(
+>s.defs
+
+# make reference list
+for i in `awk '{print $2}' defs | sort -f | uniq`
+do
+       defs=`egrep '^[0-9]+ '$i'( |$)' defs | awk '{print $1}'`
+       echo $i $defs >>s.defs
+       uses=`egrep -h '([^a-zA-Z_0-9])'$i'($|[^a-zA-Z_0-9])' alltext | awk '{print $1}'`
+       if [ "x$defs" != "x$uses" ]; then
+               echo $i $defs
+               echo $uses |fmt -29 | sed 's/^/    /'
+#      else
+#              echo $i defined but not used >&2
+       fi
+done
+) >refs
+
+# build defs list
+awk '
+{
+       printf("%04d %s\n", $2, $1);
+       for(i=3; i<=NF; i++)
+               printf("%04d    \" \n", $i);
+}
+' s.defs > t.defs
+
+# format the whole thing
+(
+       ../pr.pl README
+       ../pr.pl -h "table of contents" toc
+       # pr -t -2 t.defs | ../pr.pl -h "definitions" | pad
+       pr -t -l50 -2 refs | ../pr.pl -h "cross-references" | pad
+       # pr.pl -h "definitions" -2 t.defs | pad
+       # pr.pl -h "cross-references" -2 refs | pad
+       ../pr.pl blank  # make sheet 1 start on left page
+       ../pr.pl blank
+       for i in $files
+       do
+               ../pr.pl -h "xv6/$i" $i
+       done
+) | mpage -m50t50b -o -bLetter -T -t -2 -FCourier -L60 >all.ps
+grep Pages: all.ps
+
+# if we have the nice font, use it
+nicefont=LucidaSans-Typewriter83
+if [ ! -f ../$nicefont ]
+then
+       if git cat-file blob font:$nicefont > ../$nicefont~; then
+               mv ../$nicefont~ ../$nicefont
+       fi
+fi
+if [ -f ../$nicefont ]
+then
+       echo nicefont
+       (sed 1q all.ps; cat ../$nicefont; sed "1d; s/Courier/$nicefont/" all.ps) >allf.ps
+else
+       echo ugly font!
+       cp all.ps allf.ps
+fi
+ps2pdf allf.ps ../xv6.pdf
+# cd ..
+# pdftops xv6.pdf xv6.ps
diff --git a/tools/runoff.list b/tools/runoff.list
new file mode 100644 (file)
index 0000000..2df9b81
--- /dev/null
@@ -0,0 +1,80 @@
+# basic headers
+types.h
+param.h
+memlayout.h
+defs.h
+x86.h
+asm.h
+mmu.h
+elf.h
+date.h
+
+# entering xv6
+entry.S
+entryother.S
+main.c
+
+# locks
+spinlock.h
+spinlock.c
+
+# processes
+vm.c
+proc.h
+proc.c
+swtch.S
+kalloc.c
+
+# system calls
+traps.h
+vectors.pl
+trapasm.S
+trap.c
+syscall.h
+syscall.c
+sysproc.c
+
+# file system
+buf.h
+sleeplock.h
+fcntl.h
+stat.h
+fs.h
+file.h
+ide.c
+bio.c
+sleeplock.c
+log.c
+fs.c
+file.c
+sysfile.c
+exec.c
+
+# pipes
+pipe.c
+
+# string operations
+string.c
+
+# low-level hardware
+mp.h
+mp.c
+lapic.c
+ioapic.c
+kbd.h
+kbd.c
+console.c
+uart.c
+
+# user-level
+initcode.S
+usys.S
+init.c
+sh.c
+
+# bootloader
+bootasm.S
+bootmain.c
+
+# link
+kernel.ld
diff --git a/tools/runoff.spec b/tools/runoff.spec
new file mode 100644 (file)
index 0000000..9247948
--- /dev/null
@@ -0,0 +1,102 @@
+# Is sheet 01 (after the TOC) a left sheet or a right sheet?
+sheet1: left
+
+# "left" and "right" specify which page of a two-page spread a file
+# must start on.  "left" means that a file must start on the first of
+# the two pages.  "right" means it must start on the second of the two
+# pages.  The file may start in either column.
+#
+# "even" and "odd" specify which column a file must start on.  "even"
+# means it must start in the left of the two columns (00).  "odd" means it
+# must start in the right of the two columns (50).
+#
+# You'd think these would be the other way around.
+
+# types.h either
+# param.h either
+# defs.h either
+# x86.h either
+# asm.h either
+# mmu.h either
+# elf.h either
+# mp.h either
+
+even: entry.S  # mild preference
+even: entryother.S  # mild preference
+even: main.c
+# mp.c don't care at all
+# even: initcode.S
+# odd: init.c
+
+left: spinlock.h
+even: spinlock.h
+
+# This gets struct proc and allocproc on the same spread
+left: proc.h
+even: proc.h
+
+# goal is to have two action-packed 2-page spreads,
+# one with
+#     userinit growproc fork exit wait
+# and another with
+#     scheduler sched yield forkret sleep wakeup1 wakeup
+right: proc.c   # VERY important
+even: proc.c   # VERY important
+
+# A few more action packed spreads
+# page table creation and process loading
+#     walkpgdir mappages setupkvm switch[ku]vm inituvm (loaduvm)
+# process memory management
+#     allocuvm deallocuvm freevm
+left: vm.c
+
+even: kalloc.c  # mild preference
+
+# syscall.h either
+# trapasm.S either
+# traps.h either
+# even: trap.c
+# vectors.pl either
+# syscall.c either
+# sysproc.c either
+
+# buf.h either
+# dev.h either
+# fcntl.h either
+# stat.h either
+# file.h either
+# fs.h either
+# fsvar.h either
+# left: ide.c # mild preference
+even: ide.c
+# odd: bio.c
+
+# log.c fits nicely in a spread
+even: log.c
+left: log.c
+
+# with fs.c starting on 2nd column of a left page, we get these 2-page spreads:
+#      ialloc iupdate iget idup ilock iunlock iput iunlockput
+#      bmap itrunc stati readi writei
+#      namecmp dirlookup dirlink skipelem namex namei
+#      fileinit filealloc filedup fileclose filestat fileread filewrite
+# starting on 2nd column of a right page is not terrible either
+odd: fs.c   # VERY important
+left: fs.c  # mild preference
+# file.c either
+# exec.c either
+# sysfile.c either
+
+# Mild preference, but makes spreads of mp.c, lapic.c, and ioapic.c+picirq.c
+even: mp.c
+left: mp.c
+
+# even: pipe.c  # mild preference
+# string.c either
+# left: kbd.h  # mild preference
+even: kbd.h
+even: console.c
+odd: sh.c
+
+even: bootasm.S   # mild preference
+even: bootmain.c  # mild preference
diff --git a/tools/runoff1 b/tools/runoff1
new file mode 100755 (executable)
index 0000000..532f844
--- /dev/null
@@ -0,0 +1,108 @@
+#!/usr/bin/perl
+
+$n = 0;
+$v = 0;
+if($ARGV[0] eq "-v") {
+       $v = 1;
+       shift @ARGV;
+}
+if($ARGV[0] eq "-n") {
+       $n = $ARGV[1];
+       shift @ARGV;
+       shift @ARGV;
+}
+$n = int(($n+49)/50)*50 - 1;
+
+$file = $ARGV[0];
+@lines = <>;
+$linenum = 0;
+foreach (@lines) {
+       $linenum++;
+       chomp;
+       s/\s+$//;
+       if(length() >= 75){
+               print STDERR "$file:$linenum: line too long\n";
+       }
+}
+@outlines = ();
+$nextout = 0;
+
+for($i=0; $i<@lines; ){
+       # Skip leading blank lines.
+       $i++ while $i<@lines && $lines[$i] =~ /^$/;
+       last if $i>=@lines;
+
+       # If the rest of the file fits, use the whole thing.
+       if(@lines <= $i+50 && !grep { /PAGEBREAK/ } @lines){
+               $breakbefore = @lines;
+       }else{
+               # Find a good next page break;
+               # Hope for end of function.
+               # but settle for a blank line (but not first blank line
+               # in function, which comes after variable declarations).
+               $breakbefore = $i;
+               $lastblank = $i;
+               $sawbrace = 0;
+               $breaksize = 15;  # 15 lines to get to function
+               for($j=$i; $j<$i+50 && $j < @lines; $j++){
+                       if($lines[$j] =~ /PAGEBREAK!/){
+                               $lines[$j] = "";
+                               $breakbefore = $j;
+                               $breaksize = 100;
+                               last;
+                       }
+                       if($lines[$j] =~ /PAGEBREAK:\s*([0-9]+)/){
+                               $breaksize = $1;
+                               $breakbefore = $j;
+                               $lines[$j] = "";
+                       }
+                       if($lines[$j] =~ /^};?$/){
+                               $breakbefore = $j+1;
+                               $breaksize = 15;
+                       }
+                       if($lines[$j] =~ /^{$/){
+                               $sawbrace = 1;
+                       }
+                       if($lines[$j] =~ /^$/){
+                               if($sawbrace){
+                                       $sawbrace = 0;
+                               }else{
+                                       $lastblank = $j;
+                               }
+                       }
+               }
+               if($j<@lines && $lines[$j] =~ /^$/){
+                       $lastblank = $j;
+               }
+
+               # If we are not putting enough on a page, try a blank line.
+               if($breakbefore - $i < 50 - $breaksize && $lastblank > $breakbefore && $lastblank >= $i+50 - 5){
+                       if($v){
+                               print STDERR "breakbefore $breakbefore i $i breaksize $breaksize\n";
+                       }
+                       $breakbefore = $lastblank;
+                       $breaksize = 5;  # only 5 lines to get to blank line
+               }
+
+               # If we are not putting enough on a page, force a full page.
+               if($breakbefore - $i < 50 - $breaksize && $breakbefore != @lines){
+                       $breakbefore = $i + 50;
+                       $breakbefore = @lines if @lines < $breakbefore;
+               }
+
+               if($breakbefore < $i+2){
+                       $breakbefore = $i+2;
+               }
+       }
+
+       # Emit the page.
+       $i50 = $i + 50;
+       for(; $i<$breakbefore; $i++){
+               printf "%04d %s\n", ++$n, $lines[$i];
+       }
+
+       # Finish page
+       for($j=$i; $j<$i50; $j++){
+               printf "%04d \n", ++$n;
+       }
+}
diff --git a/tools/show1 b/tools/show1
new file mode 100755 (executable)
index 0000000..e0d3d83
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps
diff --git a/tools/spinp b/tools/spinp
new file mode 100755 (executable)
index 0000000..db9614b
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+if [ $# != 1 ] || [ ! -f "$1" ]; then
+       echo 'usage: spinp file.p' 1>&2
+       exit 1
+fi
+
+rm -f $1.trail
+spin -a $1 || exit 1
+cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c
+pan -i
+rm pan.* pan
+if [ -f $1.trail ]; then
+       spin -t -p $1
+fi
+
diff --git a/tools/toc.ftr b/tools/toc.ftr
new file mode 100644 (file)
index 0000000..0061c1d
--- /dev/null
@@ -0,0 +1,13 @@
+
+
+The source listing is preceded by a cross-reference that lists every defined 
+constant, struct, global variable, and function in xv6.  Each entry gives,
+on the same line as the name, the line number (or, in a few cases, numbers)
+where the name is defined.  Successive lines in an entry list the line
+numbers where the name is used.  For example, this entry:
+
+    swtch 2658
+        0374 2428 2466 2657 2658
+
+indicates that swtch is defined on line 2658 and is mentioned on five lines
+on sheets 03, 24, and 26.
diff --git a/tools/toc.hdr b/tools/toc.hdr
new file mode 100644 (file)
index 0000000..3698d81
--- /dev/null
@@ -0,0 +1,6 @@
+The numbers to the left of the file names in the table are sheet numbers.
+The source code has been printed in a double column format with fifty
+lines per column, giving one hundred lines per sheet (or page).
+Thus there is a convenient relationship between line numbers and sheet numbers.
+
+
diff --git a/trap.c b/trap.c
deleted file mode 100644 (file)
index 41c66eb..0000000
--- a/trap.c
+++ /dev/null
@@ -1,112 +0,0 @@
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "x86.h"
-#include "traps.h"
-#include "spinlock.h"
-
-// Interrupt descriptor table (shared by all CPUs).
-struct gatedesc idt[256];
-extern uint vectors[];  // in vectors.S: array of 256 entry pointers
-struct spinlock tickslock;
-uint ticks;
-
-void
-tvinit(void)
-{
-  int i;
-
-  for(i = 0; i < 256; i++)
-    SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0);
-  SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER);
-
-  initlock(&tickslock, "time");
-}
-
-void
-idtinit(void)
-{
-  lidt(idt, sizeof(idt));
-}
-
-//PAGEBREAK: 41
-void
-trap(struct trapframe *tf)
-{
-  if(tf->trapno == T_SYSCALL){
-    if(myproc()->killed)
-      exit();
-    myproc()->tf = tf;
-    syscall();
-    if(myproc()->killed)
-      exit();
-    return;
-  }
-
-  switch(tf->trapno){
-  case T_IRQ0 + IRQ_TIMER:
-    if(cpuid() == 0){
-      acquire(&tickslock);
-      ticks++;
-      wakeup(&ticks);
-      release(&tickslock);
-    }
-    lapiceoi();
-    break;
-  case T_IRQ0 + IRQ_IDE:
-    ideintr();
-    lapiceoi();
-    break;
-  case T_IRQ0 + IRQ_IDE+1:
-    // Bochs generates spurious IDE1 interrupts.
-    break;
-  case T_IRQ0 + IRQ_KBD:
-    kbdintr();
-    lapiceoi();
-    break;
-  case T_IRQ0 + IRQ_COM1:
-    uartintr();
-    lapiceoi();
-    break;
-  case T_IRQ0 + 7:
-  case T_IRQ0 + IRQ_SPURIOUS:
-    cprintf("cpu%d: spurious interrupt at %x:%x\n",
-            cpuid(), tf->cs, tf->eip);
-    lapiceoi();
-    break;
-
-  //PAGEBREAK: 13
-  default:
-    if(myproc() == 0 || (tf->cs&3) == 0){
-      // In kernel, it must be our mistake.
-      cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
-              tf->trapno, cpuid(), tf->eip, rcr2());
-      panic("trap");
-    }
-    // In user space, assume process misbehaved.
-    cprintf("pid %d %s: trap %d err %d on cpu %d "
-            "eip 0x%x addr 0x%x--kill proc\n",
-            myproc()->pid, myproc()->name, tf->trapno,
-            tf->err, cpuid(), tf->eip, rcr2());
-    myproc()->killed = 1;
-  }
-
-  // Force process exit if it has been killed and is in user space.
-  // (If it is still executing in the kernel, let it keep running
-  // until it gets to the regular system call return.)
-  if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
-    exit();
-
-  // Force process to give up CPU on clock tick.
-  // If interrupts were on while locks held, would need to check nlock.
-  if(myproc() && myproc()->state == RUNNING &&
-     tf->trapno == T_IRQ0+IRQ_TIMER)
-    yield();
-
-  // Check if the process has been killed since we yielded
-  if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
-    exit();
-}
diff --git a/trapasm.S b/trapasm.S
deleted file mode 100644 (file)
index da8aefc..0000000
--- a/trapasm.S
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "mmu.h"
-
-  # vectors.S sends all traps here.
-.globl alltraps
-alltraps:
-  # Build trap frame.
-  pushl %ds
-  pushl %es
-  pushl %fs
-  pushl %gs
-  pushal
-  
-  # Set up data segments.
-  movw $(SEG_KDATA<<3), %ax
-  movw %ax, %ds
-  movw %ax, %es
-
-  # Call trap(tf), where tf=%esp
-  pushl %esp
-  call trap
-  addl $4, %esp
-
-  # Return falls through to trapret...
-.globl trapret
-trapret:
-  popal
-  popl %gs
-  popl %fs
-  popl %es
-  popl %ds
-  addl $0x8, %esp  # trapno and errcode
-  iret
diff --git a/traps.h b/traps.h
deleted file mode 100644 (file)
index 0bd1fd8..0000000
--- a/traps.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// x86 trap and interrupt constants.
-
-// Processor-defined:
-#define T_DIVIDE         0      // divide error
-#define T_DEBUG          1      // debug exception
-#define T_NMI            2      // non-maskable interrupt
-#define T_BRKPT          3      // breakpoint
-#define T_OFLOW          4      // overflow
-#define T_BOUND          5      // bounds check
-#define T_ILLOP          6      // illegal opcode
-#define T_DEVICE         7      // device not available
-#define T_DBLFLT         8      // double fault
-// #define T_COPROC      9      // reserved (not used since 486)
-#define T_TSS           10      // invalid task switch segment
-#define T_SEGNP         11      // segment not present
-#define T_STACK         12      // stack exception
-#define T_GPFLT         13      // general protection fault
-#define T_PGFLT         14      // page fault
-// #define T_RES        15      // reserved
-#define T_FPERR         16      // floating point error
-#define T_ALIGN         17      // aligment check
-#define T_MCHK          18      // machine check
-#define T_SIMDERR       19      // SIMD floating point error
-
-// These are arbitrarily chosen, but with care not to overlap
-// processor defined exceptions or interrupt vectors.
-#define T_SYSCALL       64      // system call
-#define T_DEFAULT      500      // catchall
-
-#define T_IRQ0          32      // IRQ 0 corresponds to int T_IRQ
-
-#define IRQ_TIMER        0
-#define IRQ_KBD          1
-#define IRQ_COM1         4
-#define IRQ_IDE         14
-#define IRQ_ERROR       19
-#define IRQ_SPURIOUS    31
-
diff --git a/types.h b/types.h
deleted file mode 100644 (file)
index e4adf64..0000000
--- a/types.h
+++ /dev/null
@@ -1,4 +0,0 @@
-typedef unsigned int   uint;
-typedef unsigned short ushort;
-typedef unsigned char  uchar;
-typedef uint pde_t;
diff --git a/uart.c b/uart.c
deleted file mode 100644 (file)
index b8946da..0000000
--- a/uart.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// Intel 8250 serial port (UART).
-
-#include "types.h"
-#include "defs.h"
-#include "param.h"
-#include "traps.h"
-#include "spinlock.h"
-#include "sleeplock.h"
-#include "fs.h"
-#include "file.h"
-#include "mmu.h"
-#include "proc.h"
-#include "x86.h"
-
-#define COM1    0x3f8
-
-static int uart;    // is there a uart?
-
-void
-uartinit(void)
-{
-  char *p;
-
-  // Turn off the FIFO
-  outb(COM1+2, 0);
-
-  // 9600 baud, 8 data bits, 1 stop bit, parity off.
-  outb(COM1+3, 0x80);    // Unlock divisor
-  outb(COM1+0, 115200/9600);
-  outb(COM1+1, 0);
-  outb(COM1+3, 0x03);    // Lock divisor, 8 data bits.
-  outb(COM1+4, 0);
-  outb(COM1+1, 0x01);    // Enable receive interrupts.
-
-  // If status is 0xFF, no serial port.
-  if(inb(COM1+5) == 0xFF)
-    return;
-  uart = 1;
-
-  // Acknowledge pre-existing interrupt conditions;
-  // enable interrupts.
-  inb(COM1+2);
-  inb(COM1+0);
-  ioapicenable(IRQ_COM1, 0);
-
-  // Announce that we're here.
-  for(p="xv6...\n"; *p; p++)
-    uartputc(*p);
-}
-
-void
-uartputc(int c)
-{
-  int i;
-
-  if(!uart)
-    return;
-  for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++)
-    microdelay(10);
-  outb(COM1+0, c);
-}
-
-static int
-uartgetc(void)
-{
-  if(!uart)
-    return -1;
-  if(!(inb(COM1+5) & 0x01))
-    return -1;
-  return inb(COM1+0);
-}
-
-void
-uartintr(void)
-{
-  consoleintr(uartgetc);
-}
diff --git a/ulib.c b/ulib.c
deleted file mode 100644 (file)
index 8e1e1a2..0000000
--- a/ulib.c
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "fcntl.h"
-#include "user.h"
-#include "x86.h"
-
-char*
-strcpy(char *s, const char *t)
-{
-  char *os;
-
-  os = s;
-  while((*s++ = *t++) != 0)
-    ;
-  return os;
-}
-
-int
-strcmp(const char *p, const char *q)
-{
-  while(*p && *p == *q)
-    p++, q++;
-  return (uchar)*p - (uchar)*q;
-}
-
-uint
-strlen(const char *s)
-{
-  int n;
-
-  for(n = 0; s[n]; n++)
-    ;
-  return n;
-}
-
-void*
-memset(void *dst, int c, uint n)
-{
-  stosb(dst, c, n);
-  return dst;
-}
-
-char*
-strchr(const char *s, char c)
-{
-  for(; *s; s++)
-    if(*s == c)
-      return (char*)s;
-  return 0;
-}
-
-char*
-gets(char *buf, int max)
-{
-  int i, cc;
-  char c;
-
-  for(i=0; i+1 < max; ){
-    cc = read(0, &c, 1);
-    if(cc < 1)
-      break;
-    buf[i++] = c;
-    if(c == '\n' || c == '\r')
-      break;
-  }
-  buf[i] = '\0';
-  return buf;
-}
-
-int
-stat(const char *n, struct stat *st)
-{
-  int fd;
-  int r;
-
-  fd = open(n, O_RDONLY);
-  if(fd < 0)
-    return -1;
-  r = fstat(fd, st);
-  close(fd);
-  return r;
-}
-
-int
-atoi(const char *s)
-{
-  int n;
-
-  n = 0;
-  while('0' <= *s && *s <= '9')
-    n = n*10 + *s++ - '0';
-  return n;
-}
-
-void*
-memmove(void *vdst, const void *vsrc, int n)
-{
-  char *dst;
-  const char *src;
-
-  dst = vdst;
-  src = vsrc;
-  while(n-- > 0)
-    *dst++ = *src++;
-  return vdst;
-}
diff --git a/umalloc.c b/umalloc.c
deleted file mode 100644 (file)
index a7e7d2c..0000000
--- a/umalloc.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-#include "param.h"
-
-// Memory allocator by Kernighan and Ritchie,
-// The C programming Language, 2nd ed.  Section 8.7.
-
-typedef long Align;
-
-union header {
-  struct {
-    union header *ptr;
-    uint size;
-  } s;
-  Align x;
-};
-
-typedef union header Header;
-
-static Header base;
-static Header *freep;
-
-void
-free(void *ap)
-{
-  Header *bp, *p;
-
-  bp = (Header*)ap - 1;
-  for(p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
-    if(p >= p->s.ptr && (bp > p || bp < p->s.ptr))
-      break;
-  if(bp + bp->s.size == p->s.ptr){
-    bp->s.size += p->s.ptr->s.size;
-    bp->s.ptr = p->s.ptr->s.ptr;
-  } else
-    bp->s.ptr = p->s.ptr;
-  if(p + p->s.size == bp){
-    p->s.size += bp->s.size;
-    p->s.ptr = bp->s.ptr;
-  } else
-    p->s.ptr = bp;
-  freep = p;
-}
-
-static Header*
-morecore(uint nu)
-{
-  char *p;
-  Header *hp;
-
-  if(nu < 4096)
-    nu = 4096;
-  p = sbrk(nu * sizeof(Header));
-  if(p == (char*)-1)
-    return 0;
-  hp = (Header*)p;
-  hp->s.size = nu;
-  free((void*)(hp + 1));
-  return freep;
-}
-
-void*
-malloc(uint nbytes)
-{
-  Header *p, *prevp;
-  uint nunits;
-
-  nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1;
-  if((prevp = freep) == 0){
-    base.s.ptr = freep = prevp = &base;
-    base.s.size = 0;
-  }
-  for(p = prevp->s.ptr; ; prevp = p, p = p->s.ptr){
-    if(p->s.size >= nunits){
-      if(p->s.size == nunits)
-        prevp->s.ptr = p->s.ptr;
-      else {
-        p->s.size -= nunits;
-        p += p->s.size;
-        p->s.size = nunits;
-      }
-      freep = prevp;
-      return (void*)(p + 1);
-    }
-    if(p == freep)
-      if((p = morecore(nunits)) == 0)
-        return 0;
-  }
-}
diff --git a/user.h b/user.h
deleted file mode 100644 (file)
index 4f99c52..0000000
--- a/user.h
+++ /dev/null
@@ -1,39 +0,0 @@
-struct stat;
-struct rtcdate;
-
-// system calls
-int fork(void);
-int exit(void) __attribute__((noreturn));
-int wait(void);
-int pipe(int*);
-int write(int, const void*, int);
-int read(int, void*, int);
-int close(int);
-int kill(int);
-int exec(char*, char**);
-int open(const char*, int);
-int mknod(const char*, short, short);
-int unlink(const char*);
-int fstat(int fd, struct stat*);
-int link(const char*, const char*);
-int mkdir(const char*);
-int chdir(const char*);
-int dup(int);
-int getpid(void);
-char* sbrk(int);
-int sleep(int);
-int uptime(void);
-
-// ulib.c
-int stat(const char*, struct stat*);
-char* strcpy(char*, const char*);
-void *memmove(void*, const void*, int);
-char* strchr(const char*, char c);
-int strcmp(const char*, const char*);
-void printf(int, const char*, ...);
-char* gets(char*, int max);
-uint strlen(const char*);
-void* memset(void*, int, uint);
-void* malloc(uint);
-void free(void*);
-int atoi(const char*);
diff --git a/user/CMakeLists.txt b/user/CMakeLists.txt
new file mode 100644 (file)
index 0000000..afee636
--- /dev/null
@@ -0,0 +1,73 @@
+project(user ASM)
+
+include_directories(include)
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static -fno-builtin -nostdinc -nostartfiles -nodefaultlibs -fno-pic -m32")
+set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
+#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -N -e main -Ttext 0")
+# FIXME: Maybe use... unclear
+set(CMAKE_C_LINK_EXECUTABLE "ld -m elf_i386 -N -e main -Ttext 0 <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+
+# We need to do several things --
+# Need ulib sources (easy enough)
+# Need to compile the programs
+#  -- binary should add a _...
+# Need to create disassembly
+# Need to create symbol files
+
+set(ulib_SOURCES
+  asm/usys.S
+
+  src/ulib.c
+  src/umalloc.c
+  src/printf.c
+  )
+
+# Start with just init...
+set(user_SOURCES
+  src/init.c
+  src/sh.c
+  src/ls.c
+  )
+
+set_property(GLOBAL PROPERTY user_programs)
+
+add_library(ulib OBJECT
+  ${ulib_SOURCES})
+
+function(add_user_program program_src)
+  # Strip out src/ and .c
+  get_filename_component(prog_base ${program_src} NAME_WE)
+  # Add _
+  set(output_exe "_${prog_base}")
+  message("Have output_exe ${output_exe}")
+
+  get_property(l_user_programs GLOBAL PROPERTY user_programs)
+  list(APPEND l_user_programs "${output_exe}")
+  set_property(GLOBAL PROPERTY user_programs ${l_user_programs})
+
+  # First, build the program
+  add_executable(${output_exe} ${program_src} $<TARGET_OBJECTS:ulib>)
+  # Second, disassemble the program
+  # Third, get symbols
+endfunction(add_user_program)
+
+foreach(prog_src ${user_SOURCES})
+  add_user_program(${prog_src})
+endforeach(prog_src)
+
+get_property(l_user_programs GLOBAL PROPERTY user_programs)
+message("USER_PROGRAMS includes: ${l_user_programs}")
+
+configure_file(${CMAKE_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/README COPYONLY)
+
+add_custom_command(
+  OUTPUT fs.img
+  COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../tools/mkfs fs.img README ${l_user_programs}
+  DEPENDS mkfs ${CMAKE_SOURCE_DIR}/README ${l_user_programs}
+)
+
+add_custom_target(
+  makeuserfs ALL
+  DEPENDS fs.img)
+
diff --git a/user/asm/usys.S b/user/asm/usys.S
new file mode 100644 (file)
index 0000000..8bfd8a1
--- /dev/null
@@ -0,0 +1,31 @@
+#include "syscall.h"
+#include "traps.h"
+
+#define SYSCALL(name) \
+  .globl name; \
+  name: \
+    movl $SYS_ ## name, %eax; \
+    int $T_SYSCALL; \
+    ret
+
+SYSCALL(fork)
+SYSCALL(exit)
+SYSCALL(wait)
+SYSCALL(pipe)
+SYSCALL(read)
+SYSCALL(write)
+SYSCALL(close)
+SYSCALL(kill)
+SYSCALL(exec)
+SYSCALL(open)
+SYSCALL(mknod)
+SYSCALL(unlink)
+SYSCALL(fstat)
+SYSCALL(link)
+SYSCALL(mkdir)
+SYSCALL(chdir)
+SYSCALL(dup)
+SYSCALL(getpid)
+SYSCALL(sbrk)
+SYSCALL(sleep)
+SYSCALL(uptime)
diff --git a/user/include/user.h b/user/include/user.h
new file mode 100644 (file)
index 0000000..4f99c52
--- /dev/null
@@ -0,0 +1,39 @@
+struct stat;
+struct rtcdate;
+
+// system calls
+int fork(void);
+int exit(void) __attribute__((noreturn));
+int wait(void);
+int pipe(int*);
+int write(int, const void*, int);
+int read(int, void*, int);
+int close(int);
+int kill(int);
+int exec(char*, char**);
+int open(const char*, int);
+int mknod(const char*, short, short);
+int unlink(const char*);
+int fstat(int fd, struct stat*);
+int link(const char*, const char*);
+int mkdir(const char*);
+int chdir(const char*);
+int dup(int);
+int getpid(void);
+char* sbrk(int);
+int sleep(int);
+int uptime(void);
+
+// ulib.c
+int stat(const char*, struct stat*);
+char* strcpy(char*, const char*);
+void *memmove(void*, const void*, int);
+char* strchr(const char*, char c);
+int strcmp(const char*, const char*);
+void printf(int, const char*, ...);
+char* gets(char*, int max);
+uint strlen(const char*);
+void* memset(void*, int, uint);
+void* malloc(uint);
+void free(void*);
+int atoi(const char*);
diff --git a/user/src/cat.c b/user/src/cat.c
new file mode 100644 (file)
index 0000000..5ddc820
--- /dev/null
@@ -0,0 +1,43 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+char buf[512];
+
+void
+cat(int fd)
+{
+  int n;
+
+  while((n = read(fd, buf, sizeof(buf))) > 0) {
+    if (write(1, buf, n) != n) {
+      printf(1, "cat: write error\n");
+      exit();
+    }
+  }
+  if(n < 0){
+    printf(1, "cat: read error\n");
+    exit();
+  }
+}
+
+int
+main(int argc, char *argv[])
+{
+  int fd, i;
+
+  if(argc <= 1){
+    cat(0);
+    exit();
+  }
+
+  for(i = 1; i < argc; i++){
+    if((fd = open(argv[i], 0)) < 0){
+      printf(1, "cat: cannot open %s\n", argv[i]);
+      exit();
+    }
+    cat(fd);
+    close(fd);
+  }
+  exit();
+}
diff --git a/user/src/echo.c b/user/src/echo.c
new file mode 100644 (file)
index 0000000..806dee0
--- /dev/null
@@ -0,0 +1,13 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+int
+main(int argc, char *argv[])
+{
+  int i;
+
+  for(i = 1; i < argc; i++)
+    printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n");
+  exit();
+}
diff --git a/user/src/forktest.c b/user/src/forktest.c
new file mode 100644 (file)
index 0000000..8bc984d
--- /dev/null
@@ -0,0 +1,56 @@
+// Test that fork fails gracefully.
+// Tiny executable so that the limit can be filling the proc table.
+
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+#define N  1000
+
+void
+printf(int fd, const char *s, ...)
+{
+  write(fd, s, strlen(s));
+}
+
+void
+forktest(void)
+{
+  int n, pid;
+
+  printf(1, "fork test\n");
+
+  for(n=0; n<N; n++){
+    pid = fork();
+    if(pid < 0)
+      break;
+    if(pid == 0)
+      exit();
+  }
+
+  if(n == N){
+    printf(1, "fork claimed to work N times!\n", N);
+    exit();
+  }
+
+  for(; n > 0; n--){
+    if(wait() < 0){
+      printf(1, "wait stopped early\n");
+      exit();
+    }
+  }
+
+  if(wait() != -1){
+    printf(1, "wait got too many\n");
+    exit();
+  }
+
+  printf(1, "fork test OK\n");
+}
+
+int
+main(void)
+{
+  forktest();
+  exit();
+}
diff --git a/user/src/grep.c b/user/src/grep.c
new file mode 100644 (file)
index 0000000..adc4835
--- /dev/null
@@ -0,0 +1,107 @@
+// Simple grep.  Only supports ^ . * $ operators.
+
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+char buf[1024];
+int match(char*, char*);
+
+void
+grep(char *pattern, int fd)
+{
+  int n, m;
+  char *p, *q;
+
+  m = 0;
+  while((n = read(fd, buf+m, sizeof(buf)-m-1)) > 0){
+    m += n;
+    buf[m] = '\0';
+    p = buf;
+    while((q = strchr(p, '\n')) != 0){
+      *q = 0;
+      if(match(pattern, p)){
+        *q = '\n';
+        write(1, p, q+1 - p);
+      }
+      p = q+1;
+    }
+    if(p == buf)
+      m = 0;
+    if(m > 0){
+      m -= p - buf;
+      memmove(buf, p, m);
+    }
+  }
+}
+
+int
+main(int argc, char *argv[])
+{
+  int fd, i;
+  char *pattern;
+
+  if(argc <= 1){
+    printf(2, "usage: grep pattern [file ...]\n");
+    exit();
+  }
+  pattern = argv[1];
+
+  if(argc <= 2){
+    grep(pattern, 0);
+    exit();
+  }
+
+  for(i = 2; i < argc; i++){
+    if((fd = open(argv[i], 0)) < 0){
+      printf(1, "grep: cannot open %s\n", argv[i]);
+      exit();
+    }
+    grep(pattern, fd);
+    close(fd);
+  }
+  exit();
+}
+
+// Regexp matcher from Kernighan & Pike,
+// The Practice of Programming, Chapter 9.
+
+int matchhere(char*, char*);
+int matchstar(int, char*, char*);
+
+int
+match(char *re, char *text)
+{
+  if(re[0] == '^')
+    return matchhere(re+1, text);
+  do{  // must look at empty string
+    if(matchhere(re, text))
+      return 1;
+  }while(*text++ != '\0');
+  return 0;
+}
+
+// matchhere: search for re at beginning of text
+int matchhere(char *re, char *text)
+{
+  if(re[0] == '\0')
+    return 1;
+  if(re[1] == '*')
+    return matchstar(re[0], re+2, text);
+  if(re[0] == '$' && re[1] == '\0')
+    return *text == '\0';
+  if(*text!='\0' && (re[0]=='.' || re[0]==*text))
+    return matchhere(re+1, text+1);
+  return 0;
+}
+
+// matchstar: search for c*re at beginning of text
+int matchstar(int c, char *re, char *text)
+{
+  do{  // a * matches zero or more instances
+    if(matchhere(re, text))
+      return 1;
+  }while(*text!='\0' && (*text++==c || c=='.'));
+  return 0;
+}
+
diff --git a/user/src/init.c b/user/src/init.c
new file mode 100644 (file)
index 0000000..046b551
--- /dev/null
@@ -0,0 +1,37 @@
+// init: The initial user-level program
+
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+#include "fcntl.h"
+
+char *argv[] = { "sh", 0 };
+
+int
+main(void)
+{
+  int pid, wpid;
+
+  if(open("console", O_RDWR) < 0){
+    mknod("console", 1, 1);
+    open("console", O_RDWR);
+  }
+  dup(0);  // stdout
+  dup(0);  // stderr
+
+  for(;;){
+    printf(1, "init: starting sh\n");
+    pid = fork();
+    if(pid < 0){
+      printf(1, "init: fork failed\n");
+      exit();
+    }
+    if(pid == 0){
+      exec("sh", argv);
+      printf(1, "init: exec sh failed\n");
+      exit();
+    }
+    while((wpid=wait()) >= 0 && wpid != pid)
+      printf(1, "zombie!\n");
+  }
+}
diff --git a/user/src/kill.c b/user/src/kill.c
new file mode 100644 (file)
index 0000000..364f6af
--- /dev/null
@@ -0,0 +1,17 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+int
+main(int argc, char **argv)
+{
+  int i;
+
+  if(argc < 2){
+    printf(2, "usage: kill pid...\n");
+    exit();
+  }
+  for(i=1; i<argc; i++)
+    kill(atoi(argv[i]));
+  exit();
+}
diff --git a/user/src/ln.c b/user/src/ln.c
new file mode 100644 (file)
index 0000000..cf8a64e
--- /dev/null
@@ -0,0 +1,15 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+int
+main(int argc, char *argv[])
+{
+  if(argc != 3){
+    printf(2, "Usage: ln old new\n");
+    exit();
+  }
+  if(link(argv[1], argv[2]) < 0)
+    printf(2, "link %s %s: failed\n", argv[1], argv[2]);
+  exit();
+}
diff --git a/user/src/ls.c b/user/src/ls.c
new file mode 100644 (file)
index 0000000..2862913
--- /dev/null
@@ -0,0 +1,85 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+#include "fs.h"
+
+char*
+fmtname(char *path)
+{
+  static char buf[DIRSIZ+1];
+  char *p;
+
+  // Find first character after last slash.
+  for(p=path+strlen(path); p >= path && *p != '/'; p--)
+    ;
+  p++;
+
+  // Return blank-padded name.
+  if(strlen(p) >= DIRSIZ)
+    return p;
+  memmove(buf, p, strlen(p));
+  memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
+  return buf;
+}
+
+void
+ls(char *path)
+{
+  char buf[512], *p;
+  int fd;
+  struct dirent de;
+  struct stat st;
+
+  if((fd = open(path, 0)) < 0){
+    printf(2, "ls: cannot open %s\n", path);
+    return;
+  }
+
+  if(fstat(fd, &st) < 0){
+    printf(2, "ls: cannot stat %s\n", path);
+    close(fd);
+    return;
+  }
+
+  switch(st.type){
+  case T_FILE:
+    printf(1, "%s %d %d %d\n", fmtname(path), st.type, st.ino, st.size);
+    break;
+
+  case T_DIR:
+    if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
+      printf(1, "ls: path too long\n");
+      break;
+    }
+    strcpy(buf, path);
+    p = buf+strlen(buf);
+    *p++ = '/';
+    while(read(fd, &de, sizeof(de)) == sizeof(de)){
+      if(de.inum == 0)
+        continue;
+      memmove(p, de.name, DIRSIZ);
+      p[DIRSIZ] = 0;
+      if(stat(buf, &st) < 0){
+        printf(1, "ls: cannot stat %s\n", buf);
+        continue;
+      }
+      printf(1, "%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
+    }
+    break;
+  }
+  close(fd);
+}
+
+int
+main(int argc, char *argv[])
+{
+  int i;
+
+  if(argc < 2){
+    ls(".");
+    exit();
+  }
+  for(i=1; i<argc; i++)
+    ls(argv[i]);
+  exit();
+}
diff --git a/user/src/mkdir.c b/user/src/mkdir.c
new file mode 100644 (file)
index 0000000..6e4c954
--- /dev/null
@@ -0,0 +1,23 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+int
+main(int argc, char *argv[])
+{
+  int i;
+
+  if(argc < 2){
+    printf(2, "Usage: mkdir files...\n");
+    exit();
+  }
+
+  for(i = 1; i < argc; i++){
+    if(mkdir(argv[i]) < 0){
+      printf(2, "mkdir: %s failed to create\n", argv[i]);
+      break;
+    }
+  }
+
+  exit();
+}
diff --git a/user/src/printf.c b/user/src/printf.c
new file mode 100644 (file)
index 0000000..b3298aa
--- /dev/null
@@ -0,0 +1,85 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+static void
+putc(int fd, char c)
+{
+  write(fd, &c, 1);
+}
+
+static void
+printint(int fd, int xx, int base, int sgn)
+{
+  static char digits[] = "0123456789ABCDEF";
+  char buf[16];
+  int i, neg;
+  uint x;
+
+  neg = 0;
+  if(sgn && xx < 0){
+    neg = 1;
+    x = -xx;
+  } else {
+    x = xx;
+  }
+
+  i = 0;
+  do{
+    buf[i++] = digits[x % base];
+  }while((x /= base) != 0);
+  if(neg)
+    buf[i++] = '-';
+
+  while(--i >= 0)
+    putc(fd, buf[i]);
+}
+
+// Print to the given fd. Only understands %d, %x, %p, %s.
+void
+printf(int fd, const char *fmt, ...)
+{
+  char *s;
+  int c, i, state;
+  uint *ap;
+
+  state = 0;
+  ap = (uint*)(void*)&fmt + 1;
+  for(i = 0; fmt[i]; i++){
+    c = fmt[i] & 0xff;
+    if(state == 0){
+      if(c == '%'){
+        state = '%';
+      } else {
+        putc(fd, c);
+      }
+    } else if(state == '%'){
+      if(c == 'd'){
+        printint(fd, *ap, 10, 1);
+        ap++;
+      } else if(c == 'x' || c == 'p'){
+        printint(fd, *ap, 16, 0);
+        ap++;
+      } else if(c == 's'){
+        s = (char*)*ap;
+        ap++;
+        if(s == 0)
+          s = "(null)";
+        while(*s != 0){
+          putc(fd, *s);
+          s++;
+        }
+      } else if(c == 'c'){
+        putc(fd, *ap);
+        ap++;
+      } else if(c == '%'){
+        putc(fd, c);
+      } else {
+        // Unknown % sequence.  Print it to draw attention.
+        putc(fd, '%');
+        putc(fd, c);
+      }
+      state = 0;
+    }
+  }
+}
diff --git a/user/src/rm.c b/user/src/rm.c
new file mode 100644 (file)
index 0000000..4fd33c8
--- /dev/null
@@ -0,0 +1,23 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+int
+main(int argc, char *argv[])
+{
+  int i;
+
+  if(argc < 2){
+    printf(2, "Usage: rm files...\n");
+    exit();
+  }
+
+  for(i = 1; i < argc; i++){
+    if(unlink(argv[i]) < 0){
+      printf(2, "rm: %s failed to delete\n", argv[i]);
+      break;
+    }
+  }
+
+  exit();
+}
diff --git a/user/src/sh.c b/user/src/sh.c
new file mode 100644 (file)
index 0000000..054bab9
--- /dev/null
@@ -0,0 +1,493 @@
+// Shell.
+
+#include "types.h"
+#include "user.h"
+#include "fcntl.h"
+
+// Parsed command representation
+#define EXEC  1
+#define REDIR 2
+#define PIPE  3
+#define LIST  4
+#define BACK  5
+
+#define MAXARGS 10
+
+struct cmd {
+  int type;
+};
+
+struct execcmd {
+  int type;
+  char *argv[MAXARGS];
+  char *eargv[MAXARGS];
+};
+
+struct redircmd {
+  int type;
+  struct cmd *cmd;
+  char *file;
+  char *efile;
+  int mode;
+  int fd;
+};
+
+struct pipecmd {
+  int type;
+  struct cmd *left;
+  struct cmd *right;
+};
+
+struct listcmd {
+  int type;
+  struct cmd *left;
+  struct cmd *right;
+};
+
+struct backcmd {
+  int type;
+  struct cmd *cmd;
+};
+
+int fork1(void);  // Fork but panics on failure.
+void panic(char*);
+struct cmd *parsecmd(char*);
+
+// Execute cmd.  Never returns.
+void
+runcmd(struct cmd *cmd)
+{
+  int p[2];
+  struct backcmd *bcmd;
+  struct execcmd *ecmd;
+  struct listcmd *lcmd;
+  struct pipecmd *pcmd;
+  struct redircmd *rcmd;
+
+  if(cmd == 0)
+    exit();
+
+  switch(cmd->type){
+  default:
+    panic("runcmd");
+
+  case EXEC:
+    ecmd = (struct execcmd*)cmd;
+    if(ecmd->argv[0] == 0)
+      exit();
+    exec(ecmd->argv[0], ecmd->argv);
+    printf(2, "exec %s failed\n", ecmd->argv[0]);
+    break;
+
+  case REDIR:
+    rcmd = (struct redircmd*)cmd;
+    close(rcmd->fd);
+    if(open(rcmd->file, rcmd->mode) < 0){
+      printf(2, "open %s failed\n", rcmd->file);
+      exit();
+    }
+    runcmd(rcmd->cmd);
+    break;
+
+  case LIST:
+    lcmd = (struct listcmd*)cmd;
+    if(fork1() == 0)
+      runcmd(lcmd->left);
+    wait();
+    runcmd(lcmd->right);
+    break;
+
+  case PIPE:
+    pcmd = (struct pipecmd*)cmd;
+    if(pipe(p) < 0)
+      panic("pipe");
+    if(fork1() == 0){
+      close(1);
+      dup(p[1]);
+      close(p[0]);
+      close(p[1]);
+      runcmd(pcmd->left);
+    }
+    if(fork1() == 0){
+      close(0);
+      dup(p[0]);
+      close(p[0]);
+      close(p[1]);
+      runcmd(pcmd->right);
+    }
+    close(p[0]);
+    close(p[1]);
+    wait();
+    wait();
+    break;
+
+  case BACK:
+    bcmd = (struct backcmd*)cmd;
+    if(fork1() == 0)
+      runcmd(bcmd->cmd);
+    break;
+  }
+  exit();
+}
+
+int
+getcmd(char *buf, int nbuf)
+{
+  printf(2, "$ ");
+  memset(buf, 0, nbuf);
+  gets(buf, nbuf);
+  if(buf[0] == 0) // EOF
+    return -1;
+  return 0;
+}
+
+int
+main(void)
+{
+  static char buf[100];
+  int fd;
+
+  // Ensure that three file descriptors are open.
+  while((fd = open("console", O_RDWR)) >= 0){
+    if(fd >= 3){
+      close(fd);
+      break;
+    }
+  }
+
+  // Read and run input commands.
+  while(getcmd(buf, sizeof(buf)) >= 0){
+    if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
+      // Chdir must be called by the parent, not the child.
+      buf[strlen(buf)-1] = 0;  // chop \n
+      if(chdir(buf+3) < 0)
+        printf(2, "cannot cd %s\n", buf+3);
+      continue;
+    }
+    if(fork1() == 0)
+      runcmd(parsecmd(buf));
+    wait();
+  }
+  exit();
+}
+
+void
+panic(char *s)
+{
+  printf(2, "%s\n", s);
+  exit();
+}
+
+int
+fork1(void)
+{
+  int pid;
+
+  pid = fork();
+  if(pid == -1)
+    panic("fork");
+  return pid;
+}
+
+//PAGEBREAK!
+// Constructors
+
+struct cmd*
+execcmd(void)
+{
+  struct execcmd *cmd;
+
+  cmd = malloc(sizeof(*cmd));
+  memset(cmd, 0, sizeof(*cmd));
+  cmd->type = EXEC;
+  return (struct cmd*)cmd;
+}
+
+struct cmd*
+redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)
+{
+  struct redircmd *cmd;
+
+  cmd = malloc(sizeof(*cmd));
+  memset(cmd, 0, sizeof(*cmd));
+  cmd->type = REDIR;
+  cmd->cmd = subcmd;
+  cmd->file = file;
+  cmd->efile = efile;
+  cmd->mode = mode;
+  cmd->fd = fd;
+  return (struct cmd*)cmd;
+}
+
+struct cmd*
+pipecmd(struct cmd *left, struct cmd *right)
+{
+  struct pipecmd *cmd;
+
+  cmd = malloc(sizeof(*cmd));
+  memset(cmd, 0, sizeof(*cmd));
+  cmd->type = PIPE;
+  cmd->left = left;
+  cmd->right = right;
+  return (struct cmd*)cmd;
+}
+
+struct cmd*
+listcmd(struct cmd *left, struct cmd *right)
+{
+  struct listcmd *cmd;
+
+  cmd = malloc(sizeof(*cmd));
+  memset(cmd, 0, sizeof(*cmd));
+  cmd->type = LIST;
+  cmd->left = left;
+  cmd->right = right;
+  return (struct cmd*)cmd;
+}
+
+struct cmd*
+backcmd(struct cmd *subcmd)
+{
+  struct backcmd *cmd;
+
+  cmd = malloc(sizeof(*cmd));
+  memset(cmd, 0, sizeof(*cmd));
+  cmd->type = BACK;
+  cmd->cmd = subcmd;
+  return (struct cmd*)cmd;
+}
+//PAGEBREAK!
+// Parsing
+
+char whitespace[] = " \t\r\n\v";
+char symbols[] = "<|>&;()";
+
+int
+gettoken(char **ps, char *es, char **q, char **eq)
+{
+  char *s;
+  int ret;
+
+  s = *ps;
+  while(s < es && strchr(whitespace, *s))
+    s++;
+  if(q)
+    *q = s;
+  ret = *s;
+  switch(*s){
+  case 0:
+    break;
+  case '|':
+  case '(':
+  case ')':
+  case ';':
+  case '&':
+  case '<':
+    s++;
+    break;
+  case '>':
+    s++;
+    if(*s == '>'){
+      ret = '+';
+      s++;
+    }
+    break;
+  default:
+    ret = 'a';
+    while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
+      s++;
+    break;
+  }
+  if(eq)
+    *eq = s;
+
+  while(s < es && strchr(whitespace, *s))
+    s++;
+  *ps = s;
+  return ret;
+}
+
+int
+peek(char **ps, char *es, char *toks)
+{
+  char *s;
+
+  s = *ps;
+  while(s < es && strchr(whitespace, *s))
+    s++;
+  *ps = s;
+  return *s && strchr(toks, *s);
+}
+
+struct cmd *parseline(char**, char*);
+struct cmd *parsepipe(char**, char*);
+struct cmd *parseexec(char**, char*);
+struct cmd *nulterminate(struct cmd*);
+
+struct cmd*
+parsecmd(char *s)
+{
+  char *es;
+  struct cmd *cmd;
+
+  es = s + strlen(s);
+  cmd = parseline(&s, es);
+  peek(&s, es, "");
+  if(s != es){
+    printf(2, "leftovers: %s\n", s);
+    panic("syntax");
+  }
+  nulterminate(cmd);
+  return cmd;
+}
+
+struct cmd*
+parseline(char **ps, char *es)
+{
+  struct cmd *cmd;
+
+  cmd = parsepipe(ps, es);
+  while(peek(ps, es, "&")){
+    gettoken(ps, es, 0, 0);
+    cmd = backcmd(cmd);
+  }
+  if(peek(ps, es, ";")){
+    gettoken(ps, es, 0, 0);
+    cmd = listcmd(cmd, parseline(ps, es));
+  }
+  return cmd;
+}
+
+struct cmd*
+parsepipe(char **ps, char *es)
+{
+  struct cmd *cmd;
+
+  cmd = parseexec(ps, es);
+  if(peek(ps, es, "|")){
+    gettoken(ps, es, 0, 0);
+    cmd = pipecmd(cmd, parsepipe(ps, es));
+  }
+  return cmd;
+}
+
+struct cmd*
+parseredirs(struct cmd *cmd, char **ps, char *es)
+{
+  int tok;
+  char *q, *eq;
+
+  while(peek(ps, es, "<>")){
+    tok = gettoken(ps, es, 0, 0);
+    if(gettoken(ps, es, &q, &eq) != 'a')
+      panic("missing file for redirection");
+    switch(tok){
+    case '<':
+      cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
+      break;
+    case '>':
+      cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
+      break;
+    case '+':  // >>
+      cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
+      break;
+    }
+  }
+  return cmd;
+}
+
+struct cmd*
+parseblock(char **ps, char *es)
+{
+  struct cmd *cmd;
+
+  if(!peek(ps, es, "("))
+    panic("parseblock");
+  gettoken(ps, es, 0, 0);
+  cmd = parseline(ps, es);
+  if(!peek(ps, es, ")"))
+    panic("syntax - missing )");
+  gettoken(ps, es, 0, 0);
+  cmd = parseredirs(cmd, ps, es);
+  return cmd;
+}
+
+struct cmd*
+parseexec(char **ps, char *es)
+{
+  char *q, *eq;
+  int tok, argc;
+  struct execcmd *cmd;
+  struct cmd *ret;
+
+  if(peek(ps, es, "("))
+    return parseblock(ps, es);
+
+  ret = execcmd();
+  cmd = (struct execcmd*)ret;
+
+  argc = 0;
+  ret = parseredirs(ret, ps, es);
+  while(!peek(ps, es, "|)&;")){
+    if((tok=gettoken(ps, es, &q, &eq)) == 0)
+      break;
+    if(tok != 'a')
+      panic("syntax");
+    cmd->argv[argc] = q;
+    cmd->eargv[argc] = eq;
+    argc++;
+    if(argc >= MAXARGS)
+      panic("too many args");
+    ret = parseredirs(ret, ps, es);
+  }
+  cmd->argv[argc] = 0;
+  cmd->eargv[argc] = 0;
+  return ret;
+}
+
+// NUL-terminate all the counted strings.
+struct cmd*
+nulterminate(struct cmd *cmd)
+{
+  int i;
+  struct backcmd *bcmd;
+  struct execcmd *ecmd;
+  struct listcmd *lcmd;
+  struct pipecmd *pcmd;
+  struct redircmd *rcmd;
+
+  if(cmd == 0)
+    return 0;
+
+  switch(cmd->type){
+  case EXEC:
+    ecmd = (struct execcmd*)cmd;
+    for(i=0; ecmd->argv[i]; i++)
+      *ecmd->eargv[i] = 0;
+    break;
+
+  case REDIR:
+    rcmd = (struct redircmd*)cmd;
+    nulterminate(rcmd->cmd);
+    *rcmd->efile = 0;
+    break;
+
+  case PIPE:
+    pcmd = (struct pipecmd*)cmd;
+    nulterminate(pcmd->left);
+    nulterminate(pcmd->right);
+    break;
+
+  case LIST:
+    lcmd = (struct listcmd*)cmd;
+    nulterminate(lcmd->left);
+    nulterminate(lcmd->right);
+    break;
+
+  case BACK:
+    bcmd = (struct backcmd*)cmd;
+    nulterminate(bcmd->cmd);
+    break;
+  }
+  return cmd;
+}
diff --git a/user/src/stressfs.c b/user/src/stressfs.c
new file mode 100644 (file)
index 0000000..c0a4743
--- /dev/null
@@ -0,0 +1,49 @@
+// Demonstrate that moving the "acquire" in iderw after the loop that
+// appends to the idequeue results in a race.
+
+// For this to work, you should also add a spin within iderw's
+// idequeue traversal loop.  Adding the following demonstrated a panic
+// after about 5 runs of stressfs in QEMU on a 2.1GHz CPU:
+//    for (i = 0; i < 40000; i++)
+//      asm volatile("");
+
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+#include "fs.h"
+#include "fcntl.h"
+
+int
+main(int argc, char *argv[])
+{
+  int fd, i;
+  char path[] = "stressfs0";
+  char data[512];
+
+  printf(1, "stressfs starting\n");
+  memset(data, 'a', sizeof(data));
+
+  for(i = 0; i < 4; i++)
+    if(fork() > 0)
+      break;
+
+  printf(1, "write %d\n", i);
+
+  path[8] += i;
+  fd = open(path, O_CREATE | O_RDWR);
+  for(i = 0; i < 20; i++)
+//    printf(fd, "%d\n", i);
+    write(fd, data, sizeof(data));
+  close(fd);
+
+  printf(1, "read\n");
+
+  fd = open(path, O_RDONLY);
+  for (i = 0; i < 20; i++)
+    read(fd, data, sizeof(data));
+  close(fd);
+
+  wait();
+
+  exit();
+}
diff --git a/user/src/ulib.c b/user/src/ulib.c
new file mode 100644 (file)
index 0000000..bca3839
--- /dev/null
@@ -0,0 +1,106 @@
+#include "types.h"
+#include "stat.h"
+#include "fcntl.h"
+#include "user.h"
+#include "asm/x86.h"
+
+char*
+strcpy(char *s, const char *t)
+{
+  char *os;
+
+  os = s;
+  while((*s++ = *t++) != 0)
+    ;
+  return os;
+}
+
+int
+strcmp(const char *p, const char *q)
+{
+  while(*p && *p == *q)
+    p++, q++;
+  return (uchar)*p - (uchar)*q;
+}
+
+uint
+strlen(const char *s)
+{
+  int n;
+
+  for(n = 0; s[n]; n++)
+    ;
+  return n;
+}
+
+void*
+memset(void *dst, int c, uint n)
+{
+  stosb(dst, c, n);
+  return dst;
+}
+
+char*
+strchr(const char *s, char c)
+{
+  for(; *s; s++)
+    if(*s == c)
+      return (char*)s;
+  return 0;
+}
+
+char*
+gets(char *buf, int max)
+{
+  int i, cc;
+  char c;
+
+  for(i=0; i+1 < max; ){
+    cc = read(0, &c, 1);
+    if(cc < 1)
+      break;
+    buf[i++] = c;
+    if(c == '\n' || c == '\r')
+      break;
+  }
+  buf[i] = '\0';
+  return buf;
+}
+
+int
+stat(const char *n, struct stat *st)
+{
+  int fd;
+  int r;
+
+  fd = open(n, O_RDONLY);
+  if(fd < 0)
+    return -1;
+  r = fstat(fd, st);
+  close(fd);
+  return r;
+}
+
+int
+atoi(const char *s)
+{
+  int n;
+
+  n = 0;
+  while('0' <= *s && *s <= '9')
+    n = n*10 + *s++ - '0';
+  return n;
+}
+
+void*
+memmove(void *vdst, const void *vsrc, int n)
+{
+  char *dst;
+  const char *src;
+
+  dst = vdst;
+  src = vsrc;
+  while(n-- > 0)
+    *dst++ = *src++;
+  return vdst;
+}
diff --git a/user/src/umalloc.c b/user/src/umalloc.c
new file mode 100644 (file)
index 0000000..a7e7d2c
--- /dev/null
@@ -0,0 +1,90 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+#include "param.h"
+
+// Memory allocator by Kernighan and Ritchie,
+// The C programming Language, 2nd ed.  Section 8.7.
+
+typedef long Align;
+
+union header {
+  struct {
+    union header *ptr;
+    uint size;
+  } s;
+  Align x;
+};
+
+typedef union header Header;
+
+static Header base;
+static Header *freep;
+
+void
+free(void *ap)
+{
+  Header *bp, *p;
+
+  bp = (Header*)ap - 1;
+  for(p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
+    if(p >= p->s.ptr && (bp > p || bp < p->s.ptr))
+      break;
+  if(bp + bp->s.size == p->s.ptr){
+    bp->s.size += p->s.ptr->s.size;
+    bp->s.ptr = p->s.ptr->s.ptr;
+  } else
+    bp->s.ptr = p->s.ptr;
+  if(p + p->s.size == bp){
+    p->s.size += bp->s.size;
+    p->s.ptr = bp->s.ptr;
+  } else
+    p->s.ptr = bp;
+  freep = p;
+}
+
+static Header*
+morecore(uint nu)
+{
+  char *p;
+  Header *hp;
+
+  if(nu < 4096)
+    nu = 4096;
+  p = sbrk(nu * sizeof(Header));
+  if(p == (char*)-1)
+    return 0;
+  hp = (Header*)p;
+  hp->s.size = nu;
+  free((void*)(hp + 1));
+  return freep;
+}
+
+void*
+malloc(uint nbytes)
+{
+  Header *p, *prevp;
+  uint nunits;
+
+  nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1;
+  if((prevp = freep) == 0){
+    base.s.ptr = freep = prevp = &base;
+    base.s.size = 0;
+  }
+  for(p = prevp->s.ptr; ; prevp = p, p = p->s.ptr){
+    if(p->s.size >= nunits){
+      if(p->s.size == nunits)
+        prevp->s.ptr = p->s.ptr;
+      else {
+        p->s.size -= nunits;
+        p += p->s.size;
+        p->s.size = nunits;
+      }
+      freep = prevp;
+      return (void*)(p + 1);
+    }
+    if(p == freep)
+      if((p = morecore(nunits)) == 0)
+        return 0;
+  }
+}
diff --git a/user/src/usertests.c b/user/src/usertests.c
new file mode 100644 (file)
index 0000000..44e57f7
--- /dev/null
@@ -0,0 +1,1803 @@
+#include "param.h"
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+#include "fs.h"
+#include "fcntl.h"
+#include "syscall.h"
+#include "traps.h"
+#include "memlayout.h"
+
+char buf[8192];
+char name[3];
+char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 };
+int stdout = 1;
+
+// does chdir() call iput(p->cwd) in a transaction?
+void
+iputtest(void)
+{
+  printf(stdout, "iput test\n");
+
+  if(mkdir("iputdir") < 0){
+    printf(stdout, "mkdir failed\n");
+    exit();
+  }
+  if(chdir("iputdir") < 0){
+    printf(stdout, "chdir iputdir failed\n");
+    exit();
+  }
+  if(unlink("../iputdir") < 0){
+    printf(stdout, "unlink ../iputdir failed\n");
+    exit();
+  }
+  if(chdir("/") < 0){
+    printf(stdout, "chdir / failed\n");
+    exit();
+  }
+  printf(stdout, "iput test ok\n");
+}
+
+// does exit() call iput(p->cwd) in a transaction?
+void
+exitiputtest(void)
+{
+  int pid;
+
+  printf(stdout, "exitiput test\n");
+
+  pid = fork();
+  if(pid < 0){
+    printf(stdout, "fork failed\n");
+    exit();
+  }
+  if(pid == 0){
+    if(mkdir("iputdir") < 0){
+      printf(stdout, "mkdir failed\n");
+      exit();
+    }
+    if(chdir("iputdir") < 0){
+      printf(stdout, "child chdir failed\n");
+      exit();
+    }
+    if(unlink("../iputdir") < 0){
+      printf(stdout, "unlink ../iputdir failed\n");
+      exit();
+    }
+    exit();
+  }
+  wait();
+  printf(stdout, "exitiput test ok\n");
+}
+
+// does the error path in open() for attempt to write a
+// directory call iput() in a transaction?
+// needs a hacked kernel that pauses just after the namei()
+// call in sys_open():
+//    if((ip = namei(path)) == 0)
+//      return -1;
+//    {
+//      int i;
+//      for(i = 0; i < 10000; i++)
+//        yield();
+//    }
+void
+openiputtest(void)
+{
+  int pid;
+
+  printf(stdout, "openiput test\n");
+  if(mkdir("oidir") < 0){
+    printf(stdout, "mkdir oidir failed\n");
+    exit();
+  }
+  pid = fork();
+  if(pid < 0){
+    printf(stdout, "fork failed\n");
+    exit();
+  }
+  if(pid == 0){
+    int fd = open("oidir", O_RDWR);
+    if(fd >= 0){
+      printf(stdout, "open directory for write succeeded\n");
+      exit();
+    }
+    exit();
+  }
+  sleep(1);
+  if(unlink("oidir") != 0){
+    printf(stdout, "unlink failed\n");
+    exit();
+  }
+  wait();
+  printf(stdout, "openiput test ok\n");
+}
+
+// simple file system tests
+
+void
+opentest(void)
+{
+  int fd;
+
+  printf(stdout, "open test\n");
+  fd = open("echo", 0);
+  if(fd < 0){
+    printf(stdout, "open echo failed!\n");
+    exit();
+  }
+  close(fd);
+  fd = open("doesnotexist", 0);
+  if(fd >= 0){
+    printf(stdout, "open doesnotexist succeeded!\n");
+    exit();
+  }
+  printf(stdout, "open test ok\n");
+}
+
+void
+writetest(void)
+{
+  int fd;
+  int i;
+
+  printf(stdout, "small file test\n");
+  fd = open("small", O_CREATE|O_RDWR);
+  if(fd >= 0){
+    printf(stdout, "creat small succeeded; ok\n");
+  } else {
+    printf(stdout, "error: creat small failed!\n");
+    exit();
+  }
+  for(i = 0; i < 100; i++){
+    if(write(fd, "aaaaaaaaaa", 10) != 10){
+      printf(stdout, "error: write aa %d new file failed\n", i);
+      exit();
+    }
+    if(write(fd, "bbbbbbbbbb", 10) != 10){
+      printf(stdout, "error: write bb %d new file failed\n", i);
+      exit();
+    }
+  }
+  printf(stdout, "writes ok\n");
+  close(fd);
+  fd = open("small", O_RDONLY);
+  if(fd >= 0){
+    printf(stdout, "open small succeeded ok\n");
+  } else {
+    printf(stdout, "error: open small failed!\n");
+    exit();
+  }
+  i = read(fd, buf, 2000);
+  if(i == 2000){
+    printf(stdout, "read succeeded ok\n");
+  } else {
+    printf(stdout, "read failed\n");
+    exit();
+  }
+  close(fd);
+
+  if(unlink("small") < 0){
+    printf(stdout, "unlink small failed\n");
+    exit();
+  }
+  printf(stdout, "small file test ok\n");
+}
+
+void
+writetest1(void)
+{
+  int i, fd, n;
+
+  printf(stdout, "big files test\n");
+
+  fd = open("big", O_CREATE|O_RDWR);
+  if(fd < 0){
+    printf(stdout, "error: creat big failed!\n");
+    exit();
+  }
+
+  for(i = 0; i < MAXFILE; i++){
+    ((int*)buf)[0] = i;
+    if(write(fd, buf, 512) != 512){
+      printf(stdout, "error: write big file failed\n", i);
+      exit();
+    }
+  }
+
+  close(fd);
+
+  fd = open("big", O_RDONLY);
+  if(fd < 0){
+    printf(stdout, "error: open big failed!\n");
+    exit();
+  }
+
+  n = 0;
+  for(;;){
+    i = read(fd, buf, 512);
+    if(i == 0){
+      if(n == MAXFILE - 1){
+        printf(stdout, "read only %d blocks from big", n);
+        exit();
+      }
+      break;
+    } else if(i != 512){
+      printf(stdout, "read failed %d\n", i);
+      exit();
+    }
+    if(((int*)buf)[0] != n){
+      printf(stdout, "read content of block %d is %d\n",
+             n, ((int*)buf)[0]);
+      exit();
+    }
+    n++;
+  }
+  close(fd);
+  if(unlink("big") < 0){
+    printf(stdout, "unlink big failed\n");
+    exit();
+  }
+  printf(stdout, "big files ok\n");
+}
+
+void
+createtest(void)
+{
+  int i, fd;
+
+  printf(stdout, "many creates, followed by unlink test\n");
+
+  name[0] = 'a';
+  name[2] = '\0';
+  for(i = 0; i < 52; i++){
+    name[1] = '0' + i;
+    fd = open(name, O_CREATE|O_RDWR);
+    close(fd);
+  }
+  name[0] = 'a';
+  name[2] = '\0';
+  for(i = 0; i < 52; i++){
+    name[1] = '0' + i;
+    unlink(name);
+  }
+  printf(stdout, "many creates, followed by unlink; ok\n");
+}
+
+void dirtest(void)
+{
+  printf(stdout, "mkdir test\n");
+
+  if(mkdir("dir0") < 0){
+    printf(stdout, "mkdir failed\n");
+    exit();
+  }
+
+  if(chdir("dir0") < 0){
+    printf(stdout, "chdir dir0 failed\n");
+    exit();
+  }
+
+  if(chdir("..") < 0){
+    printf(stdout, "chdir .. failed\n");
+    exit();
+  }
+
+  if(unlink("dir0") < 0){
+    printf(stdout, "unlink dir0 failed\n");
+    exit();
+  }
+  printf(stdout, "mkdir test ok\n");
+}
+
+void
+exectest(void)
+{
+  printf(stdout, "exec test\n");
+  if(exec("echo", echoargv) < 0){
+    printf(stdout, "exec echo failed\n");
+    exit();
+  }
+}
+
+// simple fork and pipe read/write
+
+void
+pipe1(void)
+{
+  int fds[2], pid;
+  int seq, i, n, cc, total;
+
+  if(pipe(fds) != 0){
+    printf(1, "pipe() failed\n");
+    exit();
+  }
+  pid = fork();
+  seq = 0;
+  if(pid == 0){
+    close(fds[0]);
+    for(n = 0; n < 5; n++){
+      for(i = 0; i < 1033; i++)
+        buf[i] = seq++;
+      if(write(fds[1], buf, 1033) != 1033){
+        printf(1, "pipe1 oops 1\n");
+        exit();
+      }
+    }
+    exit();
+  } else if(pid > 0){
+    close(fds[1]);
+    total = 0;
+    cc = 1;
+    while((n = read(fds[0], buf, cc)) > 0){
+      for(i = 0; i < n; i++){
+        if((buf[i] & 0xff) != (seq++ & 0xff)){
+          printf(1, "pipe1 oops 2\n");
+          return;
+        }
+      }
+      total += n;
+      cc = cc * 2;
+      if(cc > sizeof(buf))
+        cc = sizeof(buf);
+    }
+    if(total != 5 * 1033){
+      printf(1, "pipe1 oops 3 total %d\n", total);
+      exit();
+    }
+    close(fds[0]);
+    wait();
+  } else {
+    printf(1, "fork() failed\n");
+    exit();
+  }
+  printf(1, "pipe1 ok\n");
+}
+
+// meant to be run w/ at most two CPUs
+void
+preempt(void)
+{
+  int pid1, pid2, pid3;
+  int pfds[2];
+
+  printf(1, "preempt: ");
+  pid1 = fork();
+  if(pid1 == 0)
+    for(;;)
+      ;
+
+  pid2 = fork();
+  if(pid2 == 0)
+    for(;;)
+      ;
+
+  pipe(pfds);
+  pid3 = fork();
+  if(pid3 == 0){
+    close(pfds[0]);
+    if(write(pfds[1], "x", 1) != 1)
+      printf(1, "preempt write error");
+    close(pfds[1]);
+    for(;;)
+      ;
+  }
+
+  close(pfds[1]);
+  if(read(pfds[0], buf, sizeof(buf)) != 1){
+    printf(1, "preempt read error");
+    return;
+  }
+  close(pfds[0]);
+  printf(1, "kill... ");
+  kill(pid1);
+  kill(pid2);
+  kill(pid3);
+  printf(1, "wait... ");
+  wait();
+  wait();
+  wait();
+  printf(1, "preempt ok\n");
+}
+
+// try to find any races between exit and wait
+void
+exitwait(void)
+{
+  int i, pid;
+
+  for(i = 0; i < 100; i++){
+    pid = fork();
+    if(pid < 0){
+      printf(1, "fork failed\n");
+      return;
+    }
+    if(pid){
+      if(wait() != pid){
+        printf(1, "wait wrong pid\n");
+        return;
+      }
+    } else {
+      exit();
+    }
+  }
+  printf(1, "exitwait ok\n");
+}
+
+void
+mem(void)
+{
+  void *m1, *m2;
+  int pid, ppid;
+
+  printf(1, "mem test\n");
+  ppid = getpid();
+  if((pid = fork()) == 0){
+    m1 = 0;
+    while((m2 = malloc(10001)) != 0){
+      *(char**)m2 = m1;
+      m1 = m2;
+    }
+    while(m1){
+      m2 = *(char**)m1;
+      free(m1);
+      m1 = m2;
+    }
+    m1 = malloc(1024*20);
+    if(m1 == 0){
+      printf(1, "couldn't allocate mem?!!\n");
+      kill(ppid);
+      exit();
+    }
+    free(m1);
+    printf(1, "mem ok\n");
+    exit();
+  } else {
+    wait();
+  }
+}
+
+// More file system tests
+
+// two processes write to the same file descriptor
+// is the offset shared? does inode locking work?
+void
+sharedfd(void)
+{
+  int fd, pid, i, n, nc, np;
+  char buf[10];
+
+  printf(1, "sharedfd test\n");
+
+  unlink("sharedfd");
+  fd = open("sharedfd", O_CREATE|O_RDWR);
+  if(fd < 0){
+    printf(1, "fstests: cannot open sharedfd for writing");
+    return;
+  }
+  pid = fork();
+  memset(buf, pid==0?'c':'p', sizeof(buf));
+  for(i = 0; i < 1000; i++){
+    if(write(fd, buf, sizeof(buf)) != sizeof(buf)){
+      printf(1, "fstests: write sharedfd failed\n");
+      break;
+    }
+  }
+  if(pid == 0)
+    exit();
+  else
+    wait();
+  close(fd);
+  fd = open("sharedfd", 0);
+  if(fd < 0){
+    printf(1, "fstests: cannot open sharedfd for reading\n");
+    return;
+  }
+  nc = np = 0;
+  while((n = read(fd, buf, sizeof(buf))) > 0){
+    for(i = 0; i < sizeof(buf); i++){
+      if(buf[i] == 'c')
+        nc++;
+      if(buf[i] == 'p')
+        np++;
+    }
+  }
+  close(fd);
+  unlink("sharedfd");
+  if(nc == 10000 && np == 10000){
+    printf(1, "sharedfd ok\n");
+  } else {
+    printf(1, "sharedfd oops %d %d\n", nc, np);
+    exit();
+  }
+}
+
+// four processes write different files at the same
+// time, to test block allocation.
+void
+fourfiles(void)
+{
+  int fd, pid, i, j, n, total, pi;
+  char *names[] = { "f0", "f1", "f2", "f3" };
+  char *fname;
+
+  printf(1, "fourfiles test\n");
+
+  for(pi = 0; pi < 4; pi++){
+    fname = names[pi];
+    unlink(fname);
+
+    pid = fork();
+    if(pid < 0){
+      printf(1, "fork failed\n");
+      exit();
+    }
+
+    if(pid == 0){
+      fd = open(fname, O_CREATE | O_RDWR);
+      if(fd < 0){
+        printf(1, "create failed\n");
+        exit();
+      }
+
+      memset(buf, '0'+pi, 512);
+      for(i = 0; i < 12; i++){
+        if((n = write(fd, buf, 500)) != 500){
+          printf(1, "write failed %d\n", n);
+          exit();
+        }
+      }
+      exit();
+    }
+  }
+
+  for(pi = 0; pi < 4; pi++){
+    wait();
+  }
+
+  for(i = 0; i < 2; i++){
+    fname = names[i];
+    fd = open(fname, 0);
+    total = 0;
+    while((n = read(fd, buf, sizeof(buf))) > 0){
+      for(j = 0; j < n; j++){
+        if(buf[j] != '0'+i){
+          printf(1, "wrong char\n");
+          exit();
+        }
+      }
+      total += n;
+    }
+    close(fd);
+    if(total != 12*500){
+      printf(1, "wrong length %d\n", total);
+      exit();
+    }
+    unlink(fname);
+  }
+
+  printf(1, "fourfiles ok\n");
+}
+
+// four processes create and delete different files in same directory
+void
+createdelete(void)
+{
+  enum { N = 20 };
+  int pid, i, fd, pi;
+  char name[32];
+
+  printf(1, "createdelete test\n");
+
+  for(pi = 0; pi < 4; pi++){
+    pid = fork();
+    if(pid < 0){
+      printf(1, "fork failed\n");
+      exit();
+    }
+
+    if(pid == 0){
+      name[0] = 'p' + pi;
+      name[2] = '\0';
+      for(i = 0; i < N; i++){
+        name[1] = '0' + i;
+        fd = open(name, O_CREATE | O_RDWR);
+        if(fd < 0){
+          printf(1, "create failed\n");
+          exit();
+        }
+        close(fd);
+        if(i > 0 && (i % 2 ) == 0){
+          name[1] = '0' + (i / 2);
+          if(unlink(name) < 0){
+            printf(1, "unlink failed\n");
+            exit();
+          }
+        }
+      }
+      exit();
+    }
+  }
+
+  for(pi = 0; pi < 4; pi++){
+    wait();
+  }
+
+  name[0] = name[1] = name[2] = 0;
+  for(i = 0; i < N; i++){
+    for(pi = 0; pi < 4; pi++){
+      name[0] = 'p' + pi;
+      name[1] = '0' + i;
+      fd = open(name, 0);
+      if((i == 0 || i >= N/2) && fd < 0){
+        printf(1, "oops createdelete %s didn't exist\n", name);
+        exit();
+      } else if((i >= 1 && i < N/2) && fd >= 0){
+        printf(1, "oops createdelete %s did exist\n", name);
+        exit();
+      }
+      if(fd >= 0)
+        close(fd);
+    }
+  }
+
+  for(i = 0; i < N; i++){
+    for(pi = 0; pi < 4; pi++){
+      name[0] = 'p' + i;
+      name[1] = '0' + i;
+      unlink(name);
+    }
+  }
+
+  printf(1, "createdelete ok\n");
+}
+
+// can I unlink a file and still read it?
+void
+unlinkread(void)
+{
+  int fd, fd1;
+
+  printf(1, "unlinkread test\n");
+  fd = open("unlinkread", O_CREATE | O_RDWR);
+  if(fd < 0){
+    printf(1, "create unlinkread failed\n");
+    exit();
+  }
+  write(fd, "hello", 5);
+  close(fd);
+
+  fd = open("unlinkread", O_RDWR);
+  if(fd < 0){
+    printf(1, "open unlinkread failed\n");
+    exit();
+  }
+  if(unlink("unlinkread") != 0){
+    printf(1, "unlink unlinkread failed\n");
+    exit();
+  }
+
+  fd1 = open("unlinkread", O_CREATE | O_RDWR);
+  write(fd1, "yyy", 3);
+  close(fd1);
+
+  if(read(fd, buf, sizeof(buf)) != 5){
+    printf(1, "unlinkread read failed");
+    exit();
+  }
+  if(buf[0] != 'h'){
+    printf(1, "unlinkread wrong data\n");
+    exit();
+  }
+  if(write(fd, buf, 10) != 10){
+    printf(1, "unlinkread write failed\n");
+    exit();
+  }
+  close(fd);
+  unlink("unlinkread");
+  printf(1, "unlinkread ok\n");
+}
+
+void
+linktest(void)
+{
+  int fd;
+
+  printf(1, "linktest\n");
+
+  unlink("lf1");
+  unlink("lf2");
+
+  fd = open("lf1", O_CREATE|O_RDWR);
+  if(fd < 0){
+    printf(1, "create lf1 failed\n");
+    exit();
+  }
+  if(write(fd, "hello", 5) != 5){
+    printf(1, "write lf1 failed\n");
+    exit();
+  }
+  close(fd);
+
+  if(link("lf1", "lf2") < 0){
+    printf(1, "link lf1 lf2 failed\n");
+    exit();
+  }
+  unlink("lf1");
+
+  if(open("lf1", 0) >= 0){
+    printf(1, "unlinked lf1 but it is still there!\n");
+    exit();
+  }
+
+  fd = open("lf2", 0);
+  if(fd < 0){
+    printf(1, "open lf2 failed\n");
+    exit();
+  }
+  if(read(fd, buf, sizeof(buf)) != 5){
+    printf(1, "read lf2 failed\n");
+    exit();
+  }
+  close(fd);
+
+  if(link("lf2", "lf2") >= 0){
+    printf(1, "link lf2 lf2 succeeded! oops\n");
+    exit();
+  }
+
+  unlink("lf2");
+  if(link("lf2", "lf1") >= 0){
+    printf(1, "link non-existant succeeded! oops\n");
+    exit();
+  }
+
+  if(link(".", "lf1") >= 0){
+    printf(1, "link . lf1 succeeded! oops\n");
+    exit();
+  }
+
+  printf(1, "linktest ok\n");
+}
+
+// test concurrent create/link/unlink of the same file
+void
+concreate(void)
+{
+  char file[3];
+  int i, pid, n, fd;
+  char fa[40];
+  struct {
+    ushort inum;
+    char name[14];
+  } de;
+
+  printf(1, "concreate test\n");
+  file[0] = 'C';
+  file[2] = '\0';
+  for(i = 0; i < 40; i++){
+    file[1] = '0' + i;
+    unlink(file);
+    pid = fork();
+    if(pid && (i % 3) == 1){
+      link("C0", file);
+    } else if(pid == 0 && (i % 5) == 1){
+      link("C0", file);
+    } else {
+      fd = open(file, O_CREATE | O_RDWR);
+      if(fd < 0){
+        printf(1, "concreate create %s failed\n", file);
+        exit();
+      }
+      close(fd);
+    }
+    if(pid == 0)
+      exit();
+    else
+      wait();
+  }
+
+  memset(fa, 0, sizeof(fa));
+  fd = open(".", 0);
+  n = 0;
+  while(read(fd, &de, sizeof(de)) > 0){
+    if(de.inum == 0)
+      continue;
+    if(de.name[0] == 'C' && de.name[2] == '\0'){
+      i = de.name[1] - '0';
+      if(i < 0 || i >= sizeof(fa)){
+        printf(1, "concreate weird file %s\n", de.name);
+        exit();
+      }
+      if(fa[i]){
+        printf(1, "concreate duplicate file %s\n", de.name);
+        exit();
+      }
+      fa[i] = 1;
+      n++;
+    }
+  }
+  close(fd);
+
+  if(n != 40){
+    printf(1, "concreate not enough files in directory listing\n");
+    exit();
+  }
+
+  for(i = 0; i < 40; i++){
+    file[1] = '0' + i;
+    pid = fork();
+    if(pid < 0){
+      printf(1, "fork failed\n");
+      exit();
+    }
+    if(((i % 3) == 0 && pid == 0) ||
+       ((i % 3) == 1 && pid != 0)){
+      close(open(file, 0));
+      close(open(file, 0));
+      close(open(file, 0));
+      close(open(file, 0));
+    } else {
+      unlink(file);
+      unlink(file);
+      unlink(file);
+      unlink(file);
+    }
+    if(pid == 0)
+      exit();
+    else
+      wait();
+  }
+
+  printf(1, "concreate ok\n");
+}
+
+// another concurrent link/unlink/create test,
+// to look for deadlocks.
+void
+linkunlink()
+{
+  int pid, i;
+
+  printf(1, "linkunlink test\n");
+
+  unlink("x");
+  pid = fork();
+  if(pid < 0){
+    printf(1, "fork failed\n");
+    exit();
+  }
+
+  unsigned int x = (pid ? 1 : 97);
+  for(i = 0; i < 100; i++){
+    x = x * 1103515245 + 12345;
+    if((x % 3) == 0){
+      close(open("x", O_RDWR | O_CREATE));
+    } else if((x % 3) == 1){
+      link("cat", "x");
+    } else {
+      unlink("x");
+    }
+  }
+
+  if(pid)
+    wait();
+  else
+    exit();
+
+  printf(1, "linkunlink ok\n");
+}
+
+// directory that uses indirect blocks
+void
+bigdir(void)
+{
+  int i, fd;
+  char name[10];
+
+  printf(1, "bigdir test\n");
+  unlink("bd");
+
+  fd = open("bd", O_CREATE);
+  if(fd < 0){
+    printf(1, "bigdir create failed\n");
+    exit();
+  }
+  close(fd);
+
+  for(i = 0; i < 500; i++){
+    name[0] = 'x';
+    name[1] = '0' + (i / 64);
+    name[2] = '0' + (i % 64);
+    name[3] = '\0';
+    if(link("bd", name) != 0){
+      printf(1, "bigdir link failed\n");
+      exit();
+    }
+  }
+
+  unlink("bd");
+  for(i = 0; i < 500; i++){
+    name[0] = 'x';
+    name[1] = '0' + (i / 64);
+    name[2] = '0' + (i % 64);
+    name[3] = '\0';
+    if(unlink(name) != 0){
+      printf(1, "bigdir unlink failed");
+      exit();
+    }
+  }
+
+  printf(1, "bigdir ok\n");
+}
+
+void
+subdir(void)
+{
+  int fd, cc;
+
+  printf(1, "subdir test\n");
+
+  unlink("ff");
+  if(mkdir("dd") != 0){
+    printf(1, "subdir mkdir dd failed\n");
+    exit();
+  }
+
+  fd = open("dd/ff", O_CREATE | O_RDWR);
+  if(fd < 0){
+    printf(1, "create dd/ff failed\n");
+    exit();
+  }
+  write(fd, "ff", 2);
+  close(fd);
+
+  if(unlink("dd") >= 0){
+    printf(1, "unlink dd (non-empty dir) succeeded!\n");
+    exit();
+  }
+
+  if(mkdir("/dd/dd") != 0){
+    printf(1, "subdir mkdir dd/dd failed\n");
+    exit();
+  }
+
+  fd = open("dd/dd/ff", O_CREATE | O_RDWR);
+  if(fd < 0){
+    printf(1, "create dd/dd/ff failed\n");
+    exit();
+  }
+  write(fd, "FF", 2);
+  close(fd);
+
+  fd = open("dd/dd/../ff", 0);
+  if(fd < 0){
+    printf(1, "open dd/dd/../ff failed\n");
+    exit();
+  }
+  cc = read(fd, buf, sizeof(buf));
+  if(cc != 2 || buf[0] != 'f'){
+    printf(1, "dd/dd/../ff wrong content\n");
+    exit();
+  }
+  close(fd);
+
+  if(link("dd/dd/ff", "dd/dd/ffff") != 0){
+    printf(1, "link dd/dd/ff dd/dd/ffff failed\n");
+    exit();
+  }
+
+  if(unlink("dd/dd/ff") != 0){
+    printf(1, "unlink dd/dd/ff failed\n");
+    exit();
+  }
+  if(open("dd/dd/ff", O_RDONLY) >= 0){
+    printf(1, "open (unlinked) dd/dd/ff succeeded\n");
+    exit();
+  }
+
+  if(chdir("dd") != 0){
+    printf(1, "chdir dd failed\n");
+    exit();
+  }
+  if(chdir("dd/../../dd") != 0){
+    printf(1, "chdir dd/../../dd failed\n");
+    exit();
+  }
+  if(chdir("dd/../../../dd") != 0){
+    printf(1, "chdir dd/../../dd failed\n");
+    exit();
+  }
+  if(chdir("./..") != 0){
+    printf(1, "chdir ./.. failed\n");
+    exit();
+  }
+
+  fd = open("dd/dd/ffff", 0);
+  if(fd < 0){
+    printf(1, "open dd/dd/ffff failed\n");
+    exit();
+  }
+  if(read(fd, buf, sizeof(buf)) != 2){
+    printf(1, "read dd/dd/ffff wrong len\n");
+    exit();
+  }
+  close(fd);
+
+  if(open("dd/dd/ff", O_RDONLY) >= 0){
+    printf(1, "open (unlinked) dd/dd/ff succeeded!\n");
+    exit();
+  }
+
+  if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){
+    printf(1, "create dd/ff/ff succeeded!\n");
+    exit();
+  }
+  if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){
+    printf(1, "create dd/xx/ff succeeded!\n");
+    exit();
+  }
+  if(open("dd", O_CREATE) >= 0){
+    printf(1, "create dd succeeded!\n");
+    exit();
+  }
+  if(open("dd", O_RDWR) >= 0){
+    printf(1, "open dd rdwr succeeded!\n");
+    exit();
+  }
+  if(open("dd", O_WRONLY) >= 0){
+    printf(1, "open dd wronly succeeded!\n");
+    exit();
+  }
+  if(link("dd/ff/ff", "dd/dd/xx") == 0){
+    printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n");
+    exit();
+  }
+  if(link("dd/xx/ff", "dd/dd/xx") == 0){
+    printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n");
+    exit();
+  }
+  if(link("dd/ff", "dd/dd/ffff") == 0){
+    printf(1, "link dd/ff dd/dd/ffff succeeded!\n");
+    exit();
+  }
+  if(mkdir("dd/ff/ff") == 0){
+    printf(1, "mkdir dd/ff/ff succeeded!\n");
+    exit();
+  }
+  if(mkdir("dd/xx/ff") == 0){
+    printf(1, "mkdir dd/xx/ff succeeded!\n");
+    exit();
+  }
+  if(mkdir("dd/dd/ffff") == 0){
+    printf(1, "mkdir dd/dd/ffff succeeded!\n");
+    exit();
+  }
+  if(unlink("dd/xx/ff") == 0){
+    printf(1, "unlink dd/xx/ff succeeded!\n");
+    exit();
+  }
+  if(unlink("dd/ff/ff") == 0){
+    printf(1, "unlink dd/ff/ff succeeded!\n");
+    exit();
+  }
+  if(chdir("dd/ff") == 0){
+    printf(1, "chdir dd/ff succeeded!\n");
+    exit();
+  }
+  if(chdir("dd/xx") == 0){
+    printf(1, "chdir dd/xx succeeded!\n");
+    exit();
+  }
+
+  if(unlink("dd/dd/ffff") != 0){
+    printf(1, "unlink dd/dd/ff failed\n");
+    exit();
+  }
+  if(unlink("dd/ff") != 0){
+    printf(1, "unlink dd/ff failed\n");
+    exit();
+  }
+  if(unlink("dd") == 0){
+    printf(1, "unlink non-empty dd succeeded!\n");
+    exit();
+  }
+  if(unlink("dd/dd") < 0){
+    printf(1, "unlink dd/dd failed\n");
+    exit();
+  }
+  if(unlink("dd") < 0){
+    printf(1, "unlink dd failed\n");
+    exit();
+  }
+
+  printf(1, "subdir ok\n");
+}
+
+// test writes that are larger than the log.
+void
+bigwrite(void)
+{
+  int fd, sz;
+
+  printf(1, "bigwrite test\n");
+
+  unlink("bigwrite");
+  for(sz = 499; sz < 12*512; sz += 471){
+    fd = open("bigwrite", O_CREATE | O_RDWR);
+    if(fd < 0){
+      printf(1, "cannot create bigwrite\n");
+      exit();
+    }
+    int i;
+    for(i = 0; i < 2; i++){
+      int cc = write(fd, buf, sz);
+      if(cc != sz){
+        printf(1, "write(%d) ret %d\n", sz, cc);
+        exit();
+      }
+    }
+    close(fd);
+    unlink("bigwrite");
+  }
+
+  printf(1, "bigwrite ok\n");
+}
+
+void
+bigfile(void)
+{
+  int fd, i, total, cc;
+
+  printf(1, "bigfile test\n");
+
+  unlink("bigfile");
+  fd = open("bigfile", O_CREATE | O_RDWR);
+  if(fd < 0){
+    printf(1, "cannot create bigfile");
+    exit();
+  }
+  for(i = 0; i < 20; i++){
+    memset(buf, i, 600);
+    if(write(fd, buf, 600) != 600){
+      printf(1, "write bigfile failed\n");
+      exit();
+    }
+  }
+  close(fd);
+
+  fd = open("bigfile", 0);
+  if(fd < 0){
+    printf(1, "cannot open bigfile\n");
+    exit();
+  }
+  total = 0;
+  for(i = 0; ; i++){
+    cc = read(fd, buf, 300);
+    if(cc < 0){
+      printf(1, "read bigfile failed\n");
+      exit();
+    }
+    if(cc == 0)
+      break;
+    if(cc != 300){
+      printf(1, "short read bigfile\n");
+      exit();
+    }
+    if(buf[0] != i/2 || buf[299] != i/2){
+      printf(1, "read bigfile wrong data\n");
+      exit();
+    }
+    total += cc;
+  }
+  close(fd);
+  if(total != 20*600){
+    printf(1, "read bigfile wrong total\n");
+    exit();
+  }
+  unlink("bigfile");
+
+  printf(1, "bigfile test ok\n");
+}
+
+void
+fourteen(void)
+{
+  int fd;
+
+  // DIRSIZ is 14.
+  printf(1, "fourteen test\n");
+
+  if(mkdir("12345678901234") != 0){
+    printf(1, "mkdir 12345678901234 failed\n");
+    exit();
+  }
+  if(mkdir("12345678901234/123456789012345") != 0){
+    printf(1, "mkdir 12345678901234/123456789012345 failed\n");
+    exit();
+  }
+  fd = open("123456789012345/123456789012345/123456789012345", O_CREATE);
+  if(fd < 0){
+    printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n");
+    exit();
+  }
+  close(fd);
+  fd = open("12345678901234/12345678901234/12345678901234", 0);
+  if(fd < 0){
+    printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n");
+    exit();
+  }
+  close(fd);
+
+  if(mkdir("12345678901234/12345678901234") == 0){
+    printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n");
+    exit();
+  }
+  if(mkdir("123456789012345/12345678901234") == 0){
+    printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n");
+    exit();
+  }
+
+  printf(1, "fourteen ok\n");
+}
+
+void
+rmdot(void)
+{
+  printf(1, "rmdot test\n");
+  if(mkdir("dots") != 0){
+    printf(1, "mkdir dots failed\n");
+    exit();
+  }
+  if(chdir("dots") != 0){
+    printf(1, "chdir dots failed\n");
+    exit();
+  }
+  if(unlink(".") == 0){
+    printf(1, "rm . worked!\n");
+    exit();
+  }
+  if(unlink("..") == 0){
+    printf(1, "rm .. worked!\n");
+    exit();
+  }
+  if(chdir("/") != 0){
+    printf(1, "chdir / failed\n");
+    exit();
+  }
+  if(unlink("dots/.") == 0){
+    printf(1, "unlink dots/. worked!\n");
+    exit();
+  }
+  if(unlink("dots/..") == 0){
+    printf(1, "unlink dots/.. worked!\n");
+    exit();
+  }
+  if(unlink("dots") != 0){
+    printf(1, "unlink dots failed!\n");
+    exit();
+  }
+  printf(1, "rmdot ok\n");
+}
+
+void
+dirfile(void)
+{
+  int fd;
+
+  printf(1, "dir vs file\n");
+
+  fd = open("dirfile", O_CREATE);
+  if(fd < 0){
+    printf(1, "create dirfile failed\n");
+    exit();
+  }
+  close(fd);
+  if(chdir("dirfile") == 0){
+    printf(1, "chdir dirfile succeeded!\n");
+    exit();
+  }
+  fd = open("dirfile/xx", 0);
+  if(fd >= 0){
+    printf(1, "create dirfile/xx succeeded!\n");
+    exit();
+  }
+  fd = open("dirfile/xx", O_CREATE);
+  if(fd >= 0){
+    printf(1, "create dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(mkdir("dirfile/xx") == 0){
+    printf(1, "mkdir dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(unlink("dirfile/xx") == 0){
+    printf(1, "unlink dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(link("README", "dirfile/xx") == 0){
+    printf(1, "link to dirfile/xx succeeded!\n");
+    exit();
+  }
+  if(unlink("dirfile") != 0){
+    printf(1, "unlink dirfile failed!\n");
+    exit();
+  }
+
+  fd = open(".", O_RDWR);
+  if(fd >= 0){
+    printf(1, "open . for writing succeeded!\n");
+    exit();
+  }
+  fd = open(".", 0);
+  if(write(fd, "x", 1) > 0){
+    printf(1, "write . succeeded!\n");
+    exit();
+  }
+  close(fd);
+
+  printf(1, "dir vs file OK\n");
+}
+
+// test that iput() is called at the end of _namei()
+void
+iref(void)
+{
+  int i, fd;
+
+  printf(1, "empty file name\n");
+
+  // the 50 is NINODE
+  for(i = 0; i < 50 + 1; i++){
+    if(mkdir("irefd") != 0){
+      printf(1, "mkdir irefd failed\n");
+      exit();
+    }
+    if(chdir("irefd") != 0){
+      printf(1, "chdir irefd failed\n");
+      exit();
+    }
+
+    mkdir("");
+    link("README", "");
+    fd = open("", O_CREATE);
+    if(fd >= 0)
+      close(fd);
+    fd = open("xx", O_CREATE);
+    if(fd >= 0)
+      close(fd);
+    unlink("xx");
+  }
+
+  chdir("/");
+  printf(1, "empty file name OK\n");
+}
+
+// test that fork fails gracefully
+// the forktest binary also does this, but it runs out of proc entries first.
+// inside the bigger usertests binary, we run out of memory first.
+void
+forktest(void)
+{
+  int n, pid;
+
+  printf(1, "fork test\n");
+
+  for(n=0; n<1000; n++){
+    pid = fork();
+    if(pid < 0)
+      break;
+    if(pid == 0)
+      exit();
+  }
+
+  if(n == 1000){
+    printf(1, "fork claimed to work 1000 times!\n");
+    exit();
+  }
+
+  for(; n > 0; n--){
+    if(wait() < 0){
+      printf(1, "wait stopped early\n");
+      exit();
+    }
+  }
+
+  if(wait() != -1){
+    printf(1, "wait got too many\n");
+    exit();
+  }
+
+  printf(1, "fork test OK\n");
+}
+
+void
+sbrktest(void)
+{
+  int fds[2], pid, pids[10], ppid;
+  char *a, *b, *c, *lastaddr, *oldbrk, *p, scratch;
+  uint amt;
+
+  printf(stdout, "sbrk test\n");
+  oldbrk = sbrk(0);
+
+  // can one sbrk() less than a page?
+  a = sbrk(0);
+  int i;
+  for(i = 0; i < 5000; i++){
+    b = sbrk(1);
+    if(b != a){
+      printf(stdout, "sbrk test failed %d %x %x\n", i, a, b);
+      exit();
+    }
+    *b = 1;
+    a = b + 1;
+  }
+  pid = fork();
+  if(pid < 0){
+    printf(stdout, "sbrk test fork failed\n");
+    exit();
+  }
+  c = sbrk(1);
+  c = sbrk(1);
+  if(c != a + 1){
+    printf(stdout, "sbrk test failed post-fork\n");
+    exit();
+  }
+  if(pid == 0)
+    exit();
+  wait();
+
+  // can one grow address space to something big?
+#define BIG (100*1024*1024)
+  a = sbrk(0);
+  amt = (BIG) - (uint)a;
+  p = sbrk(amt);
+  if (p != a) {
+    printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n");
+    exit();
+  }
+  lastaddr = (char*) (BIG-1);
+  *lastaddr = 99;
+
+  // can one de-allocate?
+  a = sbrk(0);
+  c = sbrk(-4096);
+  if(c == (char*)0xffffffff){
+    printf(stdout, "sbrk could not deallocate\n");
+    exit();
+  }
+  c = sbrk(0);
+  if(c != a - 4096){
+    printf(stdout, "sbrk deallocation produced wrong address, a %x c %x\n", a, c);
+    exit();
+  }
+
+  // can one re-allocate that page?
+  a = sbrk(0);
+  c = sbrk(4096);
+  if(c != a || sbrk(0) != a + 4096){
+    printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c);
+    exit();
+  }
+  if(*lastaddr == 99){
+    // should be zero
+    printf(stdout, "sbrk de-allocation didn't really deallocate\n");
+    exit();
+  }
+
+  a = sbrk(0);
+  c = sbrk(-(sbrk(0) - oldbrk));
+  if(c != a){
+    printf(stdout, "sbrk downsize failed, a %x c %x\n", a, c);
+    exit();
+  }
+
+  // can we read the kernel's memory?
+  for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){
+    ppid = getpid();
+    pid = fork();
+    if(pid < 0){
+      printf(stdout, "fork failed\n");
+      exit();
+    }
+    if(pid == 0){
+      printf(stdout, "oops could read %x = %x\n", a, *a);
+      kill(ppid);
+      exit();
+    }
+    wait();
+  }
+
+  // if we run the system out of memory, does it clean up the last
+  // failed allocation?
+  if(pipe(fds) != 0){
+    printf(1, "pipe() failed\n");
+    exit();
+  }
+  for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
+    if((pids[i] = fork()) == 0){
+      // allocate a lot of memory
+      sbrk(BIG - (uint)sbrk(0));
+      write(fds[1], "x", 1);
+      // sit around until killed
+      for(;;) sleep(1000);
+    }
+    if(pids[i] != -1)
+      read(fds[0], &scratch, 1);
+  }
+  // if those failed allocations freed up the pages they did allocate,
+  // we'll be able to allocate here
+  c = sbrk(4096);
+  for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
+    if(pids[i] == -1)
+      continue;
+    kill(pids[i]);
+    wait();
+  }
+  if(c == (char*)0xffffffff){
+    printf(stdout, "failed sbrk leaked memory\n");
+    exit();
+  }
+
+  if(sbrk(0) > oldbrk)
+    sbrk(-(sbrk(0) - oldbrk));
+
+  printf(stdout, "sbrk test OK\n");
+}
+
+void
+validateint(int *p)
+{
+  int res;
+  __asm__("mov %%esp, %%ebx\n\t"
+      "mov %3, %%esp\n\t"
+      "int %2\n\t"
+      "mov %%ebx, %%esp" :
+      "=a" (res) :
+      "a" (SYS_sleep), "n" (T_SYSCALL), "c" (p) :
+      "ebx");
+}
+
+void
+validatetest(void)
+{
+  int hi, pid;
+  uint p;
+
+  printf(stdout, "validate test\n");
+  hi = 1100*1024;
+
+  for(p = 0; p <= (uint)hi; p += 4096){
+    if((pid = fork()) == 0){
+      // try to crash the kernel by passing in a badly placed integer
+      validateint((int*)p);
+      exit();
+    }
+    sleep(0);
+    sleep(0);
+    kill(pid);
+    wait();
+
+    // try to crash the kernel by passing in a bad string pointer
+    if(link("nosuchfile", (char*)p) != -1){
+      printf(stdout, "link should not succeed\n");
+      exit();
+    }
+  }
+
+  printf(stdout, "validate ok\n");
+}
+
+// does unintialized data start out zero?
+char uninit[10000];
+void
+bsstest(void)
+{
+  int i;
+
+  printf(stdout, "bss test\n");
+  for(i = 0; i < sizeof(uninit); i++){
+    if(uninit[i] != '\0'){
+      printf(stdout, "bss test failed\n");
+      exit();
+    }
+  }
+  printf(stdout, "bss test ok\n");
+}
+
+// does exec return an error if the arguments
+// are larger than a page? or does it write
+// below the stack and wreck the instructions/data?
+void
+bigargtest(void)
+{
+  int pid, fd;
+
+  unlink("bigarg-ok");
+  pid = fork();
+  if(pid == 0){
+    static char *args[MAXARG];
+    int i;
+    for(i = 0; i < MAXARG-1; i++)
+      args[i] = "bigargs test: failed\n                                                                                                                                                                                                       ";
+    args[MAXARG-1] = 0;
+    printf(stdout, "bigarg test\n");
+    exec("echo", args);
+    printf(stdout, "bigarg test ok\n");
+    fd = open("bigarg-ok", O_CREATE);
+    close(fd);
+    exit();
+  } else if(pid < 0){
+    printf(stdout, "bigargtest: fork failed\n");
+    exit();
+  }
+  wait();
+  fd = open("bigarg-ok", 0);
+  if(fd < 0){
+    printf(stdout, "bigarg test failed!\n");
+    exit();
+  }
+  close(fd);
+  unlink("bigarg-ok");
+}
+
+// what happens when the file system runs out of blocks?
+// answer: balloc panics, so this test is not useful.
+void
+fsfull()
+{
+  int nfiles;
+  int fsblocks = 0;
+
+  printf(1, "fsfull test\n");
+
+  for(nfiles = 0; ; nfiles++){
+    char name[64];
+    name[0] = 'f';
+    name[1] = '0' + nfiles / 1000;
+    name[2] = '0' + (nfiles % 1000) / 100;
+    name[3] = '0' + (nfiles % 100) / 10;
+    name[4] = '0' + (nfiles % 10);
+    name[5] = '\0';
+    printf(1, "writing %s\n", name);
+    int fd = open(name, O_CREATE|O_RDWR);
+    if(fd < 0){
+      printf(1, "open %s failed\n", name);
+      break;
+    }
+    int total = 0;
+    while(1){
+      int cc = write(fd, buf, 512);
+      if(cc < 512)
+        break;
+      total += cc;
+      fsblocks++;
+    }
+    printf(1, "wrote %d bytes\n", total);
+    close(fd);
+    if(total == 0)
+      break;
+  }
+
+  while(nfiles >= 0){
+    char name[64];
+    name[0] = 'f';
+    name[1] = '0' + nfiles / 1000;
+    name[2] = '0' + (nfiles % 1000) / 100;
+    name[3] = '0' + (nfiles % 100) / 10;
+    name[4] = '0' + (nfiles % 10);
+    name[5] = '\0';
+    unlink(name);
+    nfiles--;
+  }
+
+  printf(1, "fsfull test finished\n");
+}
+
+void
+uio()
+{
+  #define RTC_ADDR 0x70
+  #define RTC_DATA 0x71
+
+  ushort port = 0;
+  uchar val = 0;
+  int pid;
+
+  printf(1, "uio test\n");
+  pid = fork();
+  if(pid == 0){
+    port = RTC_ADDR;
+    val = 0x09;  /* year */
+    /* http://wiki.osdev.org/Inline_Assembly/Examples */
+    __asm__ volatile("outb %0,%1"::"a"(val), "d" (port));
+    port = RTC_DATA;
+    __asm__ volatile("inb %1,%0" : "=a" (val) : "d" (port));
+    printf(1, "uio: uio succeeded; test FAILED\n");
+    exit();
+  } else if(pid < 0){
+    printf (1, "fork failed\n");
+    exit();
+  }
+  wait();
+  printf(1, "uio test done\n");
+}
+
+void argptest()
+{
+  int fd;
+  fd = open("init", O_RDONLY);
+  if (fd < 0) {
+    printf(2, "open failed\n");
+    exit();
+  }
+  read(fd, sbrk(0) - 1, -1);
+  close(fd);
+  printf(1, "arg test passed\n");
+}
+
+unsigned long randstate = 1;
+unsigned int
+rand()
+{
+  randstate = randstate * 1664525 + 1013904223;
+  return randstate;
+}
+
+int
+main(int argc, char *argv[])
+{
+  printf(1, "usertests starting\n");
+
+  if(open("usertests.ran", 0) >= 0){
+    printf(1, "already ran user tests -- rebuild fs.img\n");
+    exit();
+  }
+  close(open("usertests.ran", O_CREATE));
+
+  argptest();
+  createdelete();
+  linkunlink();
+  concreate();
+  fourfiles();
+  sharedfd();
+
+  bigargtest();
+  bigwrite();
+  bigargtest();
+  bsstest();
+  sbrktest();
+  validatetest();
+
+  opentest();
+  writetest();
+  writetest1();
+  createtest();
+
+  openiputtest();
+  exitiputtest();
+  iputtest();
+
+  mem();
+  pipe1();
+  preempt();
+  exitwait();
+
+  rmdot();
+  fourteen();
+  bigfile();
+  subdir();
+  linktest();
+  unlinkread();
+  dirfile();
+  iref();
+  forktest();
+  bigdir(); // slow
+
+  uio();
+
+  exectest();
+
+  exit();
+}
diff --git a/user/src/wc.c b/user/src/wc.c
new file mode 100644 (file)
index 0000000..d6a54df
--- /dev/null
@@ -0,0 +1,54 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+char buf[512];
+
+void
+wc(int fd, char *name)
+{
+  int i, n;
+  int l, w, c, inword;
+
+  l = w = c = 0;
+  inword = 0;
+  while((n = read(fd, buf, sizeof(buf))) > 0){
+    for(i=0; i<n; i++){
+      c++;
+      if(buf[i] == '\n')
+        l++;
+      if(strchr(" \r\t\n\v", buf[i]))
+        inword = 0;
+      else if(!inword){
+        w++;
+        inword = 1;
+      }
+    }
+  }
+  if(n < 0){
+    printf(1, "wc: read error\n");
+    exit();
+  }
+  printf(1, "%d %d %d %s\n", l, w, c, name);
+}
+
+int
+main(int argc, char *argv[])
+{
+  int fd, i;
+
+  if(argc <= 1){
+    wc(0, "");
+    exit();
+  }
+
+  for(i = 1; i < argc; i++){
+    if((fd = open(argv[i], 0)) < 0){
+      printf(1, "wc: cannot open %s\n", argv[i]);
+      exit();
+    }
+    wc(fd, argv[i]);
+    close(fd);
+  }
+  exit();
+}
diff --git a/user/src/zombie.c b/user/src/zombie.c
new file mode 100644 (file)
index 0000000..ee817da
--- /dev/null
@@ -0,0 +1,14 @@
+// Create a zombie process that
+// must be reparented at exit.
+
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+int
+main(void)
+{
+  if(fork() > 0)
+    sleep(5);  // Let child exit before parent.
+  exit();
+}
diff --git a/usertests.c b/usertests.c
deleted file mode 100644 (file)
index 44e57f7..0000000
+++ /dev/null
@@ -1,1803 +0,0 @@
-#include "param.h"
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-#include "fs.h"
-#include "fcntl.h"
-#include "syscall.h"
-#include "traps.h"
-#include "memlayout.h"
-
-char buf[8192];
-char name[3];
-char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 };
-int stdout = 1;
-
-// does chdir() call iput(p->cwd) in a transaction?
-void
-iputtest(void)
-{
-  printf(stdout, "iput test\n");
-
-  if(mkdir("iputdir") < 0){
-    printf(stdout, "mkdir failed\n");
-    exit();
-  }
-  if(chdir("iputdir") < 0){
-    printf(stdout, "chdir iputdir failed\n");
-    exit();
-  }
-  if(unlink("../iputdir") < 0){
-    printf(stdout, "unlink ../iputdir failed\n");
-    exit();
-  }
-  if(chdir("/") < 0){
-    printf(stdout, "chdir / failed\n");
-    exit();
-  }
-  printf(stdout, "iput test ok\n");
-}
-
-// does exit() call iput(p->cwd) in a transaction?
-void
-exitiputtest(void)
-{
-  int pid;
-
-  printf(stdout, "exitiput test\n");
-
-  pid = fork();
-  if(pid < 0){
-    printf(stdout, "fork failed\n");
-    exit();
-  }
-  if(pid == 0){
-    if(mkdir("iputdir") < 0){
-      printf(stdout, "mkdir failed\n");
-      exit();
-    }
-    if(chdir("iputdir") < 0){
-      printf(stdout, "child chdir failed\n");
-      exit();
-    }
-    if(unlink("../iputdir") < 0){
-      printf(stdout, "unlink ../iputdir failed\n");
-      exit();
-    }
-    exit();
-  }
-  wait();
-  printf(stdout, "exitiput test ok\n");
-}
-
-// does the error path in open() for attempt to write a
-// directory call iput() in a transaction?
-// needs a hacked kernel that pauses just after the namei()
-// call in sys_open():
-//    if((ip = namei(path)) == 0)
-//      return -1;
-//    {
-//      int i;
-//      for(i = 0; i < 10000; i++)
-//        yield();
-//    }
-void
-openiputtest(void)
-{
-  int pid;
-
-  printf(stdout, "openiput test\n");
-  if(mkdir("oidir") < 0){
-    printf(stdout, "mkdir oidir failed\n");
-    exit();
-  }
-  pid = fork();
-  if(pid < 0){
-    printf(stdout, "fork failed\n");
-    exit();
-  }
-  if(pid == 0){
-    int fd = open("oidir", O_RDWR);
-    if(fd >= 0){
-      printf(stdout, "open directory for write succeeded\n");
-      exit();
-    }
-    exit();
-  }
-  sleep(1);
-  if(unlink("oidir") != 0){
-    printf(stdout, "unlink failed\n");
-    exit();
-  }
-  wait();
-  printf(stdout, "openiput test ok\n");
-}
-
-// simple file system tests
-
-void
-opentest(void)
-{
-  int fd;
-
-  printf(stdout, "open test\n");
-  fd = open("echo", 0);
-  if(fd < 0){
-    printf(stdout, "open echo failed!\n");
-    exit();
-  }
-  close(fd);
-  fd = open("doesnotexist", 0);
-  if(fd >= 0){
-    printf(stdout, "open doesnotexist succeeded!\n");
-    exit();
-  }
-  printf(stdout, "open test ok\n");
-}
-
-void
-writetest(void)
-{
-  int fd;
-  int i;
-
-  printf(stdout, "small file test\n");
-  fd = open("small", O_CREATE|O_RDWR);
-  if(fd >= 0){
-    printf(stdout, "creat small succeeded; ok\n");
-  } else {
-    printf(stdout, "error: creat small failed!\n");
-    exit();
-  }
-  for(i = 0; i < 100; i++){
-    if(write(fd, "aaaaaaaaaa", 10) != 10){
-      printf(stdout, "error: write aa %d new file failed\n", i);
-      exit();
-    }
-    if(write(fd, "bbbbbbbbbb", 10) != 10){
-      printf(stdout, "error: write bb %d new file failed\n", i);
-      exit();
-    }
-  }
-  printf(stdout, "writes ok\n");
-  close(fd);
-  fd = open("small", O_RDONLY);
-  if(fd >= 0){
-    printf(stdout, "open small succeeded ok\n");
-  } else {
-    printf(stdout, "error: open small failed!\n");
-    exit();
-  }
-  i = read(fd, buf, 2000);
-  if(i == 2000){
-    printf(stdout, "read succeeded ok\n");
-  } else {
-    printf(stdout, "read failed\n");
-    exit();
-  }
-  close(fd);
-
-  if(unlink("small") < 0){
-    printf(stdout, "unlink small failed\n");
-    exit();
-  }
-  printf(stdout, "small file test ok\n");
-}
-
-void
-writetest1(void)
-{
-  int i, fd, n;
-
-  printf(stdout, "big files test\n");
-
-  fd = open("big", O_CREATE|O_RDWR);
-  if(fd < 0){
-    printf(stdout, "error: creat big failed!\n");
-    exit();
-  }
-
-  for(i = 0; i < MAXFILE; i++){
-    ((int*)buf)[0] = i;
-    if(write(fd, buf, 512) != 512){
-      printf(stdout, "error: write big file failed\n", i);
-      exit();
-    }
-  }
-
-  close(fd);
-
-  fd = open("big", O_RDONLY);
-  if(fd < 0){
-    printf(stdout, "error: open big failed!\n");
-    exit();
-  }
-
-  n = 0;
-  for(;;){
-    i = read(fd, buf, 512);
-    if(i == 0){
-      if(n == MAXFILE - 1){
-        printf(stdout, "read only %d blocks from big", n);
-        exit();
-      }
-      break;
-    } else if(i != 512){
-      printf(stdout, "read failed %d\n", i);
-      exit();
-    }
-    if(((int*)buf)[0] != n){
-      printf(stdout, "read content of block %d is %d\n",
-             n, ((int*)buf)[0]);
-      exit();
-    }
-    n++;
-  }
-  close(fd);
-  if(unlink("big") < 0){
-    printf(stdout, "unlink big failed\n");
-    exit();
-  }
-  printf(stdout, "big files ok\n");
-}
-
-void
-createtest(void)
-{
-  int i, fd;
-
-  printf(stdout, "many creates, followed by unlink test\n");
-
-  name[0] = 'a';
-  name[2] = '\0';
-  for(i = 0; i < 52; i++){
-    name[1] = '0' + i;
-    fd = open(name, O_CREATE|O_RDWR);
-    close(fd);
-  }
-  name[0] = 'a';
-  name[2] = '\0';
-  for(i = 0; i < 52; i++){
-    name[1] = '0' + i;
-    unlink(name);
-  }
-  printf(stdout, "many creates, followed by unlink; ok\n");
-}
-
-void dirtest(void)
-{
-  printf(stdout, "mkdir test\n");
-
-  if(mkdir("dir0") < 0){
-    printf(stdout, "mkdir failed\n");
-    exit();
-  }
-
-  if(chdir("dir0") < 0){
-    printf(stdout, "chdir dir0 failed\n");
-    exit();
-  }
-
-  if(chdir("..") < 0){
-    printf(stdout, "chdir .. failed\n");
-    exit();
-  }
-
-  if(unlink("dir0") < 0){
-    printf(stdout, "unlink dir0 failed\n");
-    exit();
-  }
-  printf(stdout, "mkdir test ok\n");
-}
-
-void
-exectest(void)
-{
-  printf(stdout, "exec test\n");
-  if(exec("echo", echoargv) < 0){
-    printf(stdout, "exec echo failed\n");
-    exit();
-  }
-}
-
-// simple fork and pipe read/write
-
-void
-pipe1(void)
-{
-  int fds[2], pid;
-  int seq, i, n, cc, total;
-
-  if(pipe(fds) != 0){
-    printf(1, "pipe() failed\n");
-    exit();
-  }
-  pid = fork();
-  seq = 0;
-  if(pid == 0){
-    close(fds[0]);
-    for(n = 0; n < 5; n++){
-      for(i = 0; i < 1033; i++)
-        buf[i] = seq++;
-      if(write(fds[1], buf, 1033) != 1033){
-        printf(1, "pipe1 oops 1\n");
-        exit();
-      }
-    }
-    exit();
-  } else if(pid > 0){
-    close(fds[1]);
-    total = 0;
-    cc = 1;
-    while((n = read(fds[0], buf, cc)) > 0){
-      for(i = 0; i < n; i++){
-        if((buf[i] & 0xff) != (seq++ & 0xff)){
-          printf(1, "pipe1 oops 2\n");
-          return;
-        }
-      }
-      total += n;
-      cc = cc * 2;
-      if(cc > sizeof(buf))
-        cc = sizeof(buf);
-    }
-    if(total != 5 * 1033){
-      printf(1, "pipe1 oops 3 total %d\n", total);
-      exit();
-    }
-    close(fds[0]);
-    wait();
-  } else {
-    printf(1, "fork() failed\n");
-    exit();
-  }
-  printf(1, "pipe1 ok\n");
-}
-
-// meant to be run w/ at most two CPUs
-void
-preempt(void)
-{
-  int pid1, pid2, pid3;
-  int pfds[2];
-
-  printf(1, "preempt: ");
-  pid1 = fork();
-  if(pid1 == 0)
-    for(;;)
-      ;
-
-  pid2 = fork();
-  if(pid2 == 0)
-    for(;;)
-      ;
-
-  pipe(pfds);
-  pid3 = fork();
-  if(pid3 == 0){
-    close(pfds[0]);
-    if(write(pfds[1], "x", 1) != 1)
-      printf(1, "preempt write error");
-    close(pfds[1]);
-    for(;;)
-      ;
-  }
-
-  close(pfds[1]);
-  if(read(pfds[0], buf, sizeof(buf)) != 1){
-    printf(1, "preempt read error");
-    return;
-  }
-  close(pfds[0]);
-  printf(1, "kill... ");
-  kill(pid1);
-  kill(pid2);
-  kill(pid3);
-  printf(1, "wait... ");
-  wait();
-  wait();
-  wait();
-  printf(1, "preempt ok\n");
-}
-
-// try to find any races between exit and wait
-void
-exitwait(void)
-{
-  int i, pid;
-
-  for(i = 0; i < 100; i++){
-    pid = fork();
-    if(pid < 0){
-      printf(1, "fork failed\n");
-      return;
-    }
-    if(pid){
-      if(wait() != pid){
-        printf(1, "wait wrong pid\n");
-        return;
-      }
-    } else {
-      exit();
-    }
-  }
-  printf(1, "exitwait ok\n");
-}
-
-void
-mem(void)
-{
-  void *m1, *m2;
-  int pid, ppid;
-
-  printf(1, "mem test\n");
-  ppid = getpid();
-  if((pid = fork()) == 0){
-    m1 = 0;
-    while((m2 = malloc(10001)) != 0){
-      *(char**)m2 = m1;
-      m1 = m2;
-    }
-    while(m1){
-      m2 = *(char**)m1;
-      free(m1);
-      m1 = m2;
-    }
-    m1 = malloc(1024*20);
-    if(m1 == 0){
-      printf(1, "couldn't allocate mem?!!\n");
-      kill(ppid);
-      exit();
-    }
-    free(m1);
-    printf(1, "mem ok\n");
-    exit();
-  } else {
-    wait();
-  }
-}
-
-// More file system tests
-
-// two processes write to the same file descriptor
-// is the offset shared? does inode locking work?
-void
-sharedfd(void)
-{
-  int fd, pid, i, n, nc, np;
-  char buf[10];
-
-  printf(1, "sharedfd test\n");
-
-  unlink("sharedfd");
-  fd = open("sharedfd", O_CREATE|O_RDWR);
-  if(fd < 0){
-    printf(1, "fstests: cannot open sharedfd for writing");
-    return;
-  }
-  pid = fork();
-  memset(buf, pid==0?'c':'p', sizeof(buf));
-  for(i = 0; i < 1000; i++){
-    if(write(fd, buf, sizeof(buf)) != sizeof(buf)){
-      printf(1, "fstests: write sharedfd failed\n");
-      break;
-    }
-  }
-  if(pid == 0)
-    exit();
-  else
-    wait();
-  close(fd);
-  fd = open("sharedfd", 0);
-  if(fd < 0){
-    printf(1, "fstests: cannot open sharedfd for reading\n");
-    return;
-  }
-  nc = np = 0;
-  while((n = read(fd, buf, sizeof(buf))) > 0){
-    for(i = 0; i < sizeof(buf); i++){
-      if(buf[i] == 'c')
-        nc++;
-      if(buf[i] == 'p')
-        np++;
-    }
-  }
-  close(fd);
-  unlink("sharedfd");
-  if(nc == 10000 && np == 10000){
-    printf(1, "sharedfd ok\n");
-  } else {
-    printf(1, "sharedfd oops %d %d\n", nc, np);
-    exit();
-  }
-}
-
-// four processes write different files at the same
-// time, to test block allocation.
-void
-fourfiles(void)
-{
-  int fd, pid, i, j, n, total, pi;
-  char *names[] = { "f0", "f1", "f2", "f3" };
-  char *fname;
-
-  printf(1, "fourfiles test\n");
-
-  for(pi = 0; pi < 4; pi++){
-    fname = names[pi];
-    unlink(fname);
-
-    pid = fork();
-    if(pid < 0){
-      printf(1, "fork failed\n");
-      exit();
-    }
-
-    if(pid == 0){
-      fd = open(fname, O_CREATE | O_RDWR);
-      if(fd < 0){
-        printf(1, "create failed\n");
-        exit();
-      }
-
-      memset(buf, '0'+pi, 512);
-      for(i = 0; i < 12; i++){
-        if((n = write(fd, buf, 500)) != 500){
-          printf(1, "write failed %d\n", n);
-          exit();
-        }
-      }
-      exit();
-    }
-  }
-
-  for(pi = 0; pi < 4; pi++){
-    wait();
-  }
-
-  for(i = 0; i < 2; i++){
-    fname = names[i];
-    fd = open(fname, 0);
-    total = 0;
-    while((n = read(fd, buf, sizeof(buf))) > 0){
-      for(j = 0; j < n; j++){
-        if(buf[j] != '0'+i){
-          printf(1, "wrong char\n");
-          exit();
-        }
-      }
-      total += n;
-    }
-    close(fd);
-    if(total != 12*500){
-      printf(1, "wrong length %d\n", total);
-      exit();
-    }
-    unlink(fname);
-  }
-
-  printf(1, "fourfiles ok\n");
-}
-
-// four processes create and delete different files in same directory
-void
-createdelete(void)
-{
-  enum { N = 20 };
-  int pid, i, fd, pi;
-  char name[32];
-
-  printf(1, "createdelete test\n");
-
-  for(pi = 0; pi < 4; pi++){
-    pid = fork();
-    if(pid < 0){
-      printf(1, "fork failed\n");
-      exit();
-    }
-
-    if(pid == 0){
-      name[0] = 'p' + pi;
-      name[2] = '\0';
-      for(i = 0; i < N; i++){
-        name[1] = '0' + i;
-        fd = open(name, O_CREATE | O_RDWR);
-        if(fd < 0){
-          printf(1, "create failed\n");
-          exit();
-        }
-        close(fd);
-        if(i > 0 && (i % 2 ) == 0){
-          name[1] = '0' + (i / 2);
-          if(unlink(name) < 0){
-            printf(1, "unlink failed\n");
-            exit();
-          }
-        }
-      }
-      exit();
-    }
-  }
-
-  for(pi = 0; pi < 4; pi++){
-    wait();
-  }
-
-  name[0] = name[1] = name[2] = 0;
-  for(i = 0; i < N; i++){
-    for(pi = 0; pi < 4; pi++){
-      name[0] = 'p' + pi;
-      name[1] = '0' + i;
-      fd = open(name, 0);
-      if((i == 0 || i >= N/2) && fd < 0){
-        printf(1, "oops createdelete %s didn't exist\n", name);
-        exit();
-      } else if((i >= 1 && i < N/2) && fd >= 0){
-        printf(1, "oops createdelete %s did exist\n", name);
-        exit();
-      }
-      if(fd >= 0)
-        close(fd);
-    }
-  }
-
-  for(i = 0; i < N; i++){
-    for(pi = 0; pi < 4; pi++){
-      name[0] = 'p' + i;
-      name[1] = '0' + i;
-      unlink(name);
-    }
-  }
-
-  printf(1, "createdelete ok\n");
-}
-
-// can I unlink a file and still read it?
-void
-unlinkread(void)
-{
-  int fd, fd1;
-
-  printf(1, "unlinkread test\n");
-  fd = open("unlinkread", O_CREATE | O_RDWR);
-  if(fd < 0){
-    printf(1, "create unlinkread failed\n");
-    exit();
-  }
-  write(fd, "hello", 5);
-  close(fd);
-
-  fd = open("unlinkread", O_RDWR);
-  if(fd < 0){
-    printf(1, "open unlinkread failed\n");
-    exit();
-  }
-  if(unlink("unlinkread") != 0){
-    printf(1, "unlink unlinkread failed\n");
-    exit();
-  }
-
-  fd1 = open("unlinkread", O_CREATE | O_RDWR);
-  write(fd1, "yyy", 3);
-  close(fd1);
-
-  if(read(fd, buf, sizeof(buf)) != 5){
-    printf(1, "unlinkread read failed");
-    exit();
-  }
-  if(buf[0] != 'h'){
-    printf(1, "unlinkread wrong data\n");
-    exit();
-  }
-  if(write(fd, buf, 10) != 10){
-    printf(1, "unlinkread write failed\n");
-    exit();
-  }
-  close(fd);
-  unlink("unlinkread");
-  printf(1, "unlinkread ok\n");
-}
-
-void
-linktest(void)
-{
-  int fd;
-
-  printf(1, "linktest\n");
-
-  unlink("lf1");
-  unlink("lf2");
-
-  fd = open("lf1", O_CREATE|O_RDWR);
-  if(fd < 0){
-    printf(1, "create lf1 failed\n");
-    exit();
-  }
-  if(write(fd, "hello", 5) != 5){
-    printf(1, "write lf1 failed\n");
-    exit();
-  }
-  close(fd);
-
-  if(link("lf1", "lf2") < 0){
-    printf(1, "link lf1 lf2 failed\n");
-    exit();
-  }
-  unlink("lf1");
-
-  if(open("lf1", 0) >= 0){
-    printf(1, "unlinked lf1 but it is still there!\n");
-    exit();
-  }
-
-  fd = open("lf2", 0);
-  if(fd < 0){
-    printf(1, "open lf2 failed\n");
-    exit();
-  }
-  if(read(fd, buf, sizeof(buf)) != 5){
-    printf(1, "read lf2 failed\n");
-    exit();
-  }
-  close(fd);
-
-  if(link("lf2", "lf2") >= 0){
-    printf(1, "link lf2 lf2 succeeded! oops\n");
-    exit();
-  }
-
-  unlink("lf2");
-  if(link("lf2", "lf1") >= 0){
-    printf(1, "link non-existant succeeded! oops\n");
-    exit();
-  }
-
-  if(link(".", "lf1") >= 0){
-    printf(1, "link . lf1 succeeded! oops\n");
-    exit();
-  }
-
-  printf(1, "linktest ok\n");
-}
-
-// test concurrent create/link/unlink of the same file
-void
-concreate(void)
-{
-  char file[3];
-  int i, pid, n, fd;
-  char fa[40];
-  struct {
-    ushort inum;
-    char name[14];
-  } de;
-
-  printf(1, "concreate test\n");
-  file[0] = 'C';
-  file[2] = '\0';
-  for(i = 0; i < 40; i++){
-    file[1] = '0' + i;
-    unlink(file);
-    pid = fork();
-    if(pid && (i % 3) == 1){
-      link("C0", file);
-    } else if(pid == 0 && (i % 5) == 1){
-      link("C0", file);
-    } else {
-      fd = open(file, O_CREATE | O_RDWR);
-      if(fd < 0){
-        printf(1, "concreate create %s failed\n", file);
-        exit();
-      }
-      close(fd);
-    }
-    if(pid == 0)
-      exit();
-    else
-      wait();
-  }
-
-  memset(fa, 0, sizeof(fa));
-  fd = open(".", 0);
-  n = 0;
-  while(read(fd, &de, sizeof(de)) > 0){
-    if(de.inum == 0)
-      continue;
-    if(de.name[0] == 'C' && de.name[2] == '\0'){
-      i = de.name[1] - '0';
-      if(i < 0 || i >= sizeof(fa)){
-        printf(1, "concreate weird file %s\n", de.name);
-        exit();
-      }
-      if(fa[i]){
-        printf(1, "concreate duplicate file %s\n", de.name);
-        exit();
-      }
-      fa[i] = 1;
-      n++;
-    }
-  }
-  close(fd);
-
-  if(n != 40){
-    printf(1, "concreate not enough files in directory listing\n");
-    exit();
-  }
-
-  for(i = 0; i < 40; i++){
-    file[1] = '0' + i;
-    pid = fork();
-    if(pid < 0){
-      printf(1, "fork failed\n");
-      exit();
-    }
-    if(((i % 3) == 0 && pid == 0) ||
-       ((i % 3) == 1 && pid != 0)){
-      close(open(file, 0));
-      close(open(file, 0));
-      close(open(file, 0));
-      close(open(file, 0));
-    } else {
-      unlink(file);
-      unlink(file);
-      unlink(file);
-      unlink(file);
-    }
-    if(pid == 0)
-      exit();
-    else
-      wait();
-  }
-
-  printf(1, "concreate ok\n");
-}
-
-// another concurrent link/unlink/create test,
-// to look for deadlocks.
-void
-linkunlink()
-{
-  int pid, i;
-
-  printf(1, "linkunlink test\n");
-
-  unlink("x");
-  pid = fork();
-  if(pid < 0){
-    printf(1, "fork failed\n");
-    exit();
-  }
-
-  unsigned int x = (pid ? 1 : 97);
-  for(i = 0; i < 100; i++){
-    x = x * 1103515245 + 12345;
-    if((x % 3) == 0){
-      close(open("x", O_RDWR | O_CREATE));
-    } else if((x % 3) == 1){
-      link("cat", "x");
-    } else {
-      unlink("x");
-    }
-  }
-
-  if(pid)
-    wait();
-  else
-    exit();
-
-  printf(1, "linkunlink ok\n");
-}
-
-// directory that uses indirect blocks
-void
-bigdir(void)
-{
-  int i, fd;
-  char name[10];
-
-  printf(1, "bigdir test\n");
-  unlink("bd");
-
-  fd = open("bd", O_CREATE);
-  if(fd < 0){
-    printf(1, "bigdir create failed\n");
-    exit();
-  }
-  close(fd);
-
-  for(i = 0; i < 500; i++){
-    name[0] = 'x';
-    name[1] = '0' + (i / 64);
-    name[2] = '0' + (i % 64);
-    name[3] = '\0';
-    if(link("bd", name) != 0){
-      printf(1, "bigdir link failed\n");
-      exit();
-    }
-  }
-
-  unlink("bd");
-  for(i = 0; i < 500; i++){
-    name[0] = 'x';
-    name[1] = '0' + (i / 64);
-    name[2] = '0' + (i % 64);
-    name[3] = '\0';
-    if(unlink(name) != 0){
-      printf(1, "bigdir unlink failed");
-      exit();
-    }
-  }
-
-  printf(1, "bigdir ok\n");
-}
-
-void
-subdir(void)
-{
-  int fd, cc;
-
-  printf(1, "subdir test\n");
-
-  unlink("ff");
-  if(mkdir("dd") != 0){
-    printf(1, "subdir mkdir dd failed\n");
-    exit();
-  }
-
-  fd = open("dd/ff", O_CREATE | O_RDWR);
-  if(fd < 0){
-    printf(1, "create dd/ff failed\n");
-    exit();
-  }
-  write(fd, "ff", 2);
-  close(fd);
-
-  if(unlink("dd") >= 0){
-    printf(1, "unlink dd (non-empty dir) succeeded!\n");
-    exit();
-  }
-
-  if(mkdir("/dd/dd") != 0){
-    printf(1, "subdir mkdir dd/dd failed\n");
-    exit();
-  }
-
-  fd = open("dd/dd/ff", O_CREATE | O_RDWR);
-  if(fd < 0){
-    printf(1, "create dd/dd/ff failed\n");
-    exit();
-  }
-  write(fd, "FF", 2);
-  close(fd);
-
-  fd = open("dd/dd/../ff", 0);
-  if(fd < 0){
-    printf(1, "open dd/dd/../ff failed\n");
-    exit();
-  }
-  cc = read(fd, buf, sizeof(buf));
-  if(cc != 2 || buf[0] != 'f'){
-    printf(1, "dd/dd/../ff wrong content\n");
-    exit();
-  }
-  close(fd);
-
-  if(link("dd/dd/ff", "dd/dd/ffff") != 0){
-    printf(1, "link dd/dd/ff dd/dd/ffff failed\n");
-    exit();
-  }
-
-  if(unlink("dd/dd/ff") != 0){
-    printf(1, "unlink dd/dd/ff failed\n");
-    exit();
-  }
-  if(open("dd/dd/ff", O_RDONLY) >= 0){
-    printf(1, "open (unlinked) dd/dd/ff succeeded\n");
-    exit();
-  }
-
-  if(chdir("dd") != 0){
-    printf(1, "chdir dd failed\n");
-    exit();
-  }
-  if(chdir("dd/../../dd") != 0){
-    printf(1, "chdir dd/../../dd failed\n");
-    exit();
-  }
-  if(chdir("dd/../../../dd") != 0){
-    printf(1, "chdir dd/../../dd failed\n");
-    exit();
-  }
-  if(chdir("./..") != 0){
-    printf(1, "chdir ./.. failed\n");
-    exit();
-  }
-
-  fd = open("dd/dd/ffff", 0);
-  if(fd < 0){
-    printf(1, "open dd/dd/ffff failed\n");
-    exit();
-  }
-  if(read(fd, buf, sizeof(buf)) != 2){
-    printf(1, "read dd/dd/ffff wrong len\n");
-    exit();
-  }
-  close(fd);
-
-  if(open("dd/dd/ff", O_RDONLY) >= 0){
-    printf(1, "open (unlinked) dd/dd/ff succeeded!\n");
-    exit();
-  }
-
-  if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){
-    printf(1, "create dd/ff/ff succeeded!\n");
-    exit();
-  }
-  if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){
-    printf(1, "create dd/xx/ff succeeded!\n");
-    exit();
-  }
-  if(open("dd", O_CREATE) >= 0){
-    printf(1, "create dd succeeded!\n");
-    exit();
-  }
-  if(open("dd", O_RDWR) >= 0){
-    printf(1, "open dd rdwr succeeded!\n");
-    exit();
-  }
-  if(open("dd", O_WRONLY) >= 0){
-    printf(1, "open dd wronly succeeded!\n");
-    exit();
-  }
-  if(link("dd/ff/ff", "dd/dd/xx") == 0){
-    printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n");
-    exit();
-  }
-  if(link("dd/xx/ff", "dd/dd/xx") == 0){
-    printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n");
-    exit();
-  }
-  if(link("dd/ff", "dd/dd/ffff") == 0){
-    printf(1, "link dd/ff dd/dd/ffff succeeded!\n");
-    exit();
-  }
-  if(mkdir("dd/ff/ff") == 0){
-    printf(1, "mkdir dd/ff/ff succeeded!\n");
-    exit();
-  }
-  if(mkdir("dd/xx/ff") == 0){
-    printf(1, "mkdir dd/xx/ff succeeded!\n");
-    exit();
-  }
-  if(mkdir("dd/dd/ffff") == 0){
-    printf(1, "mkdir dd/dd/ffff succeeded!\n");
-    exit();
-  }
-  if(unlink("dd/xx/ff") == 0){
-    printf(1, "unlink dd/xx/ff succeeded!\n");
-    exit();
-  }
-  if(unlink("dd/ff/ff") == 0){
-    printf(1, "unlink dd/ff/ff succeeded!\n");
-    exit();
-  }
-  if(chdir("dd/ff") == 0){
-    printf(1, "chdir dd/ff succeeded!\n");
-    exit();
-  }
-  if(chdir("dd/xx") == 0){
-    printf(1, "chdir dd/xx succeeded!\n");
-    exit();
-  }
-
-  if(unlink("dd/dd/ffff") != 0){
-    printf(1, "unlink dd/dd/ff failed\n");
-    exit();
-  }
-  if(unlink("dd/ff") != 0){
-    printf(1, "unlink dd/ff failed\n");
-    exit();
-  }
-  if(unlink("dd") == 0){
-    printf(1, "unlink non-empty dd succeeded!\n");
-    exit();
-  }
-  if(unlink("dd/dd") < 0){
-    printf(1, "unlink dd/dd failed\n");
-    exit();
-  }
-  if(unlink("dd") < 0){
-    printf(1, "unlink dd failed\n");
-    exit();
-  }
-
-  printf(1, "subdir ok\n");
-}
-
-// test writes that are larger than the log.
-void
-bigwrite(void)
-{
-  int fd, sz;
-
-  printf(1, "bigwrite test\n");
-
-  unlink("bigwrite");
-  for(sz = 499; sz < 12*512; sz += 471){
-    fd = open("bigwrite", O_CREATE | O_RDWR);
-    if(fd < 0){
-      printf(1, "cannot create bigwrite\n");
-      exit();
-    }
-    int i;
-    for(i = 0; i < 2; i++){
-      int cc = write(fd, buf, sz);
-      if(cc != sz){
-        printf(1, "write(%d) ret %d\n", sz, cc);
-        exit();
-      }
-    }
-    close(fd);
-    unlink("bigwrite");
-  }
-
-  printf(1, "bigwrite ok\n");
-}
-
-void
-bigfile(void)
-{
-  int fd, i, total, cc;
-
-  printf(1, "bigfile test\n");
-
-  unlink("bigfile");
-  fd = open("bigfile", O_CREATE | O_RDWR);
-  if(fd < 0){
-    printf(1, "cannot create bigfile");
-    exit();
-  }
-  for(i = 0; i < 20; i++){
-    memset(buf, i, 600);
-    if(write(fd, buf, 600) != 600){
-      printf(1, "write bigfile failed\n");
-      exit();
-    }
-  }
-  close(fd);
-
-  fd = open("bigfile", 0);
-  if(fd < 0){
-    printf(1, "cannot open bigfile\n");
-    exit();
-  }
-  total = 0;
-  for(i = 0; ; i++){
-    cc = read(fd, buf, 300);
-    if(cc < 0){
-      printf(1, "read bigfile failed\n");
-      exit();
-    }
-    if(cc == 0)
-      break;
-    if(cc != 300){
-      printf(1, "short read bigfile\n");
-      exit();
-    }
-    if(buf[0] != i/2 || buf[299] != i/2){
-      printf(1, "read bigfile wrong data\n");
-      exit();
-    }
-    total += cc;
-  }
-  close(fd);
-  if(total != 20*600){
-    printf(1, "read bigfile wrong total\n");
-    exit();
-  }
-  unlink("bigfile");
-
-  printf(1, "bigfile test ok\n");
-}
-
-void
-fourteen(void)
-{
-  int fd;
-
-  // DIRSIZ is 14.
-  printf(1, "fourteen test\n");
-
-  if(mkdir("12345678901234") != 0){
-    printf(1, "mkdir 12345678901234 failed\n");
-    exit();
-  }
-  if(mkdir("12345678901234/123456789012345") != 0){
-    printf(1, "mkdir 12345678901234/123456789012345 failed\n");
-    exit();
-  }
-  fd = open("123456789012345/123456789012345/123456789012345", O_CREATE);
-  if(fd < 0){
-    printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n");
-    exit();
-  }
-  close(fd);
-  fd = open("12345678901234/12345678901234/12345678901234", 0);
-  if(fd < 0){
-    printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n");
-    exit();
-  }
-  close(fd);
-
-  if(mkdir("12345678901234/12345678901234") == 0){
-    printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n");
-    exit();
-  }
-  if(mkdir("123456789012345/12345678901234") == 0){
-    printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n");
-    exit();
-  }
-
-  printf(1, "fourteen ok\n");
-}
-
-void
-rmdot(void)
-{
-  printf(1, "rmdot test\n");
-  if(mkdir("dots") != 0){
-    printf(1, "mkdir dots failed\n");
-    exit();
-  }
-  if(chdir("dots") != 0){
-    printf(1, "chdir dots failed\n");
-    exit();
-  }
-  if(unlink(".") == 0){
-    printf(1, "rm . worked!\n");
-    exit();
-  }
-  if(unlink("..") == 0){
-    printf(1, "rm .. worked!\n");
-    exit();
-  }
-  if(chdir("/") != 0){
-    printf(1, "chdir / failed\n");
-    exit();
-  }
-  if(unlink("dots/.") == 0){
-    printf(1, "unlink dots/. worked!\n");
-    exit();
-  }
-  if(unlink("dots/..") == 0){
-    printf(1, "unlink dots/.. worked!\n");
-    exit();
-  }
-  if(unlink("dots") != 0){
-    printf(1, "unlink dots failed!\n");
-    exit();
-  }
-  printf(1, "rmdot ok\n");
-}
-
-void
-dirfile(void)
-{
-  int fd;
-
-  printf(1, "dir vs file\n");
-
-  fd = open("dirfile", O_CREATE);
-  if(fd < 0){
-    printf(1, "create dirfile failed\n");
-    exit();
-  }
-  close(fd);
-  if(chdir("dirfile") == 0){
-    printf(1, "chdir dirfile succeeded!\n");
-    exit();
-  }
-  fd = open("dirfile/xx", 0);
-  if(fd >= 0){
-    printf(1, "create dirfile/xx succeeded!\n");
-    exit();
-  }
-  fd = open("dirfile/xx", O_CREATE);
-  if(fd >= 0){
-    printf(1, "create dirfile/xx succeeded!\n");
-    exit();
-  }
-  if(mkdir("dirfile/xx") == 0){
-    printf(1, "mkdir dirfile/xx succeeded!\n");
-    exit();
-  }
-  if(unlink("dirfile/xx") == 0){
-    printf(1, "unlink dirfile/xx succeeded!\n");
-    exit();
-  }
-  if(link("README", "dirfile/xx") == 0){
-    printf(1, "link to dirfile/xx succeeded!\n");
-    exit();
-  }
-  if(unlink("dirfile") != 0){
-    printf(1, "unlink dirfile failed!\n");
-    exit();
-  }
-
-  fd = open(".", O_RDWR);
-  if(fd >= 0){
-    printf(1, "open . for writing succeeded!\n");
-    exit();
-  }
-  fd = open(".", 0);
-  if(write(fd, "x", 1) > 0){
-    printf(1, "write . succeeded!\n");
-    exit();
-  }
-  close(fd);
-
-  printf(1, "dir vs file OK\n");
-}
-
-// test that iput() is called at the end of _namei()
-void
-iref(void)
-{
-  int i, fd;
-
-  printf(1, "empty file name\n");
-
-  // the 50 is NINODE
-  for(i = 0; i < 50 + 1; i++){
-    if(mkdir("irefd") != 0){
-      printf(1, "mkdir irefd failed\n");
-      exit();
-    }
-    if(chdir("irefd") != 0){
-      printf(1, "chdir irefd failed\n");
-      exit();
-    }
-
-    mkdir("");
-    link("README", "");
-    fd = open("", O_CREATE);
-    if(fd >= 0)
-      close(fd);
-    fd = open("xx", O_CREATE);
-    if(fd >= 0)
-      close(fd);
-    unlink("xx");
-  }
-
-  chdir("/");
-  printf(1, "empty file name OK\n");
-}
-
-// test that fork fails gracefully
-// the forktest binary also does this, but it runs out of proc entries first.
-// inside the bigger usertests binary, we run out of memory first.
-void
-forktest(void)
-{
-  int n, pid;
-
-  printf(1, "fork test\n");
-
-  for(n=0; n<1000; n++){
-    pid = fork();
-    if(pid < 0)
-      break;
-    if(pid == 0)
-      exit();
-  }
-
-  if(n == 1000){
-    printf(1, "fork claimed to work 1000 times!\n");
-    exit();
-  }
-
-  for(; n > 0; n--){
-    if(wait() < 0){
-      printf(1, "wait stopped early\n");
-      exit();
-    }
-  }
-
-  if(wait() != -1){
-    printf(1, "wait got too many\n");
-    exit();
-  }
-
-  printf(1, "fork test OK\n");
-}
-
-void
-sbrktest(void)
-{
-  int fds[2], pid, pids[10], ppid;
-  char *a, *b, *c, *lastaddr, *oldbrk, *p, scratch;
-  uint amt;
-
-  printf(stdout, "sbrk test\n");
-  oldbrk = sbrk(0);
-
-  // can one sbrk() less than a page?
-  a = sbrk(0);
-  int i;
-  for(i = 0; i < 5000; i++){
-    b = sbrk(1);
-    if(b != a){
-      printf(stdout, "sbrk test failed %d %x %x\n", i, a, b);
-      exit();
-    }
-    *b = 1;
-    a = b + 1;
-  }
-  pid = fork();
-  if(pid < 0){
-    printf(stdout, "sbrk test fork failed\n");
-    exit();
-  }
-  c = sbrk(1);
-  c = sbrk(1);
-  if(c != a + 1){
-    printf(stdout, "sbrk test failed post-fork\n");
-    exit();
-  }
-  if(pid == 0)
-    exit();
-  wait();
-
-  // can one grow address space to something big?
-#define BIG (100*1024*1024)
-  a = sbrk(0);
-  amt = (BIG) - (uint)a;
-  p = sbrk(amt);
-  if (p != a) {
-    printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n");
-    exit();
-  }
-  lastaddr = (char*) (BIG-1);
-  *lastaddr = 99;
-
-  // can one de-allocate?
-  a = sbrk(0);
-  c = sbrk(-4096);
-  if(c == (char*)0xffffffff){
-    printf(stdout, "sbrk could not deallocate\n");
-    exit();
-  }
-  c = sbrk(0);
-  if(c != a - 4096){
-    printf(stdout, "sbrk deallocation produced wrong address, a %x c %x\n", a, c);
-    exit();
-  }
-
-  // can one re-allocate that page?
-  a = sbrk(0);
-  c = sbrk(4096);
-  if(c != a || sbrk(0) != a + 4096){
-    printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c);
-    exit();
-  }
-  if(*lastaddr == 99){
-    // should be zero
-    printf(stdout, "sbrk de-allocation didn't really deallocate\n");
-    exit();
-  }
-
-  a = sbrk(0);
-  c = sbrk(-(sbrk(0) - oldbrk));
-  if(c != a){
-    printf(stdout, "sbrk downsize failed, a %x c %x\n", a, c);
-    exit();
-  }
-
-  // can we read the kernel's memory?
-  for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){
-    ppid = getpid();
-    pid = fork();
-    if(pid < 0){
-      printf(stdout, "fork failed\n");
-      exit();
-    }
-    if(pid == 0){
-      printf(stdout, "oops could read %x = %x\n", a, *a);
-      kill(ppid);
-      exit();
-    }
-    wait();
-  }
-
-  // if we run the system out of memory, does it clean up the last
-  // failed allocation?
-  if(pipe(fds) != 0){
-    printf(1, "pipe() failed\n");
-    exit();
-  }
-  for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
-    if((pids[i] = fork()) == 0){
-      // allocate a lot of memory
-      sbrk(BIG - (uint)sbrk(0));
-      write(fds[1], "x", 1);
-      // sit around until killed
-      for(;;) sleep(1000);
-    }
-    if(pids[i] != -1)
-      read(fds[0], &scratch, 1);
-  }
-  // if those failed allocations freed up the pages they did allocate,
-  // we'll be able to allocate here
-  c = sbrk(4096);
-  for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
-    if(pids[i] == -1)
-      continue;
-    kill(pids[i]);
-    wait();
-  }
-  if(c == (char*)0xffffffff){
-    printf(stdout, "failed sbrk leaked memory\n");
-    exit();
-  }
-
-  if(sbrk(0) > oldbrk)
-    sbrk(-(sbrk(0) - oldbrk));
-
-  printf(stdout, "sbrk test OK\n");
-}
-
-void
-validateint(int *p)
-{
-  int res;
-  __asm__("mov %%esp, %%ebx\n\t"
-      "mov %3, %%esp\n\t"
-      "int %2\n\t"
-      "mov %%ebx, %%esp" :
-      "=a" (res) :
-      "a" (SYS_sleep), "n" (T_SYSCALL), "c" (p) :
-      "ebx");
-}
-
-void
-validatetest(void)
-{
-  int hi, pid;
-  uint p;
-
-  printf(stdout, "validate test\n");
-  hi = 1100*1024;
-
-  for(p = 0; p <= (uint)hi; p += 4096){
-    if((pid = fork()) == 0){
-      // try to crash the kernel by passing in a badly placed integer
-      validateint((int*)p);
-      exit();
-    }
-    sleep(0);
-    sleep(0);
-    kill(pid);
-    wait();
-
-    // try to crash the kernel by passing in a bad string pointer
-    if(link("nosuchfile", (char*)p) != -1){
-      printf(stdout, "link should not succeed\n");
-      exit();
-    }
-  }
-
-  printf(stdout, "validate ok\n");
-}
-
-// does unintialized data start out zero?
-char uninit[10000];
-void
-bsstest(void)
-{
-  int i;
-
-  printf(stdout, "bss test\n");
-  for(i = 0; i < sizeof(uninit); i++){
-    if(uninit[i] != '\0'){
-      printf(stdout, "bss test failed\n");
-      exit();
-    }
-  }
-  printf(stdout, "bss test ok\n");
-}
-
-// does exec return an error if the arguments
-// are larger than a page? or does it write
-// below the stack and wreck the instructions/data?
-void
-bigargtest(void)
-{
-  int pid, fd;
-
-  unlink("bigarg-ok");
-  pid = fork();
-  if(pid == 0){
-    static char *args[MAXARG];
-    int i;
-    for(i = 0; i < MAXARG-1; i++)
-      args[i] = "bigargs test: failed\n                                                                                                                                                                                                       ";
-    args[MAXARG-1] = 0;
-    printf(stdout, "bigarg test\n");
-    exec("echo", args);
-    printf(stdout, "bigarg test ok\n");
-    fd = open("bigarg-ok", O_CREATE);
-    close(fd);
-    exit();
-  } else if(pid < 0){
-    printf(stdout, "bigargtest: fork failed\n");
-    exit();
-  }
-  wait();
-  fd = open("bigarg-ok", 0);
-  if(fd < 0){
-    printf(stdout, "bigarg test failed!\n");
-    exit();
-  }
-  close(fd);
-  unlink("bigarg-ok");
-}
-
-// what happens when the file system runs out of blocks?
-// answer: balloc panics, so this test is not useful.
-void
-fsfull()
-{
-  int nfiles;
-  int fsblocks = 0;
-
-  printf(1, "fsfull test\n");
-
-  for(nfiles = 0; ; nfiles++){
-    char name[64];
-    name[0] = 'f';
-    name[1] = '0' + nfiles / 1000;
-    name[2] = '0' + (nfiles % 1000) / 100;
-    name[3] = '0' + (nfiles % 100) / 10;
-    name[4] = '0' + (nfiles % 10);
-    name[5] = '\0';
-    printf(1, "writing %s\n", name);
-    int fd = open(name, O_CREATE|O_RDWR);
-    if(fd < 0){
-      printf(1, "open %s failed\n", name);
-      break;
-    }
-    int total = 0;
-    while(1){
-      int cc = write(fd, buf, 512);
-      if(cc < 512)
-        break;
-      total += cc;
-      fsblocks++;
-    }
-    printf(1, "wrote %d bytes\n", total);
-    close(fd);
-    if(total == 0)
-      break;
-  }
-
-  while(nfiles >= 0){
-    char name[64];
-    name[0] = 'f';
-    name[1] = '0' + nfiles / 1000;
-    name[2] = '0' + (nfiles % 1000) / 100;
-    name[3] = '0' + (nfiles % 100) / 10;
-    name[4] = '0' + (nfiles % 10);
-    name[5] = '\0';
-    unlink(name);
-    nfiles--;
-  }
-
-  printf(1, "fsfull test finished\n");
-}
-
-void
-uio()
-{
-  #define RTC_ADDR 0x70
-  #define RTC_DATA 0x71
-
-  ushort port = 0;
-  uchar val = 0;
-  int pid;
-
-  printf(1, "uio test\n");
-  pid = fork();
-  if(pid == 0){
-    port = RTC_ADDR;
-    val = 0x09;  /* year */
-    /* http://wiki.osdev.org/Inline_Assembly/Examples */
-    __asm__ volatile("outb %0,%1"::"a"(val), "d" (port));
-    port = RTC_DATA;
-    __asm__ volatile("inb %1,%0" : "=a" (val) : "d" (port));
-    printf(1, "uio: uio succeeded; test FAILED\n");
-    exit();
-  } else if(pid < 0){
-    printf (1, "fork failed\n");
-    exit();
-  }
-  wait();
-  printf(1, "uio test done\n");
-}
-
-void argptest()
-{
-  int fd;
-  fd = open("init", O_RDONLY);
-  if (fd < 0) {
-    printf(2, "open failed\n");
-    exit();
-  }
-  read(fd, sbrk(0) - 1, -1);
-  close(fd);
-  printf(1, "arg test passed\n");
-}
-
-unsigned long randstate = 1;
-unsigned int
-rand()
-{
-  randstate = randstate * 1664525 + 1013904223;
-  return randstate;
-}
-
-int
-main(int argc, char *argv[])
-{
-  printf(1, "usertests starting\n");
-
-  if(open("usertests.ran", 0) >= 0){
-    printf(1, "already ran user tests -- rebuild fs.img\n");
-    exit();
-  }
-  close(open("usertests.ran", O_CREATE));
-
-  argptest();
-  createdelete();
-  linkunlink();
-  concreate();
-  fourfiles();
-  sharedfd();
-
-  bigargtest();
-  bigwrite();
-  bigargtest();
-  bsstest();
-  sbrktest();
-  validatetest();
-
-  opentest();
-  writetest();
-  writetest1();
-  createtest();
-
-  openiputtest();
-  exitiputtest();
-  iputtest();
-
-  mem();
-  pipe1();
-  preempt();
-  exitwait();
-
-  rmdot();
-  fourteen();
-  bigfile();
-  subdir();
-  linktest();
-  unlinkread();
-  dirfile();
-  iref();
-  forktest();
-  bigdir(); // slow
-
-  uio();
-
-  exectest();
-
-  exit();
-}
diff --git a/usys.S b/usys.S
deleted file mode 100644 (file)
index 8bfd8a1..0000000
--- a/usys.S
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "syscall.h"
-#include "traps.h"
-
-#define SYSCALL(name) \
-  .globl name; \
-  name: \
-    movl $SYS_ ## name, %eax; \
-    int $T_SYSCALL; \
-    ret
-
-SYSCALL(fork)
-SYSCALL(exit)
-SYSCALL(wait)
-SYSCALL(pipe)
-SYSCALL(read)
-SYSCALL(write)
-SYSCALL(close)
-SYSCALL(kill)
-SYSCALL(exec)
-SYSCALL(open)
-SYSCALL(mknod)
-SYSCALL(unlink)
-SYSCALL(fstat)
-SYSCALL(link)
-SYSCALL(mkdir)
-SYSCALL(chdir)
-SYSCALL(dup)
-SYSCALL(getpid)
-SYSCALL(sbrk)
-SYSCALL(sleep)
-SYSCALL(uptime)
diff --git a/vectors.pl b/vectors.pl
deleted file mode 100755 (executable)
index 57b49dd..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/perl -w
-
-# Generate vectors.S, the trap/interrupt entry points.
-# There has to be one entry point per interrupt number
-# since otherwise there's no way for trap() to discover
-# the interrupt number.
-
-print "# generated by vectors.pl - do not edit\n";
-print "# handlers\n";
-print ".globl alltraps\n";
-for(my $i = 0; $i < 256; $i++){
-    print ".globl vector$i\n";
-    print "vector$i:\n";
-    if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){
-        print "  pushl \$0\n";
-    }
-    print "  pushl \$$i\n";
-    print "  jmp alltraps\n";
-}
-
-print "\n# vector table\n";
-print ".data\n";
-print ".globl vectors\n";
-print "vectors:\n";
-for(my $i = 0; $i < 256; $i++){
-    print "  .long vector$i\n";
-}
-
-# sample output:
-#   # handlers
-#   .globl alltraps
-#   .globl vector0
-#   vector0:
-#     pushl $0
-#     pushl $0
-#     jmp alltraps
-#   ...
-#   
-#   # vector table
-#   .data
-#   .globl vectors
-#   vectors:
-#     .long vector0
-#     .long vector1
-#     .long vector2
-#   ...
-
diff --git a/vm.c b/vm.c
deleted file mode 100644 (file)
index 7134cff..0000000
--- a/vm.c
+++ /dev/null
@@ -1,394 +0,0 @@
-#include "param.h"
-#include "types.h"
-#include "defs.h"
-#include "x86.h"
-#include "memlayout.h"
-#include "mmu.h"
-#include "proc.h"
-#include "elf.h"
-
-extern char data[];  // defined by kernel.ld
-pde_t *kpgdir;  // for use in scheduler()
-
-// Set up CPU's kernel segment descriptors.
-// Run once on entry on each CPU.
-void
-seginit(void)
-{
-  struct cpu *c;
-
-  // Map "logical" addresses to virtual addresses using identity map.
-  // Cannot share a CODE descriptor for both kernel and user
-  // because it would have to have DPL_USR, but the CPU forbids
-  // an interrupt from CPL=0 to DPL=3.
-  c = &cpus[cpuid()];
-  c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
-  c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
-  c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);
-  c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
-  lgdt(c->gdt, sizeof(c->gdt));
-}
-
-// Return the address of the PTE in page table pgdir
-// that corresponds to virtual address va.  If alloc!=0,
-// create any required page table pages.
-static pte_t *
-walkpgdir(pde_t *pgdir, const void *va, int alloc)
-{
-  pde_t *pde;
-  pte_t *pgtab;
-
-  pde = &pgdir[PDX(va)];
-  if(*pde & PTE_P){
-    pgtab = (pte_t*)P2V(PTE_ADDR(*pde));
-  } else {
-    if(!alloc || (pgtab = (pte_t*)kalloc()) == 0)
-      return 0;
-    // Make sure all those PTE_P bits are zero.
-    memset(pgtab, 0, PGSIZE);
-    // The permissions here are overly generous, but they can
-    // be further restricted by the permissions in the page table
-    // entries, if necessary.
-    *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U;
-  }
-  return &pgtab[PTX(va)];
-}
-
-// Create PTEs for virtual addresses starting at va that refer to
-// physical addresses starting at pa. va and size might not
-// be page-aligned.
-static int
-mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm)
-{
-  char *a, *last;
-  pte_t *pte;
-
-  a = (char*)PGROUNDDOWN((uint)va);
-  last = (char*)PGROUNDDOWN(((uint)va) + size - 1);
-  for(;;){
-    if((pte = walkpgdir(pgdir, a, 1)) == 0)
-      return -1;
-    if(*pte & PTE_P)
-      panic("remap");
-    *pte = pa | perm | PTE_P;
-    if(a == last)
-      break;
-    a += PGSIZE;
-    pa += PGSIZE;
-  }
-  return 0;
-}
-
-// There is one page table per process, plus one that's used when
-// a CPU is not running any process (kpgdir). The kernel uses the
-// current process's page table during system calls and interrupts;
-// page protection bits prevent user code from using the kernel's
-// mappings.
-//
-// setupkvm() and exec() set up every page table like this:
-//
-//   0..KERNBASE: user memory (text+data+stack+heap), mapped to
-//                phys memory allocated by the kernel
-//   KERNBASE..KERNBASE+EXTMEM: mapped to 0..EXTMEM (for I/O space)
-//   KERNBASE+EXTMEM..data: mapped to EXTMEM..V2P(data)
-//                for the kernel's instructions and r/o data
-//   data..KERNBASE+PHYSTOP: mapped to V2P(data)..PHYSTOP,
-//                                  rw data + free physical memory
-//   0xfe000000..0: mapped direct (devices such as ioapic)
-//
-// The kernel allocates physical memory for its heap and for user memory
-// between V2P(end) and the end of physical memory (PHYSTOP)
-// (directly addressable from end..P2V(PHYSTOP)).
-
-// This table defines the kernel's mappings, which are present in
-// every process's page table.
-static struct kmap {
-  void *virt;
-  uint phys_start;
-  uint phys_end;
-  int perm;
-} kmap[] = {
- { (void*)KERNBASE, 0,             EXTMEM,    PTE_W}, // I/O space
- { (void*)KERNLINK, V2P(KERNLINK), V2P(data), 0},     // kern text+rodata
- { (void*)data,     V2P(data),     PHYSTOP,   PTE_W}, // kern data+memory
- { (void*)DEVSPACE, DEVSPACE,      0,         PTE_W}, // more devices
-};
-
-// Set up kernel part of a page table.
-pde_t*
-setupkvm(void)
-{
-  pde_t *pgdir;
-  struct kmap *k;
-
-  if((pgdir = (pde_t*)kalloc()) == 0)
-    return 0;
-  memset(pgdir, 0, PGSIZE);
-  if (P2V(PHYSTOP) > (void*)DEVSPACE)
-    panic("PHYSTOP too high");
-  for(k = kmap; k < &kmap[NELEM(kmap)]; k++)
-    if(mappages(pgdir, k->virt, k->phys_end - k->phys_start,
-                (uint)k->phys_start, k->perm) < 0) {
-      freevm(pgdir);
-      return 0;
-    }
-  return pgdir;
-}
-
-// Allocate one page table for the machine for the kernel address
-// space for scheduler processes.
-void
-kvmalloc(void)
-{
-  kpgdir = setupkvm();
-  switchkvm();
-}
-
-// Switch h/w page table register to the kernel-only page table,
-// for when no process is running.
-void
-switchkvm(void)
-{
-  lcr3(V2P(kpgdir));   // switch to the kernel page table
-}
-
-// Switch TSS and h/w page table to correspond to process p.
-void
-switchuvm(struct proc *p)
-{
-  if(p == 0)
-    panic("switchuvm: no process");
-  if(p->kstack == 0)
-    panic("switchuvm: no kstack");
-  if(p->pgdir == 0)
-    panic("switchuvm: no pgdir");
-
-  pushcli();
-  mycpu()->gdt[SEG_TSS] = SEG16(STS_T32A, &mycpu()->ts,
-                                sizeof(mycpu()->ts)-1, 0);
-  mycpu()->gdt[SEG_TSS].s = 0;
-  mycpu()->ts.ss0 = SEG_KDATA << 3;
-  mycpu()->ts.esp0 = (uint)p->kstack + KSTACKSIZE;
-  // setting IOPL=0 in eflags *and* iomb beyond the tss segment limit
-  // forbids I/O instructions (e.g., inb and outb) from user space
-  mycpu()->ts.iomb = (ushort) 0xFFFF;
-  ltr(SEG_TSS << 3);
-  lcr3(V2P(p->pgdir));  // switch to process's address space
-  popcli();
-}
-
-// Load the initcode into address 0 of pgdir.
-// sz must be less than a page.
-void
-inituvm(pde_t *pgdir, char *init, uint sz)
-{
-  char *mem;
-
-  if(sz >= PGSIZE)
-    panic("inituvm: more than a page");
-  mem = kalloc();
-  memset(mem, 0, PGSIZE);
-  mappages(pgdir, 0, PGSIZE, V2P(mem), PTE_W|PTE_U);
-  memmove(mem, init, sz);
-}
-
-// Load a program segment into pgdir.  addr must be page-aligned
-// and the pages from addr to addr+sz must already be mapped.
-int
-loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)
-{
-  uint i, pa, n;
-  pte_t *pte;
-
-  if((uint) addr % PGSIZE != 0)
-    panic("loaduvm: addr must be page aligned");
-  for(i = 0; i < sz; i += PGSIZE){
-    if((pte = walkpgdir(pgdir, addr+i, 0)) == 0)
-      panic("loaduvm: address should exist");
-    pa = PTE_ADDR(*pte);
-    if(sz - i < PGSIZE)
-      n = sz - i;
-    else
-      n = PGSIZE;
-    if(readi(ip, P2V(pa), offset+i, n) != n)
-      return -1;
-  }
-  return 0;
-}
-
-// Allocate page tables and physical memory to grow process from oldsz to
-// newsz, which need not be page aligned.  Returns new size or 0 on error.
-int
-allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
-{
-  char *mem;
-  uint a;
-
-  if(newsz >= KERNBASE)
-    return 0;
-  if(newsz < oldsz)
-    return oldsz;
-
-  a = PGROUNDUP(oldsz);
-  for(; a < newsz; a += PGSIZE){
-    mem = kalloc();
-    if(mem == 0){
-      cprintf("allocuvm out of memory\n");
-      deallocuvm(pgdir, newsz, oldsz);
-      return 0;
-    }
-    memset(mem, 0, PGSIZE);
-    if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){
-      cprintf("allocuvm out of memory (2)\n");
-      deallocuvm(pgdir, newsz, oldsz);
-      kfree(mem);
-      return 0;
-    }
-  }
-  return newsz;
-}
-
-// Deallocate user pages to bring the process size from oldsz to
-// newsz.  oldsz and newsz need not be page-aligned, nor does newsz
-// need to be less than oldsz.  oldsz can be larger than the actual
-// process size.  Returns the new process size.
-int
-deallocuvm(pde_t *pgdir, uint oldsz, uint newsz)
-{
-  pte_t *pte;
-  uint a, pa;
-
-  if(newsz >= oldsz)
-    return oldsz;
-
-  a = PGROUNDUP(newsz);
-  for(; a  < oldsz; a += PGSIZE){
-    pte = walkpgdir(pgdir, (char*)a, 0);
-    if(!pte)
-      a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
-    else if((*pte & PTE_P) != 0){
-      pa = PTE_ADDR(*pte);
-      if(pa == 0)
-        panic("kfree");
-      char *v = P2V(pa);
-      kfree(v);
-      *pte = 0;
-    }
-  }
-  return newsz;
-}
-
-// Free a page table and all the physical memory pages
-// in the user part.
-void
-freevm(pde_t *pgdir)
-{
-  uint i;
-
-  if(pgdir == 0)
-    panic("freevm: no pgdir");
-  deallocuvm(pgdir, KERNBASE, 0);
-  for(i = 0; i < NPDENTRIES; i++){
-    if(pgdir[i] & PTE_P){
-      char * v = P2V(PTE_ADDR(pgdir[i]));
-      kfree(v);
-    }
-  }
-  kfree((char*)pgdir);
-}
-
-// Clear PTE_U on a page. Used to create an inaccessible
-// page beneath the user stack.
-void
-clearpteu(pde_t *pgdir, char *uva)
-{
-  pte_t *pte;
-
-  pte = walkpgdir(pgdir, uva, 0);
-  if(pte == 0)
-    panic("clearpteu");
-  *pte &= ~PTE_U;
-}
-
-// Given a parent process's page table, create a copy
-// of it for a child.
-pde_t*
-copyuvm(pde_t *pgdir, uint sz)
-{
-  pde_t *d;
-  pte_t *pte;
-  uint pa, i, flags;
-  char *mem;
-
-  if((d = setupkvm()) == 0)
-    return 0;
-  for(i = 0; i < sz; i += PGSIZE){
-    if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0)
-      panic("copyuvm: pte should exist");
-    if(!(*pte & PTE_P))
-      panic("copyuvm: page not present");
-    pa = PTE_ADDR(*pte);
-    flags = PTE_FLAGS(*pte);
-    if((mem = kalloc()) == 0)
-      goto bad;
-    memmove(mem, (char*)P2V(pa), PGSIZE);
-    if(mappages(d, (void*)i, PGSIZE, V2P(mem), flags) < 0) {
-      kfree(mem);
-      goto bad;
-    }
-  }
-  return d;
-
-bad:
-  freevm(d);
-  return 0;
-}
-
-//PAGEBREAK!
-// Map user virtual address to kernel address.
-char*
-uva2ka(pde_t *pgdir, char *uva)
-{
-  pte_t *pte;
-
-  pte = walkpgdir(pgdir, uva, 0);
-  if((*pte & PTE_P) == 0)
-    return 0;
-  if((*pte & PTE_U) == 0)
-    return 0;
-  return (char*)P2V(PTE_ADDR(*pte));
-}
-
-// Copy len bytes from p to user address va in page table pgdir.
-// Most useful when pgdir is not the current page table.
-// uva2ka ensures this only works for PTE_U pages.
-int
-copyout(pde_t *pgdir, uint va, void *p, uint len)
-{
-  char *buf, *pa0;
-  uint n, va0;
-
-  buf = (char*)p;
-  while(len > 0){
-    va0 = (uint)PGROUNDDOWN(va);
-    pa0 = uva2ka(pgdir, (char*)va0);
-    if(pa0 == 0)
-      return -1;
-    n = PGSIZE - (va - va0);
-    if(n > len)
-      n = len;
-    memmove(pa0 + (va - va0), buf, n);
-    len -= n;
-    buf += n;
-    va = va0 + PGSIZE;
-  }
-  return 0;
-}
-
-//PAGEBREAK!
-// Blank page.
-//PAGEBREAK!
-// Blank page.
-//PAGEBREAK!
-// Blank page.
-
diff --git a/wc.c b/wc.c
deleted file mode 100644 (file)
index d6a54df..0000000
--- a/wc.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-char buf[512];
-
-void
-wc(int fd, char *name)
-{
-  int i, n;
-  int l, w, c, inword;
-
-  l = w = c = 0;
-  inword = 0;
-  while((n = read(fd, buf, sizeof(buf))) > 0){
-    for(i=0; i<n; i++){
-      c++;
-      if(buf[i] == '\n')
-        l++;
-      if(strchr(" \r\t\n\v", buf[i]))
-        inword = 0;
-      else if(!inword){
-        w++;
-        inword = 1;
-      }
-    }
-  }
-  if(n < 0){
-    printf(1, "wc: read error\n");
-    exit();
-  }
-  printf(1, "%d %d %d %s\n", l, w, c, name);
-}
-
-int
-main(int argc, char *argv[])
-{
-  int fd, i;
-
-  if(argc <= 1){
-    wc(0, "");
-    exit();
-  }
-
-  for(i = 1; i < argc; i++){
-    if((fd = open(argv[i], 0)) < 0){
-      printf(1, "wc: cannot open %s\n", argv[i]);
-      exit();
-    }
-    wc(fd, argv[i]);
-    close(fd);
-  }
-  exit();
-}
diff --git a/x86.h b/x86.h
deleted file mode 100644 (file)
index 6c7c8ec..0000000
--- a/x86.h
+++ /dev/null
@@ -1,170 +0,0 @@
-// Routines to let C code use special x86 instructions.
-
-static inline uchar
-inb(ushort port)
-{
-  uchar data;
-
-  __asm__ volatile("in %1,%0" : "=a" (data) : "d" (port));
-  return data;
-}
-
-static inline void
-insl(int port, void *addr, int cnt)
-{
-  __asm__ volatile("cld; rep insl" :
-               "=D" (addr), "=c" (cnt) :
-               "d" (port), "0" (addr), "1" (cnt) :
-               "memory", "cc");
-}
-
-static inline void
-outb(ushort port, uchar data)
-{
-  __asm__ volatile("out %0,%1" : : "a" (data), "d" (port));
-}
-
-static inline void
-outw(ushort port, ushort data)
-{
-  __asm__ volatile("out %0,%1" : : "a" (data), "d" (port));
-}
-
-static inline void
-outsl(int port, const void *addr, int cnt)
-{
-  __asm__ volatile("cld; rep outsl" :
-               "=S" (addr), "=c" (cnt) :
-               "d" (port), "0" (addr), "1" (cnt) :
-               "cc");
-}
-
-static inline void
-stosb(void *addr, int data, int cnt)
-{
-  __asm__ volatile("cld; rep stosb" :
-               "=D" (addr), "=c" (cnt) :
-               "0" (addr), "1" (cnt), "a" (data) :
-               "memory", "cc");
-}
-
-static inline void
-stosl(void *addr, int data, int cnt)
-{
-  __asm__ volatile("cld; rep stosl" :
-               "=D" (addr), "=c" (cnt) :
-               "0" (addr), "1" (cnt), "a" (data) :
-               "memory", "cc");
-}
-
-struct segdesc;
-
-static inline void
-lgdt(struct segdesc *p, int size)
-{
-  volatile ushort pd[3];
-
-  pd[0] = size-1;
-  pd[1] = (uint)p;
-  pd[2] = (uint)p >> 16;
-
-  __asm__ volatile("lgdt (%0)" : : "r" (pd));
-}
-
-struct gatedesc;
-
-static inline void
-lidt(struct gatedesc *p, int size)
-{
-  volatile ushort pd[3];
-
-  pd[0] = size-1;
-  pd[1] = (uint)p;
-  pd[2] = (uint)p >> 16;
-
-  __asm__ volatile("lidt (%0)" : : "r" (pd));
-}
-
-static inline void
-ltr(ushort sel)
-{
-  __asm__ volatile("ltr %0" : : "r" (sel));
-}
-
-static inline uint
-readeflags(void)
-{
-  uint eflags;
-  __asm__ volatile("pushfl; popl %0" : "=r" (eflags));
-  return eflags;
-}
-
-static inline void
-loadgs(ushort v)
-{
-  __asm__ volatile("movw %0, %%gs" : : "r" (v));
-}
-
-static inline void
-cli(void)
-{
-  __asm__ volatile("cli");
-}
-
-static inline void
-sti(void)
-{
-  __asm__ volatile("sti");
-}
-
-static inline uint
-rcr2(void)
-{
-  uint val;
-  __asm__ volatile("movl %%cr2,%0" : "=r" (val));
-  return val;
-}
-
-static inline void
-lcr3(uint val)
-{
-  __asm__ volatile("movl %0,%%cr3" : : "r" (val));
-}
-
-//PAGEBREAK: 36
-// Layout of the trap frame built on the stack by the
-// hardware and by trapasm.S, and passed to trap().
-struct trapframe {
-  // registers as pushed by pusha
-  uint edi;
-  uint esi;
-  uint ebp;
-  uint oesp;      // useless & ignored
-  uint ebx;
-  uint edx;
-  uint ecx;
-  uint eax;
-
-  // rest of trap frame
-  ushort gs;
-  ushort padding1;
-  ushort fs;
-  ushort padding2;
-  ushort es;
-  ushort padding3;
-  ushort ds;
-  ushort padding4;
-  uint trapno;
-
-  // below here defined by x86 hardware
-  uint err;
-  uint eip;
-  ushort cs;
-  ushort padding5;
-  uint eflags;
-
-  // below here only when crossing rings, such as from user to kernel
-  uint esp;
-  ushort ss;
-  ushort padding6;
-};
diff --git a/zombie.c b/zombie.c
deleted file mode 100644 (file)
index ee817da..0000000
--- a/zombie.c
+++ /dev/null
@@ -1,14 +0,0 @@
-// Create a zombie process that
-// must be reparented at exit.
-
-#include "types.h"
-#include "stat.h"
-#include "user.h"
-
-int
-main(void)
-{
-  if(fork() > 0)
-    sleep(5);  // Let child exit before parent.
-  exit();
-}