Compare commits

...

11 commits

Author SHA1 Message Date
Imbus
362d5adeb2 Type names (uint32 -> u32, e.t.c.) 2024-05-24 11:26:40 +02:00
Frans Kaashoek
f5b93ef12f Update acks
61810
2022-08-25 14:20:52 -04:00
Frans Kaashoek
3d6ce9b308 Separate tests in slow and quick. The slow tests run xv6 out of
memory, out of disk space, or test big directories.

Support -q option to run only the quick tests, which saves about
7mins.

Clean up driver by removing duplicated code.
2022-08-25 09:45:35 -04:00
Robert Morris
ed101befee comment the sfences 2022-08-24 13:47:47 -04:00
Robert Morris
581bc4cbd1 sfence before enabling paging 2022-08-24 13:42:59 -04:00
Robert Morris
29ce3161f8 Merge branch 'riscv' of g.csail.mit.edu:xv6-dev into riscv 2022-08-24 13:24:37 -04:00
Robert Morris
9c1b8a4eb0 sfence before writing satp, as well as after 2022-08-24 13:24:24 -04:00
Frans Kaashoek
cc486ddee0 Help students read this C syntax 2022-08-24 08:57:56 -04:00
Robert Morris
96047832c6 Merge branch 'riscv' of g.csail.mit.edu:xv6-dev into riscv 2022-08-23 12:26:39 -04:00
Robert Morris
7c1810e1ae tolerate running out of inodes 2022-08-23 12:26:26 -04:00
Frans Kaashoek
ac8c0bb177 x 2022-08-23 11:56:29 -04:00
41 changed files with 853 additions and 768 deletions

36
README
View file

