diff options
| author | rtm <rtm> | 2006-07-27 21:10:00 +0000 | 
|---|---|---|
| committer | rtm <rtm> | 2006-07-27 21:10:00 +0000 | 
| commit | c59361f1430ec485596d1bf5d43339af0b5a2705 (patch) | |
| tree | 1cb1898c928857c94f2927f74fdb0e2cd3772793 | |
| parent | 54a4b00346575f3e2da1c9aeb023aaba4412a31d (diff) | |
| download | xv6-labs-c59361f1430ec485596d1bf5d43339af0b5a2705.tar.gz xv6-labs-c59361f1430ec485596d1bf5d43339af0b5a2705.tar.bz2 xv6-labs-c59361f1430ec485596d1bf5d43339af0b5a2705.zip | |
primitive exec
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | defs.h | 1 | ||||
| -rw-r--r-- | fs.c | 23 | ||||
| -rw-r--r-- | main.c | 1 | ||||
| -rw-r--r-- | mkfs.c | 150 | ||||
| -rw-r--r-- | proc.c | 3 | ||||
| -rw-r--r-- | syscall.c | 100 | ||||
| -rw-r--r-- | syscall.h | 1 | ||||
| -rw-r--r-- | userfs.c | 1 | ||||
| -rw-r--r-- | usys.S | 1 | 
10 files changed, 243 insertions, 42 deletions
| @@ -73,8 +73,8 @@ userfs : userfs.o $(ULIB)  mkfs : mkfs.c fs.h  	cc -o mkfs mkfs.c -fs.img : mkfs -	./mkfs fs.img +fs.img : mkfs usertests +	./mkfs fs.img usertests  -include *.d @@ -102,3 +102,4 @@ void iunlock(struct inode *ip);  void iincref(struct inode *ip);  void iput(struct inode *ip);  struct inode * namei(char *path); +int readi(struct inode *ip, void *xdst, uint off, uint n); @@ -133,6 +133,29 @@ bmap(struct inode *ip, uint bn)    return x;  } +#define min(a, b) ((a) < (b) ? (a) : (b)) + +int +readi(struct inode *ip, void *xdst, uint off, uint n) +{ +  char *dst = (char *) xdst; +  uint target = n, n1; +  struct buf *bp; + +  while(n > 0 && off < ip->size){ +    bp = bread(ip->dev, bmap(ip, off / 512)); +    n1 = min(n, ip->size - off); +    n1 = min(n1, 512 - (off % 512)); +    memmove(dst, bp->data + (off % 512), n1); +    n -= n1; +    off += n1; +    dst += n1; +    brelse(bp); +  } + +  return target - n; +} +  struct inode *  namei(char *path)  { @@ -100,6 +100,7 @@ mpmain(void)    lapic_enableintr();    // Enable interrupts on this processor. +  cprintf("cpu %d initial nlock %d\n", cpu(), cpus[cpu()].nlock);    cpus[cpu()].nlock--;    sti(); @@ -3,6 +3,7 @@  #include <stdlib.h>  #include <string.h>  #include <fcntl.h> +#include <assert.h>  #include "types.h"  #include "param.h"  #include "fs.h" @@ -10,14 +11,17 @@  int nblocks = 1009;  int ninodes = 100; -int fd; +int fsfd;  struct superblock sb;  char zeroes[512];  uint freeblock; +uint freeinode = 1;  void wsect(uint, void *);  void winode(uint, struct dinode *);  void rsect(uint sec, void *buf); +uint ialloc(ushort type); +void iappend(uint inum, void *p, int n);  // convert to intel byte order  ushort @@ -44,27 +48,21 @@ xint(uint x)  main(int argc, char *argv[])  { -  int i; -  struct dinode din; -  char dbuf[512]; -  uint bn; +  int i, cc, fd; +  uint bn, rootino, inum; +  struct dirent de; +  char buf[512]; -  if(argc != 2){ -    fprintf(stderr, "Usage: mkfs fs.img\n"); +  if(argc < 2){ +    fprintf(stderr, "Usage: mkfs fs.img files...\n");      exit(1);    } -  if((512 % sizeof(struct dinode)) != 0){ -    fprintf(stderr, "sizeof(dinode) must divide 512\n"); -    exit(1); -  } -  if((512 % sizeof(struct dirent)) != 0){ -    fprintf(stderr, "sizeof(dirent) must divide 512\n"); -    exit(1); -  } +  assert((512 % sizeof(struct dinode)) == 0); +  assert((512 % sizeof(struct dirent)) == 0); -  fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); -  if(fd < 0){ +  fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); +  if(fsfd < 0){      perror(argv[1]);      exit(1);    } @@ -79,20 +77,38 @@ main(int argc, char *argv[])    wsect(1, &sb); -  bzero(&din, sizeof(din)); -  din.type = xshort(T_DIR); -  din.nlink = xshort(2); -  din.size = xint(512); -  bn = freeblock++; -  din.addrs[0] = xint(bn); -  winode(1, &din); - -  bzero(dbuf, sizeof(dbuf)); -  ((struct dirent *) dbuf)[0].inum = xshort(1); -  strcpy(((struct dirent *) dbuf)[0].name, "."); -  ((struct dirent *) dbuf)[1].inum = xshort(1); -  strcpy(((struct dirent *) dbuf)[1].name, ".."); -  wsect(bn, dbuf); +  rootino = ialloc(T_DIR); +  assert(rootino == 1); + +  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); +    } + +    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); +  }    exit(0);  } @@ -100,11 +116,11 @@ main(int argc, char *argv[])  void  wsect(uint sec, void *buf)  { -  if(lseek(fd, sec * 512L, 0) != sec * 512L){ +  if(lseek(fsfd, sec * 512L, 0) != sec * 512L){      perror("lseek");      exit(1);    } -  if(write(fd, buf, 512) != 512){ +  if(write(fsfd, buf, 512) != 512){      perror("write");      exit(1);    } @@ -127,20 +143,80 @@ winode(uint inum, struct dinode *ip)    rsect(bn, buf);    dip = ((struct dinode *) buf) + (inum % IPB);    *dip = *ip; -  printf("bn %d off %d\n", -         bn, (unsigned)dip - (unsigned) buf);    wsect(bn, buf); +  printf("wi %d size %d addrs %d %d...\n", +         inum, +         xint(dip->size), +         xint(dip->addrs[0]), +         xint(dip->addrs[1])); +} + +void +rinode(uint inum, struct dinode *ip) +{ +  char buf[512]; +  uint bn; +  struct dinode *dip; + +  bn = i2b(inum); +  rsect(bn, buf); +  dip = ((struct dinode *) buf) + (inum % IPB); +  *ip = *dip;  }  void  rsect(uint sec, void *buf)  { -  if(lseek(fd, sec * 512L, 0) != sec * 512L){ +  if(lseek(fsfd, sec * 512L, 0) != sec * 512L){      perror("lseek");      exit(1);    } -  if(read(fd, buf, 512) != 512){ +  if(read(fsfd, buf, 512) != 512){      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; +} + +#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[512]; + +  rinode(inum, &din); + +  off = xint(din.size); +  while(n > 0){ +    fbn = off / 512; +    assert(fbn < NDIRECT); +    if(din.addrs[fbn] == 0) +      din.addrs[fbn] = xint(freeblock++); +    n1 = min(n, (fbn + 1) * 512 - off); +    rsect(xint(din.addrs[fbn]), buf); +    bcopy(p, buf + off - (fbn * 512), n1); +    wsect(xint(din.addrs[fbn]), buf); +    n -= n1; +    off += n1; +    p += n1; +  } +  din.size = xint(off); +  winode(inum, &din); +} @@ -137,6 +137,9 @@ scheduler(void)    cprintf("start scheduler on cpu %d jmpbuf %p\n", cpu(), &cpus[cpu()].jmpbuf);    cpus[cpu()].lastproc = &proc[0]; +  if(cpus[cpu()].nlock != 0) +    panic("holding locks at first entry to scheduler"); +    for(;;){      // Loop over process table looking for process to run.      acquire(&proc_table_lock); @@ -10,6 +10,7 @@  #include "buf.h"  #include "fs.h"  #include "fsvar.h" +#include "elf.h"  /*   * User code makes a system call with INT T_SYSCALL. @@ -57,6 +58,21 @@ fetcharg(int argno, void *ip)    return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip);  } +// check that an entire string is valid in user space +int +checkstring(uint s) +{ +  char c; + +  while(1){ +    if(fetchbyte(curproc[cpu()], s, &c) < 0) +      return -1; +    if(c == '\0') +      return 0; +    s++; +  } +} +  int  putint(struct proc *p, uint addr, int x)  { @@ -225,6 +241,81 @@ sys_cons_puts(void)  }  int +sys_exec(void) +{ +  struct proc *cp = curproc[cpu()]; +  uint arg0, sz; +  int i; +  struct inode *ip; +  struct elfhdr elf; +  struct proghdr ph; + +  if(fetcharg(0, &arg0) < 0) +    return -1; +  if(checkstring(arg0) < 0) +    return -1; +  ip = namei(cp->mem + arg0); +  if(ip == 0) +    return -1; + +  if(readi(ip, &elf, 0, sizeof(elf)) < sizeof(elf)) +    goto bad; + +  if(elf.magic != ELF_MAGIC) +    goto bad; + +  sz = 0; +  for(i = 0; i < elf.phnum; i++){ +    if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph)) +      goto bad; +    if(ph.type != ELF_PROG_LOAD) +      continue; +    if(ph.memsz < ph.filesz) +      goto bad; +    sz += ph.memsz; +  } +   +  sz += 4096 - (sz % 4096); +  sz += 4096; + +  // commit to the new image. +  kfree(cp->mem, cp->sz); +  cp->sz = sz; +  cp->mem = kalloc(cp->sz); + +  for(i = 0; i < elf.phnum; i++){ +    if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph)) +      goto bad; +    if(ph.type != ELF_PROG_LOAD) +      continue; +    if(ph.va + ph.memsz > sz) +      goto bad2; +    if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz) +      goto bad2; +    memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz); +  } + +  iput(ip); + +  cp->tf->eip = elf.entry; +  cp->tf->esp = cp->sz; +  setupsegs(cp); + +  return 0; + + bad: +  cprintf("exec failed early\n"); +  iput(ip); +  return -1; + + bad2: +  cprintf("exec failed late\n"); +  iput(ip); +  proc_exit(); +  return 0; +} + +int  sys_block(void)  {    int i, j; @@ -248,14 +339,14 @@ sys_block(void)            ip->type, ip->nlink, ip->size, ip->addrs[0]);    iput(ip); -  ip = namei(".././//./../"); +  ip = namei(".././//./../usertests");    if(ip){ -    cprintf("namei: %d %d %d %d %d %d %d %d\n", +    cprintf("namei(usertests): %d %d %d %d %d %d %d %d\n",              ip->dev, ip->inum, ip->count, ip->busy,              ip->type, ip->nlink, ip->size, ip->addrs[0]);      iput(ip);    } else { -    cprintf("namei failed\n"); +    cprintf("namei(usertests) failed\n");    }    return 0; @@ -317,6 +408,9 @@ syscall(void)    case SYS_cons_puts:      ret = sys_cons_puts();      break; +  case SYS_exec: +    ret = sys_exec(); +    break;    default:      cprintf("unknown sys call %d\n", num);      // XXX fault @@ -10,3 +10,4 @@  #define SYS_kill 10  #define SYS_panic 11  #define SYS_cons_puts 12 +#define SYS_exec 13 @@ -9,5 +9,6 @@ main(void)  {    puts("userfs running\n");    block(); +  exec("usertests");    return 0;  } @@ -20,3 +20,4 @@ STUB(block)  STUB(kill)  STUB(panic)  STUB(cons_puts) +STUB(exec) | 
