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
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.
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.
We are also grateful for the bug reports and patches contributed by
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, Ian Chen, Dan
Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi, eyalz800, Nelson
Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel Filardo, flespark,
Peter Froehlich, Yakir Goaron, Shivam Handa, Matt Harvey, Bryan Henry,
jaichenhengjie, Jim Huang, Matúš Jókay, Alexander Kapshuk, Anders
Kaseorg, kehao95, Wolfgang Keller, Jungwoo Kim, Jonathan Kimmitt,
Eddie Kohler, Vadim Kolontsov, Austin Liew, l0stman, Pavan
Maddamsetti, Imbar Marinescu, Yandong Mao, Matan Shabtay, Hitoshi
Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel Nider,
OptimisticSide, Greg Price, Jude Rich, Ayan Shafqat, Eldar Sehayek,
Yongming Shen, Fumiya Shigemitsu, Cam Tenny, tyfkda, Warren Toomey,
Stephen Tu, Rafael Ubal, Amane Uehara, Pablo Ventura, Xi Wang, Keiichi
Watanabe, Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy
Zheng, ZhUyU1997, and Zou Chang Wei.
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, carlclone, Ian
Chen, Dan Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi,
eyalz800, Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel
Filardo, flespark, Peter Froehlich, Yakir Goaron, Shivam Handa, Matt
Harvey, Bryan Henry, jaichenhengjie, Jim Huang, Matúš Jókay, John
Jolly, Alexander Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller,
Jungwoo Kim, Jonathan Kimmitt, Eddie Kohler, Vadim Kolontsov, Austin
Liew, l0stman, Pavan Maddamsetti, Imbar Marinescu, Yandong Mao, Matan
Shabtay, Hitoshi Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel
Nider, Hayato Ohhashi, OptimisticSide, Harry Porter, Greg Price, Jude
Rich, segfault, Ayan Shafqat, Eldar Sehayek, Yongming Shen, Fumiya
Shigemitsu, Cam Tenny, tyfkda, Warren Toomey, Stephen Tu, Rafael Ubal,
Amane Uehara, Pablo Ventura, Xi Wang, WaheedHafez, Keiichi Watanabe,
Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng,
ZhUyU1997, and Zou Chang Wei.
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
Please send errors and suggestions to Frans Kaashoek and Robert Morris
(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.
BUILDING AND RUNNING XV6

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -62,8 +62,8 @@ bzero(int dev, int bno)
// Allocate a zeroed disk block.
// returns 0 if out of disk space.
static uint
balloc(uint dev)
static u32
balloc(u32 dev)
{
int b, bi, m;
struct buf *bp;
@ -89,7 +89,7 @@ balloc(uint dev)
// Free a disk block.
static void
bfree(int dev, uint b)
bfree(int dev, u32 b)
{
struct buf *bp;
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.
// 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*
ialloc(uint dev, short type)
ialloc(u32 dev, short type)
{
int inum;
struct buf *bp;
@ -213,7 +214,8 @@ ialloc(uint dev, short type)
}
brelse(bp);
}
panic("ialloc: no inodes");
printf("ialloc: no inodes\n");
return 0;
}
// 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
// the inode and does not read it from disk.
static struct inode*
iget(uint dev, uint inum)
iget(u32 dev, u32 inum)
{
struct inode *ip, *empty;
@ -377,10 +379,10 @@ iunlockput(struct inode *ip)
// Return the disk block address of the nth block in inode ip.
// If there is no such block, bmap allocates one.
// returns 0 if out of disk space.
static uint
bmap(struct inode *ip, uint bn)
static u32
bmap(struct inode *ip, u32 bn)
{
uint addr, *a;
u32 addr, *a;
struct buf *bp;
if(bn < NDIRECT){
@ -403,7 +405,7 @@ bmap(struct inode *ip, uint bn)
ip->addrs[NDIRECT] = addr;
}
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
a = (u32*)bp->data;
if((addr = a[bn]) == 0){
addr = balloc(ip->dev);
if(addr){
@ -425,7 +427,7 @@ itrunc(struct inode *ip)
{
int i, j;
struct buf *bp;
uint *a;
u32 *a;
for(i = 0; i < NDIRECT; i++){
if(ip->addrs[i]){
@ -436,7 +438,7 @@ itrunc(struct inode *ip)
if(ip->addrs[NDIRECT]){
bp = bread(ip->dev, ip->addrs[NDIRECT]);
a = (uint*)bp->data;
a = (u32*)bp->data;
for(j = 0; j < NINDIRECT; j++){
if(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;
// otherwise, dst is a kernel address.
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;
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;
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)
break;
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,
// there was an error of some kind.
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;
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;
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)
break;
bp = bread(ip->dev, addr);
@ -547,16 +549,16 @@ namecmp(const char *s, const char *t)
// Look for a directory entry in a directory.
// If found, set *poff to byte offset of entry.
struct inode*
dirlookup(struct inode *dp, char *name, uint *poff)
dirlookup(struct inode *dp, char *name, u32 *poff)
{
uint off, inum;
u32 off, inum;
struct dirent de;
if(dp->type != T_DIR)
panic("dirlookup not DIR");
for(off = 0; off < dp->size; off += sizeof(de)){
if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
if(readi(dp, 0, (u64)&de, off, sizeof(de)) != sizeof(de))
panic("dirlookup read");
if(de.inum == 0)
continue;
@ -575,7 +577,7 @@ dirlookup(struct inode *dp, char *name, uint *poff)
// Write a new directory entry (name, inum) into the directory dp.
// Returns 0 on success, -1 on failure (e.g. out of disk blocks).
int
dirlink(struct inode *dp, char *name, uint inum)
dirlink(struct inode *dp, char *name, u32 inum)
{
int off;
struct dirent de;
@ -589,7 +591,7 @@ dirlink(struct inode *dp, char *name, uint inum)
// Look for an empty dirent.
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");
if(de.inum == 0)
break;
@ -597,7 +599,7 @@ dirlink(struct inode *dp, char *name, uint inum)
strncpy(de.name, name, DIRSIZ);
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 0;

View file

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

View file

@ -34,7 +34,7 @@ void
freerange(void *pa_start, void *pa_end)
{
char *p;
p = (char*)PGROUNDUP((uint64)pa_start);
p = (char*)PGROUNDUP((u64)pa_start);
for(; p + PGSIZE <= (char*)pa_end; p += PGSIZE)
kfree(p);
}
@ -48,7 +48,7 @@ kfree(void *pa)
{
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");
// Fill with junk to catch dangling refs.

View file

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

View file

@ -12,8 +12,8 @@ void
plicinit(void)
{
// set desired IRQ priorities non-zero (otherwise disabled).
*(uint32*)(PLIC + UART0_IRQ*4) = 1;
*(uint32*)(PLIC + VIRTIO0_IRQ*4) = 1;
*(u32*)(PLIC + UART0_IRQ*4) = 1;
*(u32*)(PLIC + VIRTIO0_IRQ*4) = 1;
}
void
@ -23,10 +23,10 @@ plicinithart(void)
// set enable bits for this hart's S-mode
// 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.
*(uint32*)PLIC_SPRIORITY(hart) = 0;
*(u32*)PLIC_SPRIORITY(hart) = 0;
}
// ask the PLIC what interrupt we should serve.
@ -34,7 +34,7 @@ int
plic_claim(void)
{
int hart = cpuid();
int irq = *(uint32*)PLIC_SCLAIM(hart);
int irq = *(u32*)PLIC_SCLAIM(hart);
return irq;
}
@ -43,5 +43,5 @@ void
plic_complete(int irq)
{
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];
int i;
uint x;
u32 x;
if(sign && (sign = xx < 0))
x = -xx;
@ -50,13 +50,13 @@ printint(int xx, int base, int sign)
}
static void
printptr(uint64 x)
printptr(u64 x)
{
int i;
consputc('0');
consputc('x');
for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4)
consputc(digits[x >> (sizeof(uint64) * 8 - 4)]);
for (i = 0; i < (sizeof(u64) * 2); i++, x <<= 4)
consputc(digits[x >> (sizeof(u64) * 8 - 4)]);
}
// Print to the console. only understands %d, %x, %p, %s.
@ -91,7 +91,7 @@ printf(char *fmt, ...)
printint(va_arg(ap, int), 16, 1);
break;
case 'p':
printptr(va_arg(ap, uint64));
printptr(va_arg(ap, u64));
break;
case 's':
if((s = va_arg(ap, char*)) == 0)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -11,7 +11,7 @@ void timerinit();
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
// 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.
extern void timervec();
@ -28,7 +28,7 @@ start()
// set M Exception Program Counter to main, for mret.
// requires gcc -mcmodel=medany
w_mepc((uint64)main);
w_mepc((u64)main);
// disable paging for now.
w_satp(0);
@ -67,19 +67,19 @@ timerinit()
// ask the CLINT for a timer interrupt.
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.
// scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register.
// 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[4] = interval;
w_mscratch((uint64)scratch);
w_mscratch((u64)scratch);
// set the machine-mode trap handler.
w_mtvec((uint64)timervec);
w_mtvec((u64)timervec);
// enable machine-mode interrupts.
w_mstatus(r_mstatus() | MSTATUS_MIE);

View file

@ -4,8 +4,8 @@
struct stat {
int dev; // File system's disk device
uint ino; // Inode number
u32 ino; // Inode number
short type; // Type of 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"
void*
memset(void *dst, int c, uint n)
memset(void *dst, int c, u32 n)
{
char *cdst = (char *) dst;
int i;
@ -12,9 +12,9 @@ memset(void *dst, int c, uint n)
}
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;
s2 = v2;
@ -28,7 +28,7 @@ memcmp(const void *v1, const void *v2, uint n)
}
void*
memmove(void *dst, const void *src, uint n)
memmove(void *dst, const void *src, u32 n)
{
const char *s;
char *d;
@ -52,19 +52,19 @@ memmove(void *dst, const void *src, uint n)
// memcpy exists to placate GCC. Use memmove.
void*
memcpy(void *dst, const void *src, uint n)
memcpy(void *dst, const void *src, u32 n)
{
return memmove(dst, src, n);
}
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)
n--, p++, q++;
if(n == 0)
return 0;
return (uchar)*p - (uchar)*q;
return (u8)*p - (u8)*q;
}
char*

View file

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

View file

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

View file

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

View file

@ -80,9 +80,18 @@ uservec:
# load the address of usertrap(), from p->trapframe->kernel_trap
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)
# 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
# flush now-stale user entries from the TLB.
sfence.vma zero, zero
# jump to usertrap(), which does not return
@ -96,6 +105,7 @@ userret:
# a0: user page table, for satp.
# switch to the user page table.
sfence.vma zero, zero
csrw satp, a0
sfence.vma zero, zero

View file

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

View file

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

View file

@ -42,8 +42,8 @@
struct spinlock uart_tx_lock;
#define UART_TX_BUF_SIZE 32
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]
uint64 uart_tx_r; // read next from uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE]
u64 uart_tx_w; // write next to uart_tx_buf[uart_tx_w % 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

View file

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

View file

@ -17,7 +17,7 @@
#include "virtio.h"
// the address of virtio mmio register r.
#define R(r) ((volatile uint32 *)(VIRTIO0 + (r)))
#define R(r) ((volatile u32 *)(VIRTIO0 + (r)))
static struct disk {
// a set (not a ring) of DMA descriptors, with which the
@ -40,7 +40,7 @@ static struct disk {
// our own book-keeping.
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,
// for use when completion interrupt arrives.
@ -61,7 +61,7 @@ static struct disk {
void
virtio_disk_init(void)
{
uint32 status = 0;
u32 status = 0;
initlock(&disk.vdisk_lock, "virtio_disk");
@ -84,7 +84,7 @@ virtio_disk_init(void)
*R(VIRTIO_MMIO_STATUS) = status;
// 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_SCSI);
features &= ~(1 << VIRTIO_BLK_F_CONFIG_WCE);
@ -111,7 +111,7 @@ virtio_disk_init(void)
panic("virtio disk should not be ready");
// check maximum queue size.
uint32 max = *R(VIRTIO_MMIO_QUEUE_NUM_MAX);
u32 max = *R(VIRTIO_MMIO_QUEUE_NUM_MAX);
if(max == 0)
panic("virtio disk has no queue 0");
if(max < NUM)
@ -131,12 +131,12 @@ virtio_disk_init(void)
*R(VIRTIO_MMIO_QUEUE_NUM) = NUM;
// write physical addresses.
*R(VIRTIO_MMIO_QUEUE_DESC_LOW) = (uint64)disk.desc;
*R(VIRTIO_MMIO_QUEUE_DESC_HIGH) = (uint64)disk.desc >> 32;
*R(VIRTIO_MMIO_DRIVER_DESC_LOW) = (uint64)disk.avail;
*R(VIRTIO_MMIO_DRIVER_DESC_HIGH) = (uint64)disk.avail >> 32;
*R(VIRTIO_MMIO_DEVICE_DESC_LOW) = (uint64)disk.used;
*R(VIRTIO_MMIO_DEVICE_DESC_HIGH) = (uint64)disk.used >> 32;
*R(VIRTIO_MMIO_QUEUE_DESC_LOW) = (u64)disk.desc;
*R(VIRTIO_MMIO_QUEUE_DESC_HIGH) = (u64)disk.desc >> 32;
*R(VIRTIO_MMIO_DRIVER_DESC_LOW) = (u64)disk.avail;
*R(VIRTIO_MMIO_DRIVER_DESC_HIGH) = (u64)disk.avail >> 32;
*R(VIRTIO_MMIO_DEVICE_DESC_LOW) = (u64)disk.used;
*R(VIRTIO_MMIO_DEVICE_DESC_HIGH) = (u64)disk.used >> 32;
// queue is ready.
*R(VIRTIO_MMIO_QUEUE_READY) = 0x1;
@ -215,7 +215,7 @@ alloc3_desc(int *idx)
void
virtio_disk_rw(struct buf *b, int write)
{
uint64 sector = b->blockno * (BSIZE / 512);
u64 sector = b->blockno * (BSIZE / 512);
acquire(&disk.vdisk_lock);
@ -244,12 +244,12 @@ virtio_disk_rw(struct buf *b, int write)
buf0->reserved = 0;
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]].flags = VRING_DESC_F_NEXT;
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;
if(write)
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.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]].flags = VRING_DESC_F_WRITE; // device writes the status
disk.desc[idx[2]].next = 0;

View file

@ -34,14 +34,14 @@ kvmmake(void)
kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
// 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.
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
// 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.
proc_mapstacks(kpgtbl);
@ -61,7 +61,12 @@ kvminit(void)
void
kvminithart()
{
// wait for any previous writes to the page table memory to finish.
sfence_vma();
w_satp(MAKE_SATP(kernel_pagetable));
// flush stale entries from the TLB.
sfence_vma();
}
@ -78,7 +83,7 @@ kvminithart()
// 12..20 -- 9 bits of level-0 index.
// 0..11 -- 12 bits of byte offset within the page.
pte_t *
walk(pagetable_t pagetable, uint64 va, int alloc)
walk(pagetable_t pagetable, u64 va, int alloc)
{
if(va >= MAXVA)
panic("walk");
@ -100,11 +105,11 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
// Look up a virtual address, return the physical address,
// or 0 if not mapped.
// Can only be used to look up user pages.
uint64
walkaddr(pagetable_t pagetable, uint64 va)
u64
walkaddr(pagetable_t pagetable, u64 va)
{
pte_t *pte;
uint64 pa;
u64 pa;
if(va >= MAXVA)
return 0;
@ -124,7 +129,7 @@ walkaddr(pagetable_t pagetable, uint64 va)
// only used when booting.
// does not flush TLB or enable paging.
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)
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
// allocate a needed page-table page.
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;
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.
// Optionally free the physical memory.
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;
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)
panic("uvmunmap: not a leaf");
if(do_free){
uint64 pa = PTE2PA(*pte);
u64 pa = PTE2PA(*pte);
kfree((void*)pa);
}
*pte = 0;
@ -203,7 +208,7 @@ uvmcreate()
// for the very first process.
// sz must be less than a page.
void
uvmfirst(pagetable_t pagetable, uchar *src, uint sz)
uvmfirst(pagetable_t pagetable, u8 *src, u32 sz)
{
char *mem;
@ -211,17 +216,17 @@ uvmfirst(pagetable_t pagetable, uchar *src, uint sz)
panic("uvmfirst: more than a page");
mem = kalloc();
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);
}
// 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.
uint64
uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
u64
uvmalloc(pagetable_t pagetable, u64 oldsz, u64 newsz, int xperm)
{
char *mem;
uint64 a;
u64 a;
if(newsz < oldsz)
return oldsz;
@ -234,7 +239,7 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
return 0;
}
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);
uvmdealloc(pagetable, a, oldsz);
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
// need to be less than oldsz. oldsz can be larger than the actual
// process size. Returns the new process size.
uint64
uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
u64
uvmdealloc(pagetable_t pagetable, u64 oldsz, u64 newsz)
{
if(newsz >= oldsz)
return oldsz;
@ -271,7 +276,7 @@ freewalk(pagetable_t pagetable)
pte_t pte = pagetable[i];
if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){
// this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte);
u64 child = PTE2PA(pte);
freewalk((pagetable_t)child);
pagetable[i] = 0;
} else if(pte & PTE_V){
@ -284,7 +289,7 @@ freewalk(pagetable_t pagetable)
// Free user memory pages,
// then free page-table pages.
void
uvmfree(pagetable_t pagetable, uint64 sz)
uvmfree(pagetable_t pagetable, u64 sz)
{
if(sz > 0)
uvmunmap(pagetable, 0, PGROUNDUP(sz)/PGSIZE, 1);
@ -298,11 +303,11 @@ uvmfree(pagetable_t pagetable, uint64 sz)
// returns 0 on success, -1 on failure.
// frees any allocated pages on failure.
int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
uvmcopy(pagetable_t old, pagetable_t new, u64 sz)
{
pte_t *pte;
uint64 pa, i;
uint flags;
u64 pa, i;
u32 flags;
char *mem;
for(i = 0; i < sz; i += PGSIZE){
@ -315,7 +320,7 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
if((mem = kalloc()) == 0)
goto err;
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);
goto err;
}
@ -330,7 +335,7 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
// mark a PTE invalid for user access.
// used by exec for the user stack guard page.
void
uvmclear(pagetable_t pagetable, uint64 va)
uvmclear(pagetable_t pagetable, u64 va)
{
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.
// Return 0 on success, -1 on error.
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){
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.
// Return 0 on success, -1 on error.
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){
va0 = PGROUNDDOWN(srcva);
@ -395,9 +400,9 @@ copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
// until a '\0', or max.
// Return 0 on success, -1 on error.
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;
while(got_null == 0 && max > 0){

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -21,15 +21,21 @@
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
// that read user memory with copyin?
void
copyin(char *s)
{
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
u64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
for(int ai = 0; ai < 2; ai++){
uint64 addr = addrs[ai];
u64 addr = addrs[ai];
int fd = open("copyin1", O_CREATE|O_WRONLY);
if(fd < 0){
@ -70,10 +76,10 @@ copyin(char *s)
void
copyout(char *s)
{
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
u64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
for(int ai = 0; ai < 2; ai++){
uint64 addr = addrs[ai];
u64 addr = addrs[ai];
int fd = open("README", 0);
if(fd < 0){
@ -111,10 +117,10 @@ copyout(char *s)
void
copyinstr1(char *s)
{
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
u64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
for(int ai = 0; ai < 2; ai++){
uint64 addr = addrs[ai];
u64 addr = addrs[ai];
int fd = open((char *)addr, O_CREATE|O_WRONLY);
if(fd >= 0){
@ -193,11 +199,11 @@ void
copyinstr3(char *s)
{
sbrk(8192);
uint64 top = (uint64) sbrk(0);
u64 top = (u64) sbrk(0);
if((top % PGSIZE) != 0){
sbrk(PGSIZE - (top % PGSIZE));
}
top = (uint64) sbrk(0);
top = (u64) sbrk(0);
if(top % PGSIZE){
printf("oops\n");
exit(1);
@ -239,14 +245,14 @@ rwsbrk()
{
int fd, n;
uint64 a = (uint64) sbrk(8192);
u64 a = (u64) sbrk(8192);
if(a == 0xffffffffffffffffLL) {
printf("sbrk(rwsbrk) failed\n");
exit(1);
}
if ((uint64) sbrk(-8192) == 0xffffffffffffffffLL) {
if ((u64) sbrk(-8192) == 0xffffffffffffffffLL) {
printf("sbrk(rwsbrk) shrink failed\n");
exit(1);
}
@ -1391,7 +1397,7 @@ concreate(char *s)
int i, pid, n, fd;
char fa[N];
struct {
ushort inum;
u16 inum;
char name[DIRSIZ];
} de;
@ -1512,46 +1518,6 @@ linkunlink(char *s)
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
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
bigfile(char *s)
@ -2149,13 +2062,13 @@ sbrkmuch(char *s)
{
enum { BIG=100*1024*1024 };
char *c, *oldbrk, *a, *lastaddr, *p;
uint64 amt;
u64 amt;
oldbrk = sbrk(0);
// can one grow address space to something big?
a = sbrk(0);
amt = BIG - (uint64)a;
amt = BIG - (u64)a;
p = sbrk(amt);
if (p != a) {
printf("%s: sbrk test failed to grow big address space; enough phys mem?\n", s);
@ -2232,7 +2145,7 @@ kernmem(char *s)
void
MAXVAplus(char *s)
{
volatile uint64 a = MAXVA;
volatile u64 a = MAXVA;
for( ; a != 0; a <<= 1){
int pid;
pid = fork();
@ -2272,7 +2185,7 @@ sbrkfail(char *s)
for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
if((pids[i] = fork()) == 0){
// allocate a lot of memory
sbrk(BIG - (uint64)sbrk(0));
sbrk(BIG - (u64)sbrk(0));
write(fds[1], "x", 1);
// sit around until killed
for(;;) sleep(1000);
@ -2354,10 +2267,10 @@ void
validatetest(char *s)
{
int hi;
uint64 p;
u64 p;
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
if(link("nosuchfile", (char*)p) != -1){
printf("%s: link should not succeed\n", s);
@ -2532,7 +2445,7 @@ textwrite(char *s)
}
// 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.
void *big = (void*) 0xeaeb0b5b00002f5e;
void
@ -2558,7 +2471,7 @@ sbrkbugs(char *s)
exit(1);
}
if(pid == 0){
int sz = (uint64) sbrk(0);
int sz = (u64) sbrk(0);
// free all user memory; there used to be a bug that
// would not adjust p->sz correctly in this case,
// causing exit() to panic.
@ -2574,7 +2487,7 @@ sbrkbugs(char *s)
exit(1);
}
if(pid == 0){
int sz = (uint64) sbrk(0);
int sz = (u64) sbrk(0);
// set the break to somewhere in the very first
// page; there used to be a bug that would incorrectly
// free the first page.
@ -2590,7 +2503,7 @@ sbrkbugs(char *s)
}
if(pid == 0){
// 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
// cause a page to be freed. this used to cause
@ -2610,13 +2523,13 @@ sbrkbugs(char *s)
void
sbrklast(char *s)
{
uint64 top = (uint64) sbrk(0);
u64 top = (u64) sbrk(0);
if((top % 4096) != 0)
sbrk(4096 - (top % 4096));
sbrk(4096);
sbrk(10);
sbrk(-20);
top = (uint64) sbrk(0);
top = (u64) sbrk(0);
char *p = (char *) (top - 64);
p[0] = 'x';
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
// 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:
@ -2679,21 +2775,6 @@ badwrite(char *s)
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
// of memory. it's really a test that such a condition
// doesn't cause a panic.
@ -2708,7 +2789,7 @@ execout(char *s)
} else if(pid == 0){
// allocate all of memory.
while(1){
uint64 a = (uint64) sbrk(4096);
u64 a = (u64) sbrk(4096);
if(a == 0xffffffffffffffffLL)
break;
*(char*)(a + 4096 - 1) = 1;
@ -2750,6 +2831,7 @@ diskfull(char *s)
unlink(name);
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
if(fd < 0){
// oops, ran out of inodes before running out of blocks.
printf("%s: could not create file %s\n", s, name);
done = 1;
break;
@ -2767,7 +2849,8 @@ diskfull(char *s)
// now that there are no free blocks, test that dirlink()
// 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;
for(int i = 0; i < nzz; i++){
char name[32];
@ -2778,14 +2861,15 @@ diskfull(char *s)
name[4] = '\0';
unlink(name);
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
if(fd < 0){
printf("%s: could not create file %s\n", s, name);
if(fd < 0)
break;
}
close(fd);
}
mkdir("diskfulldir");
// this mkdir() is expected to fail.
if(mkdir("diskfulldir") == 0)
printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n");
unlink("diskfulldir");
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.
// touches the pages to force allocation.
@ -2836,7 +3005,7 @@ countfree()
close(fds[0]);
while(1){
uint64 a = (uint64) sbrk(4096);
u64 a = (u64) sbrk(4096);
if(a == 0xffffffffffffffff){
break;
}
@ -2875,165 +3044,58 @@ countfree()
return n;
}
// 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;
}
drivetests(int quick, int continuous, char *justone) {
do {
printf("usertests starting\n");
int free0 = countfree();
int free1 = 0;
if (runtests(quicktests, justone)) {
if(continuous != 2) {
return 1;
}
}
if(!quick) {
if (justone == 0)
printf("usertests slow tests starting\n");
if (runtests(slowtests, justone)) {
if(continuous != 2) {
return 1;
}
}
}
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
main(int argc, char *argv[])
{
int continuous = 0;
int quick = 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;
} else if(argc == 2 && strcmp(argv[1], "-C") == 0){
continuous = 2;
} else if(argc == 2 && argv[1][0] != '-'){
justone = argv[1];
} else if(argc > 1){
printf("Usage: usertests [-c] [testname]\n");
printf("Usage: usertests [-c] [-C] [-q] [testname]\n");
exit(1);
}
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");
if (drivetests(quick, continuous, justone)) {
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);
}