@ -6,7 +6,7 @@ ACKNOWLEDGMENTS
xv6 is inspired by John Lions's Commentary on UNIX 6th Edition (Peer xv6 is inspired by John Lions's Commentary on UNIX 6th Edition (Peer
to Peer Communications; ISBN: 1-57398-013-7; 1st edition (June 14, to Peer Communications; ISBN: 1-57398-013-7; 1st edition (June 14,
2000)). See also https://pdos.csail.mit.edu/6.828/, which provides 2000)). See also https://pdos.csail.mit.edu/6.1810/, which provides
pointers to on-line resources for v6. pointers to on-line resources for v6.
The following people have made contributions: Russ Cox (context switching, The following people have made contributions: Russ Cox (context switching,
@ -14,29 +14,31 @@ locking), Cliff Frey (MP), Xiao Yu (MP), Nickolai Zeldovich, and Austin
Clements. Clements.
We are also grateful for the bug reports and patches contributed by We are also grateful for the bug reports and patches contributed by
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, Ian Chen, Dan Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, carlclone, Ian
Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi, eyalz800, Nelson Chen, Dan Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi,
Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel Filardo, flespark, eyalz800, Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel
Peter Froehlich, Yakir Goaron, Shivam Handa, Matt Harvey, Bryan Henry, Filardo, flespark, Peter Froehlich, Yakir Goaron, Shivam Handa, Matt
jaichenhengjie, Jim Huang, Matúš Jókay, Alexander Kapshuk, Anders Harvey, Bryan Henry, jaichenhengjie, Jim Huang, Matúš Jókay, John
Kaseorg, kehao95, Wolfgang Keller, Jungwoo Kim, Jonathan Kimmitt, Jolly, Alexander Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller,
Eddie Kohler, Vadim Kolontsov, Austin Liew, l0stman, Pavan Jungwoo Kim, Jonathan Kimmitt, Eddie Kohler, Vadim Kolontsov, Austin
Maddamsetti, Imbar Marinescu, Yandong Mao, Matan Shabtay, Hitoshi Liew, l0stman, Pavan Maddamsetti, Imbar Marinescu, Yandong Mao, Matan
Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel Nider, Shabtay, Hitoshi Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel
OptimisticSide, Greg Price, Jude Rich, Ayan Shafqat, Eldar Sehayek, Nider, Hayato Ohhashi, OptimisticSide, Harry Porter, Greg Price, Jude
Yongming Shen, Fumiya Shigemitsu, Cam Tenny, tyfkda, Warren Toomey, Rich, segfault, Ayan Shafqat, Eldar Sehayek, Yongming Shen, Fumiya
Stephen Tu, Rafael Ubal, Amane Uehara, Pablo Ventura, Xi Wang, Keiichi Shigemitsu, Cam Tenny, tyfkda, Warren Toomey, Stephen Tu, Rafael Ubal,
Watanabe, Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Amane Uehara, Pablo Ventura, Xi Wang, WaheedHafez, Keiichi Watanabe,
Zheng, ZhUyU1997, and Zou Chang Wei. Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng,
ZhUyU1997, and Zou Chang Wei.
The code in the files that constitute xv6 is The code in the files that constitute xv6 is
Copyright 2006-2020 Frans Kaashoek, Robert Morris, and Russ Cox. Copyright 2006-2022 Frans Kaashoek, Robert Morris, and Russ Cox.
ERROR REPORTS ERROR REPORTS
Please send errors and suggestions to Frans Kaashoek and Robert Morris Please send errors and suggestions to Frans Kaashoek and Robert Morris
(kaashoek,rtm@mit.edu). The main purpose of xv6 is as a teaching (kaashoek,rtm@mit.edu). The main purpose of xv6 is as a teaching
operating system for MIT's 6.S081, so we are more interested in operating system for MIT's 6.1810, so we are more interested in
simplifications and clarifications than new features. simplifications and clarifications than new features.
BUILDING AND RUNNING XV6 BUILDING AND RUNNING XV6

View file

@ -56,7 +56,7 @@ binit(void)
// If not found, allocate a buffer. // If not found, allocate a buffer.
// In either case, return locked buffer. // In either case, return locked buffer.
static struct buf* static struct buf*
bget(uint dev, uint blockno) bget(u32 dev, u32 blockno)
{ {
struct buf *b; struct buf *b;
@ -90,7 +90,7 @@ bget(uint dev, uint blockno)
// Return a locked buf with the contents of the indicated block. // Return a locked buf with the contents of the indicated block.
struct buf* struct buf*
bread(uint dev, uint blockno) bread(u32 dev, u32 blockno)
{ {
struct buf *b; struct buf *b;

View file

@ -1,12 +1,12 @@
struct buf { struct buf {
int valid; // has data been read from disk? int valid; // has data been read from disk?
int disk; // does disk "own" buf? int disk; // does disk "own" buf?
uint dev; u32 dev;
uint blockno; u32 blockno;
struct sleeplock lock; struct sleeplock lock;
uint refcnt; u32 refcnt;
struct buf *prev; // LRU cache list struct buf *prev; // LRU cache list
struct buf *next; struct buf *next;
uchar data[BSIZE]; u8 data[BSIZE];
}; };

View file

@ -47,16 +47,16 @@ struct {
// input // input
#define INPUT_BUF_SIZE 128 #define INPUT_BUF_SIZE 128
char buf[INPUT_BUF_SIZE]; char buf[INPUT_BUF_SIZE];
uint r; // Read index u32 r; // Read index
uint w; // Write index u32 w; // Write index
uint e; // Edit index u32 e; // Edit index
} cons; } cons;
// //
// user write()s to the console go here. // user write()s to the console go here.
// //
int int
consolewrite(int user_src, uint64 src, int n) consolewrite(int user_src, u64 src, int n)
{ {
int i; int i;
@ -77,9 +77,9 @@ consolewrite(int user_src, uint64 src, int n)
// or kernel address. // or kernel address.
// //
int int
consoleread(int user_dst, uint64 dst, int n) consoleread(int user_dst, u64 dst, int n)
{ {
uint target; u32 target;
int c; int c;
char cbuf; char cbuf;

View file

@ -11,7 +11,7 @@ struct superblock;
// bio.c // bio.c
void binit(void); void binit(void);
struct buf* bread(uint, uint); struct buf* bread(u32, u32);
void brelse(struct buf*); void brelse(struct buf*);
void bwrite(struct buf*); void bwrite(struct buf*);
void bpin(struct buf*); void bpin(struct buf*);
@ -30,15 +30,15 @@ struct file* filealloc(void);
void fileclose(struct file*); void fileclose(struct file*);
struct file* filedup(struct file*); struct file* filedup(struct file*);
void fileinit(void); void fileinit(void);
int fileread(struct file*, uint64, int n); int fileread(struct file*, u64, int n);
int filestat(struct file*, uint64 addr); int filestat(struct file*, u64 addr);
int filewrite(struct file*, uint64, int n); int filewrite(struct file*, u64, int n);
// fs.c // fs.c
void fsinit(int); void fsinit(int);
int dirlink(struct inode*, char*, uint); int dirlink(struct inode*, char*, u32);
struct inode* dirlookup(struct inode*, char*, uint*); struct inode* dirlookup(struct inode*, char*, u32*);
struct inode* ialloc(uint, short); struct inode* ialloc(u32, short);
struct inode* idup(struct inode*); struct inode* idup(struct inode*);
void iinit(); void iinit();
void ilock(struct inode*); void ilock(struct inode*);
@ -49,9 +49,9 @@ void iupdate(struct inode*);
int namecmp(const char*, const char*); int namecmp(const char*, const char*);
struct inode* namei(char*); struct inode* namei(char*);
struct inode* nameiparent(char*, char*); struct inode* nameiparent(char*, char*);
int readi(struct inode*, int, uint64, uint, uint); int readi(struct inode*, int, u64, u32, u32);
void stati(struct inode*, struct stat*); void stati(struct inode*, struct stat*);
int writei(struct inode*, int, uint64, uint, uint); int writei(struct inode*, int, u64, u32, u32);
void itrunc(struct inode*); void itrunc(struct inode*);
// ramdisk.c // ramdisk.c
@ -73,8 +73,8 @@ void end_op(void);
// pipe.c // pipe.c
int pipealloc(struct file**, struct file**); int pipealloc(struct file**, struct file**);
void pipeclose(struct pipe*, int); void pipeclose(struct pipe*, int);
int piperead(struct pipe*, uint64, int); int piperead(struct pipe*, u64, int);
int pipewrite(struct pipe*, uint64, int); int pipewrite(struct pipe*, u64, int);
// printf.c // printf.c
void printf(char*, ...); void printf(char*, ...);
@ -88,7 +88,7 @@ int fork(void);
int growproc(int); int growproc(int);
void proc_mapstacks(pagetable_t); void proc_mapstacks(pagetable_t);
pagetable_t proc_pagetable(struct proc *); pagetable_t proc_pagetable(struct proc *);
void proc_freepagetable(pagetable_t, uint64); void proc_freepagetable(pagetable_t, u64);
int kill(int); int kill(int);
int killed(struct proc*); int killed(struct proc*);
void setkilled(struct proc*); void setkilled(struct proc*);
@ -100,11 +100,11 @@ void scheduler(void) __attribute__((noreturn));
void sched(void); void sched(void);
void sleep(void*, struct spinlock*); void sleep(void*, struct spinlock*);
void userinit(void); void userinit(void);
int wait(uint64); int wait(u64);
void wakeup(void*); void wakeup(void*);
void yield(void); void yield(void);
int either_copyout(int user_dst, uint64 dst, void *src, uint64 len); int either_copyout(int user_dst, u64 dst, void *src, u64 len);
int either_copyin(void *dst, int user_src, uint64 src, uint64 len); int either_copyin(void *dst, int user_src, u64 src, u64 len);
void procdump(void); void procdump(void);
// swtch.S // swtch.S
@ -125,24 +125,24 @@ int holdingsleep(struct sleeplock*);
void initsleeplock(struct sleeplock*, char*); void initsleeplock(struct sleeplock*, char*);
// string.c // string.c
int memcmp(const void*, const void*, uint); int memcmp(const void*, const void*, u32);
void* memmove(void*, const void*, uint); void* memmove(void*, const void*, u32);
void* memset(void*, int, uint); void* memset(void*, int, u32);
char* safestrcpy(char*, const char*, int); char* safestrcpy(char*, const char*, int);
int strlen(const char*); int strlen(const char*);
int strncmp(const char*, const char*, uint); int strncmp(const char*, const char*, u32);
char* strncpy(char*, const char*, int); char* strncpy(char*, const char*, int);
// syscall.c // syscall.c
void argint(int, int*); void argint(int, int*);
int argstr(int, char*, int); int argstr(int, char*, int);
void argaddr(int, uint64 *); void argaddr(int, u64 *);
int fetchstr(uint64, char*, int); int fetchstr(u64, char*, int);
int fetchaddr(uint64, uint64*); int fetchaddr(u64, u64*);
void syscall(); void syscall();
// trap.c // trap.c
extern uint ticks; extern u32 ticks;
void trapinit(void); void trapinit(void);
void trapinithart(void); void trapinithart(void);
extern struct spinlock tickslock; extern struct spinlock tickslock;
@ -158,21 +158,21 @@ int uartgetc(void);
// vm.c // vm.c
void kvminit(void); void kvminit(void);
void kvminithart(void); void kvminithart(void);
void kvmmap(pagetable_t, uint64, uint64, uint64, int); void kvmmap(pagetable_t, u64, u64, u64, int);
int mappages(pagetable_t, uint64, uint64, uint64, int); int mappages(pagetable_t, u64, u64, u64, int);
pagetable_t uvmcreate(void); pagetable_t uvmcreate(void);
void uvmfirst(pagetable_t, uchar *, uint); void uvmfirst(pagetable_t, u8 *, u32);
uint64 uvmalloc(pagetable_t, uint64, uint64, int); u64 uvmalloc(pagetable_t, u64, u64, int);
uint64 uvmdealloc(pagetable_t, uint64, uint64); u64 uvmdealloc(pagetable_t, u64, u64);
int uvmcopy(pagetable_t, pagetable_t, uint64); int uvmcopy(pagetable_t, pagetable_t, u64);
void uvmfree(pagetable_t, uint64); void uvmfree(pagetable_t, u64);
void uvmunmap(pagetable_t, uint64, uint64, int); void uvmunmap(pagetable_t, u64, u64, int);
void uvmclear(pagetable_t, uint64); void uvmclear(pagetable_t, u64);
pte_t * walk(pagetable_t, uint64, int); pte_t * walk(pagetable_t, u64, int);
uint64 walkaddr(pagetable_t, uint64); u64 walkaddr(pagetable_t, u64);
int copyout(pagetable_t, uint64, char *, uint64); int copyout(pagetable_t, u64, char *, u64);
int copyin(pagetable_t, char *, uint64, uint64); int copyin(pagetable_t, char *, u64, u64);
int copyinstr(pagetable_t, char *, uint64, uint64); int copyinstr(pagetable_t, char *, u64, u64);
// plic.c // plic.c
void plicinit(void); void plicinit(void);

View file

@ -4,33 +4,33 @@
// File header // File header
struct elfhdr { struct elfhdr {
uint magic; // must equal ELF_MAGIC u32 magic; // must equal ELF_MAGIC
uchar elf[12]; u8 elf[12];
ushort type; u16 type;
ushort machine; u16 machine;
uint version; u32 version;
uint64 entry; u64 entry;
uint64 phoff; u64 phoff;
uint64 shoff; u64 shoff;
uint flags; u32 flags;
ushort ehsize; u16 ehsize;
ushort phentsize; u16 phentsize;
ushort phnum; u16 phnum;
ushort shentsize; u16 shentsize;
ushort shnum; u16 shnum;
ushort shstrndx; u16 shstrndx;
}; };
// Program section header // Program section header
struct proghdr { struct proghdr {
uint32 type; u32 type;
uint32 flags; u32 flags;
uint64 off; u64 off;
uint64 vaddr; u64 vaddr;
uint64 paddr; u64 paddr;
uint64 filesz; u64 filesz;
uint64 memsz; u64 memsz;
uint64 align; u64 align;
}; };
// Values for Proghdr type // Values for Proghdr type

View file

@ -7,7 +7,7 @@
#include "defs.h" #include "defs.h"
#include "elf.h" #include "elf.h"
static int loadseg(pde_t *, uint64, struct inode *, uint, uint); static int loadseg(pde_t *, u64, struct inode *, u32, u32);
int flags2perm(int flags) int flags2perm(int flags)
{ {
@ -24,7 +24,7 @@ exec(char *path, char **argv)
{ {
char *s, *last; char *s, *last;
int i, off; int i, off;
uint64 argc, sz = 0, sp, ustack[MAXARG], stackbase; u64 argc, sz = 0, sp, ustack[MAXARG], stackbase;
struct elfhdr elf; struct elfhdr elf;
struct inode *ip; struct inode *ip;
struct proghdr ph; struct proghdr ph;
@ -40,7 +40,7 @@ exec(char *path, char **argv)
ilock(ip); ilock(ip);
// Check ELF header // Check ELF header
if(readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf)) if(readi(ip, 0, (u64)&elf, 0, sizeof(elf)) != sizeof(elf))
goto bad; goto bad;
if(elf.magic != ELF_MAGIC) if(elf.magic != ELF_MAGIC)
@ -51,7 +51,7 @@ exec(char *path, char **argv)
// Load program into memory. // Load program into memory.
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
if(readi(ip, 0, (uint64)&ph, off, sizeof(ph)) != sizeof(ph)) if(readi(ip, 0, (u64)&ph, off, sizeof(ph)) != sizeof(ph))
goto bad; goto bad;
if(ph.type != ELF_PROG_LOAD) if(ph.type != ELF_PROG_LOAD)
continue; continue;
@ -61,7 +61,7 @@ exec(char *path, char **argv)
goto bad; goto bad;
if(ph.vaddr % PGSIZE != 0) if(ph.vaddr % PGSIZE != 0)
goto bad; goto bad;
uint64 sz1; u64 sz1;
if((sz1 = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz, flags2perm(ph.flags))) == 0) if((sz1 = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz, flags2perm(ph.flags))) == 0)
goto bad; goto bad;
sz = sz1; sz = sz1;
@ -73,13 +73,13 @@ exec(char *path, char **argv)
ip = 0; ip = 0;
p = myproc(); p = myproc();
uint64 oldsz = p->sz; u64 oldsz = p->sz;
// Allocate two pages at the next page boundary. // Allocate two pages at the next page boundary.
// Make the first inaccessible as a stack guard. // Make the first inaccessible as a stack guard.
// Use the second as the user stack. // Use the second as the user stack.
sz = PGROUNDUP(sz); sz = PGROUNDUP(sz);
uint64 sz1; u64 sz1;
if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE, PTE_W)) == 0) if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE, PTE_W)) == 0)
goto bad; goto bad;
sz = sz1; sz = sz1;
@ -102,11 +102,11 @@ exec(char *path, char **argv)
ustack[argc] = 0; ustack[argc] = 0;
// push the array of argv[] pointers. // push the array of argv[] pointers.
sp -= (argc+1) * sizeof(uint64); sp -= (argc+1) * sizeof(u64);
sp -= sp % 16; sp -= sp % 16;
if(sp < stackbase) if(sp < stackbase)
goto bad; goto bad;
if(copyout(pagetable, sp, (char *)ustack, (argc+1)*sizeof(uint64)) < 0) if(copyout(pagetable, sp, (char *)ustack, (argc+1)*sizeof(u64)) < 0)
goto bad; goto bad;
// arguments to user main(argc, argv) // arguments to user main(argc, argv)
@ -145,10 +145,10 @@ exec(char *path, char **argv)
// and the pages from va to va+sz must already be mapped. // and the pages from va to va+sz must already be mapped.
// Returns 0 on success, -1 on failure. // Returns 0 on success, -1 on failure.
static int static int
loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, uint offset, uint sz) loadseg(pagetable_t pagetable, u64 va, struct inode *ip, u32 offset, u32 sz)
{ {
uint i, n; u32 i, n;
uint64 pa; u64 pa;
for(i = 0; i < sz; i += PGSIZE){ for(i = 0; i < sz; i += PGSIZE){
pa = walkaddr(pagetable, va + i); pa = walkaddr(pagetable, va + i);
@ -158,7 +158,7 @@ loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, uint offset, uint sz
n = sz - i; n = sz - i;
else else
n = PGSIZE; n = PGSIZE;
if(readi(ip, 0, (uint64)pa, offset+i, n) != n) if(readi(ip, 0, (u64)pa, offset+i, n) != n)
return -1; return -1;
} }

View file

@ -85,7 +85,7 @@ fileclose(struct file *f)
// Get metadata about file f. // Get metadata about file f.
// addr is a user virtual address, pointing to a struct stat. // addr is a user virtual address, pointing to a struct stat.
int int
filestat(struct file *f, uint64 addr) filestat(struct file *f, u64 addr)
{ {
struct proc *p = myproc(); struct proc *p = myproc();
struct stat st; struct stat st;
@ -104,7 +104,7 @@ filestat(struct file *f, uint64 addr)
// Read from file f. // Read from file f.
// addr is a user virtual address. // addr is a user virtual address.
int int
fileread(struct file *f, uint64 addr, int n) fileread(struct file *f, u64 addr, int n)
{ {
int r = 0; int r = 0;
@ -132,7 +132,7 @@ fileread(struct file *f, uint64 addr, int n)
// Write to file f. // Write to file f.
// addr is a user virtual address. // addr is a user virtual address.
int int
filewrite(struct file *f, uint64 addr, int n) filewrite(struct file *f, u64 addr, int n)
{ {
int r, ret = 0; int r, ret = 0;

View file

@ -5,18 +5,18 @@ struct file {
char writable; char writable;
struct pipe *pipe; // FD_PIPE struct pipe *pipe; // FD_PIPE
struct inode *ip; // FD_INODE and FD_DEVICE struct inode *ip; // FD_INODE and FD_DEVICE
uint off; // FD_INODE u32 off; // FD_INODE
short major; // FD_DEVICE short major; // FD_DEVICE
}; };
#define major(dev) ((dev) >> 16 & 0xFFFF) #define major(dev) ((dev) >> 16 & 0xFFFF)
#define minor(dev) ((dev) & 0xFFFF) #define minor(dev) ((dev) & 0xFFFF)
#define mkdev(m,n) ((uint)((m)<<16| (n))) #define mkdev(m,n) ((u32)((m)<<16| (n)))
// in-memory copy of an inode // in-memory copy of an inode
struct inode { struct inode {
uint dev; // Device number u32 dev; // Device number
uint inum; // Inode number u32 inum; // Inode number
int ref; // Reference count int ref; // Reference count
struct sleeplock lock; // protects everything below here struct sleeplock lock; // protects everything below here
int valid; // inode has been read from disk? int valid; // inode has been read from disk?
@ -25,14 +25,14 @@ struct inode {
short major; short major;
short minor; short minor;
short nlink; short nlink;
uint size; u32 size;
uint addrs[NDIRECT+1]; u32 addrs[NDIRECT+1];
}; };
// map major device number to device functions. // map major device number to device functions.
struct devsw { struct devsw {
int (*read)(int, uint64, int); int (*read)(int, u64, int);
int (*write)(int, uint64, int); int (*write)(int, u64, int);
}; };
extern struct devsw devsw[]; extern struct devsw devsw[];

View file

@ -62,8 +62,8 @@ bzero(int dev, int bno)
// Allocate a zeroed disk block. // Allocate a zeroed disk block.
// returns 0 if out of disk space. // returns 0 if out of disk space.
static uint static u32
balloc(uint dev) balloc(u32 dev)
{ {
int b, bi, m; int b, bi, m;
struct buf *bp; struct buf *bp;
@ -89,7 +89,7 @@ balloc(uint dev)
// Free a disk block. // Free a disk block.
static void static void
bfree(int dev, uint b) bfree(int dev, u32 b)
{ {
struct buf *bp; struct buf *bp;
int bi, m; int bi, m;
@ -189,13 +189,14 @@ iinit()
} }
} }
static struct inode* iget(uint dev, uint inum); static struct inode* iget(u32 dev, u32 inum);
// Allocate an inode on device dev. // Allocate an inode on device dev.
// Mark it as allocated by giving it type type. // Mark it as allocated by giving it type type.
// Returns an unlocked but allocated and referenced inode. // Returns an unlocked but allocated and referenced inode,
// or NULL if there is no free inode.
struct inode* struct inode*
ialloc(uint dev, short type) ialloc(u32 dev, short type)
{ {
int inum; int inum;
struct buf *bp; struct buf *bp;
@ -213,7 +214,8 @@ ialloc(uint dev, short type)
} }
brelse(bp); brelse(bp);
} }
panic("ialloc: no inodes"); printf("ialloc: no inodes\n");
return 0;
} }
// Copy a modified in-memory inode to disk. // Copy a modified in-memory inode to disk.
@ -242,7 +244,7 @@ iupdate(struct inode *ip)
// and return the in-memory copy. Does not lock // and return the in-memory copy. Does not lock
// the inode and does not read it from disk. // the inode and does not read it from disk.
static struct inode* static struct inode*
iget(uint dev, uint inum) iget(u32 dev, u32 inum)
{ {
struct inode *ip, *empty; struct inode *ip, *empty;
@ -377,10 +379,10 @@ iunlockput(struct inode *ip)
// Return the disk block address of the nth block in inode ip. // Return the disk block address of the nth block in inode ip.
// If there is no such block, bmap allocates one. // If there is no such block, bmap allocates one.
// returns 0 if out of disk space. // returns 0 if out of disk space.
static uint static u32
bmap(struct inode *ip, uint bn) bmap(struct inode *ip, u32 bn)
{ {
uint addr, *a; u32 addr, *a;
struct buf *bp; struct buf *bp;
if(bn < NDIRECT){ if(bn < NDIRECT){
@ -403,7 +405,7 @@ bmap(struct inode *ip, uint bn)
ip->addrs[NDIRECT] = addr; ip->addrs[NDIRECT] = addr;
} }
bp = bread(ip->dev, addr); bp = bread(ip->dev, addr);
a = (uint*)bp->data; a = (u32*)bp->data;
if((addr = a[bn]) == 0){ if((addr = a[bn]) == 0){
addr = balloc(ip->dev); addr = balloc(ip->dev);
if(addr){ if(addr){
@ -425,7 +427,7 @@ itrunc(struct inode *ip)
{ {
int i, j; int i, j;
struct buf *bp; struct buf *bp;
uint *a; u32 *a;
for(i = 0; i < NDIRECT; i++){ for(i = 0; i < NDIRECT; i++){
if(ip->addrs[i]){ if(ip->addrs[i]){
@ -436,7 +438,7 @@ itrunc(struct inode *ip)
if(ip->addrs[NDIRECT]){ if(ip->addrs[NDIRECT]){
bp = bread(ip->dev, ip->addrs[NDIRECT]); bp = bread(ip->dev, ip->addrs[NDIRECT]);
a = (uint*)bp->data; a = (u32*)bp->data;
for(j = 0; j < NINDIRECT; j++){ for(j = 0; j < NINDIRECT; j++){
if(a[j]) if(a[j])
bfree(ip->dev, a[j]); bfree(ip->dev, a[j]);
@ -467,9 +469,9 @@ stati(struct inode *ip, struct stat *st)
// If user_dst==1, then dst is a user virtual address; // If user_dst==1, then dst is a user virtual address;
// otherwise, dst is a kernel address. // otherwise, dst is a kernel address.
int int
readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n) readi(struct inode *ip, int user_dst, u64 dst, u32 off, u32 n)
{ {
uint tot, m; u32 tot, m;
struct buf *bp; struct buf *bp;
if(off > ip->size || off + n < off) if(off > ip->size || off + n < off)
@ -478,7 +480,7 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n)
n = ip->size - off; n = ip->size - off;
for(tot=0; tot<n; tot+=m, off+=m, dst+=m){ for(tot=0; tot<n; tot+=m, off+=m, dst+=m){
uint addr = bmap(ip, off/BSIZE); u32 addr = bmap(ip, off/BSIZE);
if(addr == 0) if(addr == 0)
break; break;
bp = bread(ip->dev, addr); bp = bread(ip->dev, addr);
@ -501,9 +503,9 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n)
// If the return value is less than the requested n, // If the return value is less than the requested n,
// there was an error of some kind. // there was an error of some kind.
int int
writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) writei(struct inode *ip, int user_src, u64 src, u32 off, u32 n)
{ {
uint tot, m; u32 tot, m;
struct buf *bp; struct buf *bp;
if(off > ip->size || off + n < off) if(off > ip->size || off + n < off)
@ -512,7 +514,7 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n)
return -1; return -1;
for(tot=0; tot<n; tot+=m, off+=m, src+=m){ for(tot=0; tot<n; tot+=m, off+=m, src+=m){
uint addr = bmap(ip, off/BSIZE); u32 addr = bmap(ip, off/BSIZE);
if(addr == 0) if(addr == 0)
break; break;
bp = bread(ip->dev, addr); bp = bread(ip->dev, addr);
@ -547,16 +549,16 @@ namecmp(const char *s, const char *t)
// Look for a directory entry in a directory. // Look for a directory entry in a directory.
// If found, set *poff to byte offset of entry. // If found, set *poff to byte offset of entry.
struct inode* struct inode*
dirlookup(struct inode *dp, char *name, uint *poff) dirlookup(struct inode *dp, char *name, u32 *poff)
{ {
uint off, inum; u32 off, inum;
struct dirent de; struct dirent de;
if(dp->type != T_DIR) if(dp->type != T_DIR)
panic("dirlookup not DIR"); panic("dirlookup not DIR");
for(off = 0; off < dp->size; off += sizeof(de)){ for(off = 0; off < dp->size; off += sizeof(de)){
if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) if(readi(dp, 0, (u64)&de, off, sizeof(de)) != sizeof(de))
panic("dirlookup read"); panic("dirlookup read");
if(de.inum == 0) if(de.inum == 0)
continue; continue;
@ -575,7 +577,7 @@ dirlookup(struct inode *dp, char *name, uint *poff)
// Write a new directory entry (name, inum) into the directory dp. // Write a new directory entry (name, inum) into the directory dp.
// Returns 0 on success, -1 on failure (e.g. out of disk blocks). // Returns 0 on success, -1 on failure (e.g. out of disk blocks).
int int
dirlink(struct inode *dp, char *name, uint inum) dirlink(struct inode *dp, char *name, u32 inum)
{ {
int off; int off;
struct dirent de; struct dirent de;
@ -589,7 +591,7 @@ dirlink(struct inode *dp, char *name, uint inum)
// Look for an empty dirent. // Look for an empty dirent.
for(off = 0; off < dp->size; off += sizeof(de)){ for(off = 0; off < dp->size; off += sizeof(de)){
if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) if(readi(dp, 0, (u64)&de, off, sizeof(de)) != sizeof(de))
panic("dirlink read"); panic("dirlink read");
if(de.inum == 0) if(de.inum == 0)
break; break;
@ -597,7 +599,7 @@ dirlink(struct inode *dp, char *name, uint inum)
strncpy(de.name, name, DIRSIZ); strncpy(de.name, name, DIRSIZ);
de.inum = inum; de.inum = inum;
if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) if(writei(dp, 0, (u64)&de, off, sizeof(de)) != sizeof(de))
return -1; return -1;
return 0; return 0;

View file

@ -12,20 +12,20 @@
// mkfs computes the super block and builds an initial file system. The // mkfs computes the super block and builds an initial file system. The
// super block describes the disk layout: // super block describes the disk layout:
struct superblock { struct superblock {
uint magic; // Must be FSMAGIC u32 magic; // Must be FSMAGIC
uint size; // Size of file system image (blocks) u32 size; // Size of file system image (blocks)
uint nblocks; // Number of data blocks u32 nblocks; // Number of data blocks
uint ninodes; // Number of inodes. u32 ninodes; // Number of inodes.
uint nlog; // Number of log blocks u32 nlog; // Number of log blocks
uint logstart; // Block number of first log block u32 logstart; // Block number of first log block
uint inodestart; // Block number of first inode block u32 inodestart; // Block number of first inode block
uint bmapstart; // Block number of first free map block u32 bmapstart; // Block number of first free map block
}; };
#define FSMAGIC 0x10203040 #define FSMAGIC 0x10203040
#define NDIRECT 12 #define NDIRECT 12
#define NINDIRECT (BSIZE / sizeof(uint)) #define NINDIRECT (BSIZE / sizeof(u32))
#define MAXFILE (NDIRECT + NINDIRECT) #define MAXFILE (NDIRECT + NINDIRECT)
// On-disk inode structure // On-disk inode structure
@ -34,8 +34,8 @@ struct dinode {
short major; // Major device number (T_DEVICE only) short major; // Major device number (T_DEVICE only)
short minor; // Minor device number (T_DEVICE only) short minor; // Minor device number (T_DEVICE only)
short nlink; // Number of links to inode in file system short nlink; // Number of links to inode in file system
uint size; // Size of file (bytes) u32 size; // Size of file (bytes)
uint addrs[NDIRECT+1]; // Data block addresses u32 addrs[NDIRECT+1]; // Data block addresses
}; };
// Inodes per block. // Inodes per block.
@ -54,7 +54,7 @@ struct dinode {
#define DIRSIZ 14 #define DIRSIZ 14
struct dirent { struct dirent {
ushort inum; u16 inum;
char name[DIRSIZ]; char name[DIRSIZ];
}; };

View file

@ -34,7 +34,7 @@ void
freerange(void *pa_start, void *pa_end) freerange(void *pa_start, void *pa_end)
{ {
char *p; char *p;
p = (char*)PGROUNDUP((uint64)pa_start); p = (char*)PGROUNDUP((u64)pa_start);
for(; p + PGSIZE <= (char*)pa_end; p += PGSIZE) for(; p + PGSIZE <= (char*)pa_end; p += PGSIZE)
kfree(p); kfree(p);
} }
@ -48,7 +48,7 @@ kfree(void *pa)
{ {
struct run *r; struct run *r;
if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP) if(((u64)pa % PGSIZE) != 0 || (char*)pa < end || (u64)pa >= PHYSTOP)
panic("kfree"); panic("kfree");
// Fill with junk to catch dangling refs. // Fill with junk to catch dangling refs.

View file

@ -13,8 +13,8 @@
struct pipe { struct pipe {
struct spinlock lock; struct spinlock lock;
char data[PIPESIZE]; char data[PIPESIZE];
uint nread; // number of bytes read u32 nread; // number of bytes read
uint nwrite; // number of bytes written u32 nwrite; // number of bytes written
int readopen; // read fd is still open int readopen; // read fd is still open
int writeopen; // write fd is still open int writeopen; // write fd is still open
}; };
@ -74,7 +74,7 @@ pipeclose(struct pipe *pi, int writable)
} }
int int
pipewrite(struct pipe *pi, uint64 addr, int n) pipewrite(struct pipe *pi, u64 addr, int n)
{ {
int i = 0; int i = 0;
struct proc *pr = myproc(); struct proc *pr = myproc();
@ -103,7 +103,7 @@ pipewrite(struct pipe *pi, uint64 addr, int n)
} }
int int
piperead(struct pipe *pi, uint64 addr, int n) piperead(struct pipe *pi, u64 addr, int n)
{ {
int i; int i;
struct proc *pr = myproc(); struct proc *pr = myproc();

View file

@ -12,8 +12,8 @@ void
plicinit(void) plicinit(void)
{ {
// set desired IRQ priorities non-zero (otherwise disabled). // set desired IRQ priorities non-zero (otherwise disabled).
*(uint32*)(PLIC + UART0_IRQ*4) = 1; *(u32*)(PLIC + UART0_IRQ*4) = 1;
*(uint32*)(PLIC + VIRTIO0_IRQ*4) = 1; *(u32*)(PLIC + VIRTIO0_IRQ*4) = 1;
} }
void void
@ -23,10 +23,10 @@ plicinithart(void)
// set enable bits for this hart's S-mode // set enable bits for this hart's S-mode
// for the uart and virtio disk. // for the uart and virtio disk.
*(uint32*)PLIC_SENABLE(hart) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ); *(u32*)PLIC_SENABLE(hart) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ);
// set this hart's S-mode priority threshold to 0. // set this hart's S-mode priority threshold to 0.
*(uint32*)PLIC_SPRIORITY(hart) = 0; *(u32*)PLIC_SPRIORITY(hart) = 0;
} }
// ask the PLIC what interrupt we should serve. // ask the PLIC what interrupt we should serve.
@ -34,7 +34,7 @@ int
plic_claim(void) plic_claim(void)
{ {
int hart = cpuid(); int hart = cpuid();
int irq = *(uint32*)PLIC_SCLAIM(hart); int irq = *(u32*)PLIC_SCLAIM(hart);
return irq; return irq;
} }
@ -43,5 +43,5 @@ void
plic_complete(int irq) plic_complete(int irq)
{ {
int hart = cpuid(); int hart = cpuid();
*(uint32*)PLIC_SCLAIM(hart) = irq; *(u32*)PLIC_SCLAIM(hart) = irq;
} }

View file

@ -30,7 +30,7 @@ printint(int xx, int base, int sign)
{ {
char buf[16]; char buf[16];
int i; int i;
uint x; u32 x;
if(sign && (sign = xx < 0)) if(sign && (sign = xx < 0))
x = -xx; x = -xx;
@ -50,13 +50,13 @@ printint(int xx, int base, int sign)
} }
static void static void
printptr(uint64 x) printptr(u64 x)
{ {
int i; int i;
consputc('0'); consputc('0');
consputc('x'); consputc('x');
for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4) for (i = 0; i < (sizeof(u64) * 2); i++, x <<= 4)
consputc(digits[x >> (sizeof(uint64) * 8 - 4)]); consputc(digits[x >> (sizeof(u64) * 8 - 4)]);
} }
// Print to the console. only understands %d, %x, %p, %s. // Print to the console. only understands %d, %x, %p, %s.
@ -91,7 +91,7 @@ printf(char *fmt, ...)
printint(va_arg(ap, int), 16, 1); printint(va_arg(ap, int), 16, 1);
break; break;
case 'p': case 'p':
printptr(va_arg(ap, uint64)); printptr(va_arg(ap, u64));
break; break;
case 's': case 's':
if((s = va_arg(ap, char*)) == 0) if((s = va_arg(ap, char*)) == 0)

View file

@ -38,8 +38,8 @@ proc_mapstacks(pagetable_t kpgtbl)
char *pa = kalloc(); char *pa = kalloc();
if(pa == 0) if(pa == 0)
panic("kalloc"); panic("kalloc");
uint64 va = KSTACK((int) (p - proc)); u64 va = KSTACK((int) (p - proc));
kvmmap(kpgtbl, va, (uint64)pa, PGSIZE, PTE_R | PTE_W); kvmmap(kpgtbl, va, (u64)pa, PGSIZE, PTE_R | PTE_W);
} }
} }
@ -143,7 +143,7 @@ found:
// Set up new context to start executing at forkret, // Set up new context to start executing at forkret,
// which returns to user space. // which returns to user space.
memset(&p->context, 0, sizeof(p->context)); memset(&p->context, 0, sizeof(p->context));
p->context.ra = (uint64)forkret; p->context.ra = (u64)forkret;
p->context.sp = p->kstack + PGSIZE; p->context.sp = p->kstack + PGSIZE;
return p; return p;
@ -188,7 +188,7 @@ proc_pagetable(struct proc *p)
// only the supervisor uses it, on the way // only the supervisor uses it, on the way
// to/from user space, so not PTE_U. // to/from user space, so not PTE_U.
if(mappages(pagetable, TRAMPOLINE, PGSIZE, if(mappages(pagetable, TRAMPOLINE, PGSIZE,
(uint64)trampoline, PTE_R | PTE_X) < 0){ (u64)trampoline, PTE_R | PTE_X) < 0){
uvmfree(pagetable, 0); uvmfree(pagetable, 0);
return 0; return 0;
} }
@ -196,7 +196,7 @@ proc_pagetable(struct proc *p)
// map the trapframe page just below the trampoline page, for // map the trapframe page just below the trampoline page, for
// trampoline.S. // trampoline.S.
if(mappages(pagetable, TRAPFRAME, PGSIZE, if(mappages(pagetable, TRAPFRAME, PGSIZE,
(uint64)(p->trapframe), PTE_R | PTE_W) < 0){ (u64)(p->trapframe), PTE_R | PTE_W) < 0){
uvmunmap(pagetable, TRAMPOLINE, 1, 0); uvmunmap(pagetable, TRAMPOLINE, 1, 0);
uvmfree(pagetable, 0); uvmfree(pagetable, 0);
return 0; return 0;
@ -208,7 +208,7 @@ proc_pagetable(struct proc *p)
// Free a process's page table, and free the // Free a process's page table, and free the
// physical memory it refers to. // physical memory it refers to.
void void
proc_freepagetable(pagetable_t pagetable, uint64 sz) proc_freepagetable(pagetable_t pagetable, u64 sz)
{ {
uvmunmap(pagetable, TRAMPOLINE, 1, 0); uvmunmap(pagetable, TRAMPOLINE, 1, 0);
uvmunmap(pagetable, TRAPFRAME, 1, 0); uvmunmap(pagetable, TRAPFRAME, 1, 0);
@ -218,7 +218,7 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz)
// a user program that calls exec("/init") // a user program that calls exec("/init")
// assembled from ../user/initcode.S // assembled from ../user/initcode.S
// od -t xC ../user/initcode // od -t xC ../user/initcode
uchar initcode[] = { u8 initcode[] = {
0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x45, 0x02, 0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x45, 0x02,
0x97, 0x05, 0x00, 0x00, 0x93, 0x85, 0x35, 0x02, 0x97, 0x05, 0x00, 0x00, 0x93, 0x85, 0x35, 0x02,
0x93, 0x08, 0x70, 0x00, 0x73, 0x00, 0x00, 0x00, 0x93, 0x08, 0x70, 0x00, 0x73, 0x00, 0x00, 0x00,
@ -259,7 +259,7 @@ userinit(void)
int int
growproc(int n) growproc(int n)
{ {
uint64 sz; u64 sz;
struct proc *p = myproc(); struct proc *p = myproc();
sz = p->sz; sz = p->sz;
@ -388,7 +388,7 @@ exit(int status)
// Wait for a child process to exit and return its pid. // Wait for a child process to exit and return its pid.
// Return -1 if this process has no children. // Return -1 if this process has no children.
int int
wait(uint64 addr) wait(u64 addr)
{ {
struct proc *pp; struct proc *pp;
int havekids, pid; int havekids, pid;
@ -626,7 +626,7 @@ killed(struct proc *p)
// depending on usr_dst. // depending on usr_dst.
// Returns 0 on success, -1 on error. // Returns 0 on success, -1 on error.
int int
either_copyout(int user_dst, uint64 dst, void *src, uint64 len) either_copyout(int user_dst, u64 dst, void *src, u64 len)
{ {
struct proc *p = myproc(); struct proc *p = myproc();
if(user_dst){ if(user_dst){
@ -641,7 +641,7 @@ either_copyout(int user_dst, uint64 dst, void *src, uint64 len)
// depending on usr_src. // depending on usr_src.
// Returns 0 on success, -1 on error. // Returns 0 on success, -1 on error.
int int
either_copyin(void *dst, int user_src, uint64 src, uint64 len) either_copyin(void *dst, int user_src, u64 src, u64 len)
{ {
struct proc *p = myproc(); struct proc *p = myproc();
if(user_src){ if(user_src){

View file

@ -1,21 +1,21 @@
// Saved registers for kernel context switches. // Saved registers for kernel context switches.
struct context { struct context {
uint64 ra; u64 ra;
uint64 sp; u64 sp;
// callee-saved // callee-saved
uint64 s0; u64 s0;
uint64 s1; u64 s1;
uint64 s2; u64 s2;
uint64 s3; u64 s3;
uint64 s4; u64 s4;
uint64 s5; u64 s5;
uint64 s6; u64 s6;
uint64 s7; u64 s7;
uint64 s8; u64 s8;
uint64 s9; u64 s9;
uint64 s10; u64 s10;
uint64 s11; u64 s11;
}; };
// Per-CPU state. // Per-CPU state.
@ -41,42 +41,42 @@ extern struct cpu cpus[NCPU];
// return-to-user path via usertrapret() doesn't return through // return-to-user path via usertrapret() doesn't return through
// the entire kernel call stack. // the entire kernel call stack.
struct trapframe { struct trapframe {
/* 0 */ uint64 kernel_satp; // kernel page table /* 0 */ u64 kernel_satp; // kernel page table
/* 8 */ uint64 kernel_sp; // top of process's kernel stack /* 8 */ u64 kernel_sp; // top of process's kernel stack
/* 16 */ uint64 kernel_trap; // usertrap() /* 16 */ u64 kernel_trap; // usertrap()
/* 24 */ uint64 epc; // saved user program counter /* 24 */ u64 epc; // saved user program counter
/* 32 */ uint64 kernel_hartid; // saved kernel tp /* 32 */ u64 kernel_hartid; // saved kernel tp
/* 40 */ uint64 ra; /* 40 */ u64 ra;
/* 48 */ uint64 sp; /* 48 */ u64 sp;
/* 56 */ uint64 gp; /* 56 */ u64 gp;
/* 64 */ uint64 tp; /* 64 */ u64 tp;
/* 72 */ uint64 t0; /* 72 */ u64 t0;
/* 80 */ uint64 t1; /* 80 */ u64 t1;
/* 88 */ uint64 t2; /* 88 */ u64 t2;
/* 96 */ uint64 s0; /* 96 */ u64 s0;
/* 104 */ uint64 s1; /* 104 */ u64 s1;
/* 112 */ uint64 a0; /* 112 */ u64 a0;
/* 120 */ uint64 a1; /* 120 */ u64 a1;
/* 128 */ uint64 a2; /* 128 */ u64 a2;
/* 136 */ uint64 a3; /* 136 */ u64 a3;
/* 144 */ uint64 a4; /* 144 */ u64 a4;
/* 152 */ uint64 a5; /* 152 */ u64 a5;
/* 160 */ uint64 a6; /* 160 */ u64 a6;
/* 168 */ uint64 a7; /* 168 */ u64 a7;
/* 176 */ uint64 s2; /* 176 */ u64 s2;
/* 184 */ uint64 s3; /* 184 */ u64 s3;
/* 192 */ uint64 s4; /* 192 */ u64 s4;
/* 200 */ uint64 s5; /* 200 */ u64 s5;
/* 208 */ uint64 s6; /* 208 */ u64 s6;
/* 216 */ uint64 s7; /* 216 */ u64 s7;
/* 224 */ uint64 s8; /* 224 */ u64 s8;
/* 232 */ uint64 s9; /* 232 */ u64 s9;
/* 240 */ uint64 s10; /* 240 */ u64 s10;
/* 248 */ uint64 s11; /* 248 */ u64 s11;
/* 256 */ uint64 t3; /* 256 */ u64 t3;
/* 264 */ uint64 t4; /* 264 */ u64 t4;
/* 272 */ uint64 t5; /* 272 */ u64 t5;
/* 280 */ uint64 t6; /* 280 */ u64 t6;
}; };
enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
@ -96,8 +96,8 @@ struct proc {
struct proc *parent; // Parent process struct proc *parent; // Parent process
// these are private to the process, so p->lock need not be held. // these are private to the process, so p->lock need not be held.
uint64 kstack; // Virtual address of kernel stack u64 kstack; // Virtual address of kernel stack
uint64 sz; // Size of process memory (bytes) u64 sz; // Size of process memory (bytes)
pagetable_t pagetable; // User page table pagetable_t pagetable; // User page table
struct trapframe *trapframe; // data page for trampoline.S struct trapframe *trapframe; // data page for trampoline.S
struct context context; // swtch() here to run process struct context context; // swtch() here to run process

View file

@ -30,7 +30,7 @@ ramdiskrw(struct buf *b)
if(b->blockno >= FSSIZE) if(b->blockno >= FSSIZE)
panic("ramdiskrw: blockno too big"); panic("ramdiskrw: blockno too big");
uint64 diskaddr = b->blockno * BSIZE; u64 diskaddr = b->blockno * BSIZE;
char *addr = (char *)RAMDISK + diskaddr; char *addr = (char *)RAMDISK + diskaddr;
if(b->flags & B_DIRTY){ if(b->flags & B_DIRTY){

View file

@ -1,10 +1,10 @@
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
// which hart (core) is this? // which hart (core) is this?
static inline uint64 static inline u64
r_mhartid() r_mhartid()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, mhartid" : "=r" (x) ); asm volatile("csrr %0, mhartid" : "=r" (x) );
return x; return x;
} }
@ -17,16 +17,16 @@ r_mhartid()
#define MSTATUS_MPP_U (0L << 11) #define MSTATUS_MPP_U (0L << 11)
#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable. #define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable.
static inline uint64 static inline u64
r_mstatus() r_mstatus()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, mstatus" : "=r" (x) ); asm volatile("csrr %0, mstatus" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_mstatus(uint64 x) w_mstatus(u64 x)
{ {
asm volatile("csrw mstatus, %0" : : "r" (x)); asm volatile("csrw mstatus, %0" : : "r" (x));
} }
@ -35,7 +35,7 @@ w_mstatus(uint64 x)
// instruction address to which a return from // instruction address to which a return from
// exception will go. // exception will go.
static inline void static inline void
w_mepc(uint64 x) w_mepc(u64 x)
{ {
asm volatile("csrw mepc, %0" : : "r" (x)); asm volatile("csrw mepc, %0" : : "r" (x));
} }
@ -48,31 +48,31 @@ w_mepc(uint64 x)
#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable #define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable
#define SSTATUS_UIE (1L << 0) // User Interrupt Enable #define SSTATUS_UIE (1L << 0) // User Interrupt Enable
static inline uint64 static inline u64
r_sstatus() r_sstatus()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, sstatus" : "=r" (x) ); asm volatile("csrr %0, sstatus" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_sstatus(uint64 x) w_sstatus(u64 x)
{ {
asm volatile("csrw sstatus, %0" : : "r" (x)); asm volatile("csrw sstatus, %0" : : "r" (x));
} }
// Supervisor Interrupt Pending // Supervisor Interrupt Pending
static inline uint64 static inline u64
r_sip() r_sip()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, sip" : "=r" (x) ); asm volatile("csrr %0, sip" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_sip(uint64 x) w_sip(u64 x)
{ {
asm volatile("csrw sip, %0" : : "r" (x)); asm volatile("csrw sip, %0" : : "r" (x));
} }
@ -81,16 +81,16 @@ w_sip(uint64 x)
#define SIE_SEIE (1L << 9) // external #define SIE_SEIE (1L << 9) // external
#define SIE_STIE (1L << 5) // timer #define SIE_STIE (1L << 5) // timer
#define SIE_SSIE (1L << 1) // software #define SIE_SSIE (1L << 1) // software
static inline uint64 static inline u64
r_sie() r_sie()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, sie" : "=r" (x) ); asm volatile("csrr %0, sie" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_sie(uint64 x) w_sie(u64 x)
{ {
asm volatile("csrw sie, %0" : : "r" (x)); asm volatile("csrw sie, %0" : : "r" (x));
} }
@ -99,16 +99,16 @@ w_sie(uint64 x)
#define MIE_MEIE (1L << 11) // external #define MIE_MEIE (1L << 11) // external
#define MIE_MTIE (1L << 7) // timer #define MIE_MTIE (1L << 7) // timer
#define MIE_MSIE (1L << 3) // software #define MIE_MSIE (1L << 3) // software
static inline uint64 static inline u64
r_mie() r_mie()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, mie" : "=r" (x) ); asm volatile("csrr %0, mie" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_mie(uint64 x) w_mie(u64 x)
{ {
asm volatile("csrw mie, %0" : : "r" (x)); asm volatile("csrw mie, %0" : : "r" (x));
} }
@ -117,45 +117,45 @@ w_mie(uint64 x)
// instruction address to which a return from // instruction address to which a return from
// exception will go. // exception will go.
static inline void static inline void
w_sepc(uint64 x) w_sepc(u64 x)
{ {
asm volatile("csrw sepc, %0" : : "r" (x)); asm volatile("csrw sepc, %0" : : "r" (x));
} }
static inline uint64 static inline u64
r_sepc() r_sepc()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, sepc" : "=r" (x) ); asm volatile("csrr %0, sepc" : "=r" (x) );
return x; return x;
} }
// Machine Exception Delegation // Machine Exception Delegation
static inline uint64 static inline u64
r_medeleg() r_medeleg()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, medeleg" : "=r" (x) ); asm volatile("csrr %0, medeleg" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_medeleg(uint64 x) w_medeleg(u64 x)
{ {
asm volatile("csrw medeleg, %0" : : "r" (x)); asm volatile("csrw medeleg, %0" : : "r" (x));
} }
// Machine Interrupt Delegation // Machine Interrupt Delegation
static inline uint64 static inline u64
r_mideleg() r_mideleg()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, mideleg" : "=r" (x) ); asm volatile("csrr %0, mideleg" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_mideleg(uint64 x) w_mideleg(u64 x)
{ {
asm volatile("csrw mideleg, %0" : : "r" (x)); asm volatile("csrw mideleg, %0" : : "r" (x));
} }
@ -163,35 +163,35 @@ w_mideleg(uint64 x)
// Supervisor Trap-Vector Base Address // Supervisor Trap-Vector Base Address
// low two bits are mode. // low two bits are mode.
static inline void static inline void
w_stvec(uint64 x) w_stvec(u64 x)
{ {
asm volatile("csrw stvec, %0" : : "r" (x)); asm volatile("csrw stvec, %0" : : "r" (x));
} }
static inline uint64 static inline u64
r_stvec() r_stvec()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, stvec" : "=r" (x) ); asm volatile("csrr %0, stvec" : "=r" (x) );
return x; return x;
} }
// Machine-mode interrupt vector // Machine-mode interrupt vector
static inline void static inline void
w_mtvec(uint64 x) w_mtvec(u64 x)
{ {
asm volatile("csrw mtvec, %0" : : "r" (x)); asm volatile("csrw mtvec, %0" : : "r" (x));
} }
// Physical Memory Protection // Physical Memory Protection
static inline void static inline void
w_pmpcfg0(uint64 x) w_pmpcfg0(u64 x)
{ {
asm volatile("csrw pmpcfg0, %0" : : "r" (x)); asm volatile("csrw pmpcfg0, %0" : : "r" (x));
} }
static inline void static inline void
w_pmpaddr0(uint64 x) w_pmpaddr0(u64 x)
{ {
asm volatile("csrw pmpaddr0, %0" : : "r" (x)); asm volatile("csrw pmpaddr0, %0" : : "r" (x));
} }
@ -199,68 +199,68 @@ w_pmpaddr0(uint64 x)
// use riscv's sv39 page table scheme. // use riscv's sv39 page table scheme.
#define SATP_SV39 (8L << 60) #define SATP_SV39 (8L << 60)
#define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12)) #define MAKE_SATP(pagetable) (SATP_SV39 | (((u64)pagetable) >> 12))
// supervisor address translation and protection; // supervisor address translation and protection;
// holds the address of the page table. // holds the address of the page table.
static inline void static inline void
w_satp(uint64 x) w_satp(u64 x)
{ {
asm volatile("csrw satp, %0" : : "r" (x)); asm volatile("csrw satp, %0" : : "r" (x));
} }
static inline uint64 static inline u64
r_satp() r_satp()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, satp" : "=r" (x) ); asm volatile("csrr %0, satp" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_mscratch(uint64 x) w_mscratch(u64 x)
{ {
asm volatile("csrw mscratch, %0" : : "r" (x)); asm volatile("csrw mscratch, %0" : : "r" (x));
} }
// Supervisor Trap Cause // Supervisor Trap Cause
static inline uint64 static inline u64
r_scause() r_scause()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, scause" : "=r" (x) ); asm volatile("csrr %0, scause" : "=r" (x) );
return x; return x;
} }
// Supervisor Trap Value // Supervisor Trap Value
static inline uint64 static inline u64
r_stval() r_stval()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, stval" : "=r" (x) ); asm volatile("csrr %0, stval" : "=r" (x) );
return x; return x;
} }
// Machine-mode Counter-Enable // Machine-mode Counter-Enable
static inline void static inline void
w_mcounteren(uint64 x) w_mcounteren(u64 x)
{ {
asm volatile("csrw mcounteren, %0" : : "r" (x)); asm volatile("csrw mcounteren, %0" : : "r" (x));
} }
static inline uint64 static inline u64
r_mcounteren() r_mcounteren()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, mcounteren" : "=r" (x) ); asm volatile("csrr %0, mcounteren" : "=r" (x) );
return x; return x;
} }
// machine-mode cycle counter // machine-mode cycle counter
static inline uint64 static inline u64
r_time() r_time()
{ {
uint64 x; u64 x;
asm volatile("csrr %0, time" : "=r" (x) ); asm volatile("csrr %0, time" : "=r" (x) );
return x; return x;
} }
@ -283,38 +283,38 @@ intr_off()
static inline int static inline int
intr_get() intr_get()
{ {
uint64 x = r_sstatus(); u64 x = r_sstatus();
return (x & SSTATUS_SIE) != 0; return (x & SSTATUS_SIE) != 0;
} }
static inline uint64 static inline u64
r_sp() r_sp()
{ {
uint64 x; u64 x;
asm volatile("mv %0, sp" : "=r" (x) ); asm volatile("mv %0, sp" : "=r" (x) );
return x; return x;
} }
// read and write tp, the thread pointer, which xv6 uses to hold // read and write tp, the thread pointer, which xv6 uses to hold
// this core's hartid (core number), the index into cpus[]. // this core's hartid (core number), the index into cpus[].
static inline uint64 static inline u64
r_tp() r_tp()
{ {
uint64 x; u64 x;
asm volatile("mv %0, tp" : "=r" (x) ); asm volatile("mv %0, tp" : "=r" (x) );
return x; return x;
} }
static inline void static inline void
w_tp(uint64 x) w_tp(u64 x)
{ {
asm volatile("mv tp, %0" : : "r" (x)); asm volatile("mv tp, %0" : : "r" (x));
} }
static inline uint64 static inline u64
r_ra() r_ra()
{ {
uint64 x; u64 x;
asm volatile("mv %0, ra" : "=r" (x) ); asm volatile("mv %0, ra" : "=r" (x) );
return x; return x;
} }
@ -327,8 +327,8 @@ sfence_vma()
asm volatile("sfence.vma zero, zero"); asm volatile("sfence.vma zero, zero");
} }
typedef uint64 pte_t; typedef u64 pte_t;
typedef uint64 *pagetable_t; // 512 PTEs typedef u64 *pagetable_t; // 512 PTEs
#endif // __ASSEMBLER__ #endif // __ASSEMBLER__
@ -345,7 +345,7 @@ typedef uint64 *pagetable_t; // 512 PTEs
#define PTE_U (1L << 4) // user can access #define PTE_U (1L << 4) // user can access
// shift a physical address to the right place for a PTE. // shift a physical address to the right place for a PTE.
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10) #define PA2PTE(pa) ((((u64)pa) >> 12) << 10)
#define PTE2PA(pte) (((pte) >> 10) << 12) #define PTE2PA(pte) (((pte) >> 10) << 12)
@ -354,7 +354,7 @@ typedef uint64 *pagetable_t; // 512 PTEs
// extract the three 9-bit page table indices from a virtual address. // extract the three 9-bit page table indices from a virtual address.
#define PXMASK 0x1FF // 9 bits #define PXMASK 0x1FF // 9 bits
#define PXSHIFT(level) (PGSHIFT+(9*(level))) #define PXSHIFT(level) (PGSHIFT+(9*(level)))
#define PX(level, va) ((((uint64) (va)) >> PXSHIFT(level)) & PXMASK) #define PX(level, va) ((((u64) (va)) >> PXSHIFT(level)) & PXMASK)
// one beyond the highest possible virtual address. // one beyond the highest possible virtual address.
// MAXVA is actually one bit less than the max allowed by // MAXVA is actually one bit less than the max allowed by

View file

@ -1,6 +1,6 @@
// Long-term locks for processes // Long-term locks for processes
struct sleeplock { struct sleeplock {
uint locked; // Is the lock held? u32 locked; // Is the lock held?
struct spinlock lk; // spinlock protecting this sleep lock struct spinlock lk; // spinlock protecting this sleep lock
// For debugging: // For debugging:

View file

@ -1,6 +1,6 @@
// Mutual exclusion lock. // Mutual exclusion lock.
struct spinlock { struct spinlock {
uint locked; // Is the lock held? u32 locked; // Is the lock held?
// For debugging: // For debugging:
char *name; // Name of lock. char *name; // Name of lock.

View file

@ -11,7 +11,7 @@ void timerinit();
__attribute__ ((aligned (16))) char stack0[4096 * NCPU]; __attribute__ ((aligned (16))) char stack0[4096 * NCPU];
// a scratch area per CPU for machine-mode timer interrupts. // a scratch area per CPU for machine-mode timer interrupts.
uint64 timer_scratch[NCPU][5]; u64 timer_scratch[NCPU][5];
// assembly code in kernelvec.S for machine-mode timer interrupt. // assembly code in kernelvec.S for machine-mode timer interrupt.
extern void timervec(); extern void timervec();
@ -28,7 +28,7 @@ start()
// set M Exception Program Counter to main, for mret. // set M Exception Program Counter to main, for mret.
// requires gcc -mcmodel=medany // requires gcc -mcmodel=medany
w_mepc((uint64)main); w_mepc((u64)main);
// disable paging for now. // disable paging for now.
w_satp(0); w_satp(0);
@ -67,19 +67,19 @@ timerinit()
// ask the CLINT for a timer interrupt. // ask the CLINT for a timer interrupt.
int interval = 1000000; // cycles; about 1/10th second in qemu. int interval = 1000000; // cycles; about 1/10th second in qemu.
*(uint64*)CLINT_MTIMECMP(id) = *(uint64*)CLINT_MTIME + interval; *(u64*)CLINT_MTIMECMP(id) = *(u64*)CLINT_MTIME + interval;
// prepare information in scratch[] for timervec. // prepare information in scratch[] for timervec.
// scratch[0..2] : space for timervec to save registers. // scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register. // scratch[3] : address of CLINT MTIMECMP register.
// scratch[4] : desired interval (in cycles) between timer interrupts. // scratch[4] : desired interval (in cycles) between timer interrupts.
uint64 *scratch = &timer_scratch[id][0]; u64 *scratch = &timer_scratch[id][0];
scratch[3] = CLINT_MTIMECMP(id); scratch[3] = CLINT_MTIMECMP(id);
scratch[4] = interval; scratch[4] = interval;
w_mscratch((uint64)scratch); w_mscratch((u64)scratch);
// set the machine-mode trap handler. // set the machine-mode trap handler.
w_mtvec((uint64)timervec); w_mtvec((u64)timervec);
// enable machine-mode interrupts. // enable machine-mode interrupts.
w_mstatus(r_mstatus() | MSTATUS_MIE); w_mstatus(r_mstatus() | MSTATUS_MIE);

View file

@ -4,8 +4,8 @@
struct stat { struct stat {
int dev; // File system's disk device int dev; // File system's disk device
uint ino; // Inode number u32 ino; // Inode number
short type; // Type of file short type; // Type of file
short nlink; // Number of links to file short nlink; // Number of links to file
uint64 size; // Size of file in bytes u64 size; // Size of file in bytes
}; };

View file

@ -1,7 +1,7 @@
#include "types.h" #include "types.h"
void* void*
memset(void *dst, int c, uint n) memset(void *dst, int c, u32 n)
{ {
char *cdst = (char *) dst; char *cdst = (char *) dst;
int i; int i;
@ -12,9 +12,9 @@ memset(void *dst, int c, uint n)
} }
int int
memcmp(const void *v1, const void *v2, uint n) memcmp(const void *v1, const void *v2, u32 n)
{ {
const uchar *s1, *s2; const u8 *s1, *s2;
s1 = v1; s1 = v1;
s2 = v2; s2 = v2;
@ -28,7 +28,7 @@ memcmp(const void *v1, const void *v2, uint n)
} }
void* void*
memmove(void *dst, const void *src, uint n) memmove(void *dst, const void *src, u32 n)
{ {
const char *s; const char *s;
char *d; char *d;
@ -52,19 +52,19 @@ memmove(void *dst, const void *src, uint n)
// memcpy exists to placate GCC. Use memmove. // memcpy exists to placate GCC. Use memmove.
void* void*
memcpy(void *dst, const void *src, uint n) memcpy(void *dst, const void *src, u32 n)
{ {
return memmove(dst, src, n); return memmove(dst, src, n);
} }
int int
strncmp(const char *p, const char *q, uint n) strncmp(const char *p, const char *q, u32 n)
{ {
while(n > 0 && *p && *p == *q) while(n > 0 && *p && *p == *q)
n--, p++, q++; n--, p++, q++;
if(n == 0) if(n == 0)
return 0; return 0;
return (uchar)*p - (uchar)*q; return (u8)*p - (u8)*q;
} }
char* char*

View file

@ -7,12 +7,12 @@
#include "syscall.h" #include "syscall.h"
#include "defs.h" #include "defs.h"
// Fetch the uint64 at addr from the current process. // Fetch the u64 at addr from the current process.
int int
fetchaddr(uint64 addr, uint64 *ip) fetchaddr(u64 addr, u64 *ip)
{ {
struct proc *p = myproc(); struct proc *p = myproc();
if(addr >= p->sz || addr+sizeof(uint64) > p->sz) // both tests needed, in case of overflow if(addr >= p->sz || addr+sizeof(u64) > p->sz) // both tests needed, in case of overflow
return -1; return -1;
if(copyin(p->pagetable, (char *)ip, addr, sizeof(*ip)) != 0) if(copyin(p->pagetable, (char *)ip, addr, sizeof(*ip)) != 0)
return -1; return -1;
@ -22,7 +22,7 @@ fetchaddr(uint64 addr, uint64 *ip)
// Fetch the nul-terminated string at addr from the current process. // Fetch the nul-terminated string at addr from the current process.
// Returns length of string, not including nul, or -1 for error. // Returns length of string, not including nul, or -1 for error.
int int
fetchstr(uint64 addr, char *buf, int max) fetchstr(u64 addr, char *buf, int max)
{ {
struct proc *p = myproc(); struct proc *p = myproc();
if(copyinstr(p->pagetable, buf, addr, max) < 0) if(copyinstr(p->pagetable, buf, addr, max) < 0)
@ -30,7 +30,7 @@ fetchstr(uint64 addr, char *buf, int max)
return strlen(buf); return strlen(buf);
} }
static uint64 static u64
argraw(int n) argraw(int n)
{ {
struct proc *p = myproc(); struct proc *p = myproc();
@ -63,7 +63,7 @@ argint(int n, int *ip)
// Doesn't check for legality, since // Doesn't check for legality, since
// copyin/copyout will do that. // copyin/copyout will do that.
void void
argaddr(int n, uint64 *ip) argaddr(int n, u64 *ip)
{ {
*ip = argraw(n); *ip = argraw(n);
} }
@ -74,34 +74,37 @@ argaddr(int n, uint64 *ip)
int int
argstr(int n, char *buf, int max) argstr(int n, char *buf, int max)
{ {
uint64 addr; u64 addr;
argaddr(n, &addr); argaddr(n, &addr);
return fetchstr(addr, buf, max); return fetchstr(addr, buf, max);
} }
extern uint64 sys_fork(void); // Prototypes for the functions that handle system calls.
extern uint64 sys_exit(void); extern u64 sys_fork(void);
extern uint64 sys_wait(void); extern u64 sys_exit(void);
extern uint64 sys_pipe(void); extern u64 sys_wait(void);
extern uint64 sys_read(void); extern u64 sys_pipe(void);
extern uint64 sys_kill(void); extern u64 sys_read(void);
extern uint64 sys_exec(void); extern u64 sys_kill(void);
extern uint64 sys_fstat(void); extern u64 sys_exec(void);
extern uint64 sys_chdir(void); extern u64 sys_fstat(void);
extern uint64 sys_dup(void); extern u64 sys_chdir(void);
extern uint64 sys_getpid(void); extern u64 sys_dup(void);
extern uint64 sys_sbrk(void); extern u64 sys_getpid(void);
extern uint64 sys_sleep(void); extern u64 sys_sbrk(void);
extern uint64 sys_uptime(void); extern u64 sys_sleep(void);
extern uint64 sys_open(void); extern u64 sys_uptime(void);
extern uint64 sys_write(void); extern u64 sys_open(void);
extern uint64 sys_mknod(void); extern u64 sys_write(void);
extern uint64 sys_unlink(void); extern u64 sys_mknod(void);
extern uint64 sys_link(void); extern u64 sys_unlink(void);
extern uint64 sys_mkdir(void); extern u64 sys_link(void);
extern uint64 sys_close(void); extern u64 sys_mkdir(void);
extern u64 sys_close(void);
static uint64 (*syscalls[])(void) = { // An array mapping syscall numbers from syscall.h
// to the function that handles the system call.
static u64 (*syscalls[])(void) = {
[SYS_fork] sys_fork, [SYS_fork] sys_fork,
[SYS_exit] sys_exit, [SYS_exit] sys_exit,
[SYS_wait] sys_wait, [SYS_wait] sys_wait,
@ -133,6 +136,8 @@ syscall(void)
num = p->trapframe->a7; num = p->trapframe->a7;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
// Use num to lookup the system call function for num, call it,
// and store its return value in p->trapframe->a0
p->trapframe->a0 = syscalls[num](); p->trapframe->a0 = syscalls[num]();
} else { } else {
printf("%d %s: unknown sys call %d\n", printf("%d %s: unknown sys call %d\n",

View file

@ -51,7 +51,7 @@ fdalloc(struct file *f)
return -1; return -1;
} }
uint64 u64
sys_dup(void) sys_dup(void)
{ {
struct file *f; struct file *f;
@ -65,12 +65,12 @@ sys_dup(void)
return fd; return fd;
} }
uint64 u64
sys_read(void) sys_read(void)
{ {
struct file *f; struct file *f;
int n; int n;
uint64 p; u64 p;
argaddr(1, &p); argaddr(1, &p);
argint(2, &n); argint(2, &n);
@ -79,12 +79,12 @@ sys_read(void)
return fileread(f, p, n); return fileread(f, p, n);
} }
uint64 u64
sys_write(void) sys_write(void)
{ {
struct file *f; struct file *f;
int n; int n;
uint64 p; u64 p;
argaddr(1, &p); argaddr(1, &p);
argint(2, &n); argint(2, &n);
@ -94,7 +94,7 @@ sys_write(void)
return filewrite(f, p, n); return filewrite(f, p, n);
} }
uint64 u64
sys_close(void) sys_close(void)
{ {
int fd; int fd;
@ -107,11 +107,11 @@ sys_close(void)
return 0; return 0;
} }
uint64 u64
sys_fstat(void) sys_fstat(void)
{ {
struct file *f; struct file *f;
uint64 st; // user pointer to struct stat u64 st; // user pointer to struct stat
argaddr(1, &st); argaddr(1, &st);
if(argfd(0, 0, &f) < 0) if(argfd(0, 0, &f) < 0)
@ -120,7 +120,7 @@ sys_fstat(void)
} }
// Create the path new as a link to the same inode as old. // Create the path new as a link to the same inode as old.
uint64 u64
sys_link(void) sys_link(void)
{ {
char name[DIRSIZ], new[MAXPATH], old[MAXPATH]; char name[DIRSIZ], new[MAXPATH], old[MAXPATH];
@ -177,7 +177,7 @@ isdirempty(struct inode *dp)
struct dirent de; struct dirent de;
for(off=2*sizeof(de); off<dp->size; off+=sizeof(de)){ for(off=2*sizeof(de); off<dp->size; off+=sizeof(de)){
if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) if(readi(dp, 0, (u64)&de, off, sizeof(de)) != sizeof(de))
panic("isdirempty: readi"); panic("isdirempty: readi");
if(de.inum != 0) if(de.inum != 0)
return 0; return 0;
@ -185,13 +185,13 @@ isdirempty(struct inode *dp)
return 1; return 1;
} }
uint64 u64
sys_unlink(void) sys_unlink(void)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
struct dirent de; struct dirent de;
char name[DIRSIZ], path[MAXPATH]; char name[DIRSIZ], path[MAXPATH];
uint off; u32 off;
if(argstr(0, path, MAXPATH) < 0) if(argstr(0, path, MAXPATH) < 0)
return -1; return -1;
@ -220,7 +220,7 @@ sys_unlink(void)
} }
memset(&de, 0, sizeof(de)); memset(&de, 0, sizeof(de));
if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) if(writei(dp, 0, (u64)&de, off, sizeof(de)) != sizeof(de))
panic("unlink: writei"); panic("unlink: writei");
if(ip->type == T_DIR){ if(ip->type == T_DIR){
dp->nlink--; dp->nlink--;
@ -262,8 +262,10 @@ create(char *path, short type, short major, short minor)
return 0; return 0;
} }
if((ip = ialloc(dp->dev, type)) == 0) if((ip = ialloc(dp->dev, type)) == 0){
panic("create: ialloc"); iunlockput(dp);
return 0;
}
ilock(ip); ilock(ip);
ip->major = major; ip->major = major;
@ -299,7 +301,7 @@ create(char *path, short type, short major, short minor)
return 0; return 0;
} }
uint64 u64
sys_open(void) sys_open(void)
{ {
char path[MAXPATH]; char path[MAXPATH];
@ -368,7 +370,7 @@ sys_open(void)
return fd; return fd;
} }
uint64 u64
sys_mkdir(void) sys_mkdir(void)
{ {
char path[MAXPATH]; char path[MAXPATH];
@ -384,7 +386,7 @@ sys_mkdir(void)
return 0; return 0;
} }
uint64 u64
sys_mknod(void) sys_mknod(void)
{ {
struct inode *ip; struct inode *ip;
@ -404,7 +406,7 @@ sys_mknod(void)
return 0; return 0;
} }
uint64 u64
sys_chdir(void) sys_chdir(void)
{ {
char path[MAXPATH]; char path[MAXPATH];
@ -429,12 +431,12 @@ sys_chdir(void)
return 0; return 0;
} }
uint64 u64
sys_exec(void) sys_exec(void)
{ {
char path[MAXPATH], *argv[MAXARG]; char path[MAXPATH], *argv[MAXARG];
int i; int i;
uint64 uargv, uarg; u64 uargv, uarg;
argaddr(1, &uargv); argaddr(1, &uargv);
if(argstr(0, path, MAXPATH) < 0) { if(argstr(0, path, MAXPATH) < 0) {
@ -445,7 +447,7 @@ sys_exec(void)
if(i >= NELEM(argv)){ if(i >= NELEM(argv)){
goto bad; goto bad;
} }
if(fetchaddr(uargv+sizeof(uint64)*i, (uint64*)&uarg) < 0){ if(fetchaddr(uargv+sizeof(u64)*i, (u64*)&uarg) < 0){
goto bad; goto bad;
} }
if(uarg == 0){ if(uarg == 0){
@ -472,10 +474,10 @@ sys_exec(void)
return -1; return -1;
} }
uint64 u64
sys_pipe(void) sys_pipe(void)
{ {
uint64 fdarray; // user pointer to array of two integers u64 fdarray; // user pointer to array of two integers
struct file *rf, *wf; struct file *rf, *wf;
int fd0, fd1; int fd0, fd1;
struct proc *p = myproc(); struct proc *p = myproc();

View file

@ -6,7 +6,7 @@
#include "spinlock.h" #include "spinlock.h"
#include "proc.h" #include "proc.h"
uint64 u64
sys_exit(void) sys_exit(void)
{ {
int n; int n;
@ -15,30 +15,30 @@ sys_exit(void)
return 0; // not reached return 0; // not reached
} }
uint64 u64
sys_getpid(void) sys_getpid(void)
{ {
return myproc()->pid; return myproc()->pid;
} }
uint64 u64
sys_fork(void) sys_fork(void)
{ {
return fork(); return fork();
} }
uint64 u64
sys_wait(void) sys_wait(void)
{ {
uint64 p; u64 p;
argaddr(0, &p); argaddr(0, &p);
return wait(p); return wait(p);
} }
uint64 u64
sys_sbrk(void) sys_sbrk(void)
{ {
uint64 addr; u64 addr;
int n; int n;
argint(0, &n); argint(0, &n);
@ -48,11 +48,11 @@ sys_sbrk(void)
return addr; return addr;
} }
uint64 u64
sys_sleep(void) sys_sleep(void)
{ {
int n; int n;
uint ticks0; u32 ticks0;
argint(0, &n); argint(0, &n);
acquire(&tickslock); acquire(&tickslock);
@ -68,7 +68,7 @@ sys_sleep(void)
return 0; return 0;
} }
uint64 u64
sys_kill(void) sys_kill(void)
{ {
int pid; int pid;
@ -79,10 +79,10 @@ sys_kill(void)
// return how many clock tick interrupts have occurred // return how many clock tick interrupts have occurred
// since start. // since start.
uint64 u64
sys_uptime(void) sys_uptime(void)
{ {
uint xticks; u32 xticks;
acquire(&tickslock); acquire(&tickslock);
xticks = ticks; xticks = ticks;

View file

@ -80,9 +80,18 @@ uservec:
# load the address of usertrap(), from p->trapframe->kernel_trap # load the address of usertrap(), from p->trapframe->kernel_trap
ld t0, 16(a0) ld t0, 16(a0)
# load the kernel page table, from p->trapframe->kernel_satp
# fetch the kernel page table address, from p->trapframe->kernel_satp.
ld t1, 0(a0) ld t1, 0(a0)
# wait for any previous memory operations to complete, so that
# they use the user page table.
sfence.vma zero, zero
# install the kernel page table.
csrw satp, t1 csrw satp, t1
# flush now-stale user entries from the TLB.
sfence.vma zero, zero sfence.vma zero, zero
# jump to usertrap(), which does not return # jump to usertrap(), which does not return
@ -96,6 +105,7 @@ userret:
# a0: user page table, for satp. # a0: user page table, for satp.
# switch to the user page table. # switch to the user page table.
sfence.vma zero, zero
csrw satp, a0 csrw satp, a0
sfence.vma zero, zero sfence.vma zero, zero

View file

@ -7,7 +7,7 @@
#include "defs.h" #include "defs.h"
struct spinlock tickslock; struct spinlock tickslock;
uint ticks; u32 ticks;
extern char trampoline[], uservec[], userret[]; extern char trampoline[], uservec[], userret[];
@ -26,7 +26,7 @@ trapinit(void)
void void
trapinithart(void) trapinithart(void)
{ {
w_stvec((uint64)kernelvec); w_stvec((u64)kernelvec);
} }
// //
@ -43,7 +43,7 @@ usertrap(void)
// send interrupts and exceptions to kerneltrap(), // send interrupts and exceptions to kerneltrap(),
// since we're now in the kernel. // since we're now in the kernel.
w_stvec((uint64)kernelvec); w_stvec((u64)kernelvec);
struct proc *p = myproc(); struct proc *p = myproc();
@ -97,14 +97,14 @@ usertrapret(void)
intr_off(); intr_off();
// send syscalls, interrupts, and exceptions to uservec in trampoline.S // send syscalls, interrupts, and exceptions to uservec in trampoline.S
uint64 trampoline_uservec = TRAMPOLINE + (uservec - trampoline); u64 trampoline_uservec = TRAMPOLINE + (uservec - trampoline);
w_stvec(trampoline_uservec); w_stvec(trampoline_uservec);
// set up trapframe values that uservec will need when // set up trapframe values that uservec will need when
// the process next traps into the kernel. // the process next traps into the kernel.
p->trapframe->kernel_satp = r_satp(); // kernel page table p->trapframe->kernel_satp = r_satp(); // kernel page table
p->trapframe->kernel_sp = p->kstack + PGSIZE; // process's kernel stack p->trapframe->kernel_sp = p->kstack + PGSIZE; // process's kernel stack
p->trapframe->kernel_trap = (uint64)usertrap; p->trapframe->kernel_trap = (u64)usertrap;
p->trapframe->kernel_hartid = r_tp(); // hartid for cpuid() p->trapframe->kernel_hartid = r_tp(); // hartid for cpuid()
// set up the registers that trampoline.S's sret will use // set up the registers that trampoline.S's sret will use
@ -120,13 +120,13 @@ usertrapret(void)
w_sepc(p->trapframe->epc); w_sepc(p->trapframe->epc);
// tell trampoline.S the user page table to switch to. // tell trampoline.S the user page table to switch to.
uint64 satp = MAKE_SATP(p->pagetable); u64 satp = MAKE_SATP(p->pagetable);
// jump to userret in trampoline.S at the top of memory, which // jump to userret in trampoline.S at the top of memory, which
// switches to the user page table, restores user registers, // switches to the user page table, restores user registers,
// and switches to user mode with sret. // and switches to user mode with sret.
uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline); u64 trampoline_userret = TRAMPOLINE + (userret - trampoline);
((void (*)(uint64))trampoline_userret)(satp); ((void (*)(u64))trampoline_userret)(satp);
} }
// interrupts and exceptions from kernel code go here via kernelvec, // interrupts and exceptions from kernel code go here via kernelvec,
@ -135,9 +135,9 @@ void
kerneltrap() kerneltrap()
{ {
int which_dev = 0; int which_dev = 0;
uint64 sepc = r_sepc(); u64 sepc = r_sepc();
uint64 sstatus = r_sstatus(); u64 sstatus = r_sstatus();
uint64 scause = r_scause(); u64 scause = r_scause();
if((sstatus & SSTATUS_SPP) == 0) if((sstatus & SSTATUS_SPP) == 0)
panic("kerneltrap: not from supervisor mode"); panic("kerneltrap: not from supervisor mode");
@ -177,7 +177,7 @@ clockintr()
int int
devintr() devintr()
{ {
uint64 scause = r_scause(); u64 scause = r_scause();
if((scause & 0x8000000000000000L) && if((scause & 0x8000000000000000L) &&
(scause & 0xff) == 9){ (scause & 0xff) == 9){

View file

@ -1,10 +1,6 @@
typedef unsigned int uint; typedef unsigned char u8;
typedef unsigned short ushort; typedef unsigned short u16;
typedef unsigned char uchar; typedef unsigned int u32;
typedef unsigned long u64;
typedef unsigned char uint8; typedef u64 pde_t;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long uint64;
typedef uint64 pde_t;

View file

@ -42,8 +42,8 @@
struct spinlock uart_tx_lock; struct spinlock uart_tx_lock;
#define UART_TX_BUF_SIZE 32 #define UART_TX_BUF_SIZE 32
char uart_tx_buf[UART_TX_BUF_SIZE]; char uart_tx_buf[UART_TX_BUF_SIZE];
uint64 uart_tx_w; // write next to uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] u64 uart_tx_w; // write next to uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE]
uint64 uart_tx_r; // read next from uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE] u64 uart_tx_r; // read next from uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE]
extern volatile int panicked; // from printf.c extern volatile int panicked; // from printf.c

View file

@ -51,32 +51,32 @@
// a single descriptor, from the spec. // a single descriptor, from the spec.
struct virtq_desc { struct virtq_desc {
uint64 addr; u64 addr;
uint32 len; u32 len;
uint16 flags; u16 flags;
uint16 next; u16 next;
}; };
#define VRING_DESC_F_NEXT 1 // chained with another descriptor #define VRING_DESC_F_NEXT 1 // chained with another descriptor
#define VRING_DESC_F_WRITE 2 // device writes (vs read) #define VRING_DESC_F_WRITE 2 // device writes (vs read)
// the (entire) avail ring, from the spec. // the (entire) avail ring, from the spec.
struct virtq_avail { struct virtq_avail {
uint16 flags; // always zero u16 flags; // always zero
uint16 idx; // driver will write ring[idx] next u16 idx; // driver will write ring[idx] next
uint16 ring[NUM]; // descriptor numbers of chain heads u16 ring[NUM]; // descriptor numbers of chain heads
uint16 unused; u16 unused;
}; };
// one entry in the "used" ring, with which the // one entry in the "used" ring, with which the
// device tells the driver about completed requests. // device tells the driver about completed requests.
struct virtq_used_elem { struct virtq_used_elem {
uint32 id; // index of start of completed descriptor chain u32 id; // index of start of completed descriptor chain
uint32 len; u32 len;
}; };
struct virtq_used { struct virtq_used {
uint16 flags; // always zero u16 flags; // always zero
uint16 idx; // device increments when it adds a ring[] entry u16 idx; // device increments when it adds a ring[] entry
struct virtq_used_elem ring[NUM]; struct virtq_used_elem ring[NUM];
}; };
@ -90,7 +90,7 @@ struct virtq_used {
// to be followed by two more descriptors containing // to be followed by two more descriptors containing
// the block, and a one-byte status. // the block, and a one-byte status.
struct virtio_blk_req { struct virtio_blk_req {
uint32 type; // VIRTIO_BLK_T_IN or ..._OUT u32 type; // VIRTIO_BLK_T_IN or ..._OUT
uint32 reserved; u32 reserved;
uint64 sector; u64 sector;
}; };

View file

@ -17,7 +17,7 @@
#include "virtio.h" #include "virtio.h"
// the address of virtio mmio register r. // the address of virtio mmio register r.
#define R(r) ((volatile uint32 *)(VIRTIO0 + (r))) #define R(r) ((volatile u32 *)(VIRTIO0 + (r)))
static struct disk { static struct disk {
// a set (not a ring) of DMA descriptors, with which the // a set (not a ring) of DMA descriptors, with which the
@ -40,7 +40,7 @@ static struct disk {
// our own book-keeping. // our own book-keeping.
char free[NUM]; // is a descriptor free? char free[NUM]; // is a descriptor free?
uint16 used_idx; // we've looked this far in used[2..NUM]. u16 used_idx; // we've looked this far in used[2..NUM].
// track info about in-flight operations, // track info about in-flight operations,
// for use when completion interrupt arrives. // for use when completion interrupt arrives.
@ -61,7 +61,7 @@ static struct disk {
void void
virtio_disk_init(void) virtio_disk_init(void)
{ {
uint32 status = 0; u32 status = 0;
initlock(&disk.vdisk_lock, "virtio_disk"); initlock(&disk.vdisk_lock, "virtio_disk");
@ -84,7 +84,7 @@ virtio_disk_init(void)
*R(VIRTIO_MMIO_STATUS) = status; *R(VIRTIO_MMIO_STATUS) = status;
// negotiate features // negotiate features
uint64 features = *R(VIRTIO_MMIO_DEVICE_FEATURES); u64 features = *R(VIRTIO_MMIO_DEVICE_FEATURES);
features &= ~(1 << VIRTIO_BLK_F_RO); features &= ~(1 << VIRTIO_BLK_F_RO);
features &= ~(1 << VIRTIO_BLK_F_SCSI); features &= ~(1 << VIRTIO_BLK_F_SCSI);
features &= ~(1 << VIRTIO_BLK_F_CONFIG_WCE); features &= ~(1 << VIRTIO_BLK_F_CONFIG_WCE);
@ -111,7 +111,7 @@ virtio_disk_init(void)
panic("virtio disk should not be ready"); panic("virtio disk should not be ready");
// check maximum queue size. // check maximum queue size.
uint32 max = *R(VIRTIO_MMIO_QUEUE_NUM_MAX); u32 max = *R(VIRTIO_MMIO_QUEUE_NUM_MAX);
if(max == 0) if(max == 0)
panic("virtio disk has no queue 0"); panic("virtio disk has no queue 0");
if(max < NUM) if(max < NUM)
@ -131,12 +131,12 @@ virtio_disk_init(void)
*R(VIRTIO_MMIO_QUEUE_NUM) = NUM; *R(VIRTIO_MMIO_QUEUE_NUM) = NUM;
// write physical addresses. // write physical addresses.
*R(VIRTIO_MMIO_QUEUE_DESC_LOW) = (uint64)disk.desc; *R(VIRTIO_MMIO_QUEUE_DESC_LOW) = (u64)disk.desc;
*R(VIRTIO_MMIO_QUEUE_DESC_HIGH) = (uint64)disk.desc >> 32; *R(VIRTIO_MMIO_QUEUE_DESC_HIGH) = (u64)disk.desc >> 32;
*R(VIRTIO_MMIO_DRIVER_DESC_LOW) = (uint64)disk.avail; *R(VIRTIO_MMIO_DRIVER_DESC_LOW) = (u64)disk.avail;
*R(VIRTIO_MMIO_DRIVER_DESC_HIGH) = (uint64)disk.avail >> 32; *R(VIRTIO_MMIO_DRIVER_DESC_HIGH) = (u64)disk.avail >> 32;
*R(VIRTIO_MMIO_DEVICE_DESC_LOW) = (uint64)disk.used; *R(VIRTIO_MMIO_DEVICE_DESC_LOW) = (u64)disk.used;
*R(VIRTIO_MMIO_DEVICE_DESC_HIGH) = (uint64)disk.used >> 32; *R(VIRTIO_MMIO_DEVICE_DESC_HIGH) = (u64)disk.used >> 32;
// queue is ready. // queue is ready.
*R(VIRTIO_MMIO_QUEUE_READY) = 0x1; *R(VIRTIO_MMIO_QUEUE_READY) = 0x1;
@ -215,7 +215,7 @@ alloc3_desc(int *idx)
void void
virtio_disk_rw(struct buf *b, int write) virtio_disk_rw(struct buf *b, int write)
{ {
uint64 sector = b->blockno * (BSIZE / 512); u64 sector = b->blockno * (BSIZE / 512);
acquire(&disk.vdisk_lock); acquire(&disk.vdisk_lock);
@ -244,12 +244,12 @@ virtio_disk_rw(struct buf *b, int write)
buf0->reserved = 0; buf0->reserved = 0;
buf0->sector = sector; buf0->sector = sector;
disk.desc[idx[0]].addr = (uint64) buf0; disk.desc[idx[0]].addr = (u64) buf0;
disk.desc[idx[0]].len = sizeof(struct virtio_blk_req); disk.desc[idx[0]].len = sizeof(struct virtio_blk_req);
disk.desc[idx[0]].flags = VRING_DESC_F_NEXT; disk.desc[idx[0]].flags = VRING_DESC_F_NEXT;
disk.desc[idx[0]].next = idx[1]; disk.desc[idx[0]].next = idx[1];
disk.desc[idx[1]].addr = (uint64) b->data; disk.desc[idx[1]].addr = (u64) b->data;
disk.desc[idx[1]].len = BSIZE; disk.desc[idx[1]].len = BSIZE;
if(write) if(write)
disk.desc[idx[1]].flags = 0; // device reads b->data disk.desc[idx[1]].flags = 0; // device reads b->data
@ -259,7 +259,7 @@ virtio_disk_rw(struct buf *b, int write)
disk.desc[idx[1]].next = idx[2]; disk.desc[idx[1]].next = idx[2];
disk.info[idx[0]].status = 0xff; // device writes 0 on success disk.info[idx[0]].status = 0xff; // device writes 0 on success
disk.desc[idx[2]].addr = (uint64) &disk.info[idx[0]].status; disk.desc[idx[2]].addr = (u64) &disk.info[idx[0]].status;
disk.desc[idx[2]].len = 1; disk.desc[idx[2]].len = 1;
disk.desc[idx[2]].flags = VRING_DESC_F_WRITE; // device writes the status disk.desc[idx[2]].flags = VRING_DESC_F_WRITE; // device writes the status
disk.desc[idx[2]].next = 0; disk.desc[idx[2]].next = 0;

View file

@ -34,14 +34,14 @@ kvmmake(void)
kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W); kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
// map kernel text executable and read-only. // map kernel text executable and read-only.
kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X); kvmmap(kpgtbl, KERNBASE, KERNBASE, (u64)etext-KERNBASE, PTE_R | PTE_X);
// map kernel data and the physical RAM we'll make use of. // map kernel data and the physical RAM we'll make use of.
kvmmap(kpgtbl, (uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W); kvmmap(kpgtbl, (u64)etext, (u64)etext, PHYSTOP-(u64)etext, PTE_R | PTE_W);
// map the trampoline for trap entry/exit to // map the trampoline for trap entry/exit to
// the highest virtual address in the kernel. // the highest virtual address in the kernel.
kvmmap(kpgtbl, TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X); kvmmap(kpgtbl, TRAMPOLINE, (u64)trampoline, PGSIZE, PTE_R | PTE_X);
// allocate and map a kernel stack for each process. // allocate and map a kernel stack for each process.
proc_mapstacks(kpgtbl); proc_mapstacks(kpgtbl);
@ -61,7 +61,12 @@ kvminit(void)
void void
kvminithart() kvminithart()
{ {
// wait for any previous writes to the page table memory to finish.
sfence_vma();
w_satp(MAKE_SATP(kernel_pagetable)); w_satp(MAKE_SATP(kernel_pagetable));
// flush stale entries from the TLB.
sfence_vma(); sfence_vma();
} }
@ -78,7 +83,7 @@ kvminithart()
// 12..20 -- 9 bits of level-0 index. // 12..20 -- 9 bits of level-0 index.
// 0..11 -- 12 bits of byte offset within the page. // 0..11 -- 12 bits of byte offset within the page.
pte_t * pte_t *
walk(pagetable_t pagetable, uint64 va, int alloc) walk(pagetable_t pagetable, u64 va, int alloc)
{ {
if(va >= MAXVA) if(va >= MAXVA)
panic("walk"); panic("walk");
@ -100,11 +105,11 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
// Look up a virtual address, return the physical address, // Look up a virtual address, return the physical address,
// or 0 if not mapped. // or 0 if not mapped.
// Can only be used to look up user pages. // Can only be used to look up user pages.
uint64 u64
walkaddr(pagetable_t pagetable, uint64 va) walkaddr(pagetable_t pagetable, u64 va)
{ {
pte_t *pte; pte_t *pte;
uint64 pa; u64 pa;
if(va >= MAXVA) if(va >= MAXVA)
return 0; return 0;
@ -124,7 +129,7 @@ walkaddr(pagetable_t pagetable, uint64 va)
// only used when booting. // only used when booting.
// does not flush TLB or enable paging. // does not flush TLB or enable paging.
void void
kvmmap(pagetable_t kpgtbl, uint64 va, uint64 pa, uint64 sz, int perm) kvmmap(pagetable_t kpgtbl, u64 va, u64 pa, u64 sz, int perm)
{ {
if(mappages(kpgtbl, va, sz, pa, perm) != 0) if(mappages(kpgtbl, va, sz, pa, perm) != 0)
panic("kvmmap"); panic("kvmmap");
@ -135,9 +140,9 @@ kvmmap(pagetable_t kpgtbl, uint64 va, uint64 pa, uint64 sz, int perm)
// be page-aligned. Returns 0 on success, -1 if walk() couldn't // be page-aligned. Returns 0 on success, -1 if walk() couldn't
// allocate a needed page-table page. // allocate a needed page-table page.
int int
mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) mappages(pagetable_t pagetable, u64 va, u64 size, u64 pa, int perm)
{ {
uint64 a, last; u64 a, last;
pte_t *pte; pte_t *pte;
if(size == 0) if(size == 0)
@ -163,9 +168,9 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
// page-aligned. The mappings must exist. // page-aligned. The mappings must exist.
// Optionally free the physical memory. // Optionally free the physical memory.
void void
uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free) uvmunmap(pagetable_t pagetable, u64 va, u64 npages, int do_free)
{ {
uint64 a; u64 a;
pte_t *pte; pte_t *pte;
if((va % PGSIZE) != 0) if((va % PGSIZE) != 0)
@ -179,7 +184,7 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
if(PTE_FLAGS(*pte) == PTE_V) if(PTE_FLAGS(*pte) == PTE_V)
panic("uvmunmap: not a leaf"); panic("uvmunmap: not a leaf");
if(do_free){ if(do_free){
uint64 pa = PTE2PA(*pte); u64 pa = PTE2PA(*pte);
kfree((void*)pa); kfree((void*)pa);
} }
*pte = 0; *pte = 0;
@ -203,7 +208,7 @@ uvmcreate()
// for the very first process. // for the very first process.
// sz must be less than a page. // sz must be less than a page.
void void
uvmfirst(pagetable_t pagetable, uchar *src, uint sz) uvmfirst(pagetable_t pagetable, u8 *src, u32 sz)
{ {
char *mem; char *mem;
@ -211,17 +216,17 @@ uvmfirst(pagetable_t pagetable, uchar *src, uint sz)
panic("uvmfirst: more than a page"); panic("uvmfirst: more than a page");
mem = kalloc(); mem = kalloc();
memset(mem, 0, PGSIZE); memset(mem, 0, PGSIZE);
mappages(pagetable, 0, PGSIZE, (uint64)mem, PTE_W|PTE_R|PTE_X|PTE_U); mappages(pagetable, 0, PGSIZE, (u64)mem, PTE_W|PTE_R|PTE_X|PTE_U);
memmove(mem, src, sz); memmove(mem, src, sz);
} }
// Allocate PTEs and physical memory to grow process from oldsz to // Allocate PTEs and physical memory to grow process from oldsz to
// newsz, which need not be page aligned. Returns new size or 0 on error. // newsz, which need not be page aligned. Returns new size or 0 on error.
uint64 u64
uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm) uvmalloc(pagetable_t pagetable, u64 oldsz, u64 newsz, int xperm)
{ {
char *mem; char *mem;
uint64 a; u64 a;
if(newsz < oldsz) if(newsz < oldsz)
return oldsz; return oldsz;
@ -234,7 +239,7 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
return 0; return 0;
} }
memset(mem, 0, PGSIZE); memset(mem, 0, PGSIZE);
if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_R|PTE_U|xperm) != 0){ if(mappages(pagetable, a, PGSIZE, (u64)mem, PTE_R|PTE_U|xperm) != 0){
kfree(mem); kfree(mem);
uvmdealloc(pagetable, a, oldsz); uvmdealloc(pagetable, a, oldsz);
return 0; return 0;
@ -247,8 +252,8 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
// newsz. oldsz and newsz need not be page-aligned, nor does newsz // 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 // need to be less than oldsz. oldsz can be larger than the actual
// process size. Returns the new process size. // process size. Returns the new process size.
uint64 u64
uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz) uvmdealloc(pagetable_t pagetable, u64 oldsz, u64 newsz)
{ {
if(newsz >= oldsz) if(newsz >= oldsz)
return oldsz; return oldsz;
@ -271,7 +276,7 @@ freewalk(pagetable_t pagetable)
pte_t pte = pagetable[i]; pte_t pte = pagetable[i];
if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){ if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){
// this PTE points to a lower-level page table. // this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte); u64 child = PTE2PA(pte);
freewalk((pagetable_t)child); freewalk((pagetable_t)child);
pagetable[i] = 0; pagetable[i] = 0;
} else if(pte & PTE_V){ } else if(pte & PTE_V){
@ -284,7 +289,7 @@ freewalk(pagetable_t pagetable)
// Free user memory pages, // Free user memory pages,
// then free page-table pages. // then free page-table pages.
void void
uvmfree(pagetable_t pagetable, uint64 sz) uvmfree(pagetable_t pagetable, u64 sz)
{ {
if(sz > 0) if(sz > 0)
uvmunmap(pagetable, 0, PGROUNDUP(sz)/PGSIZE, 1); uvmunmap(pagetable, 0, PGROUNDUP(sz)/PGSIZE, 1);
@ -298,11 +303,11 @@ uvmfree(pagetable_t pagetable, uint64 sz)
// returns 0 on success, -1 on failure. // returns 0 on success, -1 on failure.
// frees any allocated pages on failure. // frees any allocated pages on failure.
int int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) uvmcopy(pagetable_t old, pagetable_t new, u64 sz)
{ {
pte_t *pte; pte_t *pte;
uint64 pa, i; u64 pa, i;
uint flags; u32 flags;
char *mem; char *mem;
for(i = 0; i < sz; i += PGSIZE){ for(i = 0; i < sz; i += PGSIZE){
@ -315,7 +320,7 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
if((mem = kalloc()) == 0) if((mem = kalloc()) == 0)
goto err; goto err;
memmove(mem, (char*)pa, PGSIZE); memmove(mem, (char*)pa, PGSIZE);
if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){ if(mappages(new, i, PGSIZE, (u64)mem, flags) != 0){
kfree(mem); kfree(mem);
goto err; goto err;
} }
@ -330,7 +335,7 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
// mark a PTE invalid for user access. // mark a PTE invalid for user access.
// used by exec for the user stack guard page. // used by exec for the user stack guard page.
void void
uvmclear(pagetable_t pagetable, uint64 va) uvmclear(pagetable_t pagetable, u64 va)
{ {
pte_t *pte; pte_t *pte;
@ -344,9 +349,9 @@ uvmclear(pagetable_t pagetable, uint64 va)
// Copy len bytes from src to virtual address dstva in a given page table. // Copy len bytes from src to virtual address dstva in a given page table.
// Return 0 on success, -1 on error. // Return 0 on success, -1 on error.
int int
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len) copyout(pagetable_t pagetable, u64 dstva, char *src, u64 len)
{ {
uint64 n, va0, pa0; u64 n, va0, pa0;
while(len > 0){ while(len > 0){
va0 = PGROUNDDOWN(dstva); va0 = PGROUNDDOWN(dstva);
@ -369,9 +374,9 @@ copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
// Copy len bytes to dst from virtual address srcva in a given page table. // Copy len bytes to dst from virtual address srcva in a given page table.
// Return 0 on success, -1 on error. // Return 0 on success, -1 on error.
int int
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len) copyin(pagetable_t pagetable, char *dst, u64 srcva, u64 len)
{ {
uint64 n, va0, pa0; u64 n, va0, pa0;
while(len > 0){ while(len > 0){
va0 = PGROUNDDOWN(srcva); va0 = PGROUNDDOWN(srcva);
@ -395,9 +400,9 @@ copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
// until a '\0', or max. // until a '\0', or max.
// Return 0 on success, -1 on error. // Return 0 on success, -1 on error.
int int
copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max) copyinstr(pagetable_t pagetable, char *dst, u64 srcva, u64 max)
{ {
uint64 n, va0, pa0; u64 n, va0, pa0;
int got_null = 0; int got_null = 0;
while(got_null == 0 && max > 0){ while(got_null == 0 && max > 0){

View file

@ -47,7 +47,7 @@ ushort
xshort(ushort x) xshort(ushort x)
{ {
ushort y; ushort y;
uchar *a = (uchar*)&y; u8 *a = (u8*)&y;
a[0] = x; a[0] = x;
a[1] = x >> 8; a[1] = x >> 8;
return y; return y;
@ -57,7 +57,7 @@ uint
xint(uint x) xint(uint x)
{ {
uint y; uint y;
uchar *a = (uchar*)&y; u8 *a = (u8*)&y;
a[0] = x; a[0] = x;
a[1] = x >> 8; a[1] = x >> 8;
a[2] = x >> 16; a[2] = x >> 16;
@ -234,7 +234,7 @@ ialloc(ushort type)
void void
balloc(int used) balloc(int used)
{ {
uchar buf[BSIZE]; u8 buf[BSIZE];
int i; int i;
printf("balloc: first %d blocks have been allocated\n", used); printf("balloc: first %d blocks have been allocated\n", used);

View file

@ -53,7 +53,7 @@ go(int which_child)
int fd = -1; int fd = -1;
static char buf[999]; static char buf[999];
char *break0 = sbrk(0); char *break0 = sbrk(0);
uint64 iters = 0; u64 iters = 0;
mkdir("grindir"); mkdir("grindir");
if(chdir("grindir") != 0){ if(chdir("grindir") != 0){
@ -305,7 +305,7 @@ iter()
exit(1); exit(1);
} }
if(pid1 == 0){ if(pid1 == 0){
rand_next = 31; rand_next ^= 31;
go(0); go(0);
exit(0); exit(0);
} }
@ -316,7 +316,7 @@ iter()
exit(1); exit(1);
} }
if(pid2 == 0){ if(pid2 == 0){
rand_next = 7177; rand_next ^= 7177;
go(1); go(1);
exit(0); exit(0);
} }
@ -346,5 +346,6 @@ main()
wait(0); wait(0);
} }
sleep(20); sleep(20);
rand_next += 1;
} }
} }

View file

@ -17,7 +17,7 @@ printint(int fd, int xx, int base, int sgn)
{ {
char buf[16]; char buf[16];
int i, neg; int i, neg;
uint x; u32 x;
neg = 0; neg = 0;
if(sgn && xx < 0){ if(sgn && xx < 0){
@ -39,12 +39,12 @@ printint(int fd, int xx, int base, int sgn)
} }
static void static void
printptr(int fd, uint64 x) { printptr(int fd, u64 x) {
int i; int i;
putc(fd, '0'); putc(fd, '0');
putc(fd, 'x'); putc(fd, 'x');
for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4) for (i = 0; i < (sizeof(u64) * 2); i++, x <<= 4)
putc(fd, digits[x >> (sizeof(uint64) * 8 - 4)]); putc(fd, digits[x >> (sizeof(u64) * 8 - 4)]);
} }
// Print to the given fd. Only understands %d, %x, %p, %s. // Print to the given fd. Only understands %d, %x, %p, %s.
@ -67,11 +67,11 @@ vprintf(int fd, const char *fmt, va_list ap)
if(c == 'd'){ if(c == 'd'){
printint(fd, va_arg(ap, int), 10, 1); printint(fd, va_arg(ap, int), 10, 1);
} else if(c == 'l') { } else if(c == 'l') {
printint(fd, va_arg(ap, uint64), 10, 0); printint(fd, va_arg(ap, u64), 10, 0);
} else if(c == 'x') { } else if(c == 'x') {
printint(fd, va_arg(ap, int), 16, 0); printint(fd, va_arg(ap, int), 16, 0);
} else if(c == 'p') { } else if(c == 'p') {
printptr(fd, va_arg(ap, uint64)); printptr(fd, va_arg(ap, u64));
} else if(c == 's'){ } else if(c == 's'){
s = va_arg(ap, char*); s = va_arg(ap, char*);
if(s == 0) if(s == 0)
@ -81,7 +81,7 @@ vprintf(int fd, const char *fmt, va_list ap)
s++; s++;
} }
} else if(c == 'c'){ } else if(c == 'c'){
putc(fd, va_arg(ap, uint)); putc(fd, va_arg(ap, u32));
} else if(c == '%'){ } else if(c == '%'){
putc(fd, c); putc(fd, c);
} else { } else {

View file

@ -30,10 +30,10 @@ strcmp(const char *p, const char *q)
{ {
while(*p && *p == *q) while(*p && *p == *q)
p++, q++; p++, q++;
return (uchar)*p - (uchar)*q; return (u8)*p - (u8)*q;
} }
uint u32
strlen(const char *s) strlen(const char *s)
{ {
int n; int n;
@ -44,7 +44,7 @@ strlen(const char *s)
} }
void* void*
memset(void *dst, int c, uint n) memset(void *dst, int c, u32 n)
{ {
char *cdst = (char *) dst; char *cdst = (char *) dst;
int i; int i;
@ -127,7 +127,7 @@ memmove(void *vdst, const void *vsrc, int n)
} }
int int
memcmp(const void *s1, const void *s2, uint n) memcmp(const void *s1, const void *s2, u32 n)
{ {
const char *p1 = s1, *p2 = s2; const char *p1 = s1, *p2 = s2;
while (n-- > 0) { while (n-- > 0) {
@ -141,7 +141,7 @@ memcmp(const void *s1, const void *s2, uint n)
} }
void * void *
memcpy(void *dst, const void *src, uint n) memcpy(void *dst, const void *src, u32 n)
{ {
return memmove(dst, src, n); return memmove(dst, src, n);
} }

View file

@ -11,7 +11,7 @@ typedef long Align;
union header { union header {
struct { struct {
union header *ptr; union header *ptr;
uint size; u32 size;
} s; } s;
Align x; Align x;
}; };
@ -44,7 +44,7 @@ free(void *ap)
} }
static Header* static Header*
morecore(uint nu) morecore(u32 nu)
{ {
char *p; char *p;
Header *hp; Header *hp;
@ -61,10 +61,10 @@ morecore(uint nu)
} }
void* void*
malloc(uint nbytes) malloc(u32 nbytes)
{ {
Header *p, *prevp; Header *p, *prevp;
uint nunits; u32 nunits;
nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1; nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1;
if((prevp = freep) == 0){ if((prevp = freep) == 0){

View file

@ -32,10 +32,10 @@ int strcmp(const char*, const char*);
void fprintf(int, const char*, ...); void fprintf(int, const char*, ...);
void printf(const char*, ...); void printf(const char*, ...);
char* gets(char*, int max); char* gets(char*, int max);
uint strlen(const char*); u32 strlen(const char*);
void* memset(void*, int, uint); void* memset(void*, int, u32);
void* malloc(uint); void* malloc(u32);
void free(void*); void free(void*);
int atoi(const char*); int atoi(const char*);
int memcmp(const void *, const void *, uint); int memcmp(const void *, const void *, u32);
void *memcpy(void *, const void *, uint); void *memcpy(void *, const void *, u32);

View file

@ -21,15 +21,21 @@
char buf[BUFSZ]; char buf[BUFSZ];
//
// Section with tests that run fairly quickly. Use -q if you want to
// run just those. With -q usertests also runs the ones that take a
// fair of time.
//
// what if you pass ridiculous pointers to system calls // what if you pass ridiculous pointers to system calls
// that read user memory with copyin? // that read user memory with copyin?
void void
copyin(char *s) copyin(char *s)
{ {
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff }; u64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
for(int ai = 0; ai < 2; ai++){ for(int ai = 0; ai < 2; ai++){
uint64 addr = addrs[ai]; u64 addr = addrs[ai];
int fd = open("copyin1", O_CREATE|O_WRONLY); int fd = open("copyin1", O_CREATE|O_WRONLY);
if(fd < 0){ if(fd < 0){
@ -70,10 +76,10 @@ copyin(char *s)
void void
copyout(char *s) copyout(char *s)
{ {
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff }; u64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
for(int ai = 0; ai < 2; ai++){ for(int ai = 0; ai < 2; ai++){
uint64 addr = addrs[ai]; u64 addr = addrs[ai];
int fd = open("README", 0); int fd = open("README", 0);
if(fd < 0){ if(fd < 0){
@ -111,10 +117,10 @@ copyout(char *s)
void void
copyinstr1(char *s) copyinstr1(char *s)
{ {
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff }; u64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
for(int ai = 0; ai < 2; ai++){ for(int ai = 0; ai < 2; ai++){
uint64 addr = addrs[ai]; u64 addr = addrs[ai];
int fd = open((char *)addr, O_CREATE|O_WRONLY); int fd = open((char *)addr, O_CREATE|O_WRONLY);
if(fd >= 0){ if(fd >= 0){
@ -193,11 +199,11 @@ void
copyinstr3(char *s) copyinstr3(char *s)
{ {
sbrk(8192); sbrk(8192);
uint64 top = (uint64) sbrk(0); u64 top = (u64) sbrk(0);
if((top % PGSIZE) != 0){ if((top % PGSIZE) != 0){
sbrk(PGSIZE - (top % PGSIZE)); sbrk(PGSIZE - (top % PGSIZE));
} }
top = (uint64) sbrk(0); top = (u64) sbrk(0);
if(top % PGSIZE){ if(top % PGSIZE){
printf("oops\n"); printf("oops\n");
exit(1); exit(1);
@ -239,14 +245,14 @@ rwsbrk()
{ {
int fd, n; int fd, n;
uint64 a = (uint64) sbrk(8192); u64 a = (u64) sbrk(8192);
if(a == 0xffffffffffffffffLL) { if(a == 0xffffffffffffffffLL) {
printf("sbrk(rwsbrk) failed\n"); printf("sbrk(rwsbrk) failed\n");
exit(1); exit(1);
} }
if ((uint64) sbrk(-8192) == 0xffffffffffffffffLL) { if ((u64) sbrk(-8192) == 0xffffffffffffffffLL) {
printf("sbrk(rwsbrk) shrink failed\n"); printf("sbrk(rwsbrk) shrink failed\n");
exit(1); exit(1);
} }
@ -1391,7 +1397,7 @@ concreate(char *s)
int i, pid, n, fd; int i, pid, n, fd;
char fa[N]; char fa[N];
struct { struct {
ushort inum; u16 inum;
char name[DIRSIZ]; char name[DIRSIZ];
} de; } de;
@ -1512,46 +1518,6 @@ linkunlink(char *s)
exit(0); exit(0);
} }
// directory that uses indirect blocks
void
bigdir(char *s)
{
enum { N = 500 };
int i, fd;
char name[10];
unlink("bd");
fd = open("bd", O_CREATE);
if(fd < 0){
printf("%s: bigdir create failed\n", s);
exit(1);
}
close(fd);
for(i = 0; i < N; i++){
name[0] = 'x';
name[1] = '0' + (i / 64);
name[2] = '0' + (i % 64);
name[3] = '\0';
if(link("bd", name) != 0){
printf("%s: bigdir link(bd, %s) failed\n", s, name);
exit(1);
}
}
unlink("bd");
for(i = 0; i < N; i++){
name[0] = 'x';
name[1] = '0' + (i / 64);
name[2] = '0' + (i % 64);
name[3] = '\0';
if(unlink(name) != 0){
printf("%s: bigdir unlink failed", s);
exit(1);
}
}
}
void void
subdir(char *s) subdir(char *s)
@ -1758,59 +1724,6 @@ bigwrite(char *s)
} }
} }
// concurrent writes to try to provoke deadlock in the virtio disk
// driver.
void
manywrites(char *s)
{
int nchildren = 4;
int howmany = 30; // increase to look for deadlock
for(int ci = 0; ci < nchildren; ci++){
int pid = fork();
if(pid < 0){
printf("fork failed\n");
exit(1);
}
if(pid == 0){
char name[3];
name[0] = 'b';
name[1] = 'a' + ci;
name[2] = '\0';
unlink(name);
for(int iters = 0; iters < howmany; iters++){
for(int i = 0; i < ci+1; i++){
int fd = open(name, O_CREATE | O_RDWR);
if(fd < 0){
printf("%s: cannot create %s\n", s, name);
exit(1);
}
int sz = sizeof(buf);
int cc = write(fd, buf, sz);
if(cc != sz){
printf("%s: write(%d) ret %d\n", s, sz, cc);
exit(1);
}
close(fd);
}
unlink(name);
}
unlink(name);
exit(0);
}
}
for(int ci = 0; ci < nchildren; ci++){
int st = 0;
wait(&st);
if(st != 0)
exit(st);
}
exit(0);
}
void void
bigfile(char *s) bigfile(char *s)
@ -2149,13 +2062,13 @@ sbrkmuch(char *s)
{ {
enum { BIG=100*1024*1024 }; enum { BIG=100*1024*1024 };
char *c, *oldbrk, *a, *lastaddr, *p; char *c, *oldbrk, *a, *lastaddr, *p;
uint64 amt; u64 amt;
oldbrk = sbrk(0); oldbrk = sbrk(0);
// can one grow address space to something big? // can one grow address space to something big?
a = sbrk(0); a = sbrk(0);
amt = BIG - (uint64)a; amt = BIG - (u64)a;
p = sbrk(amt); p = sbrk(amt);
if (p != a) { if (p != a) {
printf("%s: sbrk test failed to grow big address space; enough phys mem?\n", s); printf("%s: sbrk test failed to grow big address space; enough phys mem?\n", s);
@ -2232,7 +2145,7 @@ kernmem(char *s)
void void
MAXVAplus(char *s) MAXVAplus(char *s)
{ {
volatile uint64 a = MAXVA; volatile u64 a = MAXVA;
for( ; a != 0; a <<= 1){ for( ; a != 0; a <<= 1){
int pid; int pid;
pid = fork(); pid = fork();
@ -2272,7 +2185,7 @@ sbrkfail(char *s)
for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
if((pids[i] = fork()) == 0){ if((pids[i] = fork()) == 0){
// allocate a lot of memory // allocate a lot of memory
sbrk(BIG - (uint64)sbrk(0)); sbrk(BIG - (u64)sbrk(0));
write(fds[1], "x", 1); write(fds[1], "x", 1);
// sit around until killed // sit around until killed
for(;;) sleep(1000); for(;;) sleep(1000);
@ -2354,10 +2267,10 @@ void
validatetest(char *s) validatetest(char *s)
{ {
int hi; int hi;
uint64 p; u64 p;
hi = 1100*1024; hi = 1100*1024;
for(p = 0; p <= (uint)hi; p += PGSIZE){ for(p = 0; p <= (u32)hi; p += PGSIZE){
// try to crash the kernel by passing in a bad string pointer // try to crash the kernel by passing in a bad string pointer
if(link("nosuchfile", (char*)p) != -1){ if(link("nosuchfile", (char*)p) != -1){
printf("%s: link should not succeed\n", s); printf("%s: link should not succeed\n", s);
@ -2532,7 +2445,7 @@ textwrite(char *s)
} }
// regression test. copyin(), copyout(), and copyinstr() used to cast // regression test. copyin(), copyout(), and copyinstr() used to cast
// the virtual page address to uint, which (with certain wild system // the virtual page address to u32, which (with certain wild system
// call arguments) resulted in a kernel page faults. // call arguments) resulted in a kernel page faults.
void *big = (void*) 0xeaeb0b5b00002f5e; void *big = (void*) 0xeaeb0b5b00002f5e;
void void
@ -2558,7 +2471,7 @@ sbrkbugs(char *s)
exit(1); exit(1);
} }
if(pid == 0){ if(pid == 0){
int sz = (uint64) sbrk(0); int sz = (u64) sbrk(0);
// free all user memory; there used to be a bug that // free all user memory; there used to be a bug that
// would not adjust p->sz correctly in this case, // would not adjust p->sz correctly in this case,
// causing exit() to panic. // causing exit() to panic.
@ -2574,7 +2487,7 @@ sbrkbugs(char *s)
exit(1); exit(1);
} }
if(pid == 0){ if(pid == 0){
int sz = (uint64) sbrk(0); int sz = (u64) sbrk(0);
// set the break to somewhere in the very first // set the break to somewhere in the very first
// page; there used to be a bug that would incorrectly // page; there used to be a bug that would incorrectly
// free the first page. // free the first page.
@ -2590,7 +2503,7 @@ sbrkbugs(char *s)
} }
if(pid == 0){ if(pid == 0){
// set the break in the middle of a page. // set the break in the middle of a page.
sbrk((10*4096 + 2048) - (uint64)sbrk(0)); sbrk((10*4096 + 2048) - (u64)sbrk(0));
// reduce the break a bit, but not enough to // reduce the break a bit, but not enough to
// cause a page to be freed. this used to cause // cause a page to be freed. this used to cause
@ -2610,13 +2523,13 @@ sbrkbugs(char *s)
void void
sbrklast(char *s) sbrklast(char *s)
{ {
uint64 top = (uint64) sbrk(0); u64 top = (u64) sbrk(0);
if((top % 4096) != 0) if((top % 4096) != 0)
sbrk(4096 - (top % 4096)); sbrk(4096 - (top % 4096));
sbrk(4096); sbrk(4096);
sbrk(10); sbrk(10);
sbrk(-20); sbrk(-20);
top = (uint64) sbrk(0); top = (u64) sbrk(0);
char *p = (char *) (top - 64); char *p = (char *) (top - 64);
p[0] = 'x'; p[0] = 'x';
p[1] = '\0'; p[1] = '\0';
@ -2642,6 +2555,189 @@ sbrk8000(char *s)
} }
// regression test. test whether exec() leaks memory if one of the
// arguments is invalid. the test passes if the kernel doesn't panic.
void
badarg(char *s)
{
for(int i = 0; i < 50000; i++){
char *argv[2];
argv[0] = (char*)0xffffffff;
argv[1] = 0;
exec("echo", argv);
}
exit(0);
}
struct test {
void (*f)(char *);
char *s;
} quicktests[] = {
{copyin, "copyin"},
{copyout, "copyout"},
{copyinstr1, "copyinstr1"},
{copyinstr2, "copyinstr2"},
{copyinstr3, "copyinstr3"},
{rwsbrk, "rwsbrk" },
{truncate1, "truncate1"},
{truncate2, "truncate2"},
{truncate3, "truncate3"},
{openiputtest, "openiput"},
{exitiputtest, "exitiput"},
{iputtest, "iput"},
{opentest, "opentest"},
{writetest, "writetest"},
{writebig, "writebig"},
{createtest, "createtest"},
{dirtest, "dirtest"},
{exectest, "exectest"},
{pipe1, "pipe1"},
{killstatus, "killstatus"},
{preempt, "preempt"},
{exitwait, "exitwait"},
{reparent, "reparent" },
{twochildren, "twochildren"},
{forkfork, "forkfork"},
{forkforkfork, "forkforkfork"},
{reparent2, "reparent2"},
{mem, "mem"},
{sharedfd, "sharedfd"},
{fourfiles, "fourfiles"},
{createdelete, "createdelete"},
{unlinkread, "unlinkread"},
{linktest, "linktest"},
{concreate, "concreate"},
{linkunlink, "linkunlink"},
{subdir, "subdir"},
{bigwrite, "bigwrite"},
{bigfile, "bigfile"},
{fourteen, "fourteen"},
{rmdot, "rmdot"},
{dirfile, "dirfile"},
{iref, "iref"},
{forktest, "forktest"},
{sbrkbasic, "sbrkbasic"},
{sbrkmuch, "sbrkmuch"},
{kernmem, "kernmem"},
{MAXVAplus, "MAXVAplus"},
{sbrkfail, "sbrkfail"},
{sbrkarg, "sbrkarg"},
{validatetest, "validatetest"},
{bsstest, "bsstest"},
{bigargtest, "bigargtest"},
{argptest, "argptest"},
{stacktest, "stacktest"},
{textwrite, "textwrite"},
{pgbug, "pgbug" },
{sbrkbugs, "sbrkbugs" },
{sbrklast, "sbrklast"},
{sbrk8000, "sbrk8000"},
{badarg, "badarg" },
{ 0, 0},
};
//
// Section with tests that take a fair bit of time
//
// directory that uses indirect blocks
void
bigdir(char *s)
{
enum { N = 500 };
int i, fd;
char name[10];
unlink("bd");
fd = open("bd", O_CREATE);
if(fd < 0){
printf("%s: bigdir create failed\n", s);
exit(1);
}
close(fd);
for(i = 0; i < N; i++){
name[0] = 'x';
name[1] = '0' + (i / 64);
name[2] = '0' + (i % 64);
name[3] = '\0';
if(link("bd", name) != 0){
printf("%s: bigdir link(bd, %s) failed\n", s, name);
exit(1);
}
}
unlink("bd");
for(i = 0; i < N; i++){
name[0] = 'x';
name[1] = '0' + (i / 64);
name[2] = '0' + (i % 64);
name[3] = '\0';
if(unlink(name) != 0){
printf("%s: bigdir unlink failed", s);
exit(1);
}
}
}
// concurrent writes to try to provoke deadlock in the virtio disk
// driver.
void
manywrites(char *s)
{
int nchildren = 4;
int howmany = 30; // increase to look for deadlock
for(int ci = 0; ci < nchildren; ci++){
int pid = fork();
if(pid < 0){
printf("fork failed\n");
exit(1);
}
if(pid == 0){
char name[3];
name[0] = 'b';
name[1] = 'a' + ci;
name[2] = '\0';
unlink(name);
for(int iters = 0; iters < howmany; iters++){
for(int i = 0; i < ci+1; i++){
int fd = open(name, O_CREATE | O_RDWR);
if(fd < 0){
printf("%s: cannot create %s\n", s, name);
exit(1);
}
int sz = sizeof(buf);
int cc = write(fd, buf, sz);
if(cc != sz){
printf("%s: write(%d) ret %d\n", s, sz, cc);
exit(1);
}
close(fd);
}
unlink(name);
}
unlink(name);
exit(0);
}
}
for(int ci = 0; ci < nchildren; ci++){
int st = 0;
wait(&st);
if(st != 0)
exit(st);
}
exit(0);
}
// regression test. does write() with an invalid buffer pointer cause // regression test. does write() with an invalid buffer pointer cause
// a block to be allocated for a file that is then not freed when the // a block to be allocated for a file that is then not freed when the
// file is deleted? if the kernel has this bug, it will panic: balloc: // file is deleted? if the kernel has this bug, it will panic: balloc:
@ -2679,21 +2775,6 @@ badwrite(char *s)
exit(0); exit(0);
} }
// regression test. test whether exec() leaks memory if one of the
// arguments is invalid. the test passes if the kernel doesn't panic.
void
badarg(char *s)
{
for(int i = 0; i < 50000; i++){
char *argv[2];
argv[0] = (char*)0xffffffff;
argv[1] = 0;
exec("echo", argv);
}
exit(0);
}
// test the exec() code that cleans up if it runs out // test the exec() code that cleans up if it runs out
// of memory. it's really a test that such a condition // of memory. it's really a test that such a condition
// doesn't cause a panic. // doesn't cause a panic.
@ -2708,7 +2789,7 @@ execout(char *s)
} else if(pid == 0){ } else if(pid == 0){
// allocate all of memory. // allocate all of memory.
while(1){ while(1){
uint64 a = (uint64) sbrk(4096); u64 a = (u64) sbrk(4096);
if(a == 0xffffffffffffffffLL) if(a == 0xffffffffffffffffLL)
break; break;
*(char*)(a + 4096 - 1) = 1; *(char*)(a + 4096 - 1) = 1;
@ -2750,6 +2831,7 @@ diskfull(char *s)
unlink(name); unlink(name);
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC); int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
if(fd < 0){ if(fd < 0){
// oops, ran out of inodes before running out of blocks.
printf("%s: could not create file %s\n", s, name); printf("%s: could not create file %s\n", s, name);
done = 1; done = 1;
break; break;
@ -2767,7 +2849,8 @@ diskfull(char *s)
// now that there are no free blocks, test that dirlink() // now that there are no free blocks, test that dirlink()
// merely fails (doesn't panic) if it can't extend // merely fails (doesn't panic) if it can't extend
// directory content. // directory content. one of these file creations
// is expected to fail.
int nzz = 128; int nzz = 128;
for(int i = 0; i < nzz; i++){ for(int i = 0; i < nzz; i++){
char name[32]; char name[32];
@ -2778,14 +2861,15 @@ diskfull(char *s)
name[4] = '\0'; name[4] = '\0';
unlink(name); unlink(name);
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC); int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
if(fd < 0){ if(fd < 0)
printf("%s: could not create file %s\n", s, name);
break; break;
}
close(fd); close(fd);
} }
mkdir("diskfulldir"); // this mkdir() is expected to fail.
if(mkdir("diskfulldir") == 0)
printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n");
unlink("diskfulldir"); unlink("diskfulldir");
for(int i = 0; i < nzz; i++){ for(int i = 0; i < nzz; i++){
@ -2809,6 +2893,91 @@ diskfull(char *s)
} }
} }
void
outofinodes(char *s)
{
int nzz = 32*32;
for(int i = 0; i < nzz; i++){
char name[32];
name[0] = 'z';
name[1] = 'z';
name[2] = '0' + (i / 32);
name[3] = '0' + (i % 32);
name[4] = '\0';
unlink(name);
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
if(fd < 0){
// failure is eventually expected.
break;
}
close(fd);
}
for(int i = 0; i < nzz; i++){
char name[32];
name[0] = 'z';
name[1] = 'z';
name[2] = '0' + (i / 32);
name[3] = '0' + (i % 32);
name[4] = '\0';
unlink(name);
}
}
struct test slowtests[] = {
{bigdir, "bigdir"},
{manywrites, "manywrites"},
{badwrite, "badwrite" },
{execout, "execout"},
{diskfull, "diskfull"},
{outofinodes, "outofinodes"},
{ 0, 0},
};
//
// drive tests
//
// run each test in its own process. run returns 1 if child's exit()
// indicates success.
int
run(void f(char *), char *s) {
int pid;
int xstatus;
printf("test %s: ", s);
if((pid = fork()) < 0) {
printf("runtest: fork error\n");
exit(1);
}
if(pid == 0) {
f(s);
exit(0);
} else {
wait(&xstatus);
if(xstatus != 0)
printf("FAILED\n");
else
printf("OK\n");
return xstatus == 0;
}
}
int
runtests(struct test *tests, char *justone) {
for (struct test *t = tests; t->s != 0; t++) {
if((justone == 0) || strcmp(t->s, justone) == 0) {
if(!run(t->f, t->s)){
printf("SOME TESTS FAILED\n");
return 1;
}
}
}
return 0;
}
// //
// use sbrk() to count how many free physical memory pages there are. // use sbrk() to count how many free physical memory pages there are.
// touches the pages to force allocation. // touches the pages to force allocation.
@ -2836,7 +3005,7 @@ countfree()
close(fds[0]); close(fds[0]);
while(1){ while(1){
uint64 a = (uint64) sbrk(4096); u64 a = (u64) sbrk(4096);
if(a == 0xffffffffffffffff){ if(a == 0xffffffffffffffff){
break; break;
} }
@ -2875,165 +3044,58 @@ countfree()
return n; return n;
} }
// run each test in its own process. run returns 1 if child's exit()
// indicates success.
int int
run(void f(char *), char *s) { drivetests(int quick, int continuous, char *justone) {
int pid; do {
int xstatus; printf("usertests starting\n");
int free0 = countfree();
printf("test %s: ", s); int free1 = 0;
if((pid = fork()) < 0) { if (runtests(quicktests, justone)) {
printf("runtest: fork error\n"); if(continuous != 2) {
exit(1); return 1;
} }
if(pid == 0) { }
f(s); if(!quick) {
exit(0); if (justone == 0)
} else { printf("usertests slow tests starting\n");
wait(&xstatus); if (runtests(slowtests, justone)) {
if(xstatus != 0) if(continuous != 2) {
printf("FAILED\n"); return 1;
else }
printf("OK\n"); }
return xstatus == 0; }
} if((free1 = countfree()) < free0) {
printf("FAILED -- lost some free pages %d (out of %d)\n", free1, free0);
if(continuous != 2) {
return 1;
}
}
} while(continuous);
return 0;
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int continuous = 0; int continuous = 0;
int quick = 0;
char *justone = 0; char *justone = 0;
if(argc == 2 && strcmp(argv[1], "-c") == 0){ if(argc == 2 && strcmp(argv[1], "-q") == 0){
quick = 1;
} else if(argc == 2 && strcmp(argv[1], "-c") == 0){
continuous = 1; continuous = 1;
} else if(argc == 2 && strcmp(argv[1], "-C") == 0){ } else if(argc == 2 && strcmp(argv[1], "-C") == 0){
continuous = 2; continuous = 2;
} else if(argc == 2 && argv[1][0] != '-'){ } else if(argc == 2 && argv[1][0] != '-'){
justone = argv[1]; justone = argv[1];
} else if(argc > 1){ } else if(argc > 1){
printf("Usage: usertests [-c] [testname]\n"); printf("Usage: usertests [-c] [-C] [-q] [testname]\n");
exit(1); exit(1);
} }
if (drivetests(quick, continuous, justone)) {
struct test {
void (*f)(char *);
char *s;
} tests[] = {
{copyin, "copyin"},
{copyout, "copyout"},
{copyinstr1, "copyinstr1"},
{copyinstr2, "copyinstr2"},
{copyinstr3, "copyinstr3"},
{rwsbrk, "rwsbrk" },
{truncate1, "truncate1"},
{truncate2, "truncate2"},
{truncate3, "truncate3"},
{openiputtest, "openiput"},
{exitiputtest, "exitiput"},
{iputtest, "iput"},
{opentest, "opentest"},
{writetest, "writetest"},
{writebig, "writebig"},
{createtest, "createtest"},
{dirtest, "dirtest"},
{exectest, "exectest"},
{pipe1, "pipe1"},
{killstatus, "killstatus"},
{preempt, "preempt"},
{exitwait, "exitwait"},
{reparent, "reparent" },
{twochildren, "twochildren"},
{forkfork, "forkfork"},
{forkforkfork, "forkforkfork"},
{reparent2, "reparent2"},
{mem, "mem"},
{sharedfd, "sharedfd"},
{fourfiles, "fourfiles"},
{createdelete, "createdelete"},
{unlinkread, "unlinkread"},
{linktest, "linktest"},
{concreate, "concreate"},
{linkunlink, "linkunlink"},
{bigdir, "bigdir"}, // slow
{subdir, "subdir"},
{bigwrite, "bigwrite"},
{manywrites, "manywrites"},
{bigfile, "bigfile"},
{fourteen, "fourteen"},
{rmdot, "rmdot"},
{dirfile, "dirfile"},
{iref, "iref"},
{forktest, "forktest"},
{sbrkbasic, "sbrkbasic"},
{sbrkmuch, "sbrkmuch"},
{kernmem, "kernmem"},
{MAXVAplus, "MAXVAplus"},
{sbrkfail, "sbrkfail"},
{sbrkarg, "sbrkarg"},
{validatetest, "validatetest"},
{bsstest, "bsstest"},
{bigargtest, "bigargtest"},
{argptest, "argptest"},
{stacktest, "stacktest"},
{textwrite, "textwrite"},
{pgbug, "pgbug" },
{sbrkbugs, "sbrkbugs" },
{sbrklast, "sbrklast"},
{sbrk8000, "sbrk8000"},
{badwrite, "badwrite" },
{badarg, "badarg" },
{execout, "execout"},
{diskfull, "diskfull"},
{ 0, 0},
};
if(continuous){
printf("continuous usertests starting\n");
while(1){
int fail = 0;
int free0 = countfree();
for (struct test *t = tests; t->s != 0; t++) {
if(!run(t->f, t->s)){
fail = 1;
break;
}
}
if(fail){
printf("SOME TESTS FAILED\n");
if(continuous != 2)
exit(1);
}
int free1 = countfree();
if(free1 < free0){
printf("FAILED -- lost %d free pages\n", free0 - free1);
if(continuous != 2)
exit(1);
}
}
}
printf("usertests starting\n");
int free0 = countfree();
int free1 = 0;
int fail = 0;
for (struct test *t = tests; t->s != 0; t++) {
if((justone == 0) || strcmp(t->s, justone) == 0) {
if(!run(t->f, t->s))
fail = 1;
}
}
if(fail){
printf("SOME TESTS FAILED\n");
exit(1); exit(1);
} else if((free1 = countfree()) < free0){
printf("FAILED -- lost some free pages %d (out of %d)\n", free1, free0);
exit(1);
} else {
printf("ALL TESTS PASSED\n");
exit(0);
} }
printf("ALL TESTS PASSED\n");
exit(0);
} }