pagetable lab initialized
This commit is contained in:
321
kernel/defs.h
321
kernel/defs.h
@@ -1,3 +1,7 @@
|
||||
#ifdef LAB_MMAP
|
||||
typedef unsigned long size_t;
|
||||
typedef long int off_t;
|
||||
#endif
|
||||
struct buf;
|
||||
struct context;
|
||||
struct file;
|
||||
@@ -10,183 +14,226 @@ struct stat;
|
||||
struct superblock;
|
||||
|
||||
// bio.c
|
||||
void binit(void);
|
||||
struct buf *bread(uint, uint);
|
||||
void brelse(struct buf *);
|
||||
void bwrite(struct buf *);
|
||||
void bpin(struct buf *);
|
||||
void bunpin(struct buf *);
|
||||
void binit(void);
|
||||
struct buf* bread(uint, uint);
|
||||
void brelse(struct buf*);
|
||||
void bwrite(struct buf*);
|
||||
void bpin(struct buf*);
|
||||
void bunpin(struct buf*);
|
||||
|
||||
// console.c
|
||||
void consoleinit(void);
|
||||
void consoleintr(int);
|
||||
void consputc(int);
|
||||
void consoleinit(void);
|
||||
void consoleintr(int);
|
||||
void consputc(int);
|
||||
|
||||
// exec.c
|
||||
int exec(char *, char **);
|
||||
int exec(char*, char**);
|
||||
|
||||
// file.c
|
||||
struct file *filealloc(void);
|
||||
void fileclose(struct file *);
|
||||
struct file *filedup(struct file *);
|
||||
void fileinit(void);
|
||||
int fileread(struct file *, uint64, int n);
|
||||
int filestat(struct file *, uint64 addr);
|
||||
int filewrite(struct file *, uint64, int n);
|
||||
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);
|
||||
|
||||
// fs.c
|
||||
void fsinit(int);
|
||||
int dirlink(struct inode *, char *, uint);
|
||||
struct inode *dirlookup(struct inode *, char *, uint *);
|
||||
struct inode *ialloc(uint, short);
|
||||
struct inode *idup(struct inode *);
|
||||
void iinit();
|
||||
void ilock(struct inode *);
|
||||
void iput(struct inode *);
|
||||
void iunlock(struct inode *);
|
||||
void iunlockput(struct inode *);
|
||||
void iupdate(struct inode *);
|
||||
int namecmp(const char *, const char *);
|
||||
struct inode *namei(char *);
|
||||
struct inode *nameiparent(char *, char *);
|
||||
int readi(struct inode *, int, uint64, uint, uint);
|
||||
void stati(struct inode *, struct stat *);
|
||||
int writei(struct inode *, int, uint64, uint, uint);
|
||||
void itrunc(struct inode *);
|
||||
void fsinit(int);
|
||||
int dirlink(struct inode*, char*, uint);
|
||||
struct inode* dirlookup(struct inode*, char*, uint*);
|
||||
struct inode* ialloc(uint, short);
|
||||
struct inode* idup(struct inode*);
|
||||
void iinit();
|
||||
void ilock(struct inode*);
|
||||
void iput(struct inode*);
|
||||
void iunlock(struct inode*);
|
||||
void iunlockput(struct inode*);
|
||||
void iupdate(struct inode*);
|
||||
int namecmp(const char*, const char*);
|
||||
struct inode* namei(char*);
|
||||
struct inode* nameiparent(char*, char*);
|
||||
int readi(struct inode*, int, uint64, uint, uint);
|
||||
void stati(struct inode*, struct stat*);
|
||||
int writei(struct inode*, int, uint64, uint, uint);
|
||||
void itrunc(struct inode*);
|
||||
|
||||
// ramdisk.c
|
||||
void ramdiskinit(void);
|
||||
void ramdiskintr(void);
|
||||
void ramdiskrw(struct buf *);
|
||||
void ramdiskinit(void);
|
||||
void ramdiskintr(void);
|
||||
void ramdiskrw(struct buf*);
|
||||
|
||||
// kalloc.c
|
||||
void *kalloc(void);
|
||||
void kfree(void *);
|
||||
void kinit(void);
|
||||
int freemem(void);
|
||||
void* kalloc(void);
|
||||
void kfree(void *);
|
||||
void kinit(void);
|
||||
|
||||
// log.c
|
||||
void initlog(int, struct superblock *);
|
||||
void log_write(struct buf *);
|
||||
void begin_op(void);
|
||||
void end_op(void);
|
||||
void initlog(int, struct superblock*);
|
||||
void log_write(struct buf*);
|
||||
void begin_op(void);
|
||||
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 pipealloc(struct file**, struct file**);
|
||||
void pipeclose(struct pipe*, int);
|
||||
int piperead(struct pipe*, uint64, int);
|
||||
int pipewrite(struct pipe*, uint64, int);
|
||||
|
||||
// printf.c
|
||||
void printf(char *, ...);
|
||||
void panic(char *) __attribute__((noreturn));
|
||||
void printfinit(void);
|
||||
int printf(char*, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void panic(char*) __attribute__((noreturn));
|
||||
void printfinit(void);
|
||||
|
||||
// proc.c
|
||||
int cpuid(void);
|
||||
void exit(int);
|
||||
int fork(void);
|
||||
int growproc(int);
|
||||
void proc_mapstacks(pagetable_t);
|
||||
pagetable_t proc_pagetable(struct proc *);
|
||||
void proc_freepagetable(pagetable_t, uint64);
|
||||
int kill(int);
|
||||
int killed(struct proc *);
|
||||
void setkilled(struct proc *);
|
||||
struct cpu *mycpu(void);
|
||||
struct cpu *getmycpu(void);
|
||||
struct proc *myproc();
|
||||
void procinit(void);
|
||||
void scheduler(void) __attribute__((noreturn));
|
||||
void sched(void);
|
||||
void sleep(void *, struct spinlock *);
|
||||
void userinit(void);
|
||||
int wait(uint64);
|
||||
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);
|
||||
void procdump(void);
|
||||
int proc_size(void);
|
||||
int update_load(void);
|
||||
int cpuid(void);
|
||||
void exit(int);
|
||||
int fork(void);
|
||||
int growproc(int);
|
||||
void proc_mapstacks(pagetable_t);
|
||||
pagetable_t proc_pagetable(struct proc *);
|
||||
void proc_freepagetable(pagetable_t, uint64);
|
||||
int kill(int);
|
||||
int killed(struct proc*);
|
||||
void setkilled(struct proc*);
|
||||
struct cpu* mycpu(void);
|
||||
struct cpu* getmycpu(void);
|
||||
struct proc* myproc();
|
||||
void procinit(void);
|
||||
void scheduler(void) __attribute__((noreturn));
|
||||
void sched(void);
|
||||
void sleep(void*, struct spinlock*);
|
||||
void userinit(void);
|
||||
int wait(uint64);
|
||||
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);
|
||||
void procdump(void);
|
||||
|
||||
// swtch.S
|
||||
void swtch(struct context *, struct context *);
|
||||
void swtch(struct context*, struct context*);
|
||||
|
||||
// spinlock.c
|
||||
void acquire(struct spinlock *);
|
||||
int holding(struct spinlock *);
|
||||
void initlock(struct spinlock *, char *);
|
||||
void release(struct spinlock *);
|
||||
void push_off(void);
|
||||
void pop_off(void);
|
||||
void acquire(struct spinlock*);
|
||||
int holding(struct spinlock*);
|
||||
void initlock(struct spinlock*, char*);
|
||||
void release(struct spinlock*);
|
||||
void push_off(void);
|
||||
void pop_off(void);
|
||||
int atomic_read4(int *addr);
|
||||
#ifdef LAB_LOCK
|
||||
void freelock(struct spinlock*);
|
||||
#endif
|
||||
|
||||
// sleeplock.c
|
||||
void acquiresleep(struct sleeplock *);
|
||||
void releasesleep(struct sleeplock *);
|
||||
int holdingsleep(struct sleeplock *);
|
||||
void initsleeplock(struct sleeplock *, char *);
|
||||
void acquiresleep(struct sleeplock*);
|
||||
void releasesleep(struct sleeplock*);
|
||||
int holdingsleep(struct sleeplock*);
|
||||
void initsleeplock(struct sleeplock*, char*);
|
||||
|
||||
// string.c
|
||||
int memcmp(const void *, const void *, uint);
|
||||
void *memmove(void *, const void *, uint);
|
||||
void *memset(void *, int, uint);
|
||||
char *safestrcpy(char *, const char *, int);
|
||||
int strlen(const char *);
|
||||
int strncmp(const char *, const char *, uint);
|
||||
char *strncpy(char *, const char *, int);
|
||||
int memcmp(const void*, const void*, uint);
|
||||
void* memmove(void*, const void*, uint);
|
||||
void* memset(void*, int, uint);
|
||||
char* safestrcpy(char*, const char*, int);
|
||||
int strlen(const char*);
|
||||
int strncmp(const char*, const char*, uint);
|
||||
char* strncpy(char*, const char*, int);
|
||||
|
||||
// syscall.c
|
||||
void argint(int, int *);
|
||||
int argstr(int, char *, int);
|
||||
void argaddr(int, uint64 *);
|
||||
int fetchstr(uint64, char *, int);
|
||||
int fetchaddr(uint64, uint64 *);
|
||||
void syscall();
|
||||
void argint(int, int*);
|
||||
int argstr(int, char*, int);
|
||||
void argaddr(int, uint64 *);
|
||||
int fetchstr(uint64, char*, int);
|
||||
int fetchaddr(uint64, uint64*);
|
||||
void syscall();
|
||||
|
||||
// trap.c
|
||||
extern uint ticks;
|
||||
void trapinit(void);
|
||||
void trapinithart(void);
|
||||
extern uint ticks;
|
||||
void trapinit(void);
|
||||
void trapinithart(void);
|
||||
extern struct spinlock tickslock;
|
||||
void usertrapret(void);
|
||||
void usertrapret(void);
|
||||
|
||||
// uart.c
|
||||
void uartinit(void);
|
||||
void uartintr(void);
|
||||
void uartputc(int);
|
||||
void uartputc_sync(int);
|
||||
int uartgetc(void);
|
||||
void uartinit(void);
|
||||
void uartintr(void);
|
||||
void uartputc(int);
|
||||
void uartputc_sync(int);
|
||||
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);
|
||||
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 kvminit(void);
|
||||
void kvminithart(void);
|
||||
void kvmmap(pagetable_t, uint64, uint64, uint64, int);
|
||||
int mappages(pagetable_t, uint64, uint64, uint64, 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);
|
||||
#if defined(LAB_PGTBL) || defined(SOL_MMAP)
|
||||
void vmprint(pagetable_t);
|
||||
#endif
|
||||
#ifdef LAB_PGTBL
|
||||
pte_t* pgpte(pagetable_t, uint64);
|
||||
#endif
|
||||
|
||||
// plic.c
|
||||
void plicinit(void);
|
||||
void plicinithart(void);
|
||||
int plic_claim(void);
|
||||
void plic_complete(int);
|
||||
void plicinit(void);
|
||||
void plicinithart(void);
|
||||
int plic_claim(void);
|
||||
void plic_complete(int);
|
||||
|
||||
// virtio_disk.c
|
||||
void virtio_disk_init(void);
|
||||
void virtio_disk_rw(struct buf *, int);
|
||||
void virtio_disk_intr(void);
|
||||
void virtio_disk_init(void);
|
||||
void virtio_disk_rw(struct buf *, int);
|
||||
void virtio_disk_intr(void);
|
||||
|
||||
// number of elements in fixed-size array
|
||||
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
// vmcopyin.c
|
||||
int copyin_new(pagetable_t, char *, uint64, uint64);
|
||||
int copyinstr_new(pagetable_t, char *, uint64, uint64);
|
||||
#endif
|
||||
|
||||
#ifdef LAB_LOCK
|
||||
// stats.c
|
||||
void statsinit(void);
|
||||
void statsinc(void);
|
||||
|
||||
// sprintf.c
|
||||
int snprintf(char*, unsigned long, const char*, ...);
|
||||
#endif
|
||||
|
||||
#ifdef KCSAN
|
||||
void kcsaninit();
|
||||
#endif
|
||||
|
||||
#ifdef LAB_NET
|
||||
// pci.c
|
||||
void pci_init();
|
||||
|
||||
// e1000.c
|
||||
void e1000_init(uint32 *);
|
||||
void e1000_intr(void);
|
||||
int e1000_transmit(char *, int);
|
||||
|
||||
// net.c
|
||||
void netinit(void);
|
||||
void net_rx(char *buf, int len);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -75,17 +75,17 @@ exec(char *path, char **argv)
|
||||
p = myproc();
|
||||
uint64 oldsz = p->sz;
|
||||
|
||||
// Allocate two pages at the next page boundary.
|
||||
// Allocate some pages at the next page boundary.
|
||||
// Make the first inaccessible as a stack guard.
|
||||
// Use the second as the user stack.
|
||||
// Use the rest as the user stack.
|
||||
sz = PGROUNDUP(sz);
|
||||
uint64 sz1;
|
||||
if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE, PTE_W)) == 0)
|
||||
if((sz1 = uvmalloc(pagetable, sz, sz + (USERSTACK+1)*PGSIZE, PTE_W)) == 0)
|
||||
goto bad;
|
||||
sz = sz1;
|
||||
uvmclear(pagetable, sz-2*PGSIZE);
|
||||
uvmclear(pagetable, sz-(USERSTACK+1)*PGSIZE);
|
||||
sp = sz;
|
||||
stackbase = sp - PGSIZE;
|
||||
stackbase = sp - USERSTACK*PGSIZE;
|
||||
|
||||
// Push argument strings, prepare rest of stack in ustack.
|
||||
for(argc = 0; argv[argc]; argc++) {
|
||||
|
||||
43
kernel/fs.h
43
kernel/fs.h
@@ -1,9 +1,9 @@
|
||||
// On-disk file system format.
|
||||
// Both the kernel and user programs use this header file.
|
||||
#include "kernel/types.h"
|
||||
|
||||
#define ROOTINO 1 // root i-number
|
||||
#define BSIZE 1024 // block size
|
||||
|
||||
#define ROOTINO 1 // root i-number
|
||||
#define BSIZE 1024 // block size
|
||||
|
||||
// Disk layout:
|
||||
// [ boot block | super block | log | inode blocks |
|
||||
@@ -12,14 +12,14 @@
|
||||
// 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
|
||||
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
|
||||
};
|
||||
|
||||
#define FSMAGIC 0x10203040
|
||||
@@ -30,25 +30,25 @@ struct superblock {
|
||||
|
||||
// On-disk inode structure
|
||||
struct dinode {
|
||||
short type; // File type
|
||||
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
|
||||
short type; // File type
|
||||
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
|
||||
};
|
||||
|
||||
// Inodes per block.
|
||||
#define IPB (BSIZE / sizeof(struct dinode))
|
||||
#define IPB (BSIZE / sizeof(struct dinode))
|
||||
|
||||
// Block containing inode i
|
||||
#define IBLOCK(i, sb) ((i) / IPB + sb.inodestart)
|
||||
#define IBLOCK(i, sb) ((i) / IPB + sb.inodestart)
|
||||
|
||||
// Bitmap bits per block
|
||||
#define BPB (BSIZE * 8)
|
||||
#define BPB (BSIZE*8)
|
||||
|
||||
// Block of free map containing bit for block b
|
||||
#define BBLOCK(b, sb) ((b) / BPB + sb.bmapstart)
|
||||
#define BBLOCK(b, sb) ((b)/BPB + sb.bmapstart)
|
||||
|
||||
// Directory is a file containing a sequence of dirent structures.
|
||||
#define DIRSIZ 14
|
||||
@@ -57,3 +57,4 @@ struct dirent {
|
||||
ushort inum;
|
||||
char name[DIRSIZ];
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "memlayout.h"
|
||||
#include "spinlock.h"
|
||||
#include "riscv.h"
|
||||
#include "proc.h"
|
||||
#include "defs.h"
|
||||
|
||||
void freerange(void *pa_start, void *pa_end);
|
||||
@@ -81,17 +80,3 @@ kalloc(void)
|
||||
memset((char*)r, 5, PGSIZE); // fill with junk
|
||||
return (void*)r;
|
||||
}
|
||||
|
||||
int
|
||||
freemem(void)
|
||||
{
|
||||
struct run* p = kmem.freelist;
|
||||
uint64 num = 0;
|
||||
while (p) {
|
||||
num += 1;
|
||||
p = p->next;
|
||||
}
|
||||
return num * PGSIZE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# mode come here.
|
||||
#
|
||||
# the current stack is a kernel stack.
|
||||
# push all registers, call kerneltrap().
|
||||
# push registers, call kerneltrap().
|
||||
# when kerneltrap() returns, restore registers, return.
|
||||
#
|
||||
.globl kerneltrap
|
||||
@@ -13,7 +13,7 @@ kernelvec:
|
||||
# make room to save registers.
|
||||
addi sp, sp, -256
|
||||
|
||||
# save the registers.
|
||||
# save caller-saved registers.
|
||||
sd ra, 0(sp)
|
||||
sd sp, 8(sp)
|
||||
sd gp, 16(sp)
|
||||
@@ -21,8 +21,6 @@ kernelvec:
|
||||
sd t0, 32(sp)
|
||||
sd t1, 40(sp)
|
||||
sd t2, 48(sp)
|
||||
sd s0, 56(sp)
|
||||
sd s1, 64(sp)
|
||||
sd a0, 72(sp)
|
||||
sd a1, 80(sp)
|
||||
sd a2, 88(sp)
|
||||
@@ -31,16 +29,6 @@ kernelvec:
|
||||
sd a5, 112(sp)
|
||||
sd a6, 120(sp)
|
||||
sd a7, 128(sp)
|
||||
sd s2, 136(sp)
|
||||
sd s3, 144(sp)
|
||||
sd s4, 152(sp)
|
||||
sd s5, 160(sp)
|
||||
sd s6, 168(sp)
|
||||
sd s7, 176(sp)
|
||||
sd s8, 184(sp)
|
||||
sd s9, 192(sp)
|
||||
sd s10, 200(sp)
|
||||
sd s11, 208(sp)
|
||||
sd t3, 216(sp)
|
||||
sd t4, 224(sp)
|
||||
sd t5, 232(sp)
|
||||
@@ -57,8 +45,6 @@ kernelvec:
|
||||
ld t0, 32(sp)
|
||||
ld t1, 40(sp)
|
||||
ld t2, 48(sp)
|
||||
ld s0, 56(sp)
|
||||
ld s1, 64(sp)
|
||||
ld a0, 72(sp)
|
||||
ld a1, 80(sp)
|
||||
ld a2, 88(sp)
|
||||
@@ -67,16 +53,6 @@ kernelvec:
|
||||
ld a5, 112(sp)
|
||||
ld a6, 120(sp)
|
||||
ld a7, 128(sp)
|
||||
ld s2, 136(sp)
|
||||
ld s3, 144(sp)
|
||||
ld s4, 152(sp)
|
||||
ld s5, 160(sp)
|
||||
ld s6, 168(sp)
|
||||
ld s7, 176(sp)
|
||||
ld s8, 184(sp)
|
||||
ld s9, 192(sp)
|
||||
ld s10, 200(sp)
|
||||
ld s11, 208(sp)
|
||||
ld t3, 216(sp)
|
||||
ld t4, 224(sp)
|
||||
ld t5, 232(sp)
|
||||
@@ -86,39 +62,3 @@ kernelvec:
|
||||
|
||||
# return to whatever we were doing in the kernel.
|
||||
sret
|
||||
|
||||
#
|
||||
# machine-mode timer interrupt.
|
||||
#
|
||||
.globl timervec
|
||||
.align 4
|
||||
timervec:
|
||||
# start.c has set up the memory that mscratch points to:
|
||||
# scratch[0,8,16] : register save area.
|
||||
# scratch[24] : address of CLINT's MTIMECMP register.
|
||||
# scratch[32] : desired interval between interrupts.
|
||||
|
||||
csrrw a0, mscratch, a0
|
||||
sd a1, 0(a0)
|
||||
sd a2, 8(a0)
|
||||
sd a3, 16(a0)
|
||||
|
||||
# schedule the next timer interrupt
|
||||
# by adding interval to mtimecmp.
|
||||
ld a1, 24(a0) # CLINT_MTIMECMP(hart)
|
||||
ld a2, 32(a0) # interval
|
||||
ld a3, 0(a1)
|
||||
add a3, a3, a2
|
||||
sd a3, 0(a1)
|
||||
|
||||
# arrange for a supervisor software interrupt
|
||||
# after this handler returns.
|
||||
li a1, 2
|
||||
csrw sip, a1
|
||||
|
||||
ld a3, 16(a0)
|
||||
ld a2, 8(a0)
|
||||
ld a1, 0(a0)
|
||||
csrrw a0, mscratch, a0
|
||||
|
||||
mret
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
#define VIRTIO0 0x10001000
|
||||
#define VIRTIO0_IRQ 1
|
||||
|
||||
// core local interruptor (CLINT), which contains the timer.
|
||||
#define CLINT 0x2000000L
|
||||
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8*(hartid))
|
||||
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.
|
||||
#ifdef LAB_NET
|
||||
#define E1000_IRQ 33
|
||||
#endif
|
||||
|
||||
// qemu puts platform-level interrupt controller (PLIC) here.
|
||||
#define PLIC 0x0c000000L
|
||||
@@ -50,7 +49,7 @@
|
||||
|
||||
// map kernel stacks beneath the trampoline,
|
||||
// each surrounded by invalid guard pages.
|
||||
#define KSTACK(p) (TRAMPOLINE - ((p)+1)* 2*PGSIZE)
|
||||
#define KSTACK(p) (TRAMPOLINE - (p)*2*PGSIZE - 3*PGSIZE)
|
||||
|
||||
// User memory layout.
|
||||
// Address zero first:
|
||||
@@ -59,6 +58,14 @@
|
||||
// fixed-size stack
|
||||
// expandable heap
|
||||
// ...
|
||||
// USYSCALL (shared with kernel)
|
||||
// TRAPFRAME (p->trapframe, used by the trampoline)
|
||||
// TRAMPOLINE (the same page as in the kernel)
|
||||
#define TRAPFRAME (TRAMPOLINE - PGSIZE)
|
||||
#ifdef LAB_PGTBL
|
||||
#define USYSCALL (TRAPFRAME - PGSIZE)
|
||||
|
||||
struct usyscall {
|
||||
int pid; // Process ID
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -11,3 +11,5 @@
|
||||
#define NBUF (MAXOPBLOCKS*3) // size of disk block cache
|
||||
#define FSSIZE 2000 // size of file system in blocks
|
||||
#define MAXPATH 128 // maximum file path name
|
||||
#define USERSTACK 1 // user stack pages
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ static struct {
|
||||
static char digits[] = "0123456789abcdef";
|
||||
|
||||
static void
|
||||
printint(int xx, int base, int sign)
|
||||
printint(long long xx, int base, int sign)
|
||||
{
|
||||
char buf[16];
|
||||
int i;
|
||||
uint x;
|
||||
unsigned long long x;
|
||||
|
||||
if(sign && (sign = xx < 0))
|
||||
if(sign && (sign = (xx < 0)))
|
||||
x = -xx;
|
||||
else
|
||||
x = xx;
|
||||
@@ -59,30 +59,71 @@ printptr(uint64 x)
|
||||
consputc(digits[x >> (sizeof(uint64) * 8 - 4)]);
|
||||
}
|
||||
|
||||
// Print to the console. only understands %d, %x, %p, %s.
|
||||
void
|
||||
// Print to the console.
|
||||
int
|
||||
printf(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, c, locking;
|
||||
int i, cx, c0, c1, c2, locking;
|
||||
char *s;
|
||||
|
||||
locking = pr.locking;
|
||||
if(locking)
|
||||
acquire(&pr.lock);
|
||||
|
||||
if (fmt == 0)
|
||||
panic("null fmt");
|
||||
|
||||
va_start(ap, fmt);
|
||||
for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
|
||||
if(c != '%'){
|
||||
consputc(c);
|
||||
for(i = 0; (cx = fmt[i] & 0xff) != 0; i++){
|
||||
if(cx != '%'){
|
||||
consputc(cx);
|
||||
continue;
|
||||
}
|
||||
c = fmt[++i] & 0xff;
|
||||
if(c == 0)
|
||||
i++;
|
||||
c0 = fmt[i+0] & 0xff;
|
||||
c1 = c2 = 0;
|
||||
if(c0) c1 = fmt[i+1] & 0xff;
|
||||
if(c1) c2 = fmt[i+2] & 0xff;
|
||||
if(c0 == 'd'){
|
||||
printint(va_arg(ap, int), 10, 1);
|
||||
} else if(c0 == 'l' && c1 == 'd'){
|
||||
printint(va_arg(ap, uint64), 10, 1);
|
||||
i += 1;
|
||||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'd'){
|
||||
printint(va_arg(ap, uint64), 10, 1);
|
||||
i += 2;
|
||||
} else if(c0 == 'u'){
|
||||
printint(va_arg(ap, int), 10, 0);
|
||||
} else if(c0 == 'l' && c1 == 'u'){
|
||||
printint(va_arg(ap, uint64), 10, 0);
|
||||
i += 1;
|
||||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'u'){
|
||||
printint(va_arg(ap, uint64), 10, 0);
|
||||
i += 2;
|
||||
} else if(c0 == 'x'){
|
||||
printint(va_arg(ap, int), 16, 0);
|
||||
} else if(c0 == 'l' && c1 == 'x'){
|
||||
printint(va_arg(ap, uint64), 16, 0);
|
||||
i += 1;
|
||||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'x'){
|
||||
printint(va_arg(ap, uint64), 16, 0);
|
||||
i += 2;
|
||||
} else if(c0 == 'p'){
|
||||
printptr(va_arg(ap, uint64));
|
||||
} else if(c0 == 's'){
|
||||
if((s = va_arg(ap, char*)) == 0)
|
||||
s = "(null)";
|
||||
for(; *s; s++)
|
||||
consputc(*s);
|
||||
} else if(c0 == '%'){
|
||||
consputc('%');
|
||||
} else if(c0 == 0){
|
||||
break;
|
||||
} else {
|
||||
// Print unknown % sequence to draw attention.
|
||||
consputc('%');
|
||||
consputc(c0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
switch(c){
|
||||
case 'd':
|
||||
printint(va_arg(ap, int), 10, 1);
|
||||
@@ -108,11 +149,14 @@ printf(char *fmt, ...)
|
||||
consputc(c);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if(locking)
|
||||
release(&pr.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -120,8 +164,7 @@ panic(char *s)
|
||||
{
|
||||
pr.locking = 0;
|
||||
printf("panic: ");
|
||||
printf(s);
|
||||
printf("\n");
|
||||
printf("%s\n", s);
|
||||
panicked = 1; // freeze uart output from other CPUs
|
||||
for(;;)
|
||||
;
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
#include "spinlock.h"
|
||||
#include "proc.h"
|
||||
#include "defs.h"
|
||||
#include "sysinfo.h"
|
||||
|
||||
uint64 current_load = 0;
|
||||
|
||||
struct cpu cpus[NCPU];
|
||||
|
||||
@@ -149,9 +146,6 @@ found:
|
||||
p->context.ra = (uint64)forkret;
|
||||
p->context.sp = p->kstack + PGSIZE;
|
||||
|
||||
// 初始化计数器
|
||||
memset(p->syscall_counts, 0, sizeof(p->syscall_counts));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -316,8 +310,6 @@ fork(void)
|
||||
|
||||
safestrcpy(np->name, p->name, sizeof(p->name));
|
||||
|
||||
// 复制掩码
|
||||
np->tracemask = p->tracemask;
|
||||
pid = np->pid;
|
||||
|
||||
release(&np->lock);
|
||||
@@ -454,7 +446,6 @@ scheduler(void)
|
||||
{
|
||||
struct proc *p;
|
||||
struct cpu *c = mycpu();
|
||||
/*update_load_avg();*/
|
||||
|
||||
c->proc = 0;
|
||||
for(;;){
|
||||
@@ -463,6 +454,7 @@ scheduler(void)
|
||||
// processes are waiting.
|
||||
intr_on();
|
||||
|
||||
int found = 0;
|
||||
for(p = proc; p < &proc[NPROC]; p++) {
|
||||
acquire(&p->lock);
|
||||
if(p->state == RUNNABLE) {
|
||||
@@ -471,15 +463,20 @@ scheduler(void)
|
||||
// before jumping back to us.
|
||||
p->state = RUNNING;
|
||||
c->proc = p;
|
||||
current_load += 1;
|
||||
swtch(&c->context, &p->context);
|
||||
|
||||
// Process is done running for now.
|
||||
// It should have changed its p->state before coming back.
|
||||
c->proc = 0;
|
||||
found = 1;
|
||||
}
|
||||
release(&p->lock);
|
||||
}
|
||||
if(found == 0) {
|
||||
// nothing to run; stop running on this core until an interrupt.
|
||||
intr_on();
|
||||
asm volatile("wfi");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,18 +693,3 @@ procdump(void)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
proc_size()
|
||||
{
|
||||
int i =0, n = 0;
|
||||
for (; i < NPROC; ++i) {
|
||||
if (proc[i].state != UNUSED) n += 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
update_load() {
|
||||
return current_load;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#include "defs.h"
|
||||
|
||||
// Saved registers for kernel context switches.
|
||||
struct context {
|
||||
uint64 ra;
|
||||
@@ -93,7 +91,6 @@ struct proc {
|
||||
int killed; // If non-zero, have been killed
|
||||
int xstate; // Exit status to be returned to parent's wait
|
||||
int pid; // Process ID
|
||||
int tracemask; // Trace Mask
|
||||
|
||||
// wait_lock must be held when using this:
|
||||
struct proc *parent; // Parent process
|
||||
@@ -107,5 +104,4 @@ struct proc {
|
||||
struct file *ofile[NOFILE]; // Open files
|
||||
struct inode *cwd; // Current directory
|
||||
char name[16]; // Process name (debugging)
|
||||
int syscall_counts[24]; // 每个系统调用的调用次数
|
||||
};
|
||||
|
||||
@@ -96,9 +96,7 @@ w_sie(uint64 x)
|
||||
}
|
||||
|
||||
// Machine-mode Interrupt Enable
|
||||
#define MIE_MEIE (1L << 11) // external
|
||||
#define MIE_MTIE (1L << 7) // timer
|
||||
#define MIE_MSIE (1L << 3) // software
|
||||
#define MIE_STIE (1L << 5) // supervisor timer
|
||||
static inline uint64
|
||||
r_mie()
|
||||
{
|
||||
@@ -176,11 +174,38 @@ r_stvec()
|
||||
return x;
|
||||
}
|
||||
|
||||
// Machine-mode interrupt vector
|
||||
static inline void
|
||||
w_mtvec(uint64 x)
|
||||
// Supervisor Timer Comparison Register
|
||||
static inline uint64
|
||||
r_stimecmp()
|
||||
{
|
||||
asm volatile("csrw mtvec, %0" : : "r" (x));
|
||||
uint64 x;
|
||||
// asm volatile("csrr %0, stimecmp" : "=r" (x) );
|
||||
asm volatile("csrr %0, 0x14d" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_stimecmp(uint64 x)
|
||||
{
|
||||
// asm volatile("csrw stimecmp, %0" : : "r" (x));
|
||||
asm volatile("csrw 0x14d, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Machine Environment Configuration Register
|
||||
static inline uint64
|
||||
r_menvcfg()
|
||||
{
|
||||
uint64 x;
|
||||
// asm volatile("csrr %0, menvcfg" : "=r" (x) );
|
||||
asm volatile("csrr %0, 0x30a" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_menvcfg(uint64 x)
|
||||
{
|
||||
//asm volatile("csrw menvcfg, %0" : : "r" (x));
|
||||
asm volatile("csrw 0x30a, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Physical Memory Protection
|
||||
@@ -217,12 +242,6 @@ r_satp()
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_mscratch(uint64 x)
|
||||
{
|
||||
asm volatile("csrw mscratch, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Supervisor Trap Cause
|
||||
static inline uint64
|
||||
r_scause()
|
||||
@@ -295,6 +314,14 @@ r_sp()
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline uint64
|
||||
r_fp()
|
||||
{
|
||||
uint64 x;
|
||||
asm volatile("mv %0, s0" : "=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
|
||||
@@ -335,6 +362,11 @@ typedef uint64 *pagetable_t; // 512 PTEs
|
||||
#define PGSIZE 4096 // bytes per page
|
||||
#define PGSHIFT 12 // bits of offset within a page
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
#define SUPERPGSIZE (2 * (1 << 20)) // bytes per page
|
||||
#define SUPERPGROUNDUP(sz) (((sz)+SUPERPGSIZE-1) & ~(SUPERPGSIZE-1))
|
||||
#endif
|
||||
|
||||
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
|
||||
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))
|
||||
|
||||
@@ -344,6 +376,12 @@ typedef uint64 *pagetable_t; // 512 PTEs
|
||||
#define PTE_X (1L << 3)
|
||||
#define PTE_U (1L << 4) // user can access
|
||||
|
||||
|
||||
|
||||
#if defined(LAB_MMAP) || defined(LAB_PGTBL)
|
||||
#define PTE_LEAF(pte) (((pte) & PTE_R) | ((pte) & PTE_W) | ((pte) & PTE_X))
|
||||
#endif
|
||||
|
||||
// shift a physical address to the right place for a PTE.
|
||||
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
|
||||
|
||||
|
||||
@@ -10,12 +10,6 @@ void timerinit();
|
||||
// entry.S needs one stack per CPU.
|
||||
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
|
||||
|
||||
// a scratch area per CPU for machine-mode timer interrupts.
|
||||
uint64 timer_scratch[NCPU][5];
|
||||
|
||||
// assembly code in kernelvec.S for machine-mode timer interrupt.
|
||||
extern void timervec();
|
||||
|
||||
// entry.S jumps here in machine mode on stack0.
|
||||
void
|
||||
start()
|
||||
@@ -54,36 +48,19 @@ start()
|
||||
asm volatile("mret");
|
||||
}
|
||||
|
||||
// arrange to receive timer interrupts.
|
||||
// they will arrive in machine mode at
|
||||
// at timervec in kernelvec.S,
|
||||
// which turns them into software interrupts for
|
||||
// devintr() in trap.c.
|
||||
// ask each hart to generate timer interrupts.
|
||||
void
|
||||
timerinit()
|
||||
{
|
||||
// each CPU has a separate source of timer interrupts.
|
||||
int id = r_mhartid();
|
||||
|
||||
// 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;
|
||||
|
||||
// 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];
|
||||
scratch[3] = CLINT_MTIMECMP(id);
|
||||
scratch[4] = interval;
|
||||
w_mscratch((uint64)scratch);
|
||||
|
||||
// set the machine-mode trap handler.
|
||||
w_mtvec((uint64)timervec);
|
||||
|
||||
// enable machine-mode interrupts.
|
||||
w_mstatus(r_mstatus() | MSTATUS_MIE);
|
||||
|
||||
// enable machine-mode timer interrupts.
|
||||
w_mie(r_mie() | MIE_MTIE);
|
||||
// enable supervisor-mode timer interrupts.
|
||||
w_mie(r_mie() | MIE_STIE);
|
||||
|
||||
// enable the sstc extension (i.e. stimecmp).
|
||||
w_menvcfg(r_menvcfg() | (1L << 63));
|
||||
|
||||
// allow supervisor to use stimecmp and time.
|
||||
w_mcounteren(r_mcounteren() | 2);
|
||||
|
||||
// ask for the very first timer interrupt.
|
||||
w_stimecmp(r_time() + 1000000);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#define T_DIR 1 // Directory
|
||||
#define T_FILE 2 // File
|
||||
#define T_DEVICE 3 // Device
|
||||
#include "types.h"
|
||||
#define T_DIR 1 // Directory
|
||||
#define T_FILE 2 // File
|
||||
#define T_DEVICE 3 // Device
|
||||
|
||||
struct stat {
|
||||
int dev; // File system's disk device
|
||||
|
||||
@@ -7,11 +7,6 @@
|
||||
#include "syscall.h"
|
||||
#include "defs.h"
|
||||
|
||||
// 保留系统调用别名
|
||||
char* syscalls_name[25] = {"", "fork", "exit", "wait", "pipe", "read", "kill", "exec",
|
||||
"fstat", "chdir", "dup", "getpid", "sbrk", "sleep", "uptime",
|
||||
"open", "write", "mknod", "unlink", "link", "mkdir", "close", "trace", "sysinfo"};
|
||||
|
||||
// Fetch the uint64 at addr from the current process.
|
||||
int
|
||||
fetchaddr(uint64 addr, uint64 *ip)
|
||||
@@ -106,8 +101,17 @@ extern uint64 sys_unlink(void);
|
||||
extern uint64 sys_link(void);
|
||||
extern uint64 sys_mkdir(void);
|
||||
extern uint64 sys_close(void);
|
||||
extern uint64 sys_trace(void);
|
||||
extern uint64 sys_sysinfo(void);
|
||||
|
||||
#ifdef LAB_NET
|
||||
extern uint64 sys_bind(void);
|
||||
extern uint64 sys_unbind(void);
|
||||
extern uint64 sys_send(void);
|
||||
extern uint64 sys_recv(void);
|
||||
#endif
|
||||
#ifdef LAB_PGTBL
|
||||
extern uint64 sys_pgpte(void);
|
||||
extern uint64 sys_kpgtbl(void);
|
||||
#endif
|
||||
|
||||
// An array mapping syscall numbers from syscall.h
|
||||
// to the function that handles the system call.
|
||||
@@ -133,10 +137,20 @@ static uint64 (*syscalls[])(void) = {
|
||||
[SYS_link] sys_link,
|
||||
[SYS_mkdir] sys_mkdir,
|
||||
[SYS_close] sys_close,
|
||||
[SYS_trace] sys_trace,
|
||||
[SYS_sysinfo] sys_sysinfo,
|
||||
#ifdef LAB_NET
|
||||
[SYS_bind] sys_bind,
|
||||
[SYS_unbind] sys_unbind,
|
||||
[SYS_send] sys_send,
|
||||
[SYS_recv] sys_recv,
|
||||
#endif
|
||||
#ifdef LAB_PGTBL
|
||||
[SYS_pgpte] sys_pgpte,
|
||||
[SYS_kpgtbl] sys_kpgtbl,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
syscall(void)
|
||||
{
|
||||
@@ -148,12 +162,6 @@ syscall(void)
|
||||
// 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]();
|
||||
if (p->tracemask & (1 << num)) {
|
||||
p->syscall_counts[num]++;
|
||||
printf("%d: syscall %s(trace counts: %d) -> %d\n",
|
||||
p->pid, syscalls_name[num], p->syscall_counts[num], p->trapframe->a0);
|
||||
printf("a1:%d a2:%d a3:%d a4:%d a5:%d a6:%d a7:%d\n",p->trapframe->a1,p->trapframe->a2,p->trapframe->a3,p->trapframe->a4,p->trapframe->a5,p->trapframe->a6,p->trapframe->a7);
|
||||
}
|
||||
} else {
|
||||
printf("%d %s: unknown sys call %d\n",
|
||||
p->pid, p->name, num);
|
||||
|
||||
@@ -20,5 +20,19 @@
|
||||
#define SYS_link 19
|
||||
#define SYS_mkdir 20
|
||||
#define SYS_close 21
|
||||
#define SYS_trace 22
|
||||
#define SYS_sysinfo 23
|
||||
|
||||
// System calls for labs
|
||||
#define SYS_trace 22
|
||||
#define SYS_sysinfo 23
|
||||
#define SYS_sigalarm 24
|
||||
#define SYS_sigreturn 25
|
||||
#define SYS_symlink 26
|
||||
#define SYS_mmap 27
|
||||
#define SYS_munmap 28
|
||||
#define SYS_bind 29
|
||||
#define SYS_unbind 30
|
||||
#define SYS_send 31
|
||||
#define SYS_recv 32
|
||||
#define SYS_pgpte 33
|
||||
#define SYS_kpgtbl 34
|
||||
#define SYS_pgaccess 35
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#include "types.h"
|
||||
#include "riscv.h"
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "defs.h"
|
||||
#include "memlayout.h"
|
||||
#include "spinlock.h"
|
||||
#include "proc.h"
|
||||
#include "sysinfo.h"
|
||||
|
||||
uint64
|
||||
sys_exit(void)
|
||||
@@ -55,6 +54,7 @@ sys_sleep(void)
|
||||
int n;
|
||||
uint ticks0;
|
||||
|
||||
|
||||
argint(0, &n);
|
||||
if(n < 0)
|
||||
n = 0;
|
||||
@@ -71,6 +71,37 @@ sys_sleep(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
int
|
||||
sys_pgpte(void)
|
||||
{
|
||||
uint64 va;
|
||||
struct proc *p;
|
||||
|
||||
p = myproc();
|
||||
argaddr(0, &va);
|
||||
pte_t *pte = pgpte(p->pagetable, va);
|
||||
if(pte != 0) {
|
||||
return (uint64) *pte;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
int
|
||||
sys_kpgtbl(void)
|
||||
{
|
||||
struct proc *p;
|
||||
|
||||
p = myproc();
|
||||
vmprint(p->pagetable);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint64
|
||||
sys_kill(void)
|
||||
{
|
||||
@@ -92,30 +123,3 @@ sys_uptime(void)
|
||||
release(&tickslock);
|
||||
return xticks;
|
||||
}
|
||||
|
||||
uint64
|
||||
sys_trace(void)
|
||||
{
|
||||
int n;
|
||||
argint(0, &n);
|
||||
if(n<0) return -1;
|
||||
myproc()->tracemask = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64
|
||||
sys_sysinfo(void)
|
||||
{
|
||||
struct sysinfo info;
|
||||
uint64 addr;
|
||||
argaddr(0, &addr);
|
||||
if (addr < 0) return -1;
|
||||
struct proc* p = myproc();
|
||||
info.nproc = proc_size();
|
||||
info.freemem = freemem();
|
||||
info.unused_proc_num = NPROC - info.nproc;
|
||||
info.load_avg = update_load() * 100 / sys_uptime();
|
||||
if (copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ usertrap(void)
|
||||
} else if((which_dev = devintr()) != 0){
|
||||
// ok
|
||||
} else {
|
||||
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
|
||||
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
|
||||
printf("usertrap(): unexpected scause 0x%lx pid=%d\n", r_scause(), p->pid);
|
||||
printf(" sepc=0x%lx stval=0x%lx\n", r_sepc(), r_stval());
|
||||
setkilled(p);
|
||||
}
|
||||
|
||||
@@ -145,13 +145,13 @@ kerneltrap()
|
||||
panic("kerneltrap: interrupts enabled");
|
||||
|
||||
if((which_dev = devintr()) == 0){
|
||||
printf("scause %p\n", scause);
|
||||
printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
|
||||
// interrupt or trap from an unknown source
|
||||
printf("scause=0x%lx sepc=0x%lx stval=0x%lx\n", scause, r_sepc(), r_stval());
|
||||
panic("kerneltrap");
|
||||
}
|
||||
|
||||
// give up the CPU if this is a timer interrupt.
|
||||
if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING)
|
||||
if(which_dev == 2 && myproc() != 0)
|
||||
yield();
|
||||
|
||||
// the yield() may have caused some traps to occur,
|
||||
@@ -163,10 +163,17 @@ kerneltrap()
|
||||
void
|
||||
clockintr()
|
||||
{
|
||||
acquire(&tickslock);
|
||||
ticks++;
|
||||
wakeup(&ticks);
|
||||
release(&tickslock);
|
||||
if(cpuid() == 0){
|
||||
acquire(&tickslock);
|
||||
ticks++;
|
||||
wakeup(&ticks);
|
||||
release(&tickslock);
|
||||
}
|
||||
|
||||
// ask for the next timer interrupt. this also clears
|
||||
// the interrupt request. 1000000 is about a tenth
|
||||
// of a second.
|
||||
w_stimecmp(r_time() + 1000000);
|
||||
}
|
||||
|
||||
// check if it's an external interrupt or software interrupt,
|
||||
@@ -179,8 +186,7 @@ devintr()
|
||||
{
|
||||
uint64 scause = r_scause();
|
||||
|
||||
if((scause & 0x8000000000000000L) &&
|
||||
(scause & 0xff) == 9){
|
||||
if(scause == 0x8000000000000009L){
|
||||
// this is a supervisor external interrupt, via PLIC.
|
||||
|
||||
// irq indicates which device interrupted.
|
||||
@@ -201,18 +207,9 @@ devintr()
|
||||
plic_complete(irq);
|
||||
|
||||
return 1;
|
||||
} else if(scause == 0x8000000000000001L){
|
||||
// software interrupt from a machine-mode timer interrupt,
|
||||
// forwarded by timervec in kernelvec.S.
|
||||
|
||||
if(cpuid() == 0){
|
||||
clockintr();
|
||||
}
|
||||
|
||||
// acknowledge the software interrupt by clearing
|
||||
// the SSIP bit in sip.
|
||||
w_sip(r_sip() & ~2);
|
||||
|
||||
} else if(scause == 0x8000000000000005L){
|
||||
// timer interrupt.
|
||||
clockintr();
|
||||
return 2;
|
||||
} else {
|
||||
return 0;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long uint64;
|
||||
|
||||
typedef uint64 pde_t;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// the UART control registers are memory-mapped
|
||||
// at address UART0. this macro returns the
|
||||
// address of one of the registers.
|
||||
#define Reg(reg) ((volatile unsigned char *)(UART0 + reg))
|
||||
#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg)))
|
||||
|
||||
// the UART control registers.
|
||||
// some have different meanings for
|
||||
@@ -136,6 +136,7 @@ uartstart()
|
||||
while(1){
|
||||
if(uart_tx_w == uart_tx_r){
|
||||
// transmit buffer is empty.
|
||||
ReadReg(ISR);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
79
kernel/vm.c
79
kernel/vm.c
@@ -4,6 +4,8 @@
|
||||
#include "elf.h"
|
||||
#include "riscv.h"
|
||||
#include "defs.h"
|
||||
#include "spinlock.h"
|
||||
#include "proc.h"
|
||||
#include "fs.h"
|
||||
|
||||
/*
|
||||
@@ -30,8 +32,16 @@ kvmmake(void)
|
||||
// virtio mmio disk interface
|
||||
kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
|
||||
|
||||
#ifdef LAB_NET
|
||||
// PCI-E ECAM (configuration space), for pci.c
|
||||
kvmmap(kpgtbl, 0x30000000L, 0x30000000L, 0x10000000, PTE_R | PTE_W);
|
||||
|
||||
// pci.c maps the e1000's registers here.
|
||||
kvmmap(kpgtbl, 0x40000000L, 0x40000000L, 0x20000, PTE_R | PTE_W);
|
||||
#endif
|
||||
|
||||
// PLIC
|
||||
kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
|
||||
kvmmap(kpgtbl, PLIC, PLIC, 0x4000000, PTE_R | PTE_W);
|
||||
|
||||
// map kernel text executable and read-only.
|
||||
kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);
|
||||
@@ -92,6 +102,11 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
|
||||
pte_t *pte = &pagetable[PX(level, va)];
|
||||
if(*pte & PTE_V) {
|
||||
pagetable = (pagetable_t)PTE2PA(*pte);
|
||||
#ifdef LAB_PGTBL
|
||||
if(PTE_LEAF(*pte)) {
|
||||
return pte;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
|
||||
return 0;
|
||||
@@ -125,6 +140,7 @@ walkaddr(pagetable_t pagetable, uint64 va)
|
||||
return pa;
|
||||
}
|
||||
|
||||
|
||||
// add a mapping to the kernel page table.
|
||||
// only used when booting.
|
||||
// does not flush TLB or enable paging.
|
||||
@@ -179,15 +195,19 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
|
||||
{
|
||||
uint64 a;
|
||||
pte_t *pte;
|
||||
int sz;
|
||||
|
||||
if((va % PGSIZE) != 0)
|
||||
panic("uvmunmap: not aligned");
|
||||
|
||||
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
|
||||
for(a = va; a < va + npages*PGSIZE; a += sz){
|
||||
sz = PGSIZE;
|
||||
if((pte = walk(pagetable, a, 0)) == 0)
|
||||
panic("uvmunmap: walk");
|
||||
if((*pte & PTE_V) == 0)
|
||||
if((*pte & PTE_V) == 0) {
|
||||
printf("va=%ld pte=%ld\n", a, *pte);
|
||||
panic("uvmunmap: not mapped");
|
||||
}
|
||||
if(PTE_FLAGS(*pte) == PTE_V)
|
||||
panic("uvmunmap: not a leaf");
|
||||
if(do_free){
|
||||
@@ -227,6 +247,7 @@ uvmfirst(pagetable_t pagetable, uchar *src, uint sz)
|
||||
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
|
||||
@@ -234,19 +255,23 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
|
||||
{
|
||||
char *mem;
|
||||
uint64 a;
|
||||
int sz;
|
||||
|
||||
if(newsz < oldsz)
|
||||
return oldsz;
|
||||
|
||||
oldsz = PGROUNDUP(oldsz);
|
||||
for(a = oldsz; a < newsz; a += PGSIZE){
|
||||
for(a = oldsz; a < newsz; a += sz){
|
||||
sz = PGSIZE;
|
||||
mem = kalloc();
|
||||
if(mem == 0){
|
||||
uvmdealloc(pagetable, a, oldsz);
|
||||
return 0;
|
||||
}
|
||||
memset(mem, 0, PGSIZE);
|
||||
if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_R|PTE_U|xperm) != 0){
|
||||
#ifndef LAB_SYSCALL
|
||||
memset(mem, 0, sz);
|
||||
#endif
|
||||
if(mappages(pagetable, a, sz, (uint64)mem, PTE_R|PTE_U|xperm) != 0){
|
||||
kfree(mem);
|
||||
uvmdealloc(pagetable, a, oldsz);
|
||||
return 0;
|
||||
@@ -316,8 +341,11 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
|
||||
uint64 pa, i;
|
||||
uint flags;
|
||||
char *mem;
|
||||
int szinc;
|
||||
|
||||
for(i = 0; i < sz; i += PGSIZE){
|
||||
for(i = 0; i < sz; i += szinc){
|
||||
szinc = PGSIZE;
|
||||
szinc = PGSIZE;
|
||||
if((pte = walk(old, i, 0)) == 0)
|
||||
panic("uvmcopy: pte should exist");
|
||||
if((*pte & PTE_V) == 0)
|
||||
@@ -363,13 +391,21 @@ copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
|
||||
|
||||
while(len > 0){
|
||||
va0 = PGROUNDDOWN(dstva);
|
||||
if(va0 >= MAXVA)
|
||||
if (va0 >= MAXVA)
|
||||
return -1;
|
||||
pte = walk(pagetable, va0, 0);
|
||||
if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 ||
|
||||
(*pte & PTE_W) == 0)
|
||||
if((pte = walk(pagetable, va0, 0)) == 0) {
|
||||
// printf("copyout: pte should exist 0x%x %d\n", dstva, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// forbid copyout over read-only user text pages.
|
||||
if((*pte & PTE_W) == 0)
|
||||
return -1;
|
||||
|
||||
pa0 = walkaddr(pagetable, va0);
|
||||
if(pa0 == 0)
|
||||
return -1;
|
||||
pa0 = PTE2PA(*pte);
|
||||
n = PGSIZE - (dstva - va0);
|
||||
if(n > len)
|
||||
n = len;
|
||||
@@ -389,7 +425,7 @@ int
|
||||
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
|
||||
{
|
||||
uint64 n, va0, pa0;
|
||||
|
||||
|
||||
while(len > 0){
|
||||
va0 = PGROUNDDOWN(srcva);
|
||||
pa0 = walkaddr(pagetable, va0);
|
||||
@@ -449,3 +485,20 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
void
|
||||
vmprint(pagetable_t pagetable) {
|
||||
// your code here
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
pte_t*
|
||||
pgpte(pagetable_t pagetable, uint64 va) {
|
||||
return walk(pagetable, va, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user