diff options
| -rw-r--r-- | Makefile | 20 | ||||
| -rw-r--r-- | bio.c | 7 | ||||
| -rw-r--r-- | defs.h | 8 | ||||
| -rw-r--r-- | file.c | 1 | ||||
| -rw-r--r-- | fs.c | 4 | ||||
| -rw-r--r-- | ide.c | 168 | ||||
| -rw-r--r-- | kalloc.c | 2 | ||||
| -rw-r--r-- | log.c | 1 | ||||
| -rw-r--r-- | main.c | 4 | ||||
| -rw-r--r-- | memlayout.h | 4 | ||||
| -rw-r--r-- | pipe.c | 2 | ||||
| -rw-r--r-- | proc.c | 27 | ||||
| -rw-r--r-- | ramdisk.c | 45 | ||||
| -rw-r--r-- | sleeplock.c | 3 | ||||
| -rw-r--r-- | trapasm.S | 132 | ||||
| -rw-r--r-- | ulib.c | 7 | ||||
| -rw-r--r-- | usertests.c | 32 | ||||
| -rw-r--r-- | usys.S | 31 | ||||
| -rwxr-xr-x | usys.pl | 38 | ||||
| -rw-r--r-- | vm.c | 5 | 
20 files changed, 138 insertions, 403 deletions
| @@ -12,7 +12,14 @@ OBJS = \    trampoline.o \    trap.o \    syscall.o \ -  sysproc.o +  sysproc.o \ +  bio.o \ +  fs.o \ +  log.o \ +  sleeplock.o \ +  file.o \ +  pipe.o \ +  ramdisk.o  XXXOBJS = \  	bio.o\ @@ -83,15 +90,15 @@ endif  LDFLAGS = -z max-page-size=4096 -kernel: $(OBJS) entry.o kernel.ld  +kernel: $(OBJS) entry.o kernel.ld initcode  	$(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS)   	$(OBJDUMP) -S kernel > kernel.asm  	$(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym  initcode: initcode.S  	$(CC) $(CFLAGS) -nostdinc -I. -c initcode.S -	#$(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o -	#$(OBJCOPY) -S -O binary initcode.out initcode +	$(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o +	$(OBJCOPY) -S -O binary initcode.out initcode  	$(OBJDUMP) -S initcode.o > initcode.asm  tags: $(OBJS) entryother.S _init @@ -107,6 +114,9 @@ _%: %.o $(ULIB)  	$(OBJDUMP) -S $@ > $*.asm  	$(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym +usys.S : usys.pl +	perl ./usys.pl > usys.S +  _forktest: forktest.o $(ULIB)  	# forktest has less library code linked in - needs to be small  	# in order to be able to max out the proc table. @@ -171,7 +181,7 @@ ifndef CPUS  CPUS := 1  endif  QEMUOPTS = -machine virt -kernel kernel -m 3G -smp $(CPUS) -nographic -#QEMUOPTS += -initrd fs.img +QEMUOPTS += -initrd fs.img  qemu: kernel  	$(QEMU) $(QEMUOPTS) @@ -19,10 +19,11 @@  //     and needs to be written to disk.  #include "types.h" -#include "defs.h"  #include "param.h"  #include "spinlock.h"  #include "sleeplock.h" +#include "riscv.h" +#include "defs.h"  #include "fs.h"  #include "buf.h" @@ -100,7 +101,7 @@ bread(uint dev, uint blockno)    b = bget(dev, blockno);    if((b->flags & B_VALID) == 0) { -    iderw(b); +    ramdiskrw(b);    }    return b;  } @@ -112,7 +113,7 @@ bwrite(struct buf *b)    if(!holdingsleep(&b->lock))      panic("bwrite");    b->flags |= B_DIRTY; -  iderw(b); +  ramdiskrw(b);  }  // Release a locked buffer. @@ -54,10 +54,10 @@ 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*); +// ramdisk.c +void            ramdiskinit(void); +void            ramdiskintr(void); +void            ramdiskrw(struct buf*);  // ioapic.c  void            ioapicenable(int irq, int cpu); @@ -3,6 +3,7 @@  //  #include "types.h" +#include "riscv.h"  #include "defs.h"  #include "param.h"  #include "fs.h" @@ -10,10 +10,10 @@  // are in sysfile.c.  #include "types.h" +#include "riscv.h"  #include "defs.h"  #include "param.h"  #include "stat.h" -#include "mmu.h"  #include "proc.h"  #include "spinlock.h"  #include "sleeplock.h" @@ -180,7 +180,7 @@ iinit(int dev)    }    readsb(dev, &sb); -  cprintf("sb: size %d nblocks %d ninodes %d nlog %d logstart %d\ +  printf("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); @@ -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); -} @@ -27,6 +27,8 @@ void  kinit()  {    initlock(&kmem.lock, "kmem"); +  if(PHYSTOP > RAMDISK) +    panic("kinit");    freerange(end, (void*)PHYSTOP);  } @@ -1,4 +1,5 @@  #include "types.h" +#include "riscv.h"  #include "defs.h"  #include "param.h"  #include "spinlock.h" @@ -17,11 +17,9 @@ main()    kvminit();       // kernel page table    procinit();      // process table    trapinit();      // trap vectors -#if 0    binit();         // buffer cache    fileinit();      // file table -  ideinit();       // disk -#endif +  ramdiskinit();   // disk    userinit();      // first user process    scheduler();         diff --git a/memlayout.h b/memlayout.h index 798621e..9bc9c5d 100644 --- a/memlayout.h +++ b/memlayout.h @@ -4,6 +4,8 @@  // 00001000 -- boot ROM, provided by qemu  // 10000000 -- uart0 registers  // 80000000 -- boot ROM jumps here in machine mode +//             -kernel loads the kernel here +// 88000000 -- -initrd fs.img ramdisk image.  // unused RAM after 80000000.  // the kernel uses physical memory thus: @@ -14,6 +16,8 @@  // registers start here in physical memory.  #define UART0 0x10000000L +#define RAMDISK 0x88000000 +  // the kernel expects there to be RAM  // for use by the kernel and user pages  // from physical address 0x80000000 to PHYSTOP. @@ -1,7 +1,7 @@  #include "types.h" +#include "riscv.h"  #include "defs.h"  #include "param.h" -#include "mmu.h"  #include "proc.h"  #include "fs.h"  #include "spinlock.h" @@ -116,16 +116,13 @@ found:    return p;  } -// XXX hack because I don't know how to incorporate initcode -// into the kernel binary. just the exec system call, no arguments. -// manually copied from initcode.asm. +// a user program that calls exec("/init") +// od -t xC initcode  unsigned char initcode[] = { -  0x85, 0x48,             // li a7, 1 -- SYS_fork -  0x73, 0x00, 0x00, 0x00, // ecall -  0x8d, 0x48,             // li a7, 3 -- SYS_wait -  0x73, 0x00, 0x00, 0x00, // ecall -  0x89, 0x48,             // li a7, 2 -- SYS_exit -  0x73, 0x00, 0x00, 0x00, // ecall +  0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x05, 0x02, 0x97, 0x05, 0x00, 0x00, 0x93, 0x85, 0x05, 0x02, +  0x9d, 0x48, 0x73, 0x00, 0x00, 0x00, 0x89, 0x48, 0x73, 0x00, 0x00, 0x00, 0xef, 0xf0, 0xbf, 0xff, +  0x2f, 0x69, 0x6e, 0x69, 0x74, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +  0x00, 0x00, 0x00  };  //PAGEBREAK: 32 @@ -146,8 +143,7 @@ userinit(void)    p->tf->sp = PGSIZE;    safestrcpy(p->name, "initcode", sizeof(p->name)); -  // XXX riscv -  //p->cwd = namei("/"); +  p->cwd = namei("/");    // this assignment to p->state lets other cores    // run this process. the acquire forces the above @@ -210,13 +206,11 @@ fork(void)    // Cause fork to return 0 in the child.    np->tf->a0 = 0; -#if 0 // XXX riscv    // increment reference counts on open file descriptors.    for(i = 0; i < NOFILE; i++)      if(p->ofile[i])        np->ofile[i] = filedup(p->ofile[i]);    np->cwd = idup(p->cwd); -#endif    safestrcpy(np->name, p->name, sizeof(p->name)); @@ -244,7 +238,6 @@ exit(void)    if(p == initproc)      panic("init exiting"); -#if 0 // XXX riscv    // Close all open files.    for(fd = 0; fd < NOFILE; fd++){      if(p->ofile[fd]){ @@ -256,7 +249,6 @@ exit(void)    begin_op();    iput(p->cwd);    end_op(); -#endif    p->cwd = 0;    acquire(&ptable.lock); @@ -423,9 +415,8 @@ forkret(void)      // of a regular process (e.g., they call sleep), and thus cannot      // be run from main().      first = 0; -    // XXX riscv -    //iinit(ROOTDEV); -    //initlog(ROOTDEV); +    iinit(ROOTDEV); +    initlog(ROOTDEV);    }    usertrapret(); diff --git a/ramdisk.c b/ramdisk.c new file mode 100644 index 0000000..9901294 --- /dev/null +++ b/ramdisk.c @@ -0,0 +1,45 @@ +// +// ramdisk that uses the disk image loaded by qemu -rdinit fs.img +// + +#include "types.h" +#include "riscv.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "buf.h" + +void +ramdiskinit(void) +{ +} + +// 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 +ramdiskrw(struct buf *b) +{ +  if(!holdingsleep(&b->lock)) +    panic("ramdiskrw: buf not locked"); +  if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) +    panic("ramdiskrw: nothing to do"); + +  if(b->blockno >= FSSIZE) +    panic("ramdiskrw: blockno too big"); + +  uint64 diskaddr = b->blockno * BSIZE; +  char *addr = (char *)RAMDISK + diskaddr; + +  if(b->flags & B_DIRTY){ +    // write +    memmove(addr, b->data, BSIZE); +    b->flags &= ~B_DIRTY; +  } else { +    // read +    memmove(b->data, addr, BSIZE); +    b->flags |= B_VALID; +  } +} diff --git a/sleeplock.c b/sleeplock.c index e0750ea..b490370 100644 --- a/sleeplock.c +++ b/sleeplock.c @@ -1,11 +1,10 @@  // Sleeping locks  #include "types.h" +#include "riscv.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" diff --git a/trapasm.S b/trapasm.S deleted file mode 100644 index 6b6b567..0000000 --- a/trapasm.S +++ /dev/null @@ -1,132 +0,0 @@ -#include "param.h" -#include "x86.h"	 -#include "mmu.h" - -# the offset of cs in trapframe (i.e., tf->cs - tf) -#define CSOFF  144 -	 -# vectors.S sends all traps here. -.globl alltraps -alltraps: -  # Build trap frame. -  push %r15 -  push %r14 -  push %r13 -  push %r12 -  push %r11 -  push %r10 -  push %r9 -  push %r8 -  push %rdi -  push %rsi -  push %rbp -  push %rdx -  push %rcx -  push %rbx -  push %rax - -  cmpw $SEG_KCODE, CSOFF(%rsp)   # compare to saved cs -  jz 1f  -  swapgs -   -1:mov  %rsp, %rdi  # frame in arg1 -  call trap - -# Return falls through to trapret... -.globl trapret -trapret: -  cli -  cmpw $SEG_KCODE, CSOFF(%rsp)  # compare to saved cs -  jz 1f -  swapgs - -1:pop %rax -  pop %rbx -  pop %rcx -  pop %rdx -  pop %rbp -  pop %rsi -  pop %rdi -  pop %r8 -  pop %r9 -  pop %r10 -  pop %r11 -  pop %r12 -  pop %r13 -  pop %r14 -  pop %r15 - -  add $16, %rsp  # discard trapnum and errorcode -  iretq - -#PAGEBREAK! - -# syscall jumps here after syscall instruction -.globl sysentry -sysentry:  # Build syscall frame. -  // load kernel stack address -  swapgs -  movq  %rax, %gs:0  // save %rax in syscallno of cpu entry -  movq  %rsp, %gs:8  // user sp -  movq  %gs:16, %rax  // proc entry -   -  movq  %ss:0(%rax), %rax // load kstack from proc -  addq  $(KSTACKSIZE), %rax - -  movq  %rax, %rsp -  movq  %gs:0, %rax  // restore rax - -  push %gs:8 -  push %rcx -  push %r11	 -  push %rax	 - -  push %rbp -  push %rbx	 -  push %r12  -  push %r13 -  push %r14 -  push %r15	 - -  push %r9 -  push %r8	 -  push %r10 -  push %rdx -  push %rsi	 -  push %rdi -	 -  mov  %rsp, %rdi  # frame in arg1 - -  call syscall -  # fall through to sysexit -	 -.globl sysexit -sysexit: -  # to make sure we don't get any interrupts on the user stack while in -  # supervisor mode.  insufficient?  (see vunerability reports for sysret) -  cli -	 -  pop %rdi -  pop %rsi -  pop %rdx -  pop %r10 -  pop %r8 -  pop %r9 - -  pop %r15 -  pop %r14 -  pop %r13 -  pop %r12 -  pop %rbx -  pop %rbp - -  pop %rax -  pop %r11 -  pop %rcx - -  mov (%rsp),%rsp  # switch to the user stack -  # there are two more values on the stack, but we don't care about them	 -  swapgs	 - -  sysretq - @@ -2,7 +2,6 @@  #include "stat.h"  #include "fcntl.h"  #include "user.h" -#include "x86.h"  char*  strcpy(char *s, const char *t) @@ -36,7 +35,11 @@ strlen(const char *s)  void*  memset(void *dst, int c, uint n)  { -  stosb(dst, c, n); +  char *cdst = (char *) dst; +  int i; +  for(i = 0; i < n; i++){ +    cdst[i] = c; +  }    return dst;  } diff --git a/usertests.c b/usertests.c index 3cd8b34..292319e 100644 --- a/usertests.c +++ b/usertests.c @@ -5,7 +5,6 @@  #include "fs.h"  #include "fcntl.h"  #include "syscall.h" -#include "traps.h"  #include "memlayout.h"  char buf[8192]; @@ -1713,35 +1712,6 @@ fsfull()    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; @@ -1813,8 +1783,6 @@ main(int argc, char *argv[])    forktest();    bigdir(); // slow -  uio(); -    exectest();    exit(); @@ -1,31 +0,0 @@ -#include "syscall.h" -#include "traps.h" - -#define SYSCALL(name) \ -  .globl name; \ -  name: \ -    mov $SYS_ ## name, %rax; \ -    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) @@ -0,0 +1,38 @@ +#!/usr/bin/perl -w + +# Generate usys.S, the stubs for syscalls. + +print "# generated by usys.pl - do not edit\n"; + +print "#include \"syscall.h\"\n"; + +sub entry { +    my $name = shift; +    print ".global $name\n"; +    print "${name}:\n"; +    print " li a7, SYS_${name}\n"; +    print " ecall\n"; +    print " ret\n"; +} +	 +entry("fork"); +entry("exit"); +entry("wait"); +entry("pipe"); +entry("read"); +entry("write"); +entry("close"); +entry("kill"); +entry("exec"); +entry("open"); +entry("mknod"); +entry("unlink"); +entry("fstat"); +entry("link"); +entry("mkdir"); +entry("chdir"); +entry("dup"); +entry("getpid"); +entry("sbrk"); +entry("sleep"); +entry("uptime"); @@ -4,6 +4,7 @@  #include "elf.h"  #include "riscv.h"  #include "defs.h" +#include "fs.h"  /*   * the kernel's page table. @@ -37,6 +38,10 @@ kvminit()    mappages(kernel_pagetable, (uint64)etext, PHYSTOP-(uint64)etext,             (uint64)etext, PTE_R | PTE_W); +  // map the qemu -initrd fs.img ramdisk +  mappages(kernel_pagetable, RAMDISK, FSSIZE * BSIZE, +           RAMDISK, PTE_R | PTE_W); +    // map the trampoline for trap entry/exit to    // the highest virtual address in the kernel.    mappages(kernel_pagetable, TRAMPOLINE, PGSIZE, | 
