├── .gitignore ├── Makefile ├── README.md ├── boot ├── Makefile └── start.S ├── drivers ├── Makefile └── gxconsole │ ├── Makefile │ ├── console.c │ └── dev_cons.h ├── fs ├── Makefile ├── bintoc ├── fs.c ├── fs.h ├── fsformat.c ├── ide.c ├── ide_asm.S ├── motd ├── newmotd ├── serv.c ├── test.c └── view ├── gxemul ├── .DS_Store ├── elfinfo ├── fsformat ├── r3000 ├── r3000_test ├── test └── view ├── include.mk ├── include ├── args.h ├── asm-mips3k │ ├── asm.h │ ├── asm.h~ │ ├── cp0regdef.h │ └── regdef.h ├── asm │ ├── asm.h │ ├── asm.h~ │ ├── cp0regdef.h │ └── regdef.h ├── env.h ├── error.h ├── fs.h ├── kclock.h ├── kerelf.h ├── mmu.h ├── pmap.h ├── print.h ├── printf.h ├── queue.h ├── sched.h ├── stackframe.h ├── trap.h ├── types.h └── unistd.h ├── init ├── Makefile ├── code.c ├── code_a.c ├── code_b.c ├── init.c └── main.c ├── lib ├── Makefile ├── env.c ├── env_asm.S ├── genex.S ├── getc.S ├── kclock.c ├── kclock_asm.S ├── kernel_elfloader.c ├── print.c ├── printf.c ├── sched.c ├── syscall.S ├── syscall_all.c └── traps.c ├── mm ├── Makefile ├── pmap.all ├── pmap.c └── tlb_asm.S ├── readelf ├── Makefile ├── kerelf.h ├── main.c ├── readelf.c ├── testELF └── types.h ├── tags ├── test.sh ├── tools ├── fsformat ├── scse0_3.lds └── scse0_3.lds~ └── user ├── Makefile ├── bintoc ├── cat.c ├── console.c ├── echo.c ├── entry.S ├── fd.c ├── fd.h ├── file.c ├── fktest.c ├── fork.c ├── fprintf.c ├── fsipc.c ├── fstest.c ├── icode.c ├── idle.c ├── init.c ├── ipc.c ├── lib.h ├── libos.c ├── ls.c ├── num.c ├── pageref.c ├── pgfault.c ├── pingpong.c ├── pipe.c ├── print.c ├── printf.c ├── sh.c ├── spawn.c ├── string.c ├── syscall_lib.c ├── syscall_wrap.S ├── testarg.c ├── testfdsharing.c ├── testpipe.c ├── testpiperace.c ├── testptelibrary.c ├── user.lds └── wait.c /.gitignore: -------------------------------------------------------------------------------- 1 | gxemul/fs.img 2 | fs/fsformat -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Main makefile 2 | # 3 | # Copyright (C) 2007 Beihang University 4 | # Written by Zhu Like ( zlike@cse.buaa.edu.cn ) 5 | # 6 | 7 | drivers_dir := drivers 8 | boot_dir := boot 9 | user_dir := user 10 | init_dir := init 11 | lib_dir := lib 12 | fs_dir := fs 13 | mm_dir := mm 14 | tools_dir := tools 15 | vmlinux_elf := gxemul/vmlinux 16 | user_disk := gxemul/fs.img 17 | 18 | link_script := $(tools_dir)/scse0_3.lds 19 | 20 | modules := boot drivers init lib mm user fs 21 | objects := $(boot_dir)/start.o \ 22 | $(init_dir)/main.o \ 23 | $(init_dir)/init.o \ 24 | $(init_dir)/code.o \ 25 | $(drivers_dir)/gxconsole/console.o \ 26 | $(lib_dir)/*.o \ 27 | $(user_dir)/*.x \ 28 | $(fs_dir)/*.x \ 29 | $(mm_dir)/*.o 30 | 31 | .PHONY: all $(modules) clean 32 | 33 | all: $(modules) vmlinux 34 | 35 | vmlinux: $(modules) 36 | $(LD) -o $(vmlinux_elf) -N -T $(link_script) $(objects) 37 | 38 | $(modules): 39 | $(MAKE) --directory=$@ 40 | 41 | clean: 42 | for d in $(modules); \ 43 | do \ 44 | $(MAKE) --directory=$$d clean; \ 45 | done; \ 46 | rm -rf *.o *~ $(vmlinux_elf) $(user_disk) 47 | 48 | include include.mk 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BUAA_OS_2020Spring 2 | 3 | 北航《操作系统课程设计》课程2020春代码 4 | -------------------------------------------------------------------------------- /boot/Makefile: -------------------------------------------------------------------------------- 1 | # Main makefile 2 | # 3 | # Copyright (C) 2007 Beihang University 4 | # Written by Zhu Like ( zlike@cse.buaa.edu.cn ) 5 | # 6 | 7 | # ========= Configuration ========= 8 | 9 | INCLUDES := -I../include/ 10 | 11 | # ======== End of configuration === 12 | 13 | %.o: %.S 14 | $(CC) $(CFLAGS) $(INCLUDES) -c $< 15 | 16 | .PHONY: clean 17 | 18 | all: start.o 19 | 20 | clean: 21 | rm -rf *~ *.o 22 | 23 | include ../include.mk 24 | -------------------------------------------------------------------------------- /boot/start.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | .section .text.exc_vec3 16 | /*** exercise 3.11 ***/ 17 | NESTED(except_vec3, 0, sp) 18 | .set noat 19 | .set noreorder 20 | 1: 21 | mfc0 k1,CP0_CAUSE 22 | la k0,exception_handlers 23 | andi k1,0x7c 24 | addu k0,k1 25 | lw k0,(k0) 26 | nop 27 | jr k0 28 | nop 29 | END(except_vec3) 30 | .set at 31 | 32 | .data 33 | .globl mCONTEXT 34 | mCONTEXT: 35 | .word 0 36 | 37 | .globl delay 38 | delay: 39 | .word 0 40 | 41 | .globl tlbra 42 | tlbra: 43 | .word 0 44 | 45 | .section .data.stk 46 | KERNEL_STACK: 47 | .space 0x8000 48 | 49 | 50 | .text 51 | LEAF(_start) 52 | 53 | .set mips2 54 | .set reorder 55 | 56 | /* Disable interrupts */ 57 | mtc0 zero, CP0_STATUS 58 | 59 | /* Disable watch exception. */ 60 | mtc0 zero, CP0_WATCHLO 61 | mtc0 zero, CP0_WATCHHI 62 | 63 | /* disable kernel mode cache */ 64 | mfc0 t0, CP0_CONFIG 65 | and t0, ~0x7 66 | ori t0, 0x2 67 | mtc0 t0, CP0_CONFIG 68 | 69 | /* set up stack */ 70 | li sp, 0x80400000 71 | 72 | li t0,0x80400000 73 | sw t0,mCONTEXT 74 | 75 | /* jump to main */ 76 | jal main 77 | 78 | loop: 79 | j loop 80 | nop 81 | END(_start) 82 | 83 | -------------------------------------------------------------------------------- /drivers/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for gxconsole module 2 | # 3 | # Copyright (C) 2007 Beihang Unversity. 4 | # Written by Zhu Like, zlike@cse.buaa.edu.cn 5 | 6 | # ========== Configuration ============= 7 | 8 | CROSS_COMPILE := /opt/eldk/usr/bin/mips_4KC- 9 | CC := $(CROSS_COMPILE)gcc 10 | CFLAGS := -O -G 0 -mno-abicalls -fno-builtin -Wall 11 | 12 | # ========= End of configuration ======= 13 | 14 | drivers := gxconsole 15 | 16 | .PHONY: all $(drivers) 17 | 18 | all: $(drivers) 19 | 20 | $(drivers): 21 | $(MAKE) --directory=$@ 22 | 23 | clean: 24 | for d in $(drivers); \ 25 | do \ 26 | $(MAKE) --directory=$$d clean; \ 27 | done 28 | -------------------------------------------------------------------------------- /drivers/gxconsole/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for gxconsole module 2 | # 3 | # Copyright (C) 2007 Beihang Unversity. 4 | # Written by Zhu Like, zlike@cse.buaa.edu.cn 5 | 6 | %.o: %.c %.h 7 | $(CC) $(CFLAGS) -c $< -o $*.o 8 | 9 | .PHONY: clean 10 | all: console.o 11 | 12 | clean: 13 | rm -rf *.o *~ 14 | 15 | 16 | 17 | include ../../include.mk 18 | -------------------------------------------------------------------------------- /drivers/gxconsole/console.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: hello.c,v 1.3 2006/05/22 04:53:52 debug Exp $ 3 | * 4 | * GXemul demo: Hello World 5 | * 6 | * This file is in the Public Domain. 7 | */ 8 | 9 | #include "dev_cons.h" 10 | 11 | /* Note: The ugly cast to a signed int (32-bit) causes the address to be 12 | sign-extended correctly on MIPS when compiled in 64-bit mode */ 13 | #define PHYSADDR_OFFSET ((signed int)0x80000000) 14 | 15 | 16 | #define PUTCHAR_ADDRESS (PHYSADDR_OFFSET + \ 17 | DEV_CONS_ADDRESS + DEV_CONS_PUTGETCHAR) 18 | #define HALT_ADDRESS (PHYSADDR_OFFSET + \ 19 | DEV_CONS_ADDRESS + DEV_CONS_HALT) 20 | 21 | 22 | void printcharc(char ch) 23 | { 24 | *((volatile unsigned char *) PUTCHAR_ADDRESS) = ch; 25 | } 26 | 27 | 28 | void halt(void) 29 | { 30 | *((volatile unsigned char *) HALT_ADDRESS) = 0; 31 | } 32 | 33 | 34 | void printstr(char *s) 35 | { 36 | while (*s) 37 | printcharc(*s++); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /drivers/gxconsole/dev_cons.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTMACHINE_CONS_H 2 | #define TESTMACHINE_CONS_H 3 | 4 | /* 5 | * Definitions used by the "cons" device in GXemul. 6 | * 7 | * $Id: dev_cons.h,v 1.2 2006/07/05 05:38:36 debug Exp $ 8 | * This file is in the public domain. 9 | */ 10 | 11 | 12 | //#define DEV_CONS_ADDRESS 0x180003f8 13 | #define DEV_CONS_ADDRESS 0x10000000 14 | #define DEV_CONS_LENGTH 0x0000000000000020 15 | #define DEV_CONS_PUTGETCHAR 0x0000 16 | #define DEV_CONS_HALT 0x0010 17 | 18 | 19 | #endif /* TESTMACHINE_CONS_H */ 20 | -------------------------------------------------------------------------------- /fs/Makefile: -------------------------------------------------------------------------------- 1 | INCLUDES = -I../include/ -I../user/ 2 | 3 | user_dir := ../user 4 | tools_dir := . 5 | USERLIB := $(user_dir)/printf.o \ 6 | $(user_dir)/print.o \ 7 | $(user_dir)/libos.o \ 8 | $(user_dir)/fork.o \ 9 | $(user_dir)/pgfault.o \ 10 | $(user_dir)/syscall_lib.o \ 11 | $(user_dir)/ipc.o \ 12 | $(user_dir)/string.o \ 13 | $(user_dir)/fd.o \ 14 | $(user_dir)/pageref.o \ 15 | $(user_dir)/file.o \ 16 | $(user_dir)/fsipc.o \ 17 | $(user_dir)/wait.o \ 18 | $(user_dir)/spawn.o \ 19 | $(user_dir)/pipe.o \ 20 | $(user_dir)/console.o \ 21 | $(user_dir)/fprintf.o 22 | 23 | FSLIB := fs.o \ 24 | ide.o \ 25 | test.o 26 | 27 | USERAPPS := $(user_dir)/num.b \ 28 | $(user_dir)/echo.b \ 29 | $(user_dir)/ls.b \ 30 | $(user_dir)/sh.b \ 31 | $(user_dir)/cat.b \ 32 | $(user_dir)/testptelibrary.b 33 | 34 | 35 | FSIMGFILES := motd newmotd $(user_dir)/testarg.b $(user_dir)/init.b $(USERAPPS) 36 | 37 | CFLAGS += -nostdlib -static 38 | 39 | all: serv.x fs.img serv.b 40 | 41 | %.x: %.b.c 42 | echo cc1 $< 43 | $(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $< 44 | 45 | %.b.c: %.b 46 | echo create $@ 47 | echo bintoc $* $< > $@~ 48 | chmod +x $(tools_dir)/bintoc 49 | $(tools_dir)/bintoc $* $< > $@~ && mv -f $@~ $@ 50 | # grep \. $@ 51 | 52 | %.b: ../user/entry.o ../user/syscall_wrap.o %.o $(USERLIB) $(FSLIB) 53 | echo ld $@ 54 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T $(user_dir)/user.lds $^ 55 | 56 | %.o: %.c 57 | echo user1 cc $< 58 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 59 | 60 | %.o: %.S 61 | echo as $< 62 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 63 | 64 | %.o: $(user_dir)/lib.h 65 | 66 | fs.img: $(FSIMGFILES) 67 | dd if=/dev/zero of=../gxemul/fs.img bs=4096 count=1024 2>/dev/null 68 | ifeq ("/home/jovyan/lib32-sysroot/usr/bin/gcc", "$(wildcard /home/jovyan/lib32-sysroot/usr/bin/gcc)") 69 | /home/jovyan/lib32-sysroot/usr/bin/gcc --sysroot /home/jovyan/lib32-sysroot/ $(INCLUDES) fsformat.c -o $(tools_dir)/fsformat -m32 70 | else 71 | gcc $(INCLUDES) fsformat.c -o $(tools_dir)/fsformat -m32 72 | endif 73 | chmod +x $(tools_dir)/fsformat 74 | $(tools_dir)/fsformat ../gxemul/fs.img $(FSIMGFILES) 75 | 76 | .PHONY: clean 77 | 78 | clean: 79 | rm -rf *~ *.o *.b.c *.b *.x 80 | 81 | include ../include.mk 82 | -------------------------------------------------------------------------------- /fs/bintoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/fs/bintoc -------------------------------------------------------------------------------- /fs/fs.h: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | #include 4 | 5 | /* IDE disk number to look on for our file system */ 6 | #define DISKNO 1 7 | 8 | #define BY2SECT 512 /* Bytes per disk sector */ 9 | #define SECT2BLK (BY2BLK/BY2SECT) /* sectors to a block */ 10 | 11 | /* Disk block n, when in memory, is mapped into the file system 12 | * server's address space at DISKMAP+(n*BY2BLK). */ 13 | #define DISKMAP 0x10000000 14 | 15 | /* Maximum disk size we can handle (1GB) */ 16 | #define DISKMAX 0x40000000 17 | 18 | /* ide.c */ 19 | void ide_read(u_int diskno, u_int secno, void *dst, u_int nsecs); 20 | void ide_write(u_int diskno, u_int secno, void *src, u_int nsecs); 21 | 22 | /* fs.c */ 23 | int file_open(char *path, struct File **pfile); 24 | int file_get_block(struct File *f, u_int blockno, void **pblk); 25 | int file_set_size(struct File *f, u_int newsize); 26 | void file_close(struct File *f); 27 | int file_remove(char *path); 28 | void fs_init(void); 29 | int file_dirty(struct File *f, u_int offset); 30 | void fs_sync(void); 31 | void file_flush(struct File*); 32 | extern u_int *bitmap; 33 | int map_block(u_int); 34 | int alloc_block(void); 35 | 36 | /* test.c */ 37 | void fs_test(void); 38 | -------------------------------------------------------------------------------- /fs/ide.c: -------------------------------------------------------------------------------- 1 | /* 2 | * operations on IDE disk. 3 | */ 4 | 5 | #include "fs.h" 6 | #include "lib.h" 7 | #include 8 | 9 | // Overview: 10 | // read data from IDE disk. First issue a read request through 11 | // disk register and then copy data from disk buffer 12 | // (512 bytes, a sector) to destination array. 13 | // 14 | // Parameters: 15 | // diskno: disk number. 16 | // secno: start sector number. 17 | // dst: destination for data read from IDE disk. 18 | // nsecs: the number of sectors to read. 19 | // 20 | // Post-Condition: 21 | // If error occurred during read the IDE disk, panic. 22 | // 23 | // Hint: use syscalls to access device registers and buffers 24 | void 25 | ide_read(u_int diskno, u_int secno, void *dst, u_int nsecs) 26 | { 27 | // 0x200: the size of a sector: 512 bytes. 28 | int offset_begin = secno * 0x200; 29 | int offset_end = offset_begin + nsecs * 0x200; 30 | int offset = 0; 31 | 32 | int tmp; 33 | 34 | while (offset_begin + offset < offset_end) { 35 | // Your code here 36 | tmp = 0; 37 | if (syscall_write_dev(&tmp, 0x13000010, 4)) user_panic("Error occurred during read the IDE disk!\n"); 38 | tmp = offset_begin + offset; 39 | if (syscall_write_dev(&tmp, 0x13000000, 4)) user_panic("Error occurred during read the IDE disk!\n"); 40 | tmp = 0; 41 | if (syscall_write_dev(&tmp, 0x13000020, 4)) user_panic("Error occurred during read the IDE disk!\n"); 42 | if (syscall_read_dev(&tmp, 0x13000030, 4)) user_panic("Error occurred during read the IDE disk!\n"); 43 | if (tmp == 0) user_panic("Error occurred during read the IDE disk!\n"); 44 | if (syscall_read_dev(dst + offset, 0x13004000, 512)) user_panic("Error occurred during read the IDE disk!\n"); 45 | offset += 0x200; 46 | // error occurred, then panic. 47 | } 48 | } 49 | 50 | 51 | // Overview: 52 | // write data to IDE disk. 53 | // 54 | // Parameters: 55 | // diskno: disk number. 56 | // secno: start sector number. 57 | // src: the source data to write into IDE disk. 58 | // nsecs: the number of sectors to write. 59 | // 60 | // Post-Condition: 61 | // If error occurred during read the IDE disk, panic. 62 | // 63 | // Hint: use syscalls to access device registers and buffers 64 | void 65 | ide_write(u_int diskno, u_int secno, void *src, u_int nsecs) 66 | { 67 | // Your code here 68 | int offset_begin = secno * 0x200; 69 | int offset_end = offset_begin + nsecs * 0x200; 70 | int offset = 0; 71 | 72 | int tmp; 73 | 74 | writef("diskno: %d\n", diskno); 75 | while (offset_begin + offset < offset_end) { 76 | // copy data from source array to disk buffer. 77 | if (syscall_write_dev(src + offset, 0x13004000, 512)) user_panic("Error occurred during write the IDE disk!\n"); 78 | tmp = 0; 79 | if (syscall_write_dev(&tmp, 0x13000010, 4)) user_panic("Error occurred during write the IDE disk!\n"); 80 | tmp = offset_begin + offset; 81 | if (syscall_write_dev(&tmp, 0x13000000, 4)) user_panic("Error occurred during write the IDE disk!\n"); 82 | tmp = 1; 83 | if (syscall_write_dev(&tmp, 0x13000020, 4)) user_panic("Error occurred during write the IDE disk!\n"); 84 | if (syscall_read_dev(&tmp, 0x13000030, 4)) user_panic("Error occurred during write the IDE disk!\n"); 85 | if (tmp == 0) user_panic("Error occurred during write the IDE disk!\n"); 86 | offset += 0x200; 87 | // if error occur, then panic. 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /fs/ide_asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | LEAF(read_sector) 6 | 7 | 8 | sw a0, 0x93000000 9 | li t0, 0 10 | sw t0 , 0x93000010 11 | li t0, 0 12 | sb t0 , 0x93000020 13 | lw v0, 0x93000030 14 | //1: j 1b 15 | nop 16 | jr ra 17 | nop 18 | END(read_sector) 19 | 20 | LEAF(write_sector) 21 | sw a0, 0x93000000 22 | li t0, 0 23 | sw t0 , 0x93000010 24 | li t0, 1 25 | sb t0 , 0x93000020 26 | lw v0, 0x93000030 27 | jr ra 28 | nop 29 | END(write_sector) 30 | -------------------------------------------------------------------------------- /fs/motd: -------------------------------------------------------------------------------- 1 | This is /motd, the message of the day. 2 | 3 | Welcome to the 6.828 kernel, now with a file system! 4 | 5 | -------------------------------------------------------------------------------- /fs/newmotd: -------------------------------------------------------------------------------- 1 | This is the NEW message of the day! 2 | 3 | -------------------------------------------------------------------------------- /fs/serv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File system server main loop - 3 | * serves IPC requests from other environments. 4 | */ 5 | 6 | #include "fs.h" 7 | #include "fd.h" 8 | #include "lib.h" 9 | #include 10 | 11 | struct Open { 12 | struct File *o_file; // mapped descriptor for open file 13 | u_int o_fileid; // file id 14 | int o_mode; // open mode 15 | struct Filefd *o_ff; // va of filefd page 16 | }; 17 | 18 | // Max number of open files in the file system at once 19 | #define MAXOPEN 1024 20 | #define FILEVA 0x60000000 21 | 22 | // initialize to force into data section 23 | struct Open opentab[MAXOPEN] = { { 0, 0, 1 } }; 24 | 25 | // Virtual address at which to receive page mappings containing client requests. 26 | #define REQVA 0x0ffff000 27 | 28 | // Overview: 29 | // Initialize file system server process. 30 | void 31 | serve_init(void) 32 | { 33 | int i; 34 | u_int va; 35 | 36 | // Set virtual address to map. 37 | va = FILEVA; 38 | 39 | // Initial array opentab. 40 | for (i = 0; i < MAXOPEN; i++) { 41 | opentab[i].o_fileid = i; 42 | opentab[i].o_ff = (struct Filefd *)va; 43 | va += BY2PG; 44 | } 45 | } 46 | 47 | // Overview: 48 | // Allocate an open file. 49 | int 50 | open_alloc(struct Open **o) 51 | { 52 | int i, r; 53 | 54 | // Find an available open-file table entry 55 | for (i = 0; i < MAXOPEN; i++) { 56 | switch (pageref(opentab[i].o_ff)) { 57 | case 0: 58 | if ((r = syscall_mem_alloc(0, (u_int)opentab[i].o_ff, 59 | PTE_V | PTE_R | PTE_LIBRARY)) < 0) { 60 | return r; 61 | } 62 | case 1: 63 | opentab[i].o_fileid += MAXOPEN; 64 | *o = &opentab[i]; 65 | user_bzero((void *)opentab[i].o_ff, BY2PG); 66 | return (*o)->o_fileid; 67 | } 68 | } 69 | 70 | return -E_MAX_OPEN; 71 | } 72 | 73 | // Overview: 74 | // Look up an open file for envid. 75 | int 76 | open_lookup(u_int envid, u_int fileid, struct Open **po) 77 | { 78 | struct Open *o; 79 | 80 | o = &opentab[fileid % MAXOPEN]; 81 | 82 | if (pageref(o->o_ff) == 1 || o->o_fileid != fileid) { 83 | return -E_INVAL; 84 | } 85 | 86 | *po = o; 87 | return 0; 88 | } 89 | 90 | // Serve requests, sending responses back to envid. 91 | // To send a result back, ipc_send(envid, r, 0, 0). 92 | // To include a page, ipc_send(envid, r, srcva, perm). 93 | 94 | void 95 | serve_open(u_int envid, struct Fsreq_open *rq) 96 | { 97 | writef("serve_open %08x %x 0x%x\n", envid, (int)rq->req_path, rq->req_omode); 98 | 99 | u_char path[MAXPATHLEN]; 100 | struct File *f; 101 | struct Filefd *ff; 102 | int fileid; 103 | int r; 104 | struct Open *o; 105 | 106 | // Copy in the path, making sure it's null-terminated 107 | user_bcopy(rq->req_path, path, MAXPATHLEN); 108 | path[MAXPATHLEN - 1] = 0; 109 | 110 | // Find a file id. 111 | if ((r = open_alloc(&o)) < 0) { 112 | user_panic("open_alloc failed: %d, invalid path: %s", r, path); 113 | ipc_send(envid, r, 0, 0); 114 | } 115 | 116 | fileid = r; 117 | 118 | // Open the file. 119 | if ((r = file_open((char *)path, &f)) < 0) { 120 | // user_panic("file_open failed: %d, invalid path: %s", r, path); 121 | ipc_send(envid, r, 0, 0); 122 | return ; 123 | } 124 | 125 | // Save the file pointer. 126 | o->o_file = f; 127 | 128 | // Fill out the Filefd structure 129 | ff = (struct Filefd *)o->o_ff; 130 | ff->f_file = *f; 131 | ff->f_fileid = o->o_fileid; 132 | o->o_mode = rq->req_omode; 133 | ff->f_fd.fd_omode = o->o_mode; 134 | ff->f_fd.fd_dev_id = devfile.dev_id; 135 | 136 | ipc_send(envid, 0, (u_int)o->o_ff, PTE_V | PTE_R | PTE_LIBRARY); 137 | } 138 | 139 | void 140 | serve_map(u_int envid, struct Fsreq_map *rq) 141 | { 142 | 143 | struct Open *pOpen; 144 | 145 | u_int filebno; 146 | 147 | void *blk; 148 | 149 | int r; 150 | 151 | if ((r = open_lookup(envid, rq->req_fileid, &pOpen)) < 0) { 152 | ipc_send(envid, r, 0, 0); 153 | return; 154 | } 155 | 156 | filebno = rq->req_offset / BY2BLK; 157 | 158 | if ((r = file_get_block(pOpen->o_file, filebno, &blk)) < 0) { 159 | ipc_send(envid, r, 0, 0); 160 | return; 161 | } 162 | 163 | ipc_send(envid, 0, (u_int)blk, PTE_V | PTE_R | PTE_LIBRARY); 164 | } 165 | 166 | void 167 | serve_set_size(u_int envid, struct Fsreq_set_size *rq) 168 | { 169 | struct Open *pOpen; 170 | int r; 171 | if ((r = open_lookup(envid, rq->req_fileid, &pOpen)) < 0) { 172 | ipc_send(envid, r, 0, 0); 173 | return; 174 | } 175 | 176 | if ((r = file_set_size(pOpen->o_file, rq->req_size)) < 0) { 177 | ipc_send(envid, r, 0, 0); 178 | return; 179 | } 180 | 181 | ipc_send(envid, 0, 0, 0); 182 | } 183 | 184 | void 185 | serve_close(u_int envid, struct Fsreq_close *rq) 186 | { 187 | struct Open *pOpen; 188 | 189 | int r; 190 | 191 | if ((r = open_lookup(envid, rq->req_fileid, &pOpen)) < 0) { 192 | ipc_send(envid, r, 0, 0); 193 | return; 194 | } 195 | 196 | file_close(pOpen->o_file); 197 | ipc_send(envid, 0, 0, 0); 198 | } 199 | 200 | // Overview: 201 | // fs service used to delete a file according path in `rq`. 202 | void 203 | serve_remove(u_int envid, struct Fsreq_remove *rq) 204 | { 205 | int r; 206 | u_char path[MAXPATHLEN]; 207 | 208 | // Step 1: Copy in the path, making sure it's terminated. 209 | // Notice: add \0 to the tail of the path 210 | user_bcopy(rq->req_path, path, MAXPATHLEN); 211 | path[MAXPATHLEN - 1] = '\0'; 212 | 213 | // Step 2: Remove file from file system and response to user-level process. 214 | // Call file_remove and ipc_send an approprite value to corresponding env. 215 | r = file_remove(path); 216 | ipc_send(envid, r, 0, 0); 217 | } 218 | 219 | void 220 | serve_dirty(u_int envid, struct Fsreq_dirty *rq) 221 | { 222 | 223 | // Your code here 224 | struct Open *pOpen; 225 | int r; 226 | 227 | if ((r = open_lookup(envid, rq->req_fileid, &pOpen)) < 0) { 228 | ipc_send(envid, r, 0, 0); 229 | return; 230 | } 231 | 232 | if ((r = file_dirty(pOpen->o_file, rq->req_offset)) < 0) { 233 | ipc_send(envid, r, 0, 0); 234 | return; 235 | } 236 | 237 | ipc_send(envid, 0, 0, 0); 238 | } 239 | 240 | void 241 | serve_sync(u_int envid) 242 | { 243 | fs_sync(); 244 | ipc_send(envid, 0, 0, 0); 245 | } 246 | 247 | void 248 | serve(void) 249 | { 250 | u_int req, whom, perm; 251 | 252 | for (;;) { 253 | perm = 0; 254 | 255 | req = ipc_recv(&whom, REQVA, &perm); 256 | 257 | 258 | // All requests must contain an argument page 259 | if (!(perm & PTE_V)) { 260 | writef("Invalid request from %08x: no argument page\n", whom); 261 | continue; // just leave it hanging, waiting for the next request. 262 | } 263 | 264 | switch (req) { 265 | case FSREQ_OPEN: 266 | serve_open(whom, (struct Fsreq_open *)REQVA); 267 | break; 268 | 269 | case FSREQ_MAP: 270 | serve_map(whom, (struct Fsreq_map *)REQVA); 271 | break; 272 | 273 | case FSREQ_SET_SIZE: 274 | serve_set_size(whom, (struct Fsreq_set_size *)REQVA); 275 | break; 276 | 277 | case FSREQ_CLOSE: 278 | serve_close(whom, (struct Fsreq_close *)REQVA); 279 | break; 280 | 281 | case FSREQ_DIRTY: 282 | serve_dirty(whom, (struct Fsreq_dirty *)REQVA); 283 | break; 284 | 285 | case FSREQ_REMOVE: 286 | serve_remove(whom, (struct Fsreq_remove *)REQVA); 287 | break; 288 | 289 | case FSREQ_SYNC: 290 | serve_sync(whom); 291 | break; 292 | 293 | default: 294 | writef("Invalid request code %d from %08x\n", whom, req); 295 | break; 296 | } 297 | 298 | syscall_mem_unmap(0, REQVA); 299 | } 300 | } 301 | 302 | void 303 | umain(void) 304 | { 305 | user_assert(sizeof(struct File) == BY2FILE); 306 | 307 | writef("FS is running\n"); 308 | 309 | writef("FS can do I/O\n"); 310 | 311 | serve_init(); 312 | fs_init(); 313 | fs_test(); 314 | 315 | serve(); 316 | } 317 | 318 | -------------------------------------------------------------------------------- /fs/test.c: -------------------------------------------------------------------------------- 1 | #include "fs.h" 2 | #include "lib.h" 3 | 4 | int 5 | strecmp(char *a, char *b) 6 | { 7 | while (*b) 8 | if(*a++ != *b++) 9 | return 1; 10 | return 0; 11 | } 12 | 13 | static char *msg = "This is the NEW message of the day!\r\n\r\n"; 14 | 15 | void 16 | fs_test(void) 17 | { 18 | struct File *f; 19 | int r; 20 | void *blk; 21 | u_int *bits; 22 | 23 | // back up bitmap 24 | if ((r=syscall_mem_alloc(0, BY2PG, PTE_V|PTE_R)) < 0) 25 | user_panic("syscall_mem_alloc: %e", r); 26 | bits = (u_int*)BY2PG; 27 | user_bcopy(bitmap, bits, BY2PG); 28 | // allocate block 29 | if ((r = alloc_block()) < 0) 30 | user_panic("alloc_block: %e", r); 31 | // check that block was free 32 | user_assert(bits[r/32]&(1<<(r%32))); 33 | // and is not free any more 34 | user_assert(!(bitmap[r/32]&(1<<(r%32)))); 35 | writef("alloc_block is good\n"); 36 | 37 | if ((r = file_open("/not-found", &f)) < 0 && r != -E_NOT_FOUND) 38 | user_panic("file_open /not-found: %e", r); 39 | else if (r == 0) 40 | user_panic("file_open /not-found succeeded!"); 41 | if ((r = file_open("/newmotd", &f)) < 0) 42 | user_panic("file_open /newmotd: %d", r); 43 | writef("file_open is good\n"); 44 | 45 | if ((r = file_get_block(f, 0, &blk)) < 0) 46 | user_panic("file_get_block: %e", r); 47 | if(strecmp(blk, msg) != 0) 48 | user_panic("file_get_block returned wrong data"); 49 | writef("file_get_block is good\n"); 50 | 51 | *(volatile char*)blk = *(volatile char*)blk; 52 | //^^^user_assert(((* vpt)[VPN(blk)]&PTE_D)); 53 | file_flush(f); 54 | //^^^user_assert(!((* vpt)[VPN(blk)]&PTE_D)); 55 | writef("file_flush is good\n"); 56 | 57 | if ((r = file_set_size(f, 0)) < 0) 58 | user_panic("file_set_size: %e", r); 59 | user_assert(f->f_direct[0] == 0); 60 | //^^^user_assert(!((* vpt)[VPN(f)]&PTE_D)); 61 | writef("file_truncate is good\n"); 62 | 63 | if ((r = file_set_size(f, strlen(msg))) < 0) 64 | user_panic("file_set_size 2: %e", r); 65 | //^^^user_assert(!((* vpt)[VPN(f)]&PTE_D));user_panic("##########################"); 66 | if ((r = file_get_block(f, 0, &blk)) < 0) 67 | user_panic("file_get_block 2: %e", r); 68 | strcpy((char*)blk, msg); 69 | //^^^user_assert(((* vpt)[VPN(blk)]&PTE_D)); 70 | file_flush(f); 71 | //^^^user_assert(!((* vpt)[VPN(blk)]&PTE_D)); 72 | file_close(f); 73 | //^^^user_assert(!((* vpt)[VPN(f)]&PTE_D)); 74 | writef("file rewrite is good\n"); 75 | } 76 | -------------------------------------------------------------------------------- /fs/view: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/fs/view -------------------------------------------------------------------------------- /gxemul/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/gxemul/.DS_Store -------------------------------------------------------------------------------- /gxemul/elfinfo: -------------------------------------------------------------------------------- 1 | ELF Header: 2 | Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00 3 | Class: ELF32 4 | Data: 2's complement, big endian 5 | Version: 1 (current) 6 | OS/ABI: UNIX - System V 7 | ABI Version: 0 8 | Type: EXEC (Executable file) 9 | Machine: MIPS R3000 10 | Version: 0x1 11 | Entry point address: 0x82000000 12 | Start of program headers: 52 (bytes into file) 13 | Start of section headers: 37164 (bytes into file) 14 | Flags: 0x50001001, noreorder, o32, mips32 15 | Size of this header: 52 (bytes) 16 | Size of program headers: 32 (bytes) 17 | Number of program headers: 3 18 | Size of section headers: 40 (bytes) 19 | Number of section headers: 14 20 | Section header string table index: 11 21 | 22 | Section Headers: 23 | [Nr] Name Type Addr Off Size ES Flg Lk Inf Al 24 | [ 0] NULL 00000000 000000 000000 00 0 0 0 25 | [ 1] .text PROGBITS 82000000 0000a0 000ae0 00 WAX 0 0 16 26 | [ 2] .reginfo MIPS_REGINFO 82000ae0 000b80 000018 18 A 0 0 4 27 | [ 3] .rodata.str1.4 PROGBITS 82000af8 000b98 0000a2 01 AMS 0 0 4 28 | [ 4] .rodata PROGBITS 82000ba0 000c40 000210 00 A 0 0 16 29 | [ 5] .data PROGBITS 82000db0 000e50 000000 00 WA 0 0 16 30 | [ 6] .data.stk PROGBITS 82000db0 000e50 008000 00 WA 0 0 1 31 | [ 7] .bss NOBITS 80500000 000094 000000 00 WA 0 0 16 32 | [ 8] .pdr PROGBITS 00000000 008e50 0001a0 00 0 0 4 33 | [ 9] .mdebug.abi32 PROGBITS 00000000 008ff0 000000 00 0 0 1 34 | [10] .comment PROGBITS 00000000 008ff0 0000c8 00 0 0 1 35 | [11] .shstrtab STRTAB 00000000 0090b8 000072 00 0 0 1 36 | [12] .symtab SYMTAB 00000000 00935c 000240 10 13 24 4 37 | [13] .strtab STRTAB 00000000 00959c 0000be 00 0 0 1 38 | Key to Flags: 39 | W (write), A (alloc), X (execute), M (merge), S (strings) 40 | I (info), L (link order), G (group), x (unknown) 41 | O (extra OS processing required) o (OS specific), p (processor specific) 42 | 43 | There are no section groups in this file. 44 | 45 | Program Headers: 46 | Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 47 | REGINFO 0x000b80 0x82000ae0 0x82000ae0 0x00018 0x00018 R 0x4 48 | LOAD 0x000090 0x80500000 0x80500000 0x00000 0x00000 RW 0x10 49 | LOAD 0x0000a0 0x82000000 0x82000000 0x08db0 0x08db0 RWE 0x10 50 | 51 | Section to Segment mapping: 52 | Segment Sections... 53 | 00 .reginfo 54 | 01 55 | 02 .text .reginfo .rodata.str1.4 .rodata .data.stk 56 | 57 | There is no dynamic section in this file. 58 | 59 | There are no relocations in this file. 60 | 61 | There are no unwind sections in this file. 62 | 63 | Symbol table '.symtab' contains 36 entries: 64 | Num: Value Size Type Bind Vis Ndx Name 65 | 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 66 | 1: 82000000 0 SECTION LOCAL DEFAULT 1 67 | 2: 82000ae0 0 SECTION LOCAL DEFAULT 2 68 | 3: 82000af8 0 SECTION LOCAL DEFAULT 3 69 | 4: 82000ba0 0 SECTION LOCAL DEFAULT 4 70 | 5: 82000db0 0 SECTION LOCAL DEFAULT 5 71 | 6: 82000db0 0 SECTION LOCAL DEFAULT 6 72 | 7: 80500000 0 SECTION LOCAL DEFAULT 7 73 | 8: 00000000 0 SECTION LOCAL DEFAULT 8 74 | 9: 00000000 0 SECTION LOCAL DEFAULT 9 75 | 10: 00000000 0 SECTION LOCAL DEFAULT 10 76 | 11: 00000000 0 SECTION LOCAL DEFAULT 11 77 | 12: 00000000 0 SECTION LOCAL DEFAULT 12 78 | 13: 00000000 0 SECTION LOCAL DEFAULT 13 79 | 14: 00000000 0 FILE LOCAL DEFAULT ABS start.S 80 | 15: 82000db0 0 NOTYPE LOCAL DEFAULT 6 KERNEL_STACK 81 | 16: 82000034 0 NOTYPE LOCAL DEFAULT 1 loop 82 | 17: 00000000 0 FILE LOCAL DEFAULT ABS main.c 83 | 18: 00000000 0 FILE LOCAL DEFAULT ABS init.c 84 | 19: 00000000 0 FILE LOCAL DEFAULT ABS console.c 85 | 20: 00000000 0 FILE LOCAL DEFAULT ABS print.c 86 | 21: 82000ba0 25 OBJECT LOCAL DEFAULT 4 theFatalMsg 87 | 22: 00000000 0 FILE LOCAL DEFAULT ABS printf.c 88 | 23: 820009a0 148 FUNC LOCAL DEFAULT 1 myoutput 89 | 24: 82000120 1388 FUNC GLOBAL DEFAULT 1 lp_Print 90 | 25: 82000a70 100 FUNC GLOBAL DEFAULT 1 _panic 91 | 26: 820000d8 60 FUNC GLOBAL DEFAULT 1 printstr 92 | 27: 82000a34 60 FUNC GLOBAL DEFAULT 1 printf 93 | 28: 82000814 384 FUNC GLOBAL DEFAULT 1 PrintNum 94 | 29: 820000b0 20 FUNC GLOBAL DEFAULT 1 printcharc 95 | 30: 82000000 64 FUNC GLOBAL DEFAULT 1 _start 96 | 31: 8200070c 264 FUNC GLOBAL DEFAULT 1 PrintString 97 | 32: 82000040 52 FUNC GLOBAL DEFAULT 1 main 98 | 33: 8200068c 128 FUNC GLOBAL DEFAULT 1 PrintChar 99 | 34: 820000c4 20 FUNC GLOBAL DEFAULT 1 halt 100 | 35: 82000080 44 FUNC GLOBAL DEFAULT 1 mips_init 101 | 102 | No version information found in this file. 103 | -------------------------------------------------------------------------------- /gxemul/fsformat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/gxemul/fsformat -------------------------------------------------------------------------------- /gxemul/r3000: -------------------------------------------------------------------------------- 1 | name("MALTA R3000") 2 | 3 | machine( 4 | name("SCSE-1 Testing") 5 | 6 | type("testmips") 7 | 8 | cpu("R3000") 9 | 10 | memory(64) 11 | 12 | disk("fs.img") 13 | 14 | load("vmlinux") 15 | 16 | ) 17 | -------------------------------------------------------------------------------- /gxemul/r3000_test: -------------------------------------------------------------------------------- 1 | name("MALTA R3000") 2 | 3 | machine( 4 | name("SCSE-1 Testing") 5 | 6 | type("testmips") 7 | 8 | cpu("R3000") 9 | 10 | memory(64) 11 | 12 | load("test") 13 | 14 | ) 15 | -------------------------------------------------------------------------------- /gxemul/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/gxemul/test -------------------------------------------------------------------------------- /gxemul/view: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/gxemul/view -------------------------------------------------------------------------------- /include.mk: -------------------------------------------------------------------------------- 1 | # Common includes in Makefile 2 | # 3 | # Copyright (C) 2007 Beihang University 4 | # Written By Zhu Like ( zlike@cse.buaa.edu.cn ) 5 | 6 | 7 | 8 | # Exercise 1.1. Please modify the CROSS_COMOILE path. 9 | 10 | CROSS_COMPILE := /OSLAB/compiler/usr/bin/mips_4KC- 11 | CC := $(CROSS_COMPILE)gcc 12 | CFLAGS := -O -G 0 -mno-abicalls -fno-builtin -Wa,-xgot -Wall -fPIC -march=r3000 13 | LD := $(CROSS_COMPILE)ld 14 | -------------------------------------------------------------------------------- /include/args.h: -------------------------------------------------------------------------------- 1 | /* simple command line parser from Plan 9 -- you are not expected to understand this */ 2 | /* see http://plan9.bell-labs.com/magic/man2html/2/arg */ 3 | 4 | 5 | #define _ARGSET(x) (x)=0 6 | #define _ARGUSED(x) if(x){}else 7 | 8 | #define ARGBEGIN for((argv?0:(argv=(void*)&argc)),\ 9 | argv++,argc--;\ 10 | argv[0] && argv[0][0]=='-' && argv[0][1];\ 11 | argc--, argv++) {\ 12 | char *_args, *_argt;\ 13 | char _argc;\ 14 | _args = &argv[0][1];\ 15 | if(_args[0]=='-' && _args[1]==0){\ 16 | argc--; argv++; break;\ 17 | }\ 18 | _argc = 0;\ 19 | while(*_args && (_argc = *_args++))\ 20 | switch(_argc) 21 | #define ARGEND _ARGSET(_argt);_ARGUSED(_argt);_ARGUSED(_argc);_ARGUSED(_args);}_ARGUSED(argv);_ARGUSED(argc); 22 | #define ARGF() (_argt=_args, _args="",\ 23 | (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) 24 | #define EARGF(x) (_argt=_args, _args="",\ 25 | (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0))) 26 | 27 | #define ARGC() _argc 28 | -------------------------------------------------------------------------------- /include/asm-mips3k/asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * asm.h: Assembler macros to make things easier to read. 3 | * 4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 | * Copyright (C) 1998 Ralf Baechle 6 | */ 7 | 8 | #include "regdef.h" 9 | #include "cp0regdef.h" 10 | 11 | /* 12 | * LEAF - declare leaf routine 13 | */ 14 | #define LEAF(symbol) \ 15 | .globl symbol; \ 16 | .align 2; \ 17 | .type symbol,@function; \ 18 | .ent symbol,0; \ 19 | symbol: .frame sp,0,ra 20 | 21 | /* 22 | * NESTED - declare nested routine entry point 23 | */ 24 | #define NESTED(symbol, framesize, rpc) \ 25 | .globl symbol; \ 26 | .align 2; \ 27 | .type symbol,@function; \ 28 | .ent symbol,0; \ 29 | symbol: .frame sp, framesize, rpc 30 | 31 | 32 | /* 33 | * END - mark end of function 34 | */ 35 | #define END(function) \ 36 | .end function; \ 37 | .size function,.-function 38 | 39 | 40 | -------------------------------------------------------------------------------- /include/asm-mips3k/asm.h~: -------------------------------------------------------------------------------- 1 | /* 2 | * asmmacro.h: Assembler macros to make things easier to read. 3 | * 4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 | * Copyright (C) 1998 Ralf Baechle 6 | */ 7 | 8 | #include "regdef.h" 9 | #include "cp0regdef.h" 10 | 11 | /* 12 | * LEAF - declare leaf routine 13 | */ 14 | #define LEAF(symbol) \ 15 | .globl symbol; \ 16 | .align 2; \ 17 | .type symbol,@function; \ 18 | .ent symbol,0; \ 19 | symbol: .frame sp,0,ra 20 | 21 | /* 22 | * NESTED - declare nested routine entry point 23 | */ 24 | #define NESTED(symbol, framesize, rpc) \ 25 | .globl symbol; \ 26 | .align 2; \ 27 | .type symbol,@function; \ 28 | .ent symbol,0; \ 29 | symbol: .frame sp, framesize, rpc 30 | 31 | 32 | /* 33 | * END - mark end of function 34 | */ 35 | #define END(function) \ 36 | .end function; \ 37 | .size function,.-function 38 | 39 | 40 | -------------------------------------------------------------------------------- /include/asm-mips3k/cp0regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle 3 | * 4 | * Copyright (C) 2001, Monta Vista Software 5 | * Author: jsun@mvista.com or jsun@junsun.net 6 | */ 7 | #ifndef _cp0regdef_h_ 8 | #define _cp0regdef_h_ 9 | 10 | #define CP0_INDEX $0 11 | #define CP0_RANDOM $1 12 | #define CP0_ENTRYLO0 $2 13 | #define CP0_ENTRYLO1 $3 14 | #define CP0_CONTEXT $4 15 | #define CP0_PAGEMASK $5 16 | #define CP0_WIRED $6 17 | #define CP0_BADVADDR $8 18 | #define CP0_COUNT $9 19 | #define CP0_ENTRYHI $10 20 | #define CP0_COMPARE $11 21 | #define CP0_STATUS $12 22 | #define CP0_CAUSE $13 23 | #define CP0_EPC $14 24 | #define CP0_PRID $15 25 | #define CP0_CONFIG $16 26 | #define CP0_LLADDR $17 27 | #define CP0_WATCHLO $18 28 | #define CP0_WATCHHI $19 29 | #define CP0_XCONTEXT $20 30 | #define CP0_FRAMEMASK $21 31 | #define CP0_DIAGNOSTIC $22 32 | #define CP0_PERFORMANCE $25 33 | #define CP0_ECC $26 34 | #define CP0_CACHEERR $27 35 | #define CP0_TAGLO $28 36 | #define CP0_TAGHI $29 37 | #define CP0_ERROREPC $30 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/asm-mips3k/regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is subject to the terms and conditions of the GNU General Public 3 | * License. See the file "COPYING" in the main directory of this archive 4 | * for more details. 5 | * 6 | * Copyright (C) 1994, 1995 by Ralf Baechle 7 | */ 8 | 9 | #ifndef __ASM_MIPS_REGDEF_H 10 | #define __ASM_MIPS_REGDEF_H 11 | 12 | /* 13 | * Symbolic register names for 32 bit ABI 14 | */ 15 | #define zero $0 /* wired zero */ 16 | #define AT $1 /* assembler temp - uppercase because of ".set at" */ 17 | #define v0 $2 /* return value */ 18 | #define v1 $3 19 | #define a0 $4 /* argument registers */ 20 | #define a1 $5 21 | #define a2 $6 22 | #define a3 $7 23 | #define t0 $8 /* caller saved */ 24 | #define t1 $9 25 | #define t2 $10 26 | #define t3 $11 27 | #define t4 $12 28 | #define t5 $13 29 | #define t6 $14 30 | #define t7 $15 31 | #define s0 $16 /* callee saved */ 32 | #define s1 $17 33 | #define s2 $18 34 | #define s3 $19 35 | #define s4 $20 36 | #define s5 $21 37 | #define s6 $22 38 | #define s7 $23 39 | #define t8 $24 /* caller saved */ 40 | #define t9 $25 41 | #define jp $25 /* PIC jump register */ 42 | #define k0 $26 /* kernel scratch */ 43 | #define k1 $27 44 | #define gp $28 /* global pointer */ 45 | #define sp $29 /* stack pointer */ 46 | #define fp $30 /* frame pointer */ 47 | #define s8 $30 /* same like fp! */ 48 | #define ra $31 /* return address */ 49 | 50 | #endif /* __ASM_MIPS_REGDEF_H */ 51 | -------------------------------------------------------------------------------- /include/asm/asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * asm.h: Assembler macros to make things easier to read. 3 | * 4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 | * Copyright (C) 1998 Ralf Baechle 6 | */ 7 | 8 | #include "regdef.h" 9 | #include "cp0regdef.h" 10 | 11 | /* 12 | * LEAF - declare leaf routine 13 | */ 14 | #define LEAF(symbol) \ 15 | .globl symbol; \ 16 | .align 2; \ 17 | .type symbol,@function; \ 18 | .ent symbol,0; \ 19 | symbol: .frame sp,0,ra 20 | 21 | /* 22 | * NESTED - declare nested routine entry point 23 | */ 24 | #define NESTED(symbol, framesize, rpc) \ 25 | .globl symbol; \ 26 | .align 2; \ 27 | .type symbol,@function; \ 28 | .ent symbol,0; \ 29 | symbol: .frame sp, framesize, rpc 30 | 31 | 32 | /* 33 | * END - mark end of function 34 | */ 35 | #define END(function) \ 36 | .end function; \ 37 | .size function,.-function 38 | 39 | #define EXPORT(symbol) \ 40 | .globl symbol; \ 41 | symbol: 42 | 43 | #define FEXPORT(symbol) \ 44 | .globl symbol; \ 45 | .type symbol,@function; \ 46 | symbol: 47 | 48 | 49 | -------------------------------------------------------------------------------- /include/asm/asm.h~: -------------------------------------------------------------------------------- 1 | /* 2 | * asmmacro.h: Assembler macros to make things easier to read. 3 | * 4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 5 | * Copyright (C) 1998 Ralf Baechle 6 | */ 7 | 8 | #include "regdef.h" 9 | #include "cp0regdef.h" 10 | 11 | /* 12 | * LEAF - declare leaf routine 13 | */ 14 | #define LEAF(symbol) \ 15 | .globl symbol; \ 16 | .align 2; \ 17 | .type symbol,@function; \ 18 | .ent symbol,0; \ 19 | symbol: .frame sp,0,ra 20 | 21 | /* 22 | * NESTED - declare nested routine entry point 23 | */ 24 | #define NESTED(symbol, framesize, rpc) \ 25 | .globl symbol; \ 26 | .align 2; \ 27 | .type symbol,@function; \ 28 | .ent symbol,0; \ 29 | symbol: .frame sp, framesize, rpc 30 | 31 | 32 | /* 33 | * END - mark end of function 34 | */ 35 | #define END(function) \ 36 | .end function; \ 37 | .size function,.-function 38 | 39 | 40 | -------------------------------------------------------------------------------- /include/asm/cp0regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle 3 | * 4 | * Copyright (C) 2001, Monta Vista Software 5 | * Author: jsun@mvista.com or jsun@junsun.net 6 | */ 7 | #ifndef _cp0regdef_h_ 8 | #define _cp0regdef_h_ 9 | 10 | #define CP0_INDEX $0 11 | #define CP0_RANDOM $1 12 | #define CP0_ENTRYLO0 $2 13 | #define CP0_ENTRYLO1 $3 14 | #define CP0_CONTEXT $4 15 | #define CP0_PAGEMASK $5 16 | #define CP0_WIRED $6 17 | #define CP0_BADVADDR $8 18 | #define CP0_COUNT $9 19 | #define CP0_ENTRYHI $10 20 | #define CP0_COMPARE $11 21 | #define CP0_STATUS $12 22 | #define CP0_CAUSE $13 23 | #define CP0_EPC $14 24 | #define CP0_PRID $15 25 | #define CP0_CONFIG $16 26 | #define CP0_LLADDR $17 27 | #define CP0_WATCHLO $18 28 | #define CP0_WATCHHI $19 29 | #define CP0_XCONTEXT $20 30 | #define CP0_FRAMEMASK $21 31 | #define CP0_DIAGNOSTIC $22 32 | #define CP0_PERFORMANCE $25 33 | #define CP0_ECC $26 34 | #define CP0_CACHEERR $27 35 | #define CP0_TAGLO $28 36 | #define CP0_TAGHI $29 37 | #define CP0_ERROREPC $30 38 | 39 | 40 | #define STATUSF_IP4 0x1000 41 | #define STATUS_CU0 0x10000000 42 | #define STATUS_KUC 0x2 43 | #endif 44 | -------------------------------------------------------------------------------- /include/asm/regdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is subject to the terms and conditions of the GNU General Public 3 | * License. See the file "COPYING" in the main directory of this archive 4 | * for more details. 5 | * 6 | * Copyright (C) 1994, 1995 by Ralf Baechle 7 | */ 8 | 9 | #ifndef __ASM_MIPS_REGDEF_H 10 | #define __ASM_MIPS_REGDEF_H 11 | 12 | /* 13 | * Symbolic register names for 32 bit ABI 14 | */ 15 | #define zero $0 /* wired zero */ 16 | #define AT $1 /* assembler temp - uppercase because of ".set at" */ 17 | #define v0 $2 /* return value */ 18 | #define v1 $3 19 | #define a0 $4 /* argument registers */ 20 | #define a1 $5 21 | #define a2 $6 22 | #define a3 $7 23 | #define t0 $8 /* caller saved */ 24 | #define t1 $9 25 | #define t2 $10 26 | #define t3 $11 27 | #define t4 $12 28 | #define t5 $13 29 | #define t6 $14 30 | #define t7 $15 31 | #define s0 $16 /* callee saved */ 32 | #define s1 $17 33 | #define s2 $18 34 | #define s3 $19 35 | #define s4 $20 36 | #define s5 $21 37 | #define s6 $22 38 | #define s7 $23 39 | #define t8 $24 /* caller saved */ 40 | #define t9 $25 41 | #define jp $25 /* PIC jump register */ 42 | #define k0 $26 /* kernel scratch */ 43 | #define k1 $27 44 | #define gp $28 /* global pointer */ 45 | #define sp $29 /* stack pointer */ 46 | #define fp $30 /* frame pointer */ 47 | #define s8 $30 /* same like fp! */ 48 | #define ra $31 /* return address */ 49 | 50 | #endif /* __ASM_MIPS_REGDEF_H */ 51 | -------------------------------------------------------------------------------- /include/env.h: -------------------------------------------------------------------------------- 1 | /* See COPYRIGHT for copyright information. */ 2 | 3 | #ifndef _ENV_H_ 4 | #define _ENV_H_ 5 | 6 | #include "types.h" 7 | #include "queue.h" 8 | #include "trap.h" 9 | #include "mmu.h" 10 | 11 | #define LOG2NENV 10 12 | #define NENV (1<> 11)<<6) 15 | 16 | // Values of env_status in struct Env 17 | #define ENV_FREE 0 18 | #define ENV_RUNNABLE 1 19 | #define ENV_NOT_RUNNABLE 2 20 | 21 | struct Env { 22 | struct Trapframe env_tf; // Saved registers 23 | LIST_ENTRY(Env) env_link; // Free list 24 | u_int env_id; // Unique environment identifier 25 | u_int env_parent_id; // env_id of this env's parent 26 | u_int env_status; // Status of the environment 27 | Pde *env_pgdir; // Kernel virtual address of page dir 28 | u_int env_cr3; 29 | LIST_ENTRY(Env) env_sched_link; 30 | u_int env_pri; 31 | // Lab 4 IPC 32 | u_int env_ipc_value; // data value sent to us 33 | u_int env_ipc_from; // envid of the sender 34 | u_int env_ipc_recving; // env is blocked receiving 35 | u_int env_ipc_dstva; // va at which to map received page 36 | u_int env_ipc_perm; // perm of page mapping received 37 | 38 | // Lab 4 fault handling 39 | u_int env_pgfault_handler; // page fault state 40 | u_int env_xstacktop; // top of exception stack 41 | 42 | // Lab 6 scheduler counts 43 | u_int env_runs; // number of times been env_run'ed 44 | u_int env_nop; // align to avoid mul instruction 45 | }; 46 | 47 | LIST_HEAD(Env_list, Env); 48 | extern struct Env *envs; // All environments 49 | extern struct Env *curenv; // the current env 50 | extern struct Env_list env_sched_list[2]; // runnable env list 51 | 52 | void env_init(void); 53 | int env_alloc(struct Env **e, u_int parent_id); 54 | void env_free(struct Env *); 55 | void env_create_priority(u_char *binary, int size, int priority); 56 | void env_create(u_char *binary, int size); 57 | void env_destroy(struct Env *e); 58 | 59 | int envid2env(u_int envid, struct Env **penv, int checkperm); 60 | void env_run(struct Env *e); 61 | 62 | 63 | // for the grading script 64 | #define ENV_CREATE2(x, y) \ 65 | { \ 66 | extern u_char x[], y[]; \ 67 | env_create(x, (int)y); \ 68 | } 69 | #define ENV_CREATE_PRIORITY(x, y) \ 70 | {\ 71 | extern u_char binary_##x##_start[]; \ 72 | extern u_int binary_##x##_size;\ 73 | env_create_priority(binary_##x##_start, \ 74 | (u_int)binary_##x##_size, y);\ 75 | } 76 | #define ENV_CREATE(x) \ 77 | { \ 78 | extern u_char binary_##x##_start[];\ 79 | extern u_int binary_##x##_size; \ 80 | env_create(binary_##x##_start, \ 81 | (u_int)binary_##x##_size); \ 82 | } 83 | 84 | #endif // !_ENV_H_ 85 | -------------------------------------------------------------------------------- /include/error.h: -------------------------------------------------------------------------------- 1 | /* See COPYRIGHT for copyright information. */ 2 | 3 | #ifndef _ERROR_H_ 4 | #define _ERROR_H_ 5 | 6 | // Kernel error codes -- keep in sync with list in kern/printf.c. 7 | #define E_UNSPECIFIED 1 // Unspecified or unknown problem 8 | #define E_BAD_ENV 2 // Environment doesn't exist or otherwise 9 | // cannot be used in requested action 10 | #define E_INVAL 3 // Invalid parameter 11 | #define E_NO_MEM 4 // Request failed due to memory shortage 12 | #define E_NO_FREE_ENV 5 // Attempt to create a new environment beyond 13 | // the maximum allowed 14 | #define E_IPC_NOT_RECV 6 // Attempt to send to env that is not recving. 15 | 16 | // File system error codes -- only seen in user-level 17 | #define E_NO_DISK 7 // No free space left on disk 18 | #define E_MAX_OPEN 8 // Too many files are open 19 | #define E_NOT_FOUND 9 // File or block not found 20 | #define E_BAD_PATH 10 // Bad path 21 | #define E_FILE_EXISTS 11 // File already exists 22 | #define E_NOT_EXEC 12 // File not a valid executable 23 | 24 | #define MAXERROR 12 25 | 26 | #endif // _ERROR_H_ 27 | -------------------------------------------------------------------------------- /include/fs.h: -------------------------------------------------------------------------------- 1 | // See COPYRIGHT for copyright information. 2 | 3 | #ifndef _FS_H_ 4 | #define _FS_H_ 1 5 | 6 | #include 7 | 8 | // File nodes (both in-memory and on-disk) 9 | 10 | // Bytes per file system block - same as page size 11 | #define BY2BLK BY2PG 12 | #define BIT2BLK (BY2BLK*8) 13 | 14 | // Maximum size of a filename (a single path component), including null 15 | #define MAXNAMELEN 128 16 | 17 | // Maximum size of a complete pathname, including null 18 | #define MAXPATHLEN 1024 19 | 20 | // Number of (direct) block pointers in a File descriptor 21 | #define NDIRECT 10 22 | #define NINDIRECT (BY2BLK/4) 23 | 24 | #define MAXFILESIZE (NINDIRECT*BY2BLK) 25 | 26 | #define BY2FILE 256 27 | 28 | struct File { 29 | u_char f_name[MAXNAMELEN]; // filename 30 | u_int f_size; // file size in bytes 31 | u_int f_type; // file type 32 | u_int f_direct[NDIRECT]; 33 | u_int f_indirect; 34 | 35 | struct File *f_dir; // valid only in memory 36 | u_char f_pad[256-MAXNAMELEN-4-4-NDIRECT*4-4-4]; 37 | }; 38 | 39 | #define FILE2BLK (BY2BLK/sizeof(struct File)) 40 | 41 | // File types 42 | #define FTYPE_REG 0 // Regular file 43 | #define FTYPE_DIR 1 // Directory 44 | 45 | 46 | // File system super-block (both in-memory and on-disk) 47 | 48 | #define FS_MAGIC 0x68286097 // Everyone's favorite OS class 49 | 50 | struct Super { 51 | u_int s_magic; // Magic number: FS_MAGIC 52 | u_int s_nblocks; // Total number of blocks on disk 53 | struct File s_root; // Root directory node 54 | }; 55 | 56 | // Definitions for requests from clients to file system 57 | 58 | #define FSREQ_OPEN 1 59 | #define FSREQ_MAP 2 60 | #define FSREQ_SET_SIZE 3 61 | #define FSREQ_CLOSE 4 62 | #define FSREQ_DIRTY 5 63 | #define FSREQ_REMOVE 6 64 | #define FSREQ_SYNC 7 65 | 66 | struct Fsreq_open { 67 | char req_path[MAXPATHLEN]; 68 | u_int req_omode; 69 | }; 70 | 71 | struct Fsreq_map { 72 | int req_fileid; 73 | u_int req_offset; 74 | }; 75 | 76 | struct Fsreq_set_size { 77 | int req_fileid; 78 | u_int req_size; 79 | }; 80 | 81 | struct Fsreq_close { 82 | int req_fileid; 83 | }; 84 | 85 | struct Fsreq_dirty { 86 | int req_fileid; 87 | u_int req_offset; 88 | }; 89 | 90 | struct Fsreq_remove { 91 | u_char req_path[MAXPATHLEN]; 92 | }; 93 | 94 | #endif // _FS_H_ 95 | -------------------------------------------------------------------------------- /include/kclock.h: -------------------------------------------------------------------------------- 1 | /* See COPYRIGHT for copyright information. */ 2 | 3 | #ifndef _KCLOCK_H_ 4 | #define _KCLOCK_H_ 5 | #define IO_RTC 0xb5000100 /* RTC port */ 6 | #ifndef __ASSEMBLER__ 7 | void kclock_init(void); 8 | #endif /* !__ASSEMBLER__ */ 9 | #endif 10 | -------------------------------------------------------------------------------- /include/kerelf.h: -------------------------------------------------------------------------------- 1 | /* This file defines standard ELF types, structures, and macros. 2 | Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | Contributed by Ian Lance Taylor . 5 | 6 | The GNU C Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The GNU C Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the GNU C Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. */ 20 | 21 | #ifndef _KER_ELF_H 22 | #define _KER_ELF_H 23 | 24 | /* ELF defination file from GNU C Library. We simplefied this 25 | * file for our lab, removing definations about ELF64, structs and 26 | * enums which we don't care. 27 | */ 28 | 29 | #include 30 | 31 | typedef u_int64_t uint64_t; 32 | typedef u_int32_t uint32_t; 33 | typedef u_int16_t uint16_t; 34 | 35 | /* Type for a 16-bit quantity. */ 36 | typedef uint16_t Elf32_Half; 37 | 38 | /* Types for signed and unsigned 32-bit quantities. */ 39 | typedef uint32_t Elf32_Word; 40 | typedef int32_t Elf32_Sword; 41 | 42 | /* Types for signed and unsigned 64-bit quantities. */ 43 | typedef uint64_t Elf32_Xword; 44 | typedef int64_t Elf32_Sxword; 45 | 46 | /* Type of addresses. */ 47 | typedef uint32_t Elf32_Addr; 48 | 49 | /* Type of file offsets. */ 50 | typedef uint32_t Elf32_Off; 51 | 52 | /* Type for section indices, which are 16-bit quantities. */ 53 | typedef uint16_t Elf32_Section; 54 | 55 | /* Type of symbol indices. */ 56 | typedef uint32_t Elf32_Symndx; 57 | 58 | 59 | /* The ELF file header. This appears at the start of every ELF file. */ 60 | 61 | #define EI_NIDENT (16) 62 | 63 | typedef struct { 64 | unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 65 | Elf32_Half e_type; /* Object file type */ 66 | Elf32_Half e_machine; /* Architecture */ 67 | Elf32_Word e_version; /* Object file version */ 68 | Elf32_Addr e_entry; /* Entry point virtual address */ 69 | Elf32_Off e_phoff; /* Program header table file offset */ 70 | Elf32_Off e_shoff; /* Section header table file offset */ 71 | Elf32_Word e_flags; /* Processor-specific flags */ 72 | Elf32_Half e_ehsize; /* ELF header size in bytes */ 73 | Elf32_Half e_phentsize; /* Program header table entry size */ 74 | Elf32_Half e_phnum; /* Program header table entry count */ 75 | Elf32_Half e_shentsize; /* Section header table entry size */ 76 | Elf32_Half e_shnum; /* Section header table entry count */ 77 | Elf32_Half e_shstrndx; /* Section header string table index */ 78 | } Elf32_Ehdr; 79 | 80 | /* Fields in the e_ident array. The EI_* macros are indices into the 81 | array. The macros under each EI_* macro are the values the byte 82 | may have. */ 83 | 84 | #define EI_MAG0 0 /* File identification byte 0 index */ 85 | #define ELFMAG0 0x7f /* Magic number byte 0 */ 86 | 87 | #define EI_MAG1 1 /* File identification byte 1 index */ 88 | #define ELFMAG1 'E' /* Magic number byte 1 */ 89 | 90 | #define EI_MAG2 2 /* File identification byte 2 index */ 91 | #define ELFMAG2 'L' /* Magic number byte 2 */ 92 | 93 | #define EI_MAG3 3 /* File identification byte 3 index */ 94 | #define ELFMAG3 'F' /* Magic number byte 3 */ 95 | 96 | /* Program segment header. */ 97 | 98 | typedef struct { 99 | Elf32_Word p_type; /* Segment type */ 100 | Elf32_Off p_offset; /* Segment file offset */ 101 | Elf32_Addr p_vaddr; /* Segment virtual address */ 102 | Elf32_Addr p_paddr; /* Segment physical address */ 103 | Elf32_Word p_filesz; /* Segment size in file */ 104 | Elf32_Word p_memsz; /* Segment size in memory */ 105 | Elf32_Word p_flags; /* Segment flags */ 106 | Elf32_Word p_align; /* Segment alignment */ 107 | } Elf32_Phdr; 108 | 109 | /* Legal values for p_type (segment type). */ 110 | 111 | #define PT_NULL 0 /* Program header table entry unused */ 112 | #define PT_LOAD 1 /* Loadable program segment */ 113 | #define PT_DYNAMIC 2 /* Dynamic linking information */ 114 | #define PT_INTERP 3 /* Program interpreter */ 115 | #define PT_NOTE 4 /* Auxiliary information */ 116 | #define PT_SHLIB 5 /* Reserved */ 117 | #define PT_PHDR 6 /* Entry for header table itself */ 118 | #define PT_NUM 7 /* Number of defined types. */ 119 | #define PT_LOOS 0x60000000 /* Start of OS-specific */ 120 | #define PT_HIOS 0x6fffffff /* End of OS-specific */ 121 | #define PT_LOPROC 0x70000000 /* Start of processor-specific */ 122 | #define PT_HIPROC 0x7fffffff /* End of processor-specific */ 123 | 124 | /* Legal values for p_flags (segment flags). */ 125 | 126 | #define PF_X (1 << 0) /* Segment is executable */ 127 | #define PF_W (1 << 1) /* Segment is writable */ 128 | #define PF_R (1 << 2) /* Segment is readable */ 129 | #define PF_MASKPROC 0xf0000000 /* Processor-specific */ 130 | 131 | int load_elf(u_char *binary, int size, 132 | u_long *entry_point, void *user_data, 133 | int (*map)(u_long, u_int32_t, u_char *, u_int32_t, void *)); 134 | 135 | #endif /* kerelf.h */ 136 | 137 | -------------------------------------------------------------------------------- /include/mmu.h: -------------------------------------------------------------------------------- 1 | #ifndef _MMU_H_ 2 | #define _MMU_H_ 3 | 4 | 5 | /* 6 | * This file contains: 7 | * 8 | * Part 1. MIPS definitions. 9 | * Part 2. Our conventions. 10 | * Part 3. Our helper functions. 11 | */ 12 | 13 | /* 14 | * Part 1. MIPS definitions. 15 | */ 16 | #define BY2PG 4096 // bytes to a page 17 | #define PDMAP (4*1024*1024) // bytes mapped by a page directory entry 18 | #define PGSHIFT 12 19 | #define PDSHIFT 22 // log2(PDMAP) 20 | #define PDX(va) ((((u_long)(va))>>22) & 0x03FF) 21 | #define PTX(va) ((((u_long)(va))>>12) & 0x03FF) 22 | #define PTE_ADDR(pte) ((u_long)(pte)&~0xFFF) 23 | 24 | // page number field of address 25 | #define PPN(va) (((u_long)(va))>>12) 26 | #define VPN(va) PPN(va) 27 | 28 | #define VA2PFN(va) (((u_long)(va)) & 0xFFFFF000 ) // va 2 PFN for EntryLo0/1 29 | #define PTE2PT 1024 30 | //$#define VA2PDE(va) (((u_long)(va)) & 0xFFC00000 ) // for context 31 | 32 | /* Page Table/Directory Entry flags 33 | * these are defined by the hardware 34 | */ 35 | #define PTE_G 0x0100 // Global bit 36 | #define PTE_V 0x0200 // Valid bit 37 | #define PTE_R 0x0400 // Dirty bit ,'0' means only read ,otherwise make interrupt 38 | #define PTE_D 0x0002 // fileSystem Cached is dirty 39 | #define PTE_COW 0x0001 // Copy On Write 40 | #define PTE_UC 0x0800 // unCached 41 | #define PTE_LIBRARY 0x0004 // share memmory 42 | /* 43 | * Part 2. Our conventions. 44 | */ 45 | 46 | /* 47 | o 4G -----------> +----------------------------+------------0x100000000 48 | o | ... | kseg3 49 | o +----------------------------+------------0xe000 0000 50 | o | ... | kseg2 51 | o +----------------------------+------------0xc000 0000 52 | o | Interrupts & Exception | kseg1 53 | o +----------------------------+------------0xa000 0000 54 | o | Invalid memory | /|\ 55 | o +----------------------------+----|-------Physics Memory Max 56 | o | ... | kseg0 57 | o VPT,KSTACKTOP-----> +----------------------------+----|-------0x8040 0000-------end 58 | o | Kernel Stack | | KSTKSIZE /|\ 59 | o +----------------------------+----|------ | 60 | o | Kernel Text | | PDMAP 61 | o KERNBASE -----> +----------------------------+----|-------0x8001 0000 | 62 | o | Interrupts & Exception | \|/ \|/ 63 | o ULIM -----> +----------------------------+------------0x8000 0000------- 64 | o | User VPT | PDMAP /|\ 65 | o UVPT -----> +----------------------------+------------0x7fc0 0000 | 66 | o | PAGES | PDMAP | 67 | o UPAGES -----> +----------------------------+------------0x7f80 0000 | 68 | o | ENVS | PDMAP | 69 | o UTOP,UENVS -----> +----------------------------+------------0x7f40 0000 | 70 | o UXSTACKTOP -/ | user exception stack | BY2PG | 71 | o +----------------------------+------------0x7f3f f000 | 72 | o | Invalid memory | BY2PG | 73 | o USTACKTOP ----> +----------------------------+------------0x7f3f e000 | 74 | o | normal user stack | BY2PG | 75 | o +----------------------------+------------0x7f3f d000 | 76 | a | | | 77 | a ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 78 | a . . | 79 | a . . kuseg 80 | a . . | 81 | a |~~~~~~~~~~~~~~~~~~~~~~~~~~~~| | 82 | a | | | 83 | o UTEXT -----> +----------------------------+ | 84 | o | | 2 * PDMAP \|/ 85 | a 0 ------------> +----------------------------+ ----------------------------- 86 | o 87 | */ 88 | 89 | #define KERNBASE 0x80010000 90 | 91 | #define VPT (ULIM + PDMAP ) 92 | #define KSTACKTOP (VPT-0x100) 93 | #define KSTKSIZE (8*BY2PG) 94 | #define ULIM 0x80000000 95 | 96 | #define UVPT (ULIM - PDMAP) 97 | #define UPAGES (UVPT - PDMAP) 98 | #define UENVS (UPAGES - PDMAP) 99 | 100 | #define UTOP UENVS 101 | #define UXSTACKTOP (UTOP) 102 | #define TIMESTACK 0x82000000 103 | 104 | #define USTACKTOP (UTOP - 2*BY2PG) 105 | #define UTEXT 0x00400000 106 | 107 | 108 | #define E_UNSPECIFIED 1 // Unspecified or unknown problem 109 | #define E_BAD_ENV 2 // Environment doesn't exist or otherwise 110 | // cannot be used in requested action 111 | #define E_INVAL 3 // Invalid parameter 112 | #define E_NO_MEM 4 // Request failed due to memory shortage 113 | #define E_NO_FREE_ENV 5 // Attempt to create a new environment beyond 114 | // the maximum allowed 115 | #define E_IPC_NOT_RECV 6 // Attempt to send to env that is not recving. 116 | 117 | // File system error codes -- only seen in user-level 118 | #define E_NO_DISK 7 // No free space left on disk 119 | #define E_MAX_OPEN 8 // Too many files are open 120 | #define E_NOT_FOUND 9 // File or block not found 121 | #define E_BAD_PATH 10 // Bad path 122 | #define E_FILE_EXISTS 11 // File already exists 123 | #define E_NOT_EXEC 12 // File not a valid executable 124 | 125 | #define MAXERROR 12 126 | 127 | #ifndef __ASSEMBLER__ 128 | 129 | /* 130 | * Part 3. Our helper functions. 131 | */ 132 | #include "types.h" 133 | void bcopy(const void *, void *, size_t); 134 | void bzero(void *, size_t); 135 | 136 | extern char bootstacktop[], bootstack[]; 137 | 138 | extern u_long npage; 139 | 140 | typedef u_long Pde; 141 | typedef u_long Pte; 142 | 143 | extern volatile Pte* vpt[]; 144 | extern volatile Pde* vpd[]; 145 | 146 | #define PADDR(kva) \ 147 | ({ \ 148 | u_long a = (u_long) (kva); \ 149 | if (a < ULIM) \ 150 | panic("PADDR called with invalid kva %08lx", a);\ 151 | a - ULIM; \ 152 | }) 153 | 154 | 155 | // translates from physical address to kernel virtual address 156 | #define KADDR(pa) \ 157 | ({ \ 158 | u_long ppn = PPN(pa); \ 159 | if (ppn >= npage) \ 160 | panic("KADDR called with invalid pa %08lx", (u_long)pa);\ 161 | (pa) + ULIM; \ 162 | }) 163 | 164 | #define assert(x) \ 165 | do { if (!(x)) panic("assertion failed: %s", #x); } while (0) 166 | 167 | #define TRUP(_p) \ 168 | ({ \ 169 | register typeof((_p)) __m_p = (_p); \ 170 | (u_int) __m_p > ULIM ? (typeof(_p)) ULIM : __m_p; \ 171 | }) 172 | 173 | 174 | 175 | extern void tlb_out(u_int entryhi); 176 | #endif //!__ASSEMBLER__ 177 | #endif // !_MMU_H_ 178 | -------------------------------------------------------------------------------- /include/pmap.h: -------------------------------------------------------------------------------- 1 | #ifndef _PMAP_H_ 2 | #define _PMAP_H_ 3 | 4 | #include "types.h" 5 | #include "queue.h" 6 | #include "mmu.h" 7 | #include "printf.h" 8 | 9 | 10 | LIST_HEAD(Page_list, Page); 11 | typedef LIST_ENTRY(Page) Page_LIST_entry_t; 12 | 13 | struct Page { 14 | Page_LIST_entry_t pp_link; /* free list link */ 15 | 16 | // Ref is the count of pointers (usually in page table entries) 17 | // to this page. This only holds for pages allocated using 18 | // page_alloc. Pages allocated at boot time using pmap.c's "alloc" 19 | // do not have valid reference count fields. 20 | 21 | u_short pp_ref; 22 | }; 23 | 24 | extern struct Page *pages; 25 | static inline u_long 26 | page2ppn(struct Page *pp) 27 | { 28 | return pp - pages; 29 | } 30 | 31 | static inline u_long 32 | page2pa(struct Page *pp) 33 | { 34 | return page2ppn(pp)<= npage) 41 | panic("pa2page called with invalid pa: %x", pa); 42 | return &pages[PPN(pa)]; 43 | } 44 | 45 | static inline u_long 46 | page2kva(struct Page *pp) 47 | { 48 | return KADDR(page2pa(pp)); 49 | } 50 | 51 | 52 | static inline u_long 53 | va2pa(Pde *pgdir, u_long va) 54 | { 55 | Pte *p; 56 | 57 | pgdir = &pgdir[PDX(va)]; 58 | if (!(*pgdir&PTE_V)) 59 | return ~0; 60 | p = (Pte*)KADDR(PTE_ADDR(*pgdir)); 61 | if (!(p[PTX(va)]&PTE_V)) 62 | return ~0; 63 | return PTE_ADDR(p[PTX(va)]); 64 | } 65 | 66 | void mips_detect_memory(); 67 | 68 | void mips_vm_init(); 69 | 70 | void mips_init(); 71 | void page_init(void); 72 | void page_check(); 73 | int page_alloc(struct Page **pp); 74 | void page_free(struct Page *pp); 75 | void page_decref(struct Page *pp); 76 | int pgdir_walk(Pde *pgdir, u_long va, int create, Pte **ppte); 77 | int page_insert(Pde *pgdir, struct Page *pp, u_long va, u_int perm); 78 | struct Page* page_lookup(Pde *pgdir, u_long va, Pte **ppte); 79 | void page_remove(Pde *pgdir, u_long va) ; 80 | void tlb_invalidate(Pde *pgdir, u_long va); 81 | 82 | void boot_map_segment(Pde *pgdir, u_long va, u_long size, u_long pa, int perm); 83 | 84 | extern struct Page *pages; 85 | 86 | 87 | #endif /* _PMAP_H_ */ 88 | -------------------------------------------------------------------------------- /include/print.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #ifndef _print_h_ 13 | #define _print_h_ 14 | 15 | #include 16 | 17 | /* this is the maximum width for a variable */ 18 | #define LP_MAX_BUF 1000 19 | 20 | /* -*- 21 | * output function takes an void pointer which is passed in as the 22 | * second argument in lp_Print(). This black-box argument gives output 23 | * function a way to track state. 24 | * 25 | * The second argument in output function is a pointer to char buffer. 26 | * The third argument specifies the number of chars to outputed. 27 | * 28 | * output function cannot assume the buffer is null-terminated after 29 | * l number of chars. 30 | */ 31 | void lp_Print(void (*output)(void *, char *, int), 32 | void * arg, 33 | char *fmt, 34 | va_list ap); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/printf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #ifndef _printf_h_ 13 | #define _printf_h_ 14 | 15 | #include 16 | void printf(char *fmt, ...); 17 | 18 | void _panic(const char *, int, const char *, ...) 19 | __attribute__((noreturn)); 20 | 21 | #define panic(...) _panic(__FILE__, __LINE__, __VA_ARGS__) 22 | 23 | #endif /* _printf_h_ */ 24 | -------------------------------------------------------------------------------- /include/sched.h: -------------------------------------------------------------------------------- 1 | /* See COPYRIGHT for copyright information. */ 2 | 3 | #ifndef __SCHED_H__ 4 | #define __SCHED_H__ 5 | 6 | void sched_init(void); 7 | void sched_yield(void); 8 | void sched_intr(int); 9 | 10 | #endif /* __SCHED_H__ */ 11 | -------------------------------------------------------------------------------- /include/stackframe.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | .macro STI 7 | mfc0 t0, CP0_STATUS 8 | li t1, (STATUS_CU0 | 0x1) 9 | or t0, t1 10 | mtc0 t0, CP0_STATUS 11 | 12 | .endm 13 | 14 | 15 | .macro CLI 16 | mfc0 t0, CP0_STATUS 17 | li t1, (STATUS_CU0 | 0x1) 18 | or t0, t1 19 | xor t0, 0x1 20 | mtc0 t0, CP0_STATUS 21 | .endm 22 | 23 | .macro SAVE_ALL 24 | 25 | mfc0 k0,CP0_STATUS 26 | sll k0,3 /* extract cu0 bit */ 27 | bltz k0,1f 28 | nop 29 | /* 30 | * Called from user mode, new stack 31 | */ 32 | //lui k1,%hi(kernelsp) 33 | //lw k1,%lo(kernelsp)(k1) //not clear right now 34 | 35 | 1: 36 | move k0,sp 37 | get_sp 38 | move k1,sp 39 | subu sp,k1,TF_SIZE 40 | sw k0,TF_REG29(sp) 41 | sw $2,TF_REG2(sp) 42 | mfc0 v0,CP0_STATUS 43 | sw v0,TF_STATUS(sp) 44 | mfc0 v0,CP0_CAUSE 45 | sw v0,TF_CAUSE(sp) 46 | mfc0 v0,CP0_EPC 47 | sw v0,TF_EPC(sp) 48 | mfc0 v0, CP0_BADVADDR 49 | sw v0, TF_BADVADDR(sp) 50 | mfhi v0 51 | sw v0,TF_HI(sp) 52 | mflo v0 53 | sw v0,TF_LO(sp) 54 | sw $0,TF_REG0(sp) 55 | sw $1,TF_REG1(sp) 56 | //sw $2,TF_REG2(sp) 57 | sw $3,TF_REG3(sp) 58 | sw $4,TF_REG4(sp) 59 | sw $5,TF_REG5(sp) 60 | sw $6,TF_REG6(sp) 61 | sw $7,TF_REG7(sp) 62 | sw $8,TF_REG8(sp) 63 | sw $9,TF_REG9(sp) 64 | sw $10,TF_REG10(sp) 65 | sw $11,TF_REG11(sp) 66 | sw $12,TF_REG12(sp) 67 | sw $13,TF_REG13(sp) 68 | sw $14,TF_REG14(sp) 69 | sw $15,TF_REG15(sp) 70 | sw $16,TF_REG16(sp) 71 | sw $17,TF_REG17(sp) 72 | sw $18,TF_REG18(sp) 73 | sw $19,TF_REG19(sp) 74 | sw $20,TF_REG20(sp) 75 | sw $21,TF_REG21(sp) 76 | sw $22,TF_REG22(sp) 77 | sw $23,TF_REG23(sp) 78 | sw $24,TF_REG24(sp) 79 | sw $25,TF_REG25(sp) 80 | sw $26,TF_REG26(sp) 81 | sw $27,TF_REG27(sp) 82 | sw $28,TF_REG28(sp) 83 | sw $30,TF_REG30(sp) 84 | sw $31,TF_REG31(sp) 85 | .endm 86 | /* 87 | * Note that we restore the IE flags from stack. This means 88 | * that a modified IE mask will be nullified. 89 | */ 90 | .macro RESTORE_SOME 91 | .set mips1 92 | mfc0 t0,CP0_STATUS 93 | ori t0,0x3 94 | xori t0,0x3 95 | mtc0 t0,CP0_STATUS 96 | lw v0,TF_STATUS(sp) 97 | li v1, 0xff00 98 | and t0, v1 99 | nor v1, $0, v1 100 | and v0, v1 101 | or v0, t0 102 | mtc0 v0,CP0_STATUS 103 | lw v1,TF_LO(sp) 104 | mtlo v1 105 | lw v0,TF_HI(sp) 106 | lw v1,TF_EPC(sp) 107 | mthi v0 108 | mtc0 v1,CP0_EPC 109 | lw $31,TF_REG31(sp) 110 | lw $30,TF_REG30(sp) 111 | lw $28,TF_REG28(sp) 112 | lw $25,TF_REG25(sp) 113 | lw $24,TF_REG24(sp) 114 | lw $23,TF_REG23(sp) 115 | lw $22,TF_REG22(sp) 116 | lw $21,TF_REG21(sp) 117 | lw $20,TF_REG20(sp) 118 | lw $19,TF_REG19(sp) 119 | lw $18,TF_REG18(sp) 120 | lw $17,TF_REG17(sp) 121 | lw $16,TF_REG16(sp) 122 | lw $15,TF_REG15(sp) 123 | lw $14,TF_REG14(sp) 124 | lw $13,TF_REG13(sp) 125 | lw $12,TF_REG12(sp) 126 | lw $11,TF_REG11(sp) 127 | lw $10,TF_REG10(sp) 128 | lw $9,TF_REG9(sp) 129 | lw $8,TF_REG8(sp) 130 | lw $7,TF_REG7(sp) 131 | lw $6,TF_REG6(sp) 132 | lw $5,TF_REG5(sp) 133 | lw $4,TF_REG4(sp) 134 | lw $3,TF_REG3(sp) 135 | lw $2,TF_REG2(sp) 136 | lw $1,TF_REG1(sp) 137 | .endm 138 | 139 | .macro RESTORE_ALL 140 | RESTORE_SOME 141 | lw sp,TF_REG29(sp) /* Deallocate stack */ 142 | .endm 143 | 144 | .set noreorder 145 | .macro RESTORE_ALL_AND_RET 146 | RESTORE_SOME 147 | lw k0,TF_EPC(sp) 148 | lw sp,TF_REG29(sp) /* Deallocate stack */ 149 | jr k0 150 | rfe 151 | .endm 152 | 153 | 154 | .macro get_sp 155 | mfc0 k1, CP0_CAUSE 156 | andi k1, 0x107C 157 | xori k1, 0x1000 158 | bnez k1, 1f 159 | nop 160 | li sp, 0x82000000 161 | j 2f 162 | nop 163 | 1: 164 | bltz sp, 2f 165 | nop 166 | lw sp, KERNEL_SP 167 | nop 168 | 169 | 2: nop 170 | 171 | 172 | .endm 173 | -------------------------------------------------------------------------------- /include/trap.h: -------------------------------------------------------------------------------- 1 | #ifndef _TRAP_H_ 2 | #define _TRAP_H_ 3 | 4 | /* these are processor defined */ 5 | #define T_DIVIDE 0 /* divide error */ 6 | #define T_DEBUG 1 /* debug exception */ 7 | #define T_NMI 2 /* non-maskable interrupt */ 8 | #define T_BRKPT 3 /* breakpoint */ 9 | #define T_OFLOW 4 /* overflow */ 10 | #define T_BOUND 5 /* bounds check */ 11 | #define T_ILLOP 6 /* illegal opcode */ 12 | #define T_DEVICE 7 /* device not available */ 13 | #define T_DBLFLT 8 /* double fault */ 14 | /* 9 is reserved */ 15 | #define T_TSS 10 /* invalid task switch segment */ 16 | #define T_SEGNP 11 /* segment not present */ 17 | #define T_STACK 12 /* stack exception */ 18 | #define T_GPFLT 13 /* genernal protection fault */ 19 | #define T_PGFLT 14 /* page fault */ 20 | /* 15 is reserved */ 21 | #define T_FPERR 16 /* floating point error */ 22 | #define T_ALIGN 17 /* aligment check */ 23 | #define T_MCHK 18 /* machine check */ 24 | 25 | /* These are arbitrarily chosen, but with care not to overlap 26 | * processor defined exceptions or interrupt vectors. 27 | */ 28 | #define T_SYSCALL 0x30 /* system call */ 29 | #define T_DEFAULT 500 /* catchall */ 30 | 31 | #ifndef __ASSEMBLER__ 32 | 33 | #include 34 | 35 | struct Trapframe { //lr:need to be modified(reference to linux pt_regs) TODO 36 | /* Saved main processor registers. */ 37 | unsigned long regs[32]; 38 | 39 | /* Saved special registers. */ 40 | unsigned long cp0_status; 41 | unsigned long hi; 42 | unsigned long lo; 43 | unsigned long cp0_badvaddr; 44 | unsigned long cp0_cause; 45 | unsigned long cp0_epc; 46 | unsigned long pc; 47 | }; 48 | void *set_except_vector(int n, void * addr); 49 | void trap_init(); 50 | 51 | #endif /* !__ASSEMBLER__ */ 52 | /* 53 | * Stack layout for all exceptions: 54 | * 55 | * ptrace needs to have all regs on the stack. If the order here is changed, 56 | * it needs to be updated in include/asm-mips/ptrace.h 57 | * 58 | * The first PTRSIZE*5 bytes are argument save space for C subroutines. 59 | */ 60 | 61 | #define TF_REG0 0 62 | #define TF_REG1 ((TF_REG0) + 4) 63 | #define TF_REG2 ((TF_REG1) + 4) 64 | #define TF_REG3 ((TF_REG2) + 4) 65 | #define TF_REG4 ((TF_REG3) + 4) 66 | #define TF_REG5 ((TF_REG4) + 4) 67 | #define TF_REG6 ((TF_REG5) + 4) 68 | #define TF_REG7 ((TF_REG6) + 4) 69 | #define TF_REG8 ((TF_REG7) + 4) 70 | #define TF_REG9 ((TF_REG8) + 4) 71 | #define TF_REG10 ((TF_REG9) + 4) 72 | #define TF_REG11 ((TF_REG10) + 4) 73 | #define TF_REG12 ((TF_REG11) + 4) 74 | #define TF_REG13 ((TF_REG12) + 4) 75 | #define TF_REG14 ((TF_REG13) + 4) 76 | #define TF_REG15 ((TF_REG14) + 4) 77 | #define TF_REG16 ((TF_REG15) + 4) 78 | #define TF_REG17 ((TF_REG16) + 4) 79 | #define TF_REG18 ((TF_REG17) + 4) 80 | #define TF_REG19 ((TF_REG18) + 4) 81 | #define TF_REG20 ((TF_REG19) + 4) 82 | #define TF_REG21 ((TF_REG20) + 4) 83 | #define TF_REG22 ((TF_REG21) + 4) 84 | #define TF_REG23 ((TF_REG22) + 4) 85 | #define TF_REG24 ((TF_REG23) + 4) 86 | #define TF_REG25 ((TF_REG24) + 4) 87 | /* 88 | * $26 (k0) and $27 (k1) not saved 89 | */ 90 | #define TF_REG26 ((TF_REG25) + 4) 91 | #define TF_REG27 ((TF_REG26) + 4) 92 | #define TF_REG28 ((TF_REG27) + 4) 93 | #define TF_REG29 ((TF_REG28) + 4) 94 | #define TF_REG30 ((TF_REG29) + 4) 95 | #define TF_REG31 ((TF_REG30) + 4) 96 | 97 | #define TF_STATUS ((TF_REG31) + 4) 98 | 99 | #define TF_HI ((TF_STATUS) + 4) 100 | #define TF_LO ((TF_HI) + 4) 101 | 102 | #define TF_BADVADDR ((TF_LO)+4) 103 | #define TF_CAUSE ((TF_BADVADDR) + 4) 104 | #define TF_EPC ((TF_CAUSE) + 4) #define TF_PC ((TF_EPC) + 4) 105 | /* 106 | * Size of stack frame, word/double word alignment 107 | */ 108 | #define TF_SIZE ((TF_PC)+4) 109 | #endif /* _TRAP_H_ */ 110 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: types.h,v 1.12 1997/11/30 18:50:18 millert Exp $ */ 2 | /* $NetBSD: types.h,v 1.29 1996/11/15 22:48:25 jtc Exp $ */ 3 | 4 | #ifndef _INC_TYPES_H_ 5 | #define _INC_TYPES_H_ 6 | 7 | #ifndef NULL 8 | #define NULL ((void *) 0) 9 | #endif /* !NULL */ 10 | 11 | 12 | typedef unsigned char u_int8_t; 13 | typedef short int16_t; 14 | typedef unsigned short u_int16_t; 15 | typedef int int32_t; 16 | typedef unsigned int u_int32_t; 17 | typedef long long int64_t; 18 | typedef unsigned long long u_int64_t; 19 | 20 | typedef int32_t register_t; 21 | 22 | typedef unsigned char u_char; 23 | typedef unsigned short u_short; 24 | typedef unsigned int u_int; 25 | typedef unsigned long u_long; 26 | 27 | typedef u_int64_t u_quad_t; /* quads */ 28 | typedef int64_t quad_t; 29 | typedef quad_t * qaddr_t; 30 | 31 | typedef u_int32_t size_t; 32 | 33 | 34 | #define MIN(_a, _b) \ 35 | ({ \ 36 | typeof(_a) __a = (_a); \ 37 | typeof(_b) __b = (_b); \ 38 | __a <= __b ? __a : __b; \ 39 | }) 40 | 41 | /* Static assert, for compile-time assertion checking */ 42 | #define static_assert(c) switch (c) case 0: case(c): 43 | 44 | #define offsetof(type, member) ((size_t)(&((type *)0)->member)) 45 | 46 | /* Rounding; only works for n = power of two */ 47 | #define ROUND(a, n) (((((u_long)(a))+(n)-1)) & ~((n)-1)) 48 | #define ROUNDDOWN(a, n) (((u_long)(a)) & ~((n)-1)) 49 | 50 | 51 | #endif /* !_INC_TYPES_H_ */ 52 | -------------------------------------------------------------------------------- /include/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef UNISTD_H 2 | #define UNISTD_H 3 | 4 | #define __SYSCALL_BASE 9527 5 | #define __NR_SYSCALLS 20 6 | 7 | 8 | #define SYS_putchar ((__SYSCALL_BASE ) + (0 ) ) 9 | #define SYS_getenvid ((__SYSCALL_BASE ) + (1 ) ) 10 | #define SYS_yield ((__SYSCALL_BASE ) + (2 ) ) 11 | #define SYS_env_destroy ((__SYSCALL_BASE ) + (3 ) ) 12 | #define SYS_set_pgfault_handler ((__SYSCALL_BASE ) + (4 ) ) 13 | #define SYS_mem_alloc ((__SYSCALL_BASE ) + (5 ) ) 14 | #define SYS_mem_map ((__SYSCALL_BASE ) + (6 ) ) 15 | #define SYS_mem_unmap ((__SYSCALL_BASE ) + (7 ) ) 16 | #define SYS_env_alloc ((__SYSCALL_BASE ) + (8 ) ) 17 | #define SYS_set_env_status ((__SYSCALL_BASE ) + (9 ) ) 18 | #define SYS_set_trapframe ((__SYSCALL_BASE ) + (10 ) ) 19 | #define SYS_panic ((__SYSCALL_BASE ) + (11 ) ) 20 | #define SYS_ipc_can_send ((__SYSCALL_BASE ) + (12 ) ) 21 | #define SYS_ipc_recv ((__SYSCALL_BASE ) + (13 ) ) 22 | #define SYS_cgetc ((__SYSCALL_BASE ) + (14 ) ) 23 | #define SYS_write_dev ((__SYSCALL_BASE ) + (15) ) 24 | #define SYS_read_dev ((__SYSCALL_BASE ) + (16) ) 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /init/Makefile: -------------------------------------------------------------------------------- 1 | INCLUDES := -I../include 2 | 3 | %.o: %.c 4 | $(CC) $(CFLAGS) $(INCLUDES) -c $< 5 | 6 | .PHONY: clean 7 | 8 | all: init.o main.o code.o 9 | 10 | clean: 11 | rm -rf *~ *.o 12 | 13 | 14 | include ../include.mk 15 | 16 | -------------------------------------------------------------------------------- /init/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | extern char aoutcode[]; 9 | extern char boutcode[]; 10 | 11 | void mips_init() 12 | { 13 | printf("init.c:\tmips_init() is called\n"); 14 | mips_detect_memory(); 15 | 16 | mips_vm_init(); 17 | page_init(); 18 | //page_check(); 19 | 20 | env_init(); 21 | 22 | //ENV_CREATE(user_fktest); 23 | //ENV_CREATE(user_pt1); 24 | //ENV_CREATE(user_idle); 25 | //ENV_CREATE(user_fktest); 26 | //ENV_CREATE(user_pingpong); 27 | //ENV_CREATE(user_testfdsharing); 28 | //ENV_CREATE(user_testpipe); 29 | //ENV_CREATE(user_testpiperace); 30 | //ENV_CREATE(user_testptelibrary); 31 | ENV_CREATE(user_icode); 32 | ENV_CREATE(fs_serv); 33 | 34 | //ENV_CREATE(user_icode); 35 | trap_init(); 36 | kclock_init(); 37 | //env_run(&envs[0]); 38 | 39 | //env_run(&envs[1]); 40 | 41 | panic("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); 42 | while(1); 43 | panic("init.c:\tend of mips_init() reached!"); 44 | } 45 | 46 | void bcopy(const void *src, void *dst, size_t len) 47 | { 48 | void *max; 49 | 50 | max = dst + len; 51 | // copy machine words while possible 52 | while (dst + 3 < max) 53 | { 54 | *(int *)dst = *(int *)src; 55 | dst+=4; 56 | src+=4; 57 | } 58 | // finish remaining 0-3 bytes 59 | while (dst < max) 60 | { 61 | *(char *)dst = *(char *)src; 62 | dst+=1; 63 | src+=1; 64 | } 65 | } 66 | 67 | void bzero(void *b, size_t len) 68 | { 69 | void *max; 70 | 71 | max = b + len; 72 | 73 | //printf("init.c:\tzero from %x to %x\n",(int)b,(int)max); 74 | 75 | // zero machine words while possible 76 | 77 | while (b + 3 < max) 78 | { 79 | *(int *)b = 0; 80 | b+=4; 81 | } 82 | 83 | // finish remaining 0-3 bytes 84 | while (b < max) 85 | { 86 | *(char *)b++ = 0; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /init/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | int main() 16 | { 17 | printf("main.c:\tmain is start ...\n"); 18 | 19 | mips_init(); 20 | panic("main is over is error!"); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | INCLUDES := -I./ -I../ -I../include/ 2 | %.o: %.c 3 | $(CC) $(CFLAGS) $(INCLUDES) -c $< 4 | 5 | %.o: %.S 6 | $(CC) $(CFLAGS) $(INCLUDES) -c $< 7 | 8 | .PHONY: clean 9 | 10 | all: kernel_elfloader.o env.o print.o printf.o sched.o env_asm.o kclock.o traps.o genex.o kclock_asm.o syscall.o syscall_all.o getc.o 11 | 12 | clean: 13 | rm -rf *~ *.o 14 | 15 | 16 | include ../include.mk 17 | -------------------------------------------------------------------------------- /lib/env_asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../include/asm/cp0regdef.h" 3 | #include 4 | #include 5 | .data 6 | .global KERNEL_SP; 7 | KERNEL_SP: 8 | .word 0 9 | 10 | 11 | 12 | .text 13 | .set noreorder 14 | // .set noat 15 | LEAF(env_pop_tf) 16 | .set mips1 17 | //1: j 1b 18 | nop 19 | move k0,a0 20 | mtc0 a1,CP0_ENTRYHI 21 | 22 | 23 | mfc0 t0,CP0_STATUS 24 | ori t0,0x3 25 | xori t0,0x3 26 | mtc0 t0,CP0_STATUS 27 | 28 | lw v1,TF_LO(k0) 29 | mtlo v1 30 | lw v0,TF_HI(k0) 31 | lw v1,TF_EPC(k0) 32 | mthi v0 33 | mtc0 v1,CP0_EPC 34 | lw $31,TF_REG31(k0) 35 | lw $30,TF_REG30(k0) 36 | lw $29,TF_REG29(k0) 37 | lw $28,TF_REG28(k0) 38 | lw $25,TF_REG25(k0) 39 | lw $24,TF_REG24(k0) 40 | lw $23,TF_REG23(k0) 41 | lw $22,TF_REG22(k0) 42 | lw $21,TF_REG21(k0) 43 | lw $20,TF_REG20(k0) 44 | lw $19,TF_REG19(k0) 45 | lw $18,TF_REG18(k0) 46 | lw $17,TF_REG17(k0) 47 | lw $16,TF_REG16(k0) 48 | lw $15,TF_REG15(k0) 49 | lw $14,TF_REG14(k0) 50 | lw $13,TF_REG13(k0) 51 | lw $12,TF_REG12(k0) 52 | lw $11,TF_REG11(k0) 53 | lw $10,TF_REG10(k0) 54 | lw $9,TF_REG9(k0) 55 | lw $8,TF_REG8(k0) 56 | lw $7,TF_REG7(k0) 57 | lw $6,TF_REG6(k0) 58 | lw $5,TF_REG5(k0) 59 | lw $4,TF_REG4(k0) 60 | lw $3,TF_REG3(k0) 61 | lw $2,TF_REG2(k0) 62 | lw $1,TF_REG1(k0) 63 | 64 | lw k1,TF_PC(k0) 65 | 66 | lw k0,TF_STATUS(k0) 67 | nop 68 | mtc0 k0,CP0_STATUS 69 | 70 | 71 | 72 | j k1 73 | rfe 74 | nop 75 | 76 | 77 | END(env_pop_tf) 78 | 79 | LEAF(lcontext) 80 | .extern mCONTEXT 81 | sw a0,mCONTEXT 82 | jr ra 83 | nop 84 | END(lcontext) 85 | 86 | 87 | -------------------------------------------------------------------------------- /lib/genex.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | .macro __build_clear_sti 7 | STI 8 | .endm 9 | 10 | .macro __build_clear_cli 11 | CLI 12 | .endm 13 | 14 | .macro BUILD_HANDLER exception handler clear 15 | .align 5 16 | NESTED(handle_\exception, TF_SIZE, sp) 17 | //.set noat 18 | 19 | nop 20 | 21 | SAVE_ALL 22 | __build_clear_\clear 23 | .set at 24 | move a0, sp 25 | jal \handler 26 | nop 27 | j ret_from_exception 28 | nop 29 | END(handle_\exception) 30 | .endm 31 | 32 | FEXPORT(ret_from_exception) 33 | .set noat 34 | .set noreorder 35 | RESTORE_SOME 36 | .set at 37 | lw k0,TF_EPC(sp) 38 | lw sp,TF_REG29(sp) /* Deallocate stack */ 39 | //1: j 1b 40 | nop 41 | jr k0 42 | rfe 43 | 44 | 45 | 46 | .set noreorder 47 | .align 5 48 | NESTED(handle_int, TF_SIZE, sp) 49 | //.set noat 50 | 51 | //1: j 1b 52 | nop 53 | 54 | SAVE_ALL 55 | CLI 56 | .set at 57 | mfc0 t0, CP0_CAUSE 58 | mfc0 t2, CP0_STATUS 59 | and t0, t2 60 | 61 | andi t1, t0, STATUSF_IP4 62 | bnez t1, timer_irq 63 | nop 64 | END(handle_int) 65 | 66 | .extern delay 67 | 68 | timer_irq: 69 | 70 | 1: j sched_yield 71 | nop 72 | /*li t1, 0xff 73 | lw t0, delay 74 | addu t0, 1 75 | sw t0, delay 76 | beq t0,t1,1f 77 | nop*/ 78 | j ret_from_exception 79 | nop 80 | 81 | LEAF(do_reserved) 82 | END(do_reserved) 83 | 84 | .extern tlbra 85 | .set noreorder 86 | NESTED(do_refill,0 , sp) 87 | //li k1, '?' 88 | //sb k1, 0x90000000 89 | .extern mCONTEXT 90 | //this "1" is important 91 | 1: //j 1b 92 | nop 93 | lw k1,mCONTEXT 94 | and k1,0xfffff000 95 | mfc0 k0,CP0_BADVADDR 96 | srl k0,20 97 | and k0,0xfffffffc 98 | addu k0,k1 99 | 100 | lw k1,0(k0) 101 | nop 102 | move t0,k1 103 | and t0,0x0200 104 | beqz t0,NOPAGE 105 | nop 106 | and k1,0xfffff000 107 | mfc0 k0,CP0_BADVADDR 108 | srl k0,10 109 | and k0,0xfffffffc 110 | and k0,0x00000fff 111 | addu k0,k1 112 | 113 | or k0,0x80000000 114 | lw k1,0(k0) 115 | nop 116 | move t0,k1 117 | and t0,0x0200 118 | beqz t0,NOPAGE 119 | nop 120 | move k0,k1 121 | and k0,0x1 122 | beqz k0,NoCOW 123 | nop 124 | and k1,0xfffffbff 125 | NoCOW: 126 | mtc0 k1,CP0_ENTRYLO0 127 | nop 128 | tlbwr 129 | 130 | j 2f 131 | nop 132 | NOPAGE: 133 | //3: j 3b 134 | nop 135 | mfc0 a0,CP0_BADVADDR 136 | lw a1,mCONTEXT 137 | nop 138 | 139 | sw ra,tlbra 140 | jal pageout 141 | nop 142 | //3: j 3b 143 | nop 144 | lw ra,tlbra 145 | nop 146 | 147 | j 1b 148 | 2: nop 149 | 150 | jr ra 151 | nop 152 | END(do_refill) 153 | 154 | 155 | 156 | BUILD_HANDLER reserved do_reserved cli 157 | BUILD_HANDLER tlb do_refill cli 158 | BUILD_HANDLER mod page_fault_handler cli 159 | -------------------------------------------------------------------------------- /lib/getc.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | .set noreorder 6 | LEAF(sys_cgetc) 7 | 8 | 1: lb t0, 0x90000000 9 | beqz t0, 1b 10 | nop 11 | move v0,t0 12 | jr ra 13 | nop 14 | END(sys_cgetc) 15 | -------------------------------------------------------------------------------- /lib/kclock.c: -------------------------------------------------------------------------------- 1 | /* See COPYRIGHT for copyright information. */ 2 | 3 | /* The Run Time Clock and other NVRAM access functions that go with it. */ 4 | /* The run time clock is hard-wired to IRQ8. */ 5 | 6 | #include 7 | 8 | 9 | extern void set_timer(); 10 | 11 | void 12 | kclock_init(void) 13 | { 14 | /* initialize 8253 clock to interrupt 100 times/sec */ 15 | //outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); 16 | //outb(IO_TIMER1, TIMER_DIV(100) % 256); 17 | //outb(IO_TIMER1, TIMER_DIV(100) / 256); 18 | //printf(" Setup timer interrupts via 8259A\n"); 19 | set_timer(); 20 | //irq_setmask_8259A (irq_mask_8259A & ~(1<<0)); 21 | //printf(" unmasked timer interrupt\n"); 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /lib/kclock_asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | 8 | .macro setup_c0_status set clr 9 | .set push 10 | mfc0 t0, CP0_STATUS 11 | or t0, \set|\clr 12 | xor t0, \clr 13 | mtc0 t0, CP0_STATUS 14 | .set pop 15 | .endm 16 | 17 | .text 18 | LEAF(set_timer) 19 | 20 | li t0, 0x01 21 | sb t0, 0xb5000100 22 | sw sp, KERNEL_SP 23 | setup_c0_status STATUS_CU0|0x1001 0 24 | jr ra 25 | 26 | nop 27 | END(set_timer) 28 | -------------------------------------------------------------------------------- /lib/kernel_elfloader.c: -------------------------------------------------------------------------------- 1 | /* This is a simplefied ELF loader for kernel. 2 | * You can contact me if you find any bugs. 3 | * 4 | * Luming Wang 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | /* Overview: 12 | * Check whether it is a ELF file. 13 | * 14 | * Pre-Condition: 15 | * binary must longer than 4 byte. 16 | * 17 | * Post-Condition: 18 | * Return 0 if `binary` isn't an elf. Otherwise 19 | * return 1. 20 | */ 21 | int is_elf_format(u_char *binary) 22 | { 23 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)binary; 24 | 25 | if (ehdr->e_ident[0] == EI_MAG0 && 26 | ehdr->e_ident[1] == EI_MAG1 && 27 | ehdr->e_ident[2] == EI_MAG2 && 28 | ehdr->e_ident[3] == EI_MAG3) { 29 | return 0; 30 | } 31 | 32 | return 1; 33 | } 34 | 35 | /* Overview: 36 | * load an elf format binary file. Map all section 37 | * at correct virtual address. 38 | * 39 | * Pre-Condition: 40 | * `binary` can't be NULL and `size` is the size of binary. 41 | * 42 | * Post-Condition: 43 | * Return 0 if success. Otherwise return < 0. 44 | * If success, the entry point of `binary` will be stored in `start` 45 | */ 46 | /*** exercise 3.7 ***/ 47 | int load_elf(u_char *binary, int size, u_long *entry_point, void *user_data, 48 | int (*map)(u_long va, u_int32_t sgsize, 49 | u_char *bin, u_int32_t bin_size, void *user_data)) 50 | { 51 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)binary; 52 | Elf32_Phdr *phdr = NULL; 53 | /* As a loader, we just care about segment, 54 | * so we just parse program headers. 55 | */ 56 | u_char *ptr_ph_table = NULL; 57 | Elf32_Half ph_entry_count; 58 | Elf32_Half ph_entry_size; 59 | int r; 60 | 61 | // check whether `binary` is a ELF file. 62 | if (size < 4 || !is_elf_format(binary)) { 63 | return -1; 64 | } 65 | 66 | ptr_ph_table = binary + ehdr->e_phoff; 67 | ph_entry_count = ehdr->e_phnum; 68 | ph_entry_size = ehdr->e_phentsize; 69 | 70 | while (ph_entry_count--) { 71 | phdr = (Elf32_Phdr *)ptr_ph_table; 72 | 73 | if (phdr->p_type == PT_LOAD) { 74 | /* Your task here! */ 75 | /* Real map all section at correct virtual address.Return < 0 if error. */ 76 | /* Hint: Call the callback function you have achieved before. */ 77 | if (map(phdr->p_vaddr, phdr->p_memsz, binary + phdr->p_offset, phdr->p_filesz, user_data)) return -1; 78 | } 79 | 80 | ptr_ph_table += ph_entry_size; 81 | } 82 | 83 | *entry_point = ehdr->e_entry; 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /lib/print.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #include 13 | 14 | /* macros */ 15 | #define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') ) 16 | #define Ctod(x) ( (x) - '0') 17 | 18 | /* forward declaration */ 19 | extern int PrintChar(char *, char, int, int); 20 | extern int PrintString(char *, char *, int, int); 21 | extern int PrintNum(char *, unsigned long, int, int, int, int, char, int); 22 | 23 | /* private variable */ 24 | static const char theFatalMsg[] = "fatal error in lp_Print!"; 25 | 26 | /* -*- 27 | * A low level printf() function. 28 | */ 29 | void 30 | lp_Print(void (*output)(void *, char *, int), 31 | void * arg, 32 | char *fmt, 33 | va_list ap) 34 | { 35 | 36 | #define OUTPUT(arg, s, l) \ 37 | { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \ 38 | (*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \ 39 | } else { \ 40 | (*output)(arg, s, l); \ 41 | } \ 42 | } 43 | 44 | char buf[LP_MAX_BUF]; 45 | 46 | char c; 47 | char *s; 48 | long int num; 49 | 50 | 51 | 52 | int longFlag; 53 | int negFlag; 54 | int width; 55 | int prec; 56 | int ladjust; 57 | char padc; 58 | 59 | int length; 60 | 61 | /* 62 | Exercise 1.5. Please fill in two parts in this file. 63 | */ 64 | 65 | for(;;) { 66 | 67 | /* Part1: your code here */ 68 | 69 | { 70 | /* scan for the next '%' */ 71 | length = 0; 72 | while (*fmt != '%') { 73 | buf[length++] = *fmt++; 74 | if (*fmt == '\0') break; 75 | } 76 | 77 | /* flush the string found so far */ 78 | OUTPUT(arg, buf, length); 79 | 80 | /* check "are we hitting the end?" */ 81 | if (*fmt == '\0') break; 82 | fmt++; 83 | } 84 | 85 | 86 | /* we found a '%' */ 87 | ladjust = 0; 88 | if (*fmt == '-') { 89 | ladjust = 1; 90 | fmt++; 91 | } 92 | 93 | padc = ' '; 94 | if (*fmt == '0') { 95 | padc = '0'; 96 | fmt++; 97 | } 98 | 99 | width = 0; 100 | while (IsDigit(*fmt)) { 101 | width *= 10; 102 | width += Ctod(*fmt); 103 | fmt++; 104 | } 105 | 106 | prec = 0; 107 | if (*fmt == '.') { 108 | fmt++; 109 | while (IsDigit(*fmt)) { 110 | prec *= 10; 111 | prec += Ctod(*fmt); 112 | fmt++; 113 | } 114 | } 115 | 116 | /* check for long */ 117 | longFlag = 0; 118 | if (*fmt == 'l') { 119 | longFlag = 1; 120 | fmt++; 121 | } 122 | 123 | /* check for other prefixes */ 124 | 125 | /* check format flag */ 126 | 127 | 128 | negFlag = 0; 129 | switch (*fmt){ 130 | case 'b': 131 | if (longFlag) { 132 | num = va_arg(ap, long int); 133 | } else { 134 | num = va_arg(ap, int); 135 | } 136 | length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0); 137 | OUTPUT(arg, buf, length); 138 | break; 139 | 140 | case 'd': 141 | case 'D': 142 | if (longFlag) { 143 | num = va_arg(ap, long int); 144 | } else { 145 | num = va_arg(ap, int); 146 | } 147 | 148 | /* Part2: 149 | your code here. 150 | Refer to other part (case 'b',case 'o' etc.) and func PrintNum to complete this part. 151 | Think the difference between case 'd' and others. (hint: negFlag). 152 | */ 153 | if (num < 0) { 154 | negFlag = 1; 155 | num = -num; 156 | } 157 | length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0); 158 | OUTPUT(arg, buf, length); 159 | break; 160 | 161 | case 'o': 162 | case 'O': 163 | if (longFlag) { 164 | num = va_arg(ap, long int); 165 | } else { 166 | num = va_arg(ap, int); 167 | } 168 | length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0); 169 | OUTPUT(arg, buf, length); 170 | break; 171 | 172 | case 'u': 173 | case 'U': 174 | if (longFlag) { 175 | num = va_arg(ap, long int); 176 | } else { 177 | num = va_arg(ap, int); 178 | } 179 | length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0); 180 | OUTPUT(arg, buf, length); 181 | break; 182 | 183 | case 'x': 184 | if (longFlag) { 185 | num = va_arg(ap, long int); 186 | } else { 187 | num = va_arg(ap, int); 188 | } 189 | length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0); 190 | OUTPUT(arg, buf, length); 191 | break; 192 | 193 | case 'X': 194 | if (longFlag) { 195 | num = va_arg(ap, long int); 196 | } else { 197 | num = va_arg(ap, int); 198 | } 199 | length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1); 200 | OUTPUT(arg, buf, length); 201 | break; 202 | 203 | case 'c': 204 | c = (char)va_arg(ap, int); 205 | length = PrintChar(buf, c, width, ladjust); 206 | OUTPUT(arg, buf, length); 207 | break; 208 | 209 | case 's': 210 | s = (char*)va_arg(ap, char *); 211 | length = PrintString(buf, s, width, ladjust); 212 | OUTPUT(arg, buf, length); 213 | break; 214 | 215 | case '\0': 216 | fmt --; 217 | break; 218 | 219 | default: 220 | /* output this char as it is */ 221 | OUTPUT(arg, fmt, 1); 222 | } /* switch (*fmt) */ 223 | 224 | fmt ++; 225 | } /* for(;;) */ 226 | 227 | /* special termination call */ 228 | OUTPUT(arg, "\0", 1); 229 | } 230 | 231 | 232 | /* --------------- local help functions --------------------- */ 233 | int 234 | PrintChar(char * buf, char c, int length, int ladjust) 235 | { 236 | int i; 237 | 238 | if (length < 1) length = 1; 239 | if (ladjust) { 240 | *buf = c; 241 | for (i=1; i< length; i++) buf[i] = ' '; 242 | } else { 243 | for (i=0; i< length-1; i++) buf[i] = ' '; 244 | buf[length - 1] = c; 245 | } 246 | return length; 247 | } 248 | 249 | int 250 | PrintString(char * buf, char* s, int length, int ladjust) 251 | { 252 | int i; 253 | int len=0; 254 | char* s1 = s; 255 | while (*s1++) len++; 256 | if (length < len) length = len; 257 | 258 | if (ladjust) { 259 | for (i=0; i< len; i++) buf[i] = s[i]; 260 | for (i=len; i< length; i++) buf[i] = ' '; 261 | } else { 262 | for (i=0; i< length-len; i++) buf[i] = ' '; 263 | for (i=length-len; i < length; i++) buf[i] = s[i-length+len]; 264 | } 265 | return length; 266 | } 267 | 268 | int 269 | PrintNum(char * buf, unsigned long u, int base, int negFlag, 270 | int length, int ladjust, char padc, int upcase) 271 | { 272 | /* algorithm : 273 | * 1. prints the number from left to right in reverse form. 274 | * 2. fill the remaining spaces with padc if length is longer than 275 | * the actual length 276 | * TRICKY : if left adjusted, no "0" padding. 277 | * if negtive, insert "0" padding between "0" and number. 278 | * 3. if (!ladjust) we reverse the whole string including paddings 279 | * 4. otherwise we only reverse the actual string representing the num. 280 | */ 281 | 282 | int actualLength =0; 283 | char *p = buf; 284 | int i; 285 | 286 | do { 287 | int tmp = u %base; 288 | if (tmp <= 9) { 289 | *p++ = '0' + tmp; 290 | } else if (upcase) { 291 | *p++ = 'A' + tmp - 10; 292 | } else { 293 | *p++ = 'a' + tmp - 10; 294 | } 295 | u /= base; 296 | } while (u != 0); 297 | 298 | if (negFlag) { 299 | *p++ = '-'; 300 | } 301 | 302 | /* figure out actual length and adjust the maximum length */ 303 | actualLength = p - buf; 304 | if (length < actualLength) length = actualLength; 305 | 306 | /* add padding */ 307 | if (ladjust) { 308 | padc = ' '; 309 | } 310 | if (negFlag && !ladjust && (padc == '0')) { 311 | for (i = actualLength-1; i< length-1; i++) buf[i] = padc; 312 | buf[length -1] = '-'; 313 | } else { 314 | for (i = actualLength; i< length; i++) buf[i] = padc; 315 | } 316 | 317 | 318 | /* prepare to reverse the string */ 319 | { 320 | int begin = 0; 321 | int end; 322 | if (ladjust) { 323 | end = actualLength - 1; 324 | } else { 325 | end = length -1; 326 | } 327 | 328 | while (end > begin) { 329 | char tmp = buf[begin]; 330 | buf[begin] = buf[end]; 331 | buf[end] = tmp; 332 | begin ++; 333 | end --; 334 | } 335 | } 336 | 337 | /* adjust the string pointer */ 338 | return length; 339 | } 340 | -------------------------------------------------------------------------------- /lib/printf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | 18 | void printcharc(char ch); 19 | 20 | void halt(void); 21 | 22 | static void myoutput(void *arg, char *s, int l) 23 | { 24 | int i; 25 | 26 | // special termination call 27 | if ((l==1) && (s[0] == '\0')) return; 28 | 29 | for (i=0; i< l; i++) { 30 | printcharc(s[i]); 31 | if (s[i] == '\n') printcharc('\n'); 32 | } 33 | } 34 | 35 | void printf(char *fmt, ...) 36 | { 37 | va_list ap; 38 | va_start(ap, fmt); 39 | lp_Print(myoutput, 0, fmt, ap); 40 | va_end(ap); 41 | } 42 | 43 | void 44 | _panic(const char *file, int line, const char *fmt,...) 45 | { 46 | va_list ap; 47 | 48 | 49 | va_start(ap, fmt); 50 | printf("panic at %s:%d: ", file, line); 51 | lp_Print(myoutput, 0, (char *)fmt, ap); 52 | printf("\n"); 53 | va_end(ap); 54 | 55 | 56 | for(;;); 57 | } 58 | -------------------------------------------------------------------------------- /lib/sched.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Overview: 6 | * Implement simple round-robin scheduling. 7 | * 8 | * 9 | * Hints: 10 | * 1. The variable which is for counting should be defined as 'static'. 11 | * 2. Use variable 'env_sched_list', which is a pointer array. 12 | * 3. CANNOT use `return` statement! 13 | */ 14 | /*** exercise 3.14 ***/ 15 | void sched_yield(void) 16 | { 17 | static int count = 0; // remaining time slices of current env 18 | static int point = 0; // current env_sched_list index 19 | 20 | static struct Env *e = NULL; 21 | /* hint: 22 | * 1. if (count==0), insert `e` into `env_sched_list[1-point]` 23 | * using LIST_REMOVE and LIST_INSERT_TAIL. 24 | * 2. if (env_sched_list[point] is empty), point = 1 - point; 25 | * then search through `env_sched_list[point]` for a runnable env `e`, 26 | * and set count = e->env_pri 27 | * 3. count-- 28 | * 4. env_run() 29 | * 30 | * functions or macros below may be used (not all): 31 | * LIST_INSERT_TAIL, LIST_REMOVE, LIST_FIRST, LIST_EMPTY 32 | */ 33 | if (count == 0 || e == NULL || e->env_status != ENV_RUNNABLE) { 34 | if (e != NULL) { 35 | LIST_REMOVE(e, env_sched_link); 36 | LIST_INSERT_TAIL(&env_sched_list[1 - point], e, env_sched_link); 37 | } 38 | while (1) { 39 | while (LIST_EMPTY(&env_sched_list[point])) point = 1 - point; 40 | e = LIST_FIRST(&env_sched_list[point]); 41 | if (e->env_status == ENV_FREE) LIST_REMOVE(e, env_sched_link); 42 | else if (e->env_status == ENV_NOT_RUNNABLE) { 43 | LIST_REMOVE(e, env_sched_link); 44 | LIST_INSERT_TAIL(&env_sched_list[1 - point], e, env_sched_link); 45 | } 46 | else { 47 | count = e->env_pri; 48 | break; 49 | } 50 | } 51 | } 52 | count--; 53 | e->env_runs++; 54 | env_run(e); 55 | } 56 | -------------------------------------------------------------------------------- /lib/syscall.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /*** exercise 4.2 ***/ 8 | NESTED(handle_sys,TF_SIZE, sp) 9 | SAVE_ALL // Macro used to save trapframe 10 | CLI // Clean Interrupt Mask 11 | nop 12 | .set at // Resume use of $at 13 | 14 | // TODO: Fetch EPC from Trapframe, calculate a proper value and store it back to trapframe. 15 | lw t0, TF_EPC(sp) 16 | addiu t0, t0, 4 17 | sw t0, TF_EPC(sp) 18 | 19 | // TODO: Copy the syscall number into $a0. 20 | lw a0, TF_REG4(sp) 21 | 22 | addiu a0, a0, -__SYSCALL_BASE // a0 <- relative syscall number 23 | sll t0, a0, 2 // t0 <- relative syscall number times 4 24 | la t1, sys_call_table // t1 <- syscall table base 25 | addu t1, t1, t0 // t1 <- table entry of specific syscall 26 | lw t2, 0(t1) // t2 <- function entry of specific syscall 27 | 28 | lw t0, TF_REG29(sp) // t0 <- user's stack pointer 29 | lw t3, 16(t0) // t3 <- the 5th argument of msyscall 30 | lw t4, 20(t0) // t4 <- the 6th argument of msyscall 31 | 32 | // TODO: Allocate a space of six arguments on current kernel stack and copy the six arguments to proper location 33 | lw a0, TF_REG4(sp) 34 | lw a1, TF_REG5(sp) 35 | lw a2, TF_REG6(sp) 36 | lw a3, TF_REG7(sp) 37 | addiu sp, sp, -24 38 | sw t3, 16(sp) 39 | sw t4, 20(sp) 40 | 41 | jalr t2 // Invoke sys_* function 42 | nop 43 | 44 | // TODO: Resume current kernel stack 45 | addiu sp, sp, 24 46 | 47 | sw v0, TF_REG2(sp) // Store return value of function sys_* (in $v0) into trapframe 48 | 49 | j ret_from_exception // Return from exeception 50 | nop 51 | END(handle_sys) 52 | 53 | sys_call_table: // Syscall Table 54 | .align 2 55 | .word sys_putchar 56 | .word sys_getenvid 57 | .word sys_yield 58 | .word sys_env_destroy 59 | .word sys_set_pgfault_handler 60 | .word sys_mem_alloc 61 | .word sys_mem_map 62 | .word sys_mem_unmap 63 | .word sys_env_alloc 64 | .word sys_set_env_status 65 | .word sys_set_trapframe 66 | .word sys_panic 67 | .word sys_ipc_can_send 68 | .word sys_ipc_recv 69 | .word sys_cgetc 70 | .word sys_write_dev 71 | .word sys_read_dev 72 | -------------------------------------------------------------------------------- /lib/traps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern void handle_int(); 6 | extern void handle_reserved(); 7 | extern void handle_tlb(); 8 | extern void handle_sys(); 9 | extern void handle_mod(); 10 | unsigned long exception_handlers[32]; 11 | 12 | void trap_init() 13 | { 14 | int i; 15 | 16 | for (i = 0; i < 32; i++) { 17 | set_except_vector(i, handle_reserved); 18 | } 19 | 20 | set_except_vector(0, handle_int); 21 | set_except_vector(1, handle_mod); 22 | set_except_vector(2, handle_tlb); 23 | set_except_vector(3, handle_tlb); 24 | set_except_vector(8, handle_sys); 25 | } 26 | void *set_except_vector(int n, void *addr) 27 | { 28 | unsigned long handler = (unsigned long)addr; 29 | unsigned long old_handler = exception_handlers[n]; 30 | exception_handlers[n] = handler; 31 | return (void *)old_handler; 32 | } 33 | 34 | 35 | struct pgfault_trap_frame { 36 | u_int fault_va; 37 | u_int err; 38 | u_int sp; 39 | u_int eflags; 40 | u_int pc; 41 | u_int empty1; 42 | u_int empty2; 43 | u_int empty3; 44 | u_int empty4; 45 | u_int empty5; 46 | }; 47 | 48 | 49 | /*** exercise 4.11 ***/ 50 | void 51 | page_fault_handler(struct Trapframe *tf) 52 | { 53 | struct Trapframe PgTrapFrame; 54 | extern struct Env *curenv; 55 | 56 | bcopy(tf, &PgTrapFrame, sizeof(struct Trapframe)); 57 | 58 | if (tf->regs[29] >= (curenv->env_xstacktop - BY2PG) && 59 | tf->regs[29] <= (curenv->env_xstacktop - 1)) { 60 | tf->regs[29] = tf->regs[29] - sizeof(struct Trapframe); 61 | bcopy(&PgTrapFrame, (void *)tf->regs[29], sizeof(struct Trapframe)); 62 | } else { 63 | tf->regs[29] = curenv->env_xstacktop - sizeof(struct Trapframe); 64 | bcopy(&PgTrapFrame,(void *)curenv->env_xstacktop - sizeof(struct Trapframe),sizeof(struct Trapframe)); 65 | } 66 | // TODO: Set EPC to a proper value in the trapframe 67 | tf->cp0_epc = curenv->env_pgfault_handler; 68 | 69 | return; 70 | } 71 | -------------------------------------------------------------------------------- /mm/Makefile: -------------------------------------------------------------------------------- 1 | INCLUDES := -I./ -I../ -I../include/ 2 | 3 | %.o: %.c 4 | $(CC) $(CFLAGS) $(INCLUDES) -c $< 5 | 6 | %.o: %.S 7 | $(CC) $(CFLAGS) $(INCLUDES) -c $< 8 | 9 | .PHONY: clean 10 | 11 | all: pmap.o tlb_asm.o 12 | 13 | clean: 14 | rm -rf *~ *.o 15 | 16 | 17 | include ../include.mk 18 | -------------------------------------------------------------------------------- /mm/pmap.all: -------------------------------------------------------------------------------- 1 | # 1 "pmap.c" 2 | # 1 "" 3 | # 1 "" 4 | # 1 "pmap.c" 5 | # 1 "mmu.h" 1 6 | 7 | 8 | 9 | # 1 "types.h" 1 10 | # 12 "types.h" 11 | typedef unsigned char u_int8_t; 12 | typedef short int16_t; 13 | typedef unsigned short u_int16_t; 14 | typedef int int32_t; 15 | typedef unsigned int u_int32_t; 16 | typedef long long int64_t; 17 | typedef unsigned long long u_int64_t; 18 | 19 | typedef int32_t register_t; 20 | 21 | typedef unsigned char u_char; 22 | typedef unsigned short u_short; 23 | typedef unsigned int u_int; 24 | typedef unsigned long u_long; 25 | 26 | typedef u_int64_t u_quad_t; 27 | typedef int64_t quad_t; 28 | typedef quad_t * qaddr_t; 29 | 30 | typedef u_int32_t size_t; 31 | # 5 "mmu.h" 2 32 | # 101 "mmu.h" 33 | void bcopy(const void *, void *, size_t); 34 | void bzero(void *, size_t); 35 | 36 | extern char bootstacktop[], bootstack[]; 37 | 38 | extern u_long npage; 39 | 40 | typedef u_long Pde; 41 | # 2 "pmap.c" 2 42 | # 1 "pmap.h" 1 43 | 44 | 45 | 46 | 47 | # 1 "queue.h" 1 48 | # 6 "pmap.h" 2 49 | 50 | 51 | struct Page_list { struct Page *lh_first; }; 52 | typedef struct { struct Page *le_next; struct Page **le_prev; } Page_LIST_entry_t; 53 | 54 | struct Page { 55 | Page_LIST_entry_t pp_link; 56 | 57 | 58 | 59 | 60 | 61 | 62 | u_short pp_ref; 63 | }; 64 | 65 | void i386_detect_memory(void); 66 | 67 | void mips_vm_init(); 68 | # 3 "pmap.c" 2 69 | # 1 "printf.h" 1 70 | # 15 "printf.h" 71 | # 1 "/usr/eldk/usr/bin/../lib/gcc/mips-linux/4.0.0/include/stdarg.h" 1 3 4 72 | # 43 "/usr/eldk/usr/bin/../lib/gcc/mips-linux/4.0.0/include/stdarg.h" 3 4 73 | typedef __builtin_va_list __gnuc_va_list; 74 | # 105 "/usr/eldk/usr/bin/../lib/gcc/mips-linux/4.0.0/include/stdarg.h" 3 4 75 | typedef __gnuc_va_list va_list; 76 | # 16 "printf.h" 2 77 | void printf(char *fmt, ...); 78 | 79 | void _panic(const char *, int, const char *, ...) 80 | __attribute__((noreturn)); 81 | # 4 "pmap.c" 2 82 | # 1 "env.h" 1 83 | # 19 "env.h" 84 | struct Env { 85 | 86 | struct { struct Env *le_next; struct Env **le_prev; } env_link; 87 | u_int env_id; 88 | u_int env_parent_id; 89 | u_int env_status; 90 | Pde *env_pgdir; 91 | u_int env_cr3; 92 | 93 | 94 | u_int env_ipc_value; 95 | u_int env_ipc_from; 96 | u_int env_ipc_recving; 97 | u_int env_ipc_dstva; 98 | u_int env_ipc_perm; 99 | 100 | 101 | u_int env_pgfault_handler; 102 | u_int env_xstacktop; 103 | 104 | 105 | u_int env_runs; 106 | }; 107 | # 5 "pmap.c" 2 108 | # 1 "error.h" 1 109 | # 6 "pmap.c" 2 110 | 111 | 112 | 113 | u_long maxpa; 114 | u_long npage; 115 | u_long basemem; 116 | u_long extmem; 117 | 118 | Pde* boot_pgdir; 119 | 120 | struct Page *pages; 121 | static u_long freemem; 122 | 123 | 124 | void mips_detect_memory() 125 | { 126 | 127 | basemem = 64*1024*1024; 128 | extmem = 0; 129 | maxpa = basemem; 130 | 131 | npage = maxpa / 4096; 132 | 133 | printf("Physical memory: %dK available, ", (int)(maxpa/1024)); 134 | printf("base = %dK, extended = %dK\n", (int)(basemem/1024), (int)(extmem/1024)); 135 | } 136 | 137 | static void * alloc(u_int n, u_int align, int clear) 138 | { 139 | extern char end[]; 140 | void *v; 141 | u_long alloced_mem; 142 | 143 | if (freemem == 0) 144 | freemem = (u_long)end; 145 | 146 | printf("pmap.c:\talloc from %x",freemem); 147 | 148 | 149 | freemem = (((((u_long)(freemem))+(align)-1)) & ~((align)-1)); 150 | 151 | alloced_mem = freemem; 152 | 153 | freemem = freemem + n; 154 | 155 | 156 | printf(" to %x\n",freemem); 157 | 158 | if (({ u_long a = (u_long) (freemem); if (a < 0x80000000) _panic("pmap.c", 54, "PADDR called with invalid kva %08lx", a); a - 0x80000000; }) >= maxpa) 159 | { 160 | _panic("pmap.c", 56, "out of memorty\n"); 161 | return -4; 162 | } 163 | 164 | if(clear) bzero(alloced_mem,n); 165 | 166 | return alloced_mem; 167 | 168 | } 169 | 170 | static Pde* boot_pgdir_walk(Pde *pgdir, u_long va, int create) 171 | { 172 | 173 | if(va>=0x80000000) _panic("pmap.c", 69, "mmu only working in low 2G space!\n"); 174 | 175 | printf("pmap.c:\tboot_pgdir_walk()\tva=%x\tpte=%x\n",va,(int)(&pgdir[((((u_long)(va))>>12) & 0x0FFFFF)*2])); 176 | 177 | return (Pde*)(&pgdir[((((u_long)(va))>>12) & 0x0FFFFF)*2]); 178 | } 179 | 180 | 181 | 182 | 183 | 184 | 185 | static void boot_map_segment(Pde *pgdir, u_long va, u_long size, u_long pa, int perm) 186 | { 187 | int i; 188 | int perm_p; 189 | u_long va_temp; 190 | Pde *pgtable_entry; 191 | 192 | if(size%4096!=0) _panic("pmap.c", 88, "size is not a multiple of BY2PG\n"); 193 | 194 | if(va>=0x80000000) _panic("pmap.c", 90, "mmu only working in low 2G space!\n"); 195 | 196 | perm_p = perm|0x002; 197 | 198 | for(i = 0;i < size;i+=4096) 199 | { 200 | va_temp = va+i; 201 | pgtable_entry = boot_pgdir_walk(pgdir, va_temp,1); 202 | *pgtable_entry = ((((u_long)(pa + i))>> 2) & 0x3FFFFFC0 )|perm_p; 203 | printf("pmap.c:\tmap()\tva=%x\tpa=%x\n",va_temp,pa+i); 204 | } 205 | 206 | return; 207 | } 208 | 209 | 210 | void mips_vm_init() 211 | { 212 | extern char KVPT[]; 213 | extern struct Env *envs; 214 | Pde* pgdir; 215 | u_int n; 216 | 217 | pgdir = (u_long *) KVPT; 218 | 219 | boot_pgdir=pgdir; 220 | printf("pmap.c:\tinit()\tKVPT:%x\n",(int)(&pgdir)); 221 | 222 | _panic("pmap.c", 118, "-------------------init not finish-------------"); 223 | 224 | pages = (struct Page*)alloc(npage*sizeof(struct Page),4096,1); 225 | n = (((((u_long)(npage * sizeof(struct Page)))+(4096)-1)) & ~((4096)-1)); 226 | boot_map_segment(pgdir,((0x80000000 - (4*1024*1024)) - (4*1024*1024)),n,({ u_long a = (u_long) (pages); if (a < 0x80000000) _panic("pmap.c", 122, "PADDR called with invalid kva %08lx", a); a - 0x80000000; }),0x018|0x004); 227 | 228 | 229 | envs = (struct Env*)alloc((1<<10)*sizeof(struct Env),4096,1); 230 | boot_map_segment(pgdir,(((0x80000000 - (4*1024*1024)) - (4*1024*1024)) - (4*1024*1024)),(1<<10)*sizeof(struct Env),({ u_long a = (u_long) (envs); if (a < 0x80000000) _panic("pmap.c", 126, "PADDR called with invalid kva %08lx", a); a - 0x80000000; }),0x018|0x004); 231 | 232 | } 233 | -------------------------------------------------------------------------------- /mm/tlb_asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | LEAF(tlb_out) 6 | //1: j 1b 7 | nop 8 | mfc0 k1,CP0_ENTRYHI 9 | mtc0 a0,CP0_ENTRYHI 10 | nop 11 | // insert tlbp or tlbwi 12 | tlbp 13 | nop 14 | nop 15 | nop 16 | nop 17 | mfc0 k0,CP0_INDEX 18 | bltz k0,NOFOUND 19 | nop 20 | mtc0 zero,CP0_ENTRYHI 21 | mtc0 zero,CP0_ENTRYLO0 22 | nop 23 | // insert tlbp or tlbwi 24 | tlbwi 25 | NOFOUND: 26 | 27 | mtc0 k1,CP0_ENTRYHI 28 | 29 | j ra 30 | nop 31 | END(tlb_out) 32 | -------------------------------------------------------------------------------- /readelf/Makefile: -------------------------------------------------------------------------------- 1 | INCLUDES := -I./ 2 | CC := gcc 3 | 4 | 5 | %.o: %.c 6 | $(CC) $(INCLUDES) -c $< 7 | 8 | .PHONY: clean 9 | 10 | readelf: main.o readelf.o 11 | $(CC) main.o readelf.o -o readelf 12 | 13 | 14 | clean: 15 | rm -rf *.o 16 | rm readelf 17 | -------------------------------------------------------------------------------- /readelf/kerelf.h: -------------------------------------------------------------------------------- 1 | /* This file defines standard ELF types, structures, and macros. 2 | Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | Contributed by Ian Lance Taylor . 5 | 6 | The GNU C Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The GNU C Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the GNU C Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. */ 20 | 21 | #ifndef _KER_ELF_H 22 | #define _KER_ELF_H 23 | 24 | /* ELF defination file from GNU C Library. We simplefied this 25 | * file for our lab, removing definations about ELF64, structs and 26 | * enums which we don't care. 27 | */ 28 | 29 | #include "types.h" 30 | 31 | typedef u_int64_t uint64_t; 32 | typedef u_int32_t uint32_t; 33 | typedef u_int16_t uint16_t; 34 | 35 | /* Type for a 16-bit quantity. */ 36 | typedef uint16_t Elf32_Half; 37 | 38 | /* Types for signed and unsigned 32-bit quantities. */ 39 | typedef uint32_t Elf32_Word; 40 | typedef int32_t Elf32_Sword; 41 | 42 | /* Types for signed and unsigned 64-bit quantities. */ 43 | typedef uint64_t Elf32_Xword; 44 | typedef int64_t Elf32_Sxword; 45 | 46 | /* Type of addresses. */ 47 | typedef uint32_t Elf32_Addr; 48 | 49 | /* Type of file offsets. */ 50 | typedef uint32_t Elf32_Off; 51 | 52 | /* Type for section indices, which are 16-bit quantities. */ 53 | typedef uint16_t Elf32_Section; 54 | 55 | /* Type of symbol indices. */ 56 | typedef uint32_t Elf32_Symndx; 57 | 58 | 59 | /* The ELF file header. This appears at the start of every ELF file. */ 60 | 61 | #define EI_NIDENT (16) 62 | 63 | typedef struct { 64 | unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 65 | Elf32_Half e_type; /* Object file type */ 66 | Elf32_Half e_machine; /* Architecture */ 67 | Elf32_Word e_version; /* Object file version */ 68 | Elf32_Addr e_entry; /* Entry point virtual address */ 69 | Elf32_Off e_phoff; /* Program header table file offset */ 70 | Elf32_Off e_shoff; /* Section header table file offset */ 71 | Elf32_Word e_flags; /* Processor-specific flags */ 72 | Elf32_Half e_ehsize; /* ELF header size in bytes */ 73 | Elf32_Half e_phentsize; /* Program header table entry size */ 74 | Elf32_Half e_phnum; /* Program header table entry count */ 75 | Elf32_Half e_shentsize; /* Section header table entry size */ 76 | Elf32_Half e_shnum; /* Section header table entry count */ 77 | Elf32_Half e_shstrndx; /* Section header string table index */ 78 | } Elf32_Ehdr; 79 | 80 | /* Fields in the e_ident array. The EI_* macros are indices into the 81 | array. The macros under each EI_* macro are the values the byte 82 | may have. */ 83 | 84 | #define EI_MAG0 0 /* File identification byte 0 index */ 85 | #define ELFMAG0 0x7f /* Magic number byte 0 */ 86 | 87 | #define EI_MAG1 1 /* File identification byte 1 index */ 88 | #define ELFMAG1 'E' /* Magic number byte 1 */ 89 | 90 | #define EI_MAG2 2 /* File identification byte 2 index */ 91 | #define ELFMAG2 'L' /* Magic number byte 2 */ 92 | 93 | #define EI_MAG3 3 /* File identification byte 3 index */ 94 | #define ELFMAG3 'F' /* Magic number byte 3 */ 95 | 96 | 97 | /* Section segment header. */ 98 | typedef struct{ 99 | Elf32_Word sh_name; /* Section name */ 100 | Elf32_Word sh_type; /* Section type */ 101 | Elf32_Word sh_flags; /* Section flags */ 102 | Elf32_Addr sh_addr; /* Section addr */ 103 | Elf32_Off sh_offset; /* Section offset */ 104 | Elf32_Word sh_size; /* Section size */ 105 | Elf32_Word sh_link; /* Section link */ 106 | Elf32_Word sh_info; /* Section extra info */ 107 | Elf32_Word sh_addralign; /* Section alignment */ 108 | Elf32_Word sh_entsize; /* Section entry size */ 109 | }Elf32_Shdr; 110 | 111 | 112 | /* Program segment header. */ 113 | 114 | typedef struct { 115 | Elf32_Word p_type; /* Segment type */ 116 | Elf32_Off p_offset; /* Segment file offset */ 117 | Elf32_Addr p_vaddr; /* Segment virtual address */ 118 | Elf32_Addr p_paddr; /* Segment physical address */ 119 | Elf32_Word p_filesz; /* Segment size in file */ 120 | Elf32_Word p_memsz; /* Segment size in memory */ 121 | Elf32_Word p_flags; /* Segment flags */ 122 | Elf32_Word p_align; /* Segment alignment */ 123 | } Elf32_Phdr; 124 | 125 | 126 | /* Legal values for p_type (segment type). */ 127 | 128 | #define PT_NULL 0 /* Program header table entry unused */ 129 | #define PT_LOAD 1 /* Loadable program segment */ 130 | #define PT_DYNAMIC 2 /* Dynamic linking information */ 131 | #define PT_INTERP 3 /* Program interpreter */ 132 | #define PT_NOTE 4 /* Auxiliary information */ 133 | #define PT_SHLIB 5 /* Reserved */ 134 | #define PT_PHDR 6 /* Entry for header table itself */ 135 | #define PT_NUM 7 /* Number of defined types. */ 136 | #define PT_LOOS 0x60000000 /* Start of OS-specific */ 137 | #define PT_HIOS 0x6fffffff /* End of OS-specific */ 138 | #define PT_LOPROC 0x70000000 /* Start of processor-specific */ 139 | #define PT_HIPROC 0x7fffffff /* End of processor-specific */ 140 | 141 | /* Legal values for p_flags (segment flags). */ 142 | 143 | #define PF_X (1 << 0) /* Segment is executable */ 144 | #define PF_W (1 << 1) /* Segment is writable */ 145 | #define PF_R (1 << 2) /* Segment is readable */ 146 | #define PF_MASKPROC 0xf0000000 /* Processor-specific */ 147 | 148 | int readelf(u_char *binary,int size); 149 | 150 | #endif /* kerelf.h */ 151 | 152 | -------------------------------------------------------------------------------- /readelf/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int readelf(u_char* binary, int size); 5 | /* 6 | overview: input a elf format file name from control line, call the readelf function 7 | to parse it. 8 | params: 9 | argc: the number of parameters 10 | argv: array of parameters, argv[1] shuold be the file name. 11 | 12 | */ 13 | int main(int argc,char *argv[]) 14 | { 15 | FILE* fp; 16 | int fsize; 17 | unsigned char *p; 18 | 19 | 20 | if(argc < 2) 21 | { 22 | printf("Please input the filename.\n"); 23 | return 0; 24 | } 25 | if((fp = fopen(argv[1],"rb"))==NULL) 26 | { 27 | printf("File not found\n"); 28 | return 0; 29 | } 30 | fseek(fp,0L,SEEK_END); 31 | fsize = ftell(fp); 32 | p = (u_char *)malloc(fsize+1); 33 | if(p == NULL) 34 | { 35 | fclose(fp); 36 | return 0; 37 | } 38 | fseek(fp,0L,SEEK_SET); 39 | fread(p,fsize,1,fp); 40 | p[fsize] = 0; 41 | 42 | 43 | readelf(p,fsize); 44 | return 0; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /readelf/readelf.c: -------------------------------------------------------------------------------- 1 | /* This is a simplefied ELF reader. 2 | * You can contact me if you find any bugs. 3 | * 4 | * Luming Wang 5 | */ 6 | 7 | #include "kerelf.h" 8 | #include 9 | /* Overview: 10 | * Check whether it is a ELF file. 11 | * 12 | * Pre-Condition: 13 | * binary must longer than 4 byte. 14 | * 15 | * Post-Condition: 16 | * Return 0 if `binary` isn't an elf. Otherwise 17 | * return 1. 18 | */ 19 | int is_elf_format(u_char *binary) 20 | { 21 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)binary; 22 | if (ehdr->e_ident[EI_MAG0] == ELFMAG0 && 23 | ehdr->e_ident[EI_MAG1] == ELFMAG1 && 24 | ehdr->e_ident[EI_MAG2] == ELFMAG2 && 25 | ehdr->e_ident[EI_MAG3] == ELFMAG3) { 26 | return 1; 27 | } 28 | 29 | return 0; 30 | } 31 | 32 | /* Overview: 33 | * read an elf format binary file. get ELF's information 34 | * 35 | * Pre-Condition: 36 | * `binary` can't be NULL and `size` is the size of binary. 37 | * 38 | * Post-Condition: 39 | * Return 0 if success. Otherwise return < 0. 40 | * If success, output address of every section in ELF. 41 | */ 42 | 43 | /* 44 | Exercise 1.2. Please complete func "readelf". 45 | */ 46 | int readelf(u_char *binary, int size) 47 | { 48 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)binary; 49 | 50 | int Nr; 51 | 52 | Elf32_Shdr *shdr = NULL; 53 | 54 | u_char *ptr_sh_table = NULL; 55 | Elf32_Half sh_entry_count; 56 | Elf32_Half sh_entry_size; 57 | 58 | 59 | // check whether `binary` is a ELF file. 60 | if (size < 4 || !is_elf_format(binary)) { 61 | printf("not a standard elf format\n"); 62 | return -1; 63 | } 64 | 65 | // get section table addr, section header number and section header size. 66 | shdr = binary + ehdr->e_shoff; 67 | sh_entry_count = ehdr->e_shnum; 68 | sh_entry_size = ehdr->e_shentsize; 69 | 70 | // for each section header, output section number and section addr. 71 | // hint: section number starts at 0. 72 | ptr_sh_table = shdr; 73 | for (Nr = 0; Nr < sh_entry_count; Nr++) { 74 | Elf32_Addr sh_addr = ((Elf32_Shdr *)ptr_sh_table)->sh_addr; 75 | printf("%d:0x%x\n", Nr, sh_addr); 76 | ptr_sh_table += sh_entry_size; 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /readelf/testELF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/readelf/testELF -------------------------------------------------------------------------------- /readelf/types.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: types.h,v 1.12 1997/11/30 18:50:18 millert Exp $ */ 2 | /* $NetBSD: types.h,v 1.29 1996/11/15 22:48:25 jtc Exp $ */ 3 | 4 | #ifndef _INC_TYPES_H_ 5 | #define _INC_TYPES_H_ 6 | 7 | #ifndef NULL 8 | #define NULL ((void *) 0) 9 | #endif /* !NULL */ 10 | 11 | 12 | typedef unsigned char u_int8_t; 13 | typedef short int16_t; 14 | typedef unsigned short u_int16_t; 15 | typedef int int32_t; 16 | typedef unsigned int u_int32_t; 17 | typedef long long int64_t; 18 | typedef unsigned long long u_int64_t; 19 | 20 | typedef int32_t register_t; 21 | 22 | typedef unsigned char u_char; 23 | typedef unsigned short u_short; 24 | typedef unsigned int u_int; 25 | typedef unsigned long u_long; 26 | 27 | typedef u_int64_t u_quad_t; /* quads */ 28 | typedef int64_t quad_t; 29 | typedef quad_t * qaddr_t; 30 | 31 | 32 | 33 | #define MIN(_a, _b) \ 34 | ({ \ 35 | typeof(_a) __a = (_a); \ 36 | typeof(_b) __b = (_b); \ 37 | __a <= __b ? __a : __b; \ 38 | }) 39 | 40 | /* Static assert, for compile-time assertion checking */ 41 | #define static_assert(c) switch (c) case 0: case(c): 42 | 43 | #define offsetof(type, member) ((size_t)(&((type *)0)->member)) 44 | 45 | /* Rounding; only works for n = power of two */ 46 | #define ROUND(a, n) (((((u_long)(a))+(n)-1)) & ~((n)-1)) 47 | #define ROUNDDOWN(a, n) (((u_long)(a)) & ~((n)-1)) 48 | 49 | 50 | #endif /* !_INC_TYPES_H_ */ 51 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gxemul -E testmips -C R3000 -M 64 -d gxemul/fs.img gxemul/vmlinux 4 | 5 | -------------------------------------------------------------------------------- /tools/fsformat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/tools/fsformat -------------------------------------------------------------------------------- /tools/scse0_3.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(mips) 2 | ENTRY(_start) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000080; 7 | .except_vec3 : { 8 | *(.text.exc_vec3) 9 | } 10 | 11 | . = 0x80010000; 12 | 13 | /*** exercise 3.12 ***/ 14 | 15 | .text : { 16 | *(.text) 17 | } 18 | 19 | .bss : { 20 | *(.bss) 21 | } 22 | 23 | .data : { 24 | *(.data) 25 | } 26 | 27 | .sdata : { 28 | *(.sdata) 29 | } 30 | 31 | . = 0x80400000; 32 | 33 | end = . ; 34 | } 35 | -------------------------------------------------------------------------------- /tools/scse0_3.lds~: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(mips) 2 | ENTRY(_start) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .interrupt1 : { 8 | *(.text.rftlb1) 9 | } 10 | 11 | . = 0x80000080; 12 | .interrupt2 : { 13 | *(.text.rftlb2) 14 | } 15 | 16 | . = 0x80010000; 17 | .text : { 18 | *(.text) 19 | *(.rodata) 20 | *(.rodata1) 21 | *(.rodata.str1.4) 22 | } 23 | 24 | .reginfo : { *(.reginfo) } 25 | 26 | .date : { 27 | *(.data) 28 | } 29 | 30 | .bss : { 31 | *(.dynbss) 32 | *(.bss) 33 | } 34 | 35 | . = 0x803F8000; 36 | .kernelstk : { 37 | *(.data.stk) 38 | } 39 | 40 | . = 0x80400000; 41 | KVPT = . ; 42 | .kernelvpt : { 43 | *(.data.vpt) 44 | } 45 | 46 | end = . ; 47 | } 48 | -------------------------------------------------------------------------------- /user/Makefile: -------------------------------------------------------------------------------- 1 | INCLUDES = -I../include/ 2 | 3 | #CROSS_COMPILE := /usr/eldk/usr/bin/mips_4KC- 4 | #CC := $(CROSS_COMPILE)gcc 5 | #CFLAGS := -O -G 0 -mno-abicalls -fno-builtin -Wa,-xgot -Wall -fPIC 6 | #LD := $(CROSS_COMPILE)ld 7 | # For embedding one program in another 8 | 9 | USERLIB := printf.o \ 10 | print.o \ 11 | libos.o \ 12 | fork.o \ 13 | pgfault.o \ 14 | syscall_lib.o \ 15 | ipc.o \ 16 | string.o \ 17 | fd.o \ 18 | pageref.o \ 19 | file.o \ 20 | pipe.o \ 21 | fsipc.o \ 22 | wait.o \ 23 | spawn.o \ 24 | console.o \ 25 | fprintf.o 26 | 27 | CFLAGS += -nostdlib -static 28 | 29 | 30 | all: echo.x echo.b num.x num.b testptelibrary.b testptelibrary.x fktest.x fktest.b pingpong.x pingpong.b idle.x testarg.b testpipe.x testpiperace.x icode.x init.b sh.b cat.b ls.b fstest.x fstest.b $(USERLIB) entry.o syscall_wrap.o 31 | 32 | %.x: %.b.c 33 | echo cc1 $< 34 | $(CC) $(CFLAGS) -c -o $@ $< 35 | 36 | %.b.c: %.b 37 | echo create $@ 38 | echo bintoc $* $< > $@~ 39 | chmod +x ./bintoc 40 | ./bintoc $* $< > $@~ && mv -f $@~ $@ 41 | # grep \. $@ 42 | 43 | %.b: entry.o syscall_wrap.o %.o $(USERLIB) 44 | echo ld $@ 45 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T ./user.lds $^ 46 | 47 | %.o: %.c 48 | echo user1 cc $< 49 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 50 | 51 | %.o: %.S 52 | echo as $< 53 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 54 | 55 | %.o: lib.h 56 | 57 | .PHONY: clean 58 | 59 | clean: 60 | rm -rf *~ *.o *.b.c *.x *.b 61 | 62 | include ../include.mk 63 | -------------------------------------------------------------------------------- /user/bintoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/refkxh/BUAA_OS_2020Spring/ec8e895c571526dcdb4e9d3d5ac385b2d27db054/user/bintoc -------------------------------------------------------------------------------- /user/cat.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | char buf[8192]; 4 | 5 | void 6 | cat(int f, char *s) 7 | { 8 | long n; 9 | int r; 10 | 11 | while((n=read(f, buf, (long)sizeof buf))>0) 12 | if((r=write(1, buf, n))!=n) 13 | user_panic("write error copying %s: %e", s, r); 14 | if(n < 0) 15 | user_panic("error reading %s: %e", s, n); 16 | } 17 | 18 | void 19 | umain(int argc, char **argv) 20 | { 21 | int f, i; 22 | 23 | if(argc == 1) 24 | cat(0, ""); 25 | else for(i=1; i 3 | 4 | static int cons_read(struct Fd*, void*, u_int, u_int); 5 | static int cons_write(struct Fd*, const void*, u_int, u_int); 6 | static int cons_close(struct Fd*); 7 | static int cons_stat(struct Fd*, struct Stat*); 8 | 9 | struct Dev devcons = 10 | { 11 | .dev_id= 'c', 12 | .dev_name= "cons", 13 | .dev_read= cons_read, 14 | .dev_write= cons_write, 15 | .dev_close= cons_close, 16 | .dev_stat= cons_stat, 17 | }; 18 | 19 | int 20 | iscons(int fdnum) 21 | { 22 | int r; 23 | struct Fd *fd; 24 | 25 | if ((r = fd_lookup(fdnum, &fd)) < 0) 26 | return r; 27 | return fd->fd_dev_id == devcons.dev_id; 28 | } 29 | 30 | int 31 | opencons(void) 32 | { 33 | int r; 34 | struct Fd *fd; 35 | 36 | if ((r = fd_alloc(&fd)) < 0) 37 | return r; 38 | if ((r = syscall_mem_alloc(0, (u_int)fd, PTE_V|PTE_R|PTE_LIBRARY)) < 0) 39 | return r; 40 | fd->fd_dev_id = devcons.dev_id; 41 | fd->fd_omode = O_RDWR; 42 | return fd2num(fd); 43 | } 44 | 45 | int 46 | cons_read(struct Fd *fd, void *vbuf, u_int n, u_int offset) 47 | { 48 | int c; 49 | 50 | USED(offset); 51 | // printf("got into cons_read"); 52 | if (n == 0) 53 | return 0; 54 | 55 | while ((c = syscall_cgetc()) == 0) 56 | syscall_yield(); 57 | 58 | if (c!='\r') 59 | writef("%c",c); 60 | else 61 | writef("\n"); 62 | if (c < 0) 63 | return c; 64 | if (c == 0x04) // ctl-d is eof 65 | return 0; 66 | *(char*)vbuf = c; 67 | return 1; 68 | } 69 | 70 | int 71 | cons_write(struct Fd *fd, const void *vbuf, u_int n, u_int offset) 72 | { 73 | int tot, m; 74 | char buf[128]; 75 | 76 | USED(offset); 77 | 78 | // mistake: have to nul-terminate arg to syscall_cputs, 79 | // so we have to copy vbuf into buf in chunks and nul-terminate. 80 | for(tot=0; tot sizeof buf-1) 83 | m = sizeof buf-1; 84 | user_bcopy((char*)vbuf+tot, buf, m); 85 | buf[m] = 0; 86 | writef("%s",buf); 87 | } 88 | return tot; 89 | } 90 | 91 | int 92 | cons_close(struct Fd *fd) 93 | { 94 | USED(fd); 95 | 96 | return 0; 97 | } 98 | 99 | int 100 | cons_stat(struct Fd *fd, struct Stat *stat) 101 | { 102 | strcpy(stat->st_name, ""); 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /user/echo.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | void 4 | umain(int argc, char **argv) 5 | { 6 | int i, nflag; 7 | 8 | nflag = 0; 9 | if (argc > 1 && strcmp(argv[1], "-n") == 0) { 10 | nflag = 1; 11 | argc--; 12 | argv++; 13 | } 14 | for (i = 1; i < argc; i++) { 15 | if (i > 1) 16 | write(1, " ", 1); 17 | write(1, argv[i], strlen(argv[i])); 18 | } 19 | if (!nflag) 20 | write(1, "\n", 1); 21 | } -------------------------------------------------------------------------------- /user/entry.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | .data 7 | 8 | .p2align 12 9 | 10 | .globl fsipcbuf 11 | fsipcbuf: 12 | .space BY2PG 13 | .globl fdtab 14 | fdtab: 15 | .space BY2PG 16 | 17 | 18 | .globl envs 19 | envs: 20 | .word UENVS 21 | 22 | .globl pages 23 | pages: 24 | .word UPAGES 25 | 26 | .globl vpt 27 | vpt: 28 | .word UVPT 29 | 30 | .globl vpd 31 | vpd: 32 | .word (UVPT+(UVPT>>12)*4) 33 | 34 | .globl __pgfault_handler 35 | __pgfault_handler: 36 | .word 0 37 | 38 | 39 | .extern libmain 40 | 41 | .text 42 | .globl _start 43 | _start: 44 | //1: j 1b 45 | lw a0, 0(sp) 46 | lw a1, 4(sp) 47 | //sw a0, -4(sp) 48 | //sw a1, -0(sp) 49 | nop 50 | jal libmain 51 | nop 52 | 53 | .set noreorder 54 | .text 55 | .globl __asm_pgfault_handler 56 | __asm_pgfault_handler: 57 | // save the caller-save registers 58 | // (your code here) 59 | //1: j 1b 60 | nop 61 | lw a0, TF_BADVADDR(sp) 62 | //sw t0, (sp) 63 | //subu sp,16 64 | lw t1, __pgfault_handler 65 | jalr t1 66 | 67 | nop 68 | // push trap-time eip, eflags onto trap-time stack 69 | // (your code here) 70 | //addu sp,16 71 | lw v1,TF_LO(sp) 72 | mtlo v1 73 | lw v0,TF_HI(sp) 74 | lw v1,TF_EPC(sp) 75 | mthi v0 76 | mtc0 v1,CP0_EPC 77 | lw $31,TF_REG31(sp) 78 | lw $30,TF_REG30(sp) 79 | lw $28,TF_REG28(sp) 80 | lw $25,TF_REG25(sp) 81 | lw $24,TF_REG24(sp) 82 | lw $23,TF_REG23(sp) 83 | lw $22,TF_REG22(sp) 84 | lw $21,TF_REG21(sp) 85 | lw $20,TF_REG20(sp) 86 | lw $19,TF_REG19(sp) 87 | lw $18,TF_REG18(sp) 88 | lw $17,TF_REG17(sp) 89 | lw $16,TF_REG16(sp) 90 | lw $15,TF_REG15(sp) 91 | lw $14,TF_REG14(sp) 92 | lw $13,TF_REG13(sp) 93 | lw $12,TF_REG12(sp) 94 | lw $11,TF_REG11(sp) 95 | lw $10,TF_REG10(sp) 96 | lw $9,TF_REG9(sp) 97 | lw $8,TF_REG8(sp) 98 | lw $7,TF_REG7(sp) 99 | lw $6,TF_REG6(sp) 100 | lw $5,TF_REG5(sp) 101 | lw $4,TF_REG4(sp) 102 | lw $3,TF_REG3(sp) 103 | lw $2,TF_REG2(sp) 104 | lw $1,TF_REG1(sp) 105 | lw k0,TF_EPC(sp) //atomic operation needed 106 | jr k0 // 107 | lw sp,TF_REG29(sp) /* Deallocate stack */ 108 | 109 | -------------------------------------------------------------------------------- /user/fd.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include "fd.h" 3 | #include 4 | #include 5 | 6 | 7 | static struct Dev *devtab[] = { 8 | &devfile, 9 | &devcons, 10 | &devpipe, 11 | 0 12 | }; 13 | 14 | int 15 | dev_lookup(int dev_id, struct Dev **dev) 16 | { 17 | int i; 18 | 19 | for (i = 0; devtab[i]; i++) 20 | if (devtab[i]->dev_id == dev_id) { 21 | *dev = devtab[i]; 22 | return 0; 23 | } 24 | 25 | writef("[%08x] unknown device type %d\n", env->env_id, dev_id); 26 | return -E_INVAL; 27 | } 28 | 29 | int 30 | fd_alloc(struct Fd **fd) 31 | { 32 | // Find the smallest i from 0 to MAXFD-1 that doesn't have 33 | // its fd page mapped. Set *fd to the fd page virtual address. 34 | // (Do not allocate a page. It is up to the caller to allocate 35 | // the page. This means that if someone calls fd_alloc twice 36 | // in a row without allocating the first page we return, we'll 37 | // return the same page the second time.) 38 | // Return 0 on success, or an error code on error. 39 | u_int va; 40 | u_int fdno; 41 | 42 | for (fdno = 0; fdno < MAXFD - 1; fdno++) { 43 | va = INDEX2FD(fdno); 44 | 45 | if (((* vpd)[va / PDMAP] & PTE_V) == 0) { 46 | *fd = (struct Fd *)va; 47 | return 0; 48 | } 49 | 50 | if (((* vpt)[va / BY2PG] & PTE_V) == 0) { //the fd is not used 51 | *fd = (struct Fd *)va; 52 | return 0; 53 | } 54 | } 55 | 56 | return -E_MAX_OPEN; 57 | } 58 | 59 | void 60 | fd_close(struct Fd *fd) 61 | { 62 | syscall_mem_unmap(0, (u_int)fd); 63 | } 64 | 65 | int 66 | fd_lookup(int fdnum, struct Fd **fd) 67 | { 68 | // Check that fdnum is in range and mapped. If not, return -E_INVAL. 69 | // Set *fd to the fd page virtual address. Return 0. 70 | u_int va; 71 | 72 | if (fdnum >= MAXFD) { 73 | return -E_INVAL; 74 | } 75 | 76 | va = INDEX2FD(fdnum); 77 | 78 | if (((* vpt)[va / BY2PG] & PTE_V) != 0) { //the fd is used 79 | *fd = (struct Fd *)va; 80 | return 0; 81 | } 82 | 83 | return -E_INVAL; 84 | } 85 | 86 | u_int 87 | fd2data(struct Fd *fd) 88 | { 89 | return INDEX2DATA(fd2num(fd)); 90 | } 91 | 92 | int 93 | fd2num(struct Fd *fd) 94 | { 95 | return ((u_int)fd - FDTABLE) / BY2PG; 96 | } 97 | 98 | int 99 | num2fd(int fd) 100 | { 101 | return fd * BY2PG + FDTABLE; 102 | } 103 | 104 | int 105 | close(int fdnum) 106 | { 107 | int r; 108 | struct Dev *dev; 109 | struct Fd *fd; 110 | 111 | if ((r = fd_lookup(fdnum, &fd)) < 0 112 | || (r = dev_lookup(fd->fd_dev_id, &dev)) < 0) { 113 | return r; 114 | } 115 | 116 | r = (*dev->dev_close)(fd); 117 | fd_close(fd); 118 | return r; 119 | } 120 | 121 | void 122 | close_all(void) 123 | { 124 | int i; 125 | 126 | for (i = 0; i < MAXFD; i++) { 127 | close(i); 128 | } 129 | } 130 | 131 | int 132 | dup(int oldfdnum, int newfdnum) 133 | { 134 | int i, r; 135 | u_int ova, nva, pte; 136 | struct Fd *oldfd, *newfd; 137 | 138 | if ((r = fd_lookup(oldfdnum, &oldfd)) < 0) { 139 | return r; 140 | } 141 | 142 | close(newfdnum); 143 | newfd = (struct Fd *)INDEX2FD(newfdnum); 144 | ova = fd2data(oldfd); 145 | nva = fd2data(newfd); 146 | 147 | if ((* vpd)[PDX(ova)]) { 148 | for (i = 0; i < PDMAP; i += BY2PG) { 149 | pte = (* vpt)[VPN(ova + i)]; 150 | 151 | if (pte & PTE_V) { 152 | // should be no error here -- pd is already allocated 153 | if ((r = syscall_mem_map(0, ova + i, 0, nva + i, 154 | pte & (PTE_V | PTE_R | PTE_LIBRARY))) < 0) { 155 | goto err; 156 | } 157 | } 158 | } 159 | } 160 | 161 | if ((r = syscall_mem_map(0, (u_int)oldfd, 0, (u_int)newfd, 162 | ((*vpt)[VPN(oldfd)]) & (PTE_V | PTE_R | PTE_LIBRARY))) < 0) { 163 | goto err; 164 | } 165 | 166 | return newfdnum; 167 | 168 | err: 169 | syscall_mem_unmap(0, (u_int)newfd); 170 | 171 | for (i = 0; i < PDMAP; i += BY2PG) { 172 | syscall_mem_unmap(0, nva + i); 173 | } 174 | 175 | return r; 176 | } 177 | 178 | // Overview: 179 | // Read 'n' bytes from 'fd' at the current seek position into 'buf'. 180 | // 181 | // Post-Condition: 182 | // Update seek position. 183 | // Return the number of bytes read successfully. 184 | // < 0 on error 185 | int 186 | read(int fdnum, void *buf, u_int n) 187 | { 188 | int r; 189 | struct Dev *dev; 190 | struct Fd *fd; 191 | 192 | // Similar to 'write' function. 193 | // Step 1: Get fd and dev. 194 | if ((r = fd_lookup(fdnum, &fd)) < 0 || (r = dev_lookup(fd->fd_dev_id, &dev)) < 0) return r; 195 | 196 | // Step 2: Check open mode. 197 | if ((fd->fd_omode & O_ACCMODE) == O_WRONLY) { 198 | writef("[%08x] read %d -- bad mode\n", env->env_id, fdnum); 199 | return -E_INVAL; 200 | } 201 | 202 | if (debug) writef("read %d %p %d via dev %s\n", fdnum, buf, n, dev->dev_name); 203 | 204 | // Step 3: Read starting from seek position. 205 | r = (*dev->dev_read)(fd, buf, n, fd->fd_offset); 206 | 207 | // Step 4: Update seek position and set '\0' at the end of buf. 208 | if (r > 0) { 209 | fd->fd_offset += r; 210 | ((char *)buf)[r] = '\0'; 211 | } 212 | 213 | return r; 214 | } 215 | 216 | int 217 | readn(int fdnum, void *buf, u_int n) 218 | { 219 | int m, tot; 220 | 221 | for (tot = 0; tot < n; tot += m) { 222 | m = read(fdnum, (char *)buf + tot, n - tot); 223 | 224 | if (m < 0) { 225 | return m; 226 | } 227 | 228 | if (m == 0) { 229 | break; 230 | } 231 | } 232 | 233 | return tot; 234 | } 235 | 236 | int 237 | write(int fdnum, const void *buf, u_int n) 238 | { 239 | int r; 240 | struct Dev *dev; 241 | struct Fd *fd; 242 | 243 | if ((r = fd_lookup(fdnum, &fd)) < 0 244 | || (r = dev_lookup(fd->fd_dev_id, &dev)) < 0) { 245 | return r; 246 | } 247 | 248 | if ((fd->fd_omode & O_ACCMODE) == O_RDONLY) { 249 | writef("[%08x] write %d -- bad mode\n", env->env_id, fdnum); 250 | return -E_INVAL; 251 | } 252 | 253 | if (debug) writef("write %d %p %d via dev %s\n", 254 | fdnum, buf, n, dev->dev_name); 255 | 256 | r = (*dev->dev_write)(fd, buf, n, fd->fd_offset); 257 | 258 | if (r > 0) { 259 | fd->fd_offset += r; 260 | } 261 | 262 | return r; 263 | } 264 | 265 | int 266 | seek(int fdnum, u_int offset) 267 | { 268 | int r; 269 | struct Fd *fd; 270 | 271 | if ((r = fd_lookup(fdnum, &fd)) < 0) { 272 | return r; 273 | } 274 | 275 | fd->fd_offset = offset; 276 | return 0; 277 | } 278 | 279 | 280 | int fstat(int fdnum, struct Stat *stat) 281 | { 282 | int r; 283 | struct Dev *dev; 284 | struct Fd *fd; 285 | 286 | if ((r = fd_lookup(fdnum, &fd)) < 0 287 | || (r = dev_lookup(fd->fd_dev_id, &dev)) < 0) { 288 | return r; 289 | } 290 | 291 | stat->st_name[0] = 0; 292 | stat->st_size = 0; 293 | stat->st_isdir = 0; 294 | stat->st_dev = dev; 295 | return (*dev->dev_stat)(fd, stat); 296 | } 297 | 298 | int 299 | stat(const char *path, struct Stat *stat) 300 | { 301 | int fd, r; 302 | 303 | if ((fd = open(path, O_RDONLY)) < 0) { 304 | return fd; 305 | } 306 | 307 | r = fstat(fd, stat); 308 | close(fd); 309 | return r; 310 | } 311 | 312 | -------------------------------------------------------------------------------- /user/fd.h: -------------------------------------------------------------------------------- 1 | #ifndef _USER_FD_H_ 2 | #define _USER_FD_H_ 1 3 | 4 | #include 5 | #include 6 | 7 | // pre-declare for forward references 8 | struct Fd; 9 | struct Stat; 10 | struct Dev; 11 | 12 | struct Dev 13 | { 14 | int dev_id; 15 | char *dev_name; 16 | int (*dev_read)(struct Fd*, void*, u_int, u_int); 17 | int (*dev_write)(struct Fd*, const void*, u_int, u_int); 18 | int (*dev_close)(struct Fd*); 19 | int (*dev_stat)(struct Fd*, struct Stat*); 20 | int (*dev_seek)(struct Fd*, u_int); 21 | }; 22 | 23 | struct Fd 24 | { 25 | u_int fd_dev_id; 26 | u_int fd_offset; 27 | u_int fd_omode; 28 | }; 29 | 30 | struct Stat 31 | { 32 | char st_name[MAXNAMELEN]; 33 | u_int st_size; 34 | u_int st_isdir; 35 | struct Dev *st_dev; 36 | }; 37 | 38 | struct Filefd 39 | { 40 | struct Fd f_fd; 41 | u_int f_fileid; 42 | struct File f_file; 43 | }; 44 | 45 | int fd_alloc(struct Fd **fd); 46 | int fd_lookup(int fdnum, struct Fd **fd); 47 | u_int fd2data(struct Fd*); 48 | int fd2num(struct Fd*); 49 | int dev_lookup(int dev_id, struct Dev **dev); 50 | int 51 | num2fd(int fd); 52 | extern struct Dev devcons; 53 | extern struct Dev devfile; 54 | extern struct Dev devpipe; 55 | #define debug 0 56 | 57 | #define MAXFD 32 58 | #define FILEBASE 0x60000000 59 | #define FDTABLE (FILEBASE-PDMAP) 60 | 61 | #define INDEX2FD(i) (FDTABLE+(i)*BY2PG) 62 | #define INDEX2DATA(i) (FILEBASE+(i)*PDMAP) 63 | 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /user/file.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | 4 | #define debug 0 5 | 6 | static int file_close(struct Fd *fd); 7 | static int file_read(struct Fd *fd, void *buf, u_int n, u_int offset); 8 | static int file_write(struct Fd *fd, const void *buf, u_int n, u_int offset); 9 | static int file_stat(struct Fd *fd, struct Stat *stat); 10 | 11 | 12 | // Dot represents choosing the variable of the same name within struct declaration 13 | // to assign, and no need to consider order of variables. 14 | struct Dev devfile = { 15 | .dev_id = 'f', 16 | .dev_name = "file", 17 | .dev_read = file_read, 18 | .dev_write = file_write, 19 | .dev_close = file_close, 20 | .dev_stat = file_stat, 21 | }; 22 | 23 | 24 | // Overview: 25 | // Open a file (or directory). 26 | // 27 | // Returns: 28 | // the file descriptor onsuccess, 29 | // < 0 on failure. 30 | int 31 | open(const char *path, int mode) 32 | { 33 | struct Fd *fd; 34 | struct Filefd *ffd; 35 | u_int size, fileid; 36 | int r; 37 | u_int va; 38 | u_int i; 39 | 40 | // Step 1: Alloc a new Fd, return error code when fail to alloc. 41 | // Hint: Please use fd_alloc. 42 | r = fd_alloc(&fd); 43 | if (r) return r; 44 | 45 | // Step 2: Get the file descriptor of the file to open. 46 | // Hint: Read fsipc.c, and choose a function. 47 | r = fsipc_open(path, mode, fd); 48 | if (r) return r; 49 | ffd = fd; 50 | 51 | // Step 3: Set the start address storing the file's content. Set size and fileid correctly. 52 | // Hint: Use fd2data to get the start address. 53 | va = fd2data(fd); 54 | size = ffd->f_file.f_size; 55 | fileid = ffd->f_fileid; 56 | 57 | // Step 4: Alloc memory, map the file content into memory. 58 | for (i = 0; i < size; i += BY2PG) { 59 | r = syscall_mem_alloc(0, va + i, PTE_R | PTE_V); 60 | if (r) return r; 61 | r = fsipc_map(fileid, i, va + i); 62 | if (r) return r; 63 | } 64 | 65 | // Step 5: Return the number of file descriptor. 66 | return fd2num(fd); 67 | 68 | } 69 | 70 | // Overview: 71 | // Close a file descriptor 72 | int 73 | file_close(struct Fd *fd) 74 | { 75 | int r; 76 | struct Filefd *ffd; 77 | u_int va, size, fileid; 78 | u_int i; 79 | 80 | ffd = (struct Filefd *)fd; 81 | fileid = ffd->f_fileid; 82 | size = ffd->f_file.f_size; 83 | 84 | // Set the start address storing the file's content. 85 | va = fd2data(fd); 86 | 87 | // Tell the file server the dirty page. 88 | for (i = 0; i < size; i += BY2PG) { 89 | fsipc_dirty(fileid, i); 90 | } 91 | 92 | // Request the file server to close the file with fsipc. 93 | if ((r = fsipc_close(fileid)) < 0) { 94 | writef("cannot close the file\n"); 95 | return r; 96 | } 97 | 98 | // Unmap the content of file, release memory. 99 | if (size == 0) { 100 | return 0; 101 | } 102 | for (i = 0; i < size; i += BY2PG) { 103 | if ((r = syscall_mem_unmap(0, va + i)) < 0) { 104 | writef("cannont unmap the file.\n"); 105 | return r; 106 | } 107 | } 108 | return 0; 109 | } 110 | 111 | // Overview: 112 | // Read 'n' bytes from 'fd' at the current seek position into 'buf'. Since files 113 | // are memory-mapped, this amounts to a user_bcopy() surrounded by a little red 114 | // tape to handle the file size and seek pointer. 115 | static int 116 | file_read(struct Fd *fd, void *buf, u_int n, u_int offset) 117 | { 118 | u_int size; 119 | struct Filefd *f; 120 | f = (struct Filefd *)fd; 121 | 122 | // Avoid reading past the end of file. 123 | size = f->f_file.f_size; 124 | 125 | if (offset > size) { 126 | return 0; 127 | } 128 | 129 | if (offset + n > size) { 130 | n = size - offset; 131 | } 132 | 133 | user_bcopy((char *)fd2data(fd) + offset, buf, n); 134 | return n; 135 | } 136 | 137 | // Overview: 138 | // Find the virtual address of the page that maps the file block 139 | // starting at 'offset'. 140 | int 141 | read_map(int fdnum, u_int offset, void **blk) 142 | { 143 | int r; 144 | u_int va; 145 | struct Fd *fd; 146 | 147 | if ((r = fd_lookup(fdnum, &fd)) < 0) { 148 | return r; 149 | } 150 | 151 | if (fd->fd_dev_id != devfile.dev_id) { 152 | return -E_INVAL; 153 | } 154 | 155 | va = fd2data(fd) + offset; 156 | 157 | if (offset >= MAXFILESIZE) { 158 | return -E_NO_DISK; 159 | } 160 | 161 | if (!((* vpd)[PDX(va)]&PTE_V) || !((* vpt)[VPN(va)]&PTE_V)) { 162 | return -E_NO_DISK; 163 | } 164 | 165 | *blk = (void *)va; 166 | return 0; 167 | } 168 | 169 | // Overview: 170 | // Write 'n' bytes from 'buf' to 'fd' at the current seek position. 171 | static int 172 | file_write(struct Fd *fd, const void *buf, u_int n, u_int offset) 173 | { 174 | int r; 175 | u_int tot; 176 | struct Filefd *f; 177 | 178 | f = (struct Filefd *)fd; 179 | 180 | // Don't write more than the maximum file size. 181 | tot = offset + n; 182 | 183 | if (tot > MAXFILESIZE) { 184 | return -E_NO_DISK; 185 | } 186 | 187 | // Increase the file's size if necessary 188 | if (tot > f->f_file.f_size) { 189 | if ((r = ftruncate(fd2num(fd), tot)) < 0) { 190 | return r; 191 | } 192 | } 193 | 194 | // Write the data 195 | user_bcopy(buf, (char *)fd2data(fd) + offset, n); 196 | return n; 197 | } 198 | 199 | static int 200 | file_stat(struct Fd *fd, struct Stat *st) 201 | { 202 | struct Filefd *f; 203 | 204 | f = (struct Filefd *)fd; 205 | 206 | strcpy(st->st_name, (char *)f->f_file.f_name); 207 | st->st_size = f->f_file.f_size; 208 | st->st_isdir = f->f_file.f_type == FTYPE_DIR; 209 | return 0; 210 | } 211 | 212 | // Overview: 213 | // Truncate or extend an open file to 'size' bytes 214 | int 215 | ftruncate(int fdnum, u_int size) 216 | { 217 | int i, r; 218 | struct Fd *fd; 219 | struct Filefd *f; 220 | u_int oldsize, va, fileid; 221 | 222 | if (size > MAXFILESIZE) { 223 | return -E_NO_DISK; 224 | } 225 | 226 | if ((r = fd_lookup(fdnum, &fd)) < 0) { 227 | return r; 228 | } 229 | 230 | if (fd->fd_dev_id != devfile.dev_id) { 231 | return -E_INVAL; 232 | } 233 | 234 | f = (struct Filefd *)fd; 235 | fileid = f->f_fileid; 236 | oldsize = f->f_file.f_size; 237 | f->f_file.f_size = size; 238 | 239 | if ((r = fsipc_set_size(fileid, size)) < 0) { 240 | return r; 241 | } 242 | 243 | va = fd2data(fd); 244 | 245 | // Map any new pages needed if extending the file 246 | for (i = ROUND(oldsize, BY2PG); i < ROUND(size, BY2PG); i += BY2PG) { 247 | if ((r = fsipc_map(fileid, i, va + i)) < 0) { 248 | fsipc_set_size(fileid, oldsize); 249 | return r; 250 | } 251 | } 252 | 253 | // Unmap pages if truncating the file 254 | for (i = ROUND(size, BY2PG); i < ROUND(oldsize, BY2PG); i += BY2PG) 255 | if ((r = syscall_mem_unmap(0, va + i)) < 0) { 256 | user_panic("ftruncate: syscall_mem_unmap %08x: %e", va + i, r); 257 | } 258 | 259 | return 0; 260 | } 261 | 262 | // Overview: 263 | // Delete a file or directory. 264 | int 265 | remove(const char *path) 266 | { 267 | // Your code here. 268 | // Call fsipc_remove. 269 | return fsipc_remove(path); 270 | } 271 | 272 | // Overview: 273 | // Synchronize disk with buffer cache 274 | int 275 | sync(void) 276 | { 277 | return fsipc_sync(); 278 | } 279 | 280 | -------------------------------------------------------------------------------- /user/fktest.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | 4 | void umain() 5 | { 6 | int a=0; 7 | int id=0; 8 | 9 | if((id=fork())==0) 10 | { 11 | if ((id=fork())==0) 12 | { 13 | a+=3; 14 | for(;;) writef("\t\tthis is child2 :a:%d\n",a); 15 | } 16 | a+=2; 17 | for(;;) writef("\tthis is child :a:%d\n",a); 18 | } 19 | a++; 20 | for(;;) writef("this is father: a:%d\n",a); 21 | } 22 | -------------------------------------------------------------------------------- /user/fork.c: -------------------------------------------------------------------------------- 1 | // implement fork from user space 2 | 3 | #include "lib.h" 4 | #include 5 | #include 6 | 7 | 8 | /* ----------------- help functions ---------------- */ 9 | 10 | /* Overview: 11 | * Copy `len` bytes from `src` to `dst`. 12 | * 13 | * Pre-Condition: 14 | * `src` and `dst` can't be NULL. Also, the `src` area 15 | * shouldn't overlap the `dest`, otherwise the behavior of this 16 | * function is undefined. 17 | */ 18 | void user_bcopy(const void *src, void *dst, size_t len) 19 | { 20 | void *max; 21 | 22 | // writef("~~~~~~~~~~~~~~~~ src:%x dst:%x len:%x\n",(int)src,(int)dst,len); 23 | max = dst + len; 24 | 25 | // copy machine words while possible 26 | if (((int)src % 4 == 0) && ((int)dst % 4 == 0)) { 27 | while (dst + 3 < max) { 28 | *(int *)dst = *(int *)src; 29 | dst += 4; 30 | src += 4; 31 | } 32 | } 33 | 34 | // finish remaining 0-3 bytes 35 | while (dst < max) { 36 | *(char *)dst = *(char *)src; 37 | dst += 1; 38 | src += 1; 39 | } 40 | 41 | //for(;;); 42 | } 43 | 44 | /* Overview: 45 | * Sets the first n bytes of the block of memory 46 | * pointed by `v` to zero. 47 | * 48 | * Pre-Condition: 49 | * `v` must be valid. 50 | * 51 | * Post-Condition: 52 | * the content of the space(from `v` to `v`+ n) 53 | * will be set to zero. 54 | */ 55 | void user_bzero(void *v, u_int n) 56 | { 57 | char *p; 58 | int m; 59 | 60 | p = v; 61 | m = n; 62 | 63 | while (--m >= 0) { 64 | *p++ = 0; 65 | } 66 | } 67 | /*--------------------------------------------------------------*/ 68 | 69 | /* Overview: 70 | * Custom page fault handler - if faulting page is copy-on-write, 71 | * map in our own private writable copy. 72 | * 73 | * Pre-Condition: 74 | * `va` is the address which leads to a TLBS exception. 75 | * 76 | * Post-Condition: 77 | * Launch a user_panic if `va` is not a copy-on-write page. 78 | * Otherwise, this handler should map a private writable copy of 79 | * the faulting page at correct address. 80 | */ 81 | /*** exercise 4.13 ***/ 82 | static void 83 | pgfault(u_int va) 84 | { 85 | u_int *tmp; 86 | u_long perm; 87 | // writef("fork.c:pgfault():\t va:%x\n",va); 88 | 89 | perm = (*vpt)[VPN(va)] & (BY2PG - 1); 90 | if ((perm & PTE_COW) == 0) user_panic("`va` is not a copy-on-write page."); 91 | perm -= PTE_COW; 92 | tmp = USTACKTOP; 93 | 94 | //map the new page at a temporary place 95 | 96 | syscall_mem_alloc(0, tmp, perm); 97 | 98 | //copy the content 99 | 100 | user_bcopy(ROUNDDOWN(va, BY2PG), tmp, BY2PG); 101 | 102 | //map the page on the appropriate place 103 | 104 | syscall_mem_map(0, tmp, 0, va, perm); 105 | 106 | //unmap the temporary place 107 | 108 | syscall_mem_unmap(0, tmp); 109 | 110 | } 111 | 112 | /* Overview: 113 | * Map our virtual page `pn` (address pn*BY2PG) into the target `envid` 114 | * at the same virtual address. 115 | * 116 | * Post-Condition: 117 | * if the page is writable or copy-on-write, the new mapping must be 118 | * created copy on write and then our mapping must be marked 119 | * copy on write as well. In another word, both of the new mapping and 120 | * our mapping should be copy-on-write if the page is writable or 121 | * copy-on-write. 122 | * 123 | * Hint: 124 | * PTE_LIBRARY indicates that the page is shared between processes. 125 | * A page with PTE_LIBRARY may have PTE_R at the same time. You 126 | * should process it correctly. 127 | */ 128 | /*** exercise 4.10 ***/ 129 | static void 130 | duppage(u_int envid, u_int pn) 131 | { 132 | u_int addr; 133 | u_int perm; 134 | int flag = 0; 135 | 136 | addr = pn << PGSHIFT; 137 | perm = (*vpt)[pn] & (BY2PG - 1); 138 | if (perm & PTE_R) { 139 | if (!(perm & PTE_LIBRARY)) { 140 | flag = 1; 141 | perm |= PTE_COW; 142 | } 143 | } 144 | syscall_mem_map(0, addr, envid, addr, perm); 145 | if (flag) syscall_mem_map(0, addr, 0, addr, perm); 146 | 147 | // user_panic("duppage not implemented"); 148 | } 149 | 150 | /* Overview: 151 | * User-level fork. Create a child and then copy our address space 152 | * and page fault handler setup to the child. 153 | * 154 | * Hint: use vpd, vpt, and duppage. 155 | * Hint: remember to fix "env" in the child process! 156 | * Note: `set_pgfault_handler`(user/pgfault.c) is different from 157 | * `syscall_set_pgfault_handler`. 158 | */ 159 | /*** exercise 4.9 4.15***/ 160 | extern void __asm_pgfault_handler(void); 161 | int 162 | fork(void) 163 | { 164 | // Your code here. 165 | u_int newenvid; 166 | extern struct Env *envs; 167 | extern struct Env *env; 168 | u_int i; 169 | 170 | //The parent installs pgfault using set_pgfault_handler 171 | set_pgfault_handler(pgfault); 172 | 173 | //alloc a new alloc 174 | newenvid = syscall_env_alloc(); 175 | if (newenvid) { 176 | for (i = 0; i < VPN(USTACKTOP); i++) { 177 | if (((*vpd)[i >> 10] & PTE_V) && ((*vpt)[i] & PTE_V)) duppage(newenvid, i); 178 | } 179 | syscall_mem_alloc(newenvid, UXSTACKTOP - BY2PG, PTE_V | PTE_R); 180 | syscall_set_pgfault_handler(newenvid, __asm_pgfault_handler, UXSTACKTOP); 181 | syscall_set_env_status(newenvid, ENV_RUNNABLE); 182 | } 183 | else env = envs + ENVX(syscall_getenvid()); 184 | 185 | 186 | return newenvid; 187 | } 188 | 189 | // Challenge! 190 | int 191 | sfork(void) 192 | { 193 | user_panic("sfork not implemented"); 194 | return -E_INVAL; 195 | } 196 | -------------------------------------------------------------------------------- /user/fprintf.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | 4 | 5 | static void user_out2string(void *arg, char *s, int l) 6 | { 7 | int i; 8 | char * b = (char *)arg; 9 | // special termination call 10 | if ((l==1) && (s[0] == '\0')) return; 11 | 12 | for (i=0; i< l; i++) { 13 | b[i]=s[i]; 14 | } 15 | } 16 | 17 | 18 | int fwritef(int fd, const char *fmt, ...) 19 | { 20 | char buf[512]; 21 | va_list ap; 22 | va_start(ap, fmt); 23 | user_bzero((void *) buf, 512); 24 | user_lp_Print(user_out2string, buf, fmt, ap); 25 | va_end(ap); 26 | return write(fd, buf, strlen(buf)); 27 | } 28 | -------------------------------------------------------------------------------- /user/fsipc.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | #include 4 | 5 | #define debug 0 6 | 7 | extern u_char fsipcbuf[BY2PG]; // page-aligned, declared in entry.S 8 | 9 | // Overview: 10 | // Send an IPC request to the file server, and wait for a reply. 11 | // 12 | // Parameters: 13 | // @type: request code, passed as the simple integer IPC value. 14 | // @fsreq: page to send containing additional request data, usually fsipcbuf. 15 | // Can be modified by server to return additional response info. 16 | // @dstva: virtual address at which to receive reply page, 0 if none. 17 | // @*perm: permissions of received page. 18 | // 19 | // Returns: 20 | // 0 if successful, 21 | // < 0 on failure. 22 | static int 23 | fsipc(u_int type, void *fsreq, u_int dstva, u_int *perm) 24 | { 25 | u_int whom; 26 | // NOTEICE: Our file system no.1 process! 27 | ipc_send(envs[1].env_id, type, (u_int)fsreq, PTE_V | PTE_R); 28 | return ipc_recv(&whom, dstva, perm); 29 | } 30 | 31 | // Overview: 32 | // Send file-open request to the file server. Includes path and 33 | // omode in request, sets *fileid and *size from reply. 34 | // 35 | // Returns: 36 | // 0 on success, 37 | // < 0 on failure. 38 | int 39 | fsipc_open(const char *path, u_int omode, struct Fd *fd) 40 | { 41 | u_int perm; 42 | struct Fsreq_open *req; 43 | 44 | req = (struct Fsreq_open *)fsipcbuf; 45 | 46 | // The path is too long. 47 | if (strlen(path) >= MAXPATHLEN) { 48 | return -E_BAD_PATH; 49 | } 50 | 51 | strcpy((char *)req->req_path, path); 52 | req->req_omode = omode; 53 | return fsipc(FSREQ_OPEN, req, (u_int)fd, &perm); 54 | } 55 | 56 | // Overview: 57 | // Make a map-block request to the file server. We send the fileid and 58 | // the (byte) offset of the desired block in the file, and the server sends 59 | // us back a mapping for a page containing that block. 60 | // 61 | // Returns: 62 | // 0 on success, 63 | // < 0 on failure. 64 | int 65 | fsipc_map(u_int fileid, u_int offset, u_int dstva) 66 | { 67 | int r; 68 | u_int perm; 69 | struct Fsreq_map *req; 70 | 71 | req = (struct Fsreq_map *)fsipcbuf; 72 | req->req_fileid = fileid; 73 | req->req_offset = offset; 74 | 75 | if ((r = fsipc(FSREQ_MAP, req, dstva, &perm)) < 0) { 76 | return r; 77 | } 78 | 79 | if ((perm & ~(PTE_R | PTE_LIBRARY)) != (PTE_V)) { 80 | user_panic("fsipc_map: unexpected permissions %08x for dstva %08x", perm, 81 | dstva); 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | // Overview: 88 | // Make a set-file-size request to the file server. 89 | int 90 | fsipc_set_size(u_int fileid, u_int size) 91 | { 92 | struct Fsreq_set_size *req; 93 | 94 | req = (struct Fsreq_set_size *)fsipcbuf; 95 | req->req_fileid = fileid; 96 | req->req_size = size; 97 | return fsipc(FSREQ_SET_SIZE, req, 0, 0); 98 | } 99 | 100 | // Overview: 101 | // Make a file-close request to the file server. After this the fileid is invalid. 102 | int 103 | fsipc_close(u_int fileid) 104 | { 105 | struct Fsreq_close *req; 106 | 107 | req = (struct Fsreq_close *)fsipcbuf; 108 | req->req_fileid = fileid; 109 | return fsipc(FSREQ_CLOSE, req, 0, 0); 110 | } 111 | 112 | // Overview: 113 | // Ask the file server to mark a particular file block dirty. 114 | int 115 | fsipc_dirty(u_int fileid, u_int offset) 116 | { 117 | struct Fsreq_dirty *req; 118 | 119 | req = (struct Fsreq_dirty *)fsipcbuf; 120 | req->req_fileid = fileid; 121 | req->req_offset = offset; 122 | return fsipc(FSREQ_DIRTY, req, 0, 0); 123 | } 124 | 125 | // Overview: 126 | // Ask the file server to delete a file, given its pathname. 127 | int 128 | fsipc_remove(const char *path) 129 | { 130 | struct Fsreq_remove *req; 131 | 132 | // Step 1: Check the length of path, decide if the path is valid. 133 | if (strlen(path) == 0 || strlen(path) >= MAXPATHLEN) return -E_BAD_PATH; 134 | 135 | // Step 2: Transform fsipcbuf to struct Fsreq_remove* 136 | req = fsipcbuf; 137 | 138 | // Step 3: Copy path to path in req. 139 | strcpy(req->req_path, path); 140 | 141 | // Step 4: Send request to fs server with IPC. 142 | return fsipc(FSREQ_REMOVE, req, 0, 0); 143 | } 144 | 145 | // Overview: 146 | // Ask the file server to update the disk by writing any dirty 147 | // blocks in the buffer cache. 148 | int 149 | fsipc_sync(void) 150 | { 151 | return fsipc(FSREQ_SYNC, fsipcbuf, 0, 0); 152 | } 153 | 154 | -------------------------------------------------------------------------------- /user/fstest.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | static char *msg = "This is the NEW message of the day!\r\n\r\n"; 4 | static char *diff_msg = "This is a different massage of the day!\r\n\r\n"; 5 | 6 | void umain() 7 | { 8 | int r; 9 | int fdnum; 10 | char buf[512]; 11 | int n; 12 | 13 | if ((r = open("/newmotd", O_RDWR)) < 0) { 14 | user_panic("open /newmotd: %d", r); 15 | } 16 | fdnum = r; 17 | writef("open is good\n"); 18 | 19 | if ((n = read(fdnum, buf, 511)) < 0) { 20 | user_panic("read /newmotd: %d", r); 21 | } 22 | if (strcmp(buf, diff_msg) != 0) { 23 | user_panic("read returned wrong data"); 24 | } 25 | writef("read is good\n"); 26 | 27 | if ((r = ftruncate(fdnum, 0)) < 0) { 28 | user_panic("ftruncate: %d", r); 29 | } 30 | seek(fdnum, 0); 31 | 32 | if ((r = write(fdnum, msg, strlen(msg) + 1)) < 0) { 33 | user_panic("write /newmotd: %d", r); 34 | } 35 | 36 | if ((r = close(fdnum)) < 0) { 37 | user_panic("close /newmotd: %d", r); 38 | } 39 | 40 | //read again 41 | if ((r = open("/newmotd", O_RDONLY)) < 0) { 42 | user_panic("open /newmotd: %d", r); 43 | } 44 | fdnum = r; 45 | writef("open again: OK\n"); 46 | 47 | if ((n = read(fdnum, buf, 511)) < 0) { 48 | user_panic("read /newmotd: %d", r); 49 | } 50 | if (strcmp(buf, msg) != 0) { 51 | user_panic("read returned wrong data"); 52 | } 53 | writef("read again: OK\n"); 54 | 55 | if ((r = close(fdnum)) < 0) { 56 | user_panic("close /newmotd: %d", r); 57 | } 58 | writef("file rewrite is good\n"); 59 | if((r = remove("/newmotd"))<0){ 60 | user_panic("remove /newmotd: %d",r); 61 | } 62 | if((r = open("/newmotd", O_RDONLY))>=0){ 63 | user_panic("open after remove /newmotd: %d",r); 64 | } 65 | writef("file remove: OK\n"); 66 | while (1) { 67 | //writef("IDLE!"); 68 | } 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /user/icode.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | void 4 | umain(void) 5 | { 6 | int fd, n, r; 7 | char buf[512+1]; 8 | 9 | writef("icode: open /motd\n"); 10 | if ((fd = open("/motd", O_RDONLY)) < 0) 11 | user_panic("icode: open /motd: %e", fd); 12 | 13 | writef("icode: read /motd\n"); 14 | while ((n = read(fd, buf, sizeof buf-1)) > 0){ 15 | buf[n] = 0; 16 | writef("%s\n",buf); 17 | } 18 | 19 | writef("icode: close /motd\n"); 20 | // close(fd); 21 | 22 | writef("icode: spawn /init\n"); 23 | if ((r = spawnl("init.b", "init", "initarg1", "initarg2", (char*)0)) < 0) 24 | user_panic("icode: spawn /init: %e", r); 25 | 26 | writef("icode: exiting\n"); 27 | } 28 | -------------------------------------------------------------------------------- /user/idle.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | umain() 4 | { 5 | while(1) 6 | writef("IDLE!"); 7 | } 8 | -------------------------------------------------------------------------------- /user/init.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | struct { 4 | char msg1[5000]; 5 | char msg2[1000]; 6 | } data = { 7 | "this is initialized data", 8 | "so is this" 9 | }; 10 | 11 | char bss[6000]; 12 | 13 | inline int MY_MUL(int a,int b) 14 | { 15 | int i; 16 | int sum; 17 | for(i=0,sum=0;i 4 | #include 5 | 6 | extern struct Env *env; 7 | 8 | // Send val to whom. This function keeps trying until 9 | // it succeeds. It should panic() on any error other than 10 | // -E_IPC_NOT_RECV. 11 | // 12 | // Hint: use syscall_yield() to be CPU-friendly. 13 | void 14 | ipc_send(u_int whom, u_int val, u_int srcva, u_int perm) 15 | { 16 | int r; 17 | 18 | while ((r=syscall_ipc_can_send(whom, val, srcva, perm)) == -E_IPC_NOT_RECV) 19 | { 20 | syscall_yield(); 21 | //writef("QQ"); 22 | } 23 | if(r == 0) 24 | return; 25 | user_panic("error in ipc_send: %d", r); 26 | } 27 | 28 | // Receive a value. Return the value and store the caller's envid 29 | // in *whom. 30 | // 31 | // Hint: use env to discover the value and who sent it. 32 | u_int 33 | ipc_recv(u_int *whom, u_int dstva, u_int *perm) 34 | { 35 | //printf("ipc_recv:come 0\n"); 36 | syscall_ipc_recv(dstva); 37 | 38 | if (whom) 39 | *whom = env->env_ipc_from; 40 | if (perm) 41 | *perm = env->env_ipc_perm; 42 | return env->env_ipc_value; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /user/lib.h: -------------------------------------------------------------------------------- 1 | #ifndef LIB_H 2 | #define LIB_H 3 | #include "fd.h" 4 | #include "pmap.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | /////////////////////////////////////////////////////head 11 | extern void umain(); 12 | extern void libmain(); 13 | extern void exit(); 14 | 15 | extern struct Env *env; 16 | 17 | 18 | #define USED(x) (void)(x) 19 | //////////////////////////////////////////////////////printf 20 | #include 21 | //#define LP_MAX_BUF 80 22 | 23 | void user_lp_Print(void (*output)(void *, const char *, int), 24 | void *arg, 25 | const char *fmt, 26 | va_list ap); 27 | 28 | void writef(char *fmt, ...); 29 | 30 | void _user_panic(const char *, int, const char *, ...) 31 | __attribute__((noreturn)); 32 | 33 | #define user_panic(...) _user_panic(__FILE__, __LINE__, __VA_ARGS__) 34 | 35 | 36 | /////////////////////////////////////////////////////fork spawn 37 | int spawn(char *prog, char **argv); 38 | int spawnl(char *prot, char *args, ...); 39 | int fork(void); 40 | 41 | void user_bcopy(const void *src, void *dst, size_t len); 42 | void user_bzero(void *v, u_int n); 43 | //////////////////////////////////////////////////syscall_lib 44 | extern int msyscall(int, int, int, int, int, int); 45 | 46 | void syscall_putchar(char ch); 47 | u_int syscall_getenvid(void); 48 | void syscall_yield(void); 49 | int syscall_env_destroy(u_int envid); 50 | int syscall_set_pgfault_handler(u_int envid, void (*func)(void), 51 | u_int xstacktop); 52 | int syscall_mem_alloc(u_int envid, u_int va, u_int perm); 53 | int syscall_mem_map(u_int srcid, u_int srcva, u_int dstid, u_int dstva, 54 | u_int perm); 55 | int syscall_mem_unmap(u_int envid, u_int va); 56 | 57 | inline static int syscall_env_alloc(void) 58 | { 59 | return msyscall(SYS_env_alloc, 0, 0, 0, 0, 0); 60 | } 61 | 62 | int syscall_set_env_status(u_int envid, u_int status); 63 | int syscall_set_trapframe(u_int envid, struct Trapframe *tf); 64 | void syscall_panic(char *msg); 65 | int syscall_ipc_can_send(u_int envid, u_int value, u_int srcva, u_int perm); 66 | void syscall_ipc_recv(u_int dstva); 67 | int syscall_cgetc(); 68 | int syscall_write_dev(u_int va,u_int dev,u_int offset); 69 | int syscall_read_dev(u_int va,u_int dev,u_int offset); 70 | 71 | 72 | // string.c 73 | int strlen(const char *s); 74 | char *strcpy(char *dst, const char *src); 75 | const char *strchr(const char *s, char c); 76 | void *memcpy(void *destaddr, void const *srcaddr, u_int len); 77 | int strcmp(const char *p, const char *q); 78 | // ipc.c 79 | void ipc_send(u_int whom, u_int val, u_int srcva, u_int perm); 80 | u_int ipc_recv(u_int *whom, u_int dstva, u_int *perm); 81 | 82 | // wait.c 83 | void wait(u_int envid); 84 | 85 | // console.c 86 | int opencons(void); 87 | int iscons(int fdnum); 88 | 89 | // pipe.c 90 | int pipe(int pfd[2]); 91 | int pipeisclosed(int fdnum); 92 | 93 | // pageref.c 94 | int pageref(void *); 95 | 96 | // pgfault.c 97 | void set_pgfault_handler(void (*fn)(u_int va)); 98 | 99 | // fprintf.c 100 | int fwritef(int fd, const char *fmt, ...); 101 | 102 | // fsipc.c 103 | int fsipc_open(const char*, u_int, struct Fd*); 104 | int fsipc_map(u_int, u_int, u_int); 105 | int fsipc_set_size(u_int, u_int); 106 | int fsipc_close(u_int); 107 | int fsipc_dirty(u_int, u_int); 108 | int fsipc_remove(const char*); 109 | int fsipc_sync(void); 110 | int fsipc_incref(u_int); 111 | 112 | // fd.c 113 | int close(int fd); 114 | int read(int fd, void *buf, u_int nbytes); 115 | int write(int fd, const void *buf, u_int nbytes); 116 | int seek(int fd, u_int offset); 117 | void close_all(void); 118 | int readn(int fd, void *buf, u_int nbytes); 119 | int dup(int oldfd, int newfd); 120 | int fstat(int fdnum, struct Stat *stat); 121 | int stat(const char *path, struct Stat*); 122 | 123 | // file.c 124 | int open(const char *path, int mode); 125 | int read_map(int fd, u_int offset, void **blk); 126 | int delete(const char *path); 127 | int ftruncate(int fd, u_int size); 128 | int sync(void); 129 | 130 | #define user_assert(x) \ 131 | do { if (!(x)) user_panic("assertion failed: %s", #x); } while (0) 132 | 133 | /* File open modes */ 134 | #define O_RDONLY 0x0000 /* open for reading only */ 135 | #define O_WRONLY 0x0001 /* open for writing only */ 136 | #define O_RDWR 0x0002 /* open for reading and writing */ 137 | #define O_ACCMODE 0x0003 /* mask for above modes */ 138 | 139 | #define O_CREAT 0x0100 /* create if nonexistent */ 140 | #define O_TRUNC 0x0200 /* truncate to zero length */ 141 | #define O_EXCL 0x0400 /* error if already exists */ 142 | #define O_MKDIR 0x0800 /* create directory, not regular file */ 143 | 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /user/libos.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | #include 4 | 5 | void 6 | exit(void) 7 | { 8 | //close_all(); 9 | syscall_env_destroy(0); 10 | } 11 | 12 | 13 | struct Env *env; 14 | 15 | void 16 | libmain(int argc, char **argv) 17 | { 18 | // set env to point at our env structure in envs[]. 19 | env = 0; // Your code here. 20 | //writef("xxxxxxxxx %x %x xxxxxxxxx\n",argc,(int)argv); 21 | int envid; 22 | envid = syscall_getenvid(); 23 | envid = ENVX(envid); 24 | env = &envs[envid]; 25 | // call user main routine 26 | umain(argc,argv); 27 | // exit gracefully 28 | exit(); 29 | //syscall_env_destroy(0); 30 | } 31 | -------------------------------------------------------------------------------- /user/ls.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int flag[256]; 4 | 5 | void lsdir(char*, char*); 6 | void ls1(char*, u_int, u_int, char*); 7 | 8 | void 9 | ls(char *path, char *prefix) 10 | { 11 | int r; 12 | struct Stat st; 13 | 14 | if ((r=stat(path, &st)) < 0) 15 | user_panic("stat %s: %e", path, r); 16 | if (st.st_isdir && !flag['d']) 17 | lsdir(path, prefix); 18 | else 19 | ls1(0, st.st_isdir, st.st_size, path); 20 | } 21 | 22 | void 23 | lsdir(char *path, char *prefix) 24 | { 25 | int fd, n; 26 | struct File f; 27 | 28 | if ((fd = open(path, O_RDONLY)) < 0) 29 | user_panic("open %s: %e", path, fd); 30 | while ((n = readn(fd, &f, sizeof f)) == sizeof f) 31 | if (f.f_name[0]) 32 | ls1(prefix, f.f_type==FTYPE_DIR, f.f_size, f.f_name); 33 | if (n > 0) 34 | user_panic("short read in directory %s", path); 35 | if (n < 0) 36 | user_panic("error reading directory %s: %e", path, n); 37 | } 38 | 39 | void 40 | ls1(char *prefix, u_int isdir, u_int size, char *name) 41 | { 42 | char *sep; 43 | 44 | if(flag['l']) 45 | fwritef(1, "%11d %c ", size, isdir ? 'd' : '-'); 46 | if(prefix) { 47 | if (prefix[0] && prefix[strlen(prefix)-1] != '/') 48 | sep = "/"; 49 | else 50 | sep = ""; 51 | fwritef(1, "%s%s", prefix, sep); 52 | } 53 | fwritef(1, "%s", name); 54 | if(flag['F'] && isdir) 55 | fwritef(1, "/"); 56 | fwritef(1, " "); 57 | } 58 | 59 | void 60 | usage(void) 61 | { 62 | fwritef(1, "usage: ls [-dFl] [file...]\n"); 63 | exit(); 64 | } 65 | 66 | void 67 | umain(int argc, char **argv) 68 | { 69 | int i; 70 | 71 | ARGBEGIN{ 72 | default: 73 | usage(); 74 | case 'd': 75 | case 'F': 76 | case 'l': 77 | flag[(u_char)ARGC()]++; 78 | break; 79 | }ARGEND 80 | 81 | if (argc == 0) 82 | ls("/", ""); 83 | else { 84 | for (i=0; i 0) { 14 | if (bol) { 15 | writef("%5d ", ++line); 16 | bol = 0; 17 | } 18 | if ((r = write(1, &c, 1)) != 1) 19 | user_panic("write error copying %s: %e", s, r); 20 | if (c == '\n') 21 | bol = 1; 22 | } 23 | if (n < 0) 24 | user_panic("error reading %s: %e", s, n); 25 | } 26 | 27 | void 28 | umain(int argc, char **argv) 29 | { 30 | int f, i; 31 | 32 | //binaryname = "num.b"; 33 | if (argc == 1) 34 | num(0, ""); 35 | else 36 | for (i = 1; i < argc; i++) { 37 | f = open(argv[i], O_RDONLY); 38 | if (f < 0) 39 | user_panic("can't open %s: %e", argv[i], f); 40 | else { 41 | num(f, argv[i]); 42 | close(f); 43 | } 44 | } 45 | exit(); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /user/pageref.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | int 4 | pageref(void *v) 5 | { 6 | u_int pte; 7 | 8 | if (!((* vpd)[PDX(v)]&PTE_V)) 9 | return 0; 10 | pte = (* vpt)[VPN(v)]; 11 | if (!(pte&PTE_V)) 12 | return 0; 13 | return pages[PPN(pte)].pp_ref; 14 | } 15 | -------------------------------------------------------------------------------- /user/pgfault.c: -------------------------------------------------------------------------------- 1 | // User-level page fault handler. We use an assembly wrapper around a C function. 2 | // The assembly wrapper is in entry.S. 3 | 4 | #include "lib.h" 5 | #include 6 | 7 | extern void (*__pgfault_handler)(u_int); 8 | extern void __asm_pgfault_handler(void); 9 | 10 | 11 | // 12 | // Set the page fault handler function. 13 | // If there isn't one yet, _pgfault_handler will be 0. 14 | // The first time we register a handler, we need to 15 | // allocate an exception stack and tell the kernel to 16 | // call _asm_pgfault_handler on it. 17 | // 18 | void 19 | set_pgfault_handler(void (*fn)(u_int va)) 20 | { 21 | if (__pgfault_handler == 0) { 22 | // Your code here: 23 | // map one page of exception stack with top at UXSTACKTOP 24 | // register assembly handler and stack with operating system 25 | if (syscall_mem_alloc(0, UXSTACKTOP - BY2PG, PTE_V | PTE_R) < 0 || 26 | syscall_set_pgfault_handler(0, __asm_pgfault_handler, UXSTACKTOP) < 0) { 27 | writef("cannot set pgfault handler\n"); 28 | return; 29 | } 30 | 31 | // panic("set_pgfault_handler not implemented"); 32 | } 33 | 34 | // Save handler pointer for assembly to call. 35 | __pgfault_handler = fn; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /user/pingpong.c: -------------------------------------------------------------------------------- 1 | // Ping-pong a counter between two processes. 2 | // Only need to start one of these -- splits into two with fork. 3 | 4 | #include "lib.h" 5 | 6 | void 7 | umain(void) 8 | { 9 | u_int who, i; 10 | 11 | if ((who = fork()) != 0) { 12 | // get the ball rolling 13 | writef("\n@@@@@send 0 from %x to %x\n", syscall_getenvid(), who); 14 | ipc_send(who, 0, 0, 0); 15 | //user_panic("&&&&&&&&&&&&&&&&&&&&&&&&m"); 16 | } 17 | 18 | for (;;) { 19 | writef("%x am waiting.....\n",syscall_getenvid()); 20 | i = ipc_recv(&who, 0, 0); 21 | 22 | writef("%x got %d from %x\n", syscall_getenvid(), i, who); 23 | 24 | //user_panic("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); 25 | if (i == 10) 26 | return; 27 | i++; 28 | writef("\n@@@@@send 0 from %x to %x\n", syscall_getenvid(), who); 29 | ipc_send(who, i, 0, 0); 30 | if (i == 10) 31 | return; 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /user/pipe.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | #include 4 | #define debug 0 5 | 6 | static int pipeclose(struct Fd*); 7 | static int piperead(struct Fd *fd, void *buf, u_int n, u_int offset); 8 | static int pipestat(struct Fd*, struct Stat*); 9 | static int pipewrite(struct Fd *fd, const void *buf, u_int n, u_int offset); 10 | 11 | struct Dev devpipe = 12 | { 13 | .dev_id= 'p', 14 | .dev_name= "pipe", 15 | .dev_read= piperead, 16 | .dev_write= pipewrite, 17 | .dev_close= pipeclose, 18 | .dev_stat= pipestat, 19 | }; 20 | 21 | #define BY2PIPE 32 // small to provoke races 22 | 23 | struct Pipe { 24 | u_int p_rpos; // read position 25 | u_int p_wpos; // write position 26 | u_char p_buf[BY2PIPE]; // data buffer 27 | }; 28 | 29 | int 30 | pipe(int pfd[2]) 31 | { 32 | int r, va; 33 | struct Fd *fd0, *fd1; 34 | 35 | // allocate the file descriptor table entries 36 | if ((r = fd_alloc(&fd0)) < 0 37 | || (r = syscall_mem_alloc(0, (u_int)fd0, PTE_V|PTE_R|PTE_LIBRARY)) < 0) 38 | goto err; 39 | 40 | if ((r = fd_alloc(&fd1)) < 0 41 | || (r = syscall_mem_alloc(0, (u_int)fd1, PTE_V|PTE_R|PTE_LIBRARY)) < 0) 42 | goto err1; 43 | 44 | // allocate the pipe structure as first data page in both 45 | va = fd2data(fd0); 46 | if ((r = syscall_mem_alloc(0, va, PTE_V|PTE_R|PTE_LIBRARY)) < 0) 47 | goto err2; 48 | if ((r = syscall_mem_map(0, va, 0, fd2data(fd1), PTE_V|PTE_R|PTE_LIBRARY)) < 0) 49 | goto err3; 50 | 51 | // set up fd structures 52 | fd0->fd_dev_id = devpipe.dev_id; 53 | fd0->fd_omode = O_RDONLY; 54 | 55 | fd1->fd_dev_id = devpipe.dev_id; 56 | fd1->fd_omode = O_WRONLY; 57 | 58 | writef("[%08x] pipecreate \n", env->env_id, (* vpt)[VPN(va)]); 59 | 60 | pfd[0] = fd2num(fd0); 61 | pfd[1] = fd2num(fd1); 62 | return 0; 63 | 64 | err3: syscall_mem_unmap(0, va); 65 | err2: syscall_mem_unmap(0, (u_int)fd1); 66 | err1: syscall_mem_unmap(0, (u_int)fd0); 67 | err: return r; 68 | } 69 | 70 | static int 71 | _pipeisclosed(struct Fd *fd, struct Pipe *p) 72 | { 73 | // Your code here. 74 | // 75 | // Check pageref(fd) and pageref(p), 76 | // returning 1 if they're the same, 0 otherwise. 77 | // 78 | // The logic here is that pageref(p) is the total 79 | // number of readers *and* writers, whereas pageref(fd) 80 | // is the number of file descriptors like fd (readers if fd is 81 | // a reader, writers if fd is a writer). 82 | // 83 | // If the number of file descriptors like fd is equal 84 | // to the total number of readers and writers, then 85 | // everybody left is what fd is. So the other end of 86 | // the pipe is closed. 87 | int pfd,pfp,runs; 88 | 89 | do { 90 | runs = env->env_runs; 91 | pfd = pageref(fd); 92 | pfp = pageref(p); 93 | } while(runs != env->env_runs); 94 | 95 | if (pfd == pfp) return 1; 96 | 97 | // user_panic("_pipeisclosed not implemented"); 98 | return 0; 99 | } 100 | 101 | int 102 | pipeisclosed(int fdnum) 103 | { 104 | struct Fd *fd; 105 | struct Pipe *p; 106 | int r; 107 | 108 | if ((r = fd_lookup(fdnum, &fd)) < 0) 109 | return r; 110 | p = (struct Pipe*)fd2data(fd); 111 | return _pipeisclosed(fd, p); 112 | } 113 | 114 | static int 115 | piperead(struct Fd *fd, void *vbuf, u_int n, u_int offset) 116 | { 117 | // Your code here. See the lab text for a description of 118 | // what piperead needs to do. Write a loop that 119 | // transfers one byte at a time. If you decide you need 120 | // to yield (because the pipe is empty), only yield if 121 | // you have not yet copied any bytes. (If you have copied 122 | // some bytes, return what you have instead of yielding.) 123 | // If the pipe is empty and closed and you didn't copy any data out, return 0. 124 | // Use _pipeisclosed to check whether the pipe is closed. 125 | int i; 126 | struct Pipe *p; 127 | char *rbuf; 128 | 129 | p = fd2data(fd); 130 | rbuf = vbuf; 131 | for (i = 0; i < n; i++) { 132 | while (p->p_rpos >= p->p_wpos) { 133 | if (_pipeisclosed(fd, p) || i > 0) return i; 134 | syscall_yield(); 135 | } 136 | rbuf[i] = p->p_buf[p->p_rpos % BY2PIPE]; 137 | p->p_rpos++; 138 | } 139 | return n; 140 | 141 | // user_panic("piperead not implemented"); 142 | // return -E_INVAL; 143 | } 144 | 145 | static int 146 | pipewrite(struct Fd *fd, const void *vbuf, u_int n, u_int offset) 147 | { 148 | // Your code here. See the lab text for a description of what 149 | // pipewrite needs to do. Write a loop that transfers one byte 150 | // at a time. Unlike in read, it is not okay to write only some 151 | // of the data. If the pipe fills and you've only copied some of 152 | // the data, wait for the pipe to empty and then keep copying. 153 | // If the pipe is full and closed, return 0. 154 | // Use _pipeisclosed to check whether the pipe is closed. 155 | int i; 156 | struct Pipe *p; 157 | char *wbuf; 158 | 159 | p = fd2data(fd); 160 | wbuf = vbuf; 161 | 162 | for (i = 0; i < n; i++) { 163 | while (p->p_wpos - p->p_rpos == BY2PIPE) { 164 | if (_pipeisclosed(fd, p)) return 0; 165 | syscall_yield(); 166 | } 167 | p->p_buf[p->p_wpos % BY2PIPE] = wbuf[i]; 168 | p->p_wpos++; 169 | } 170 | 171 | // return -E_INVAL; 172 | 173 | 174 | // user_panic("pipewrite not implemented"); 175 | 176 | return n; 177 | } 178 | 179 | static int 180 | pipestat(struct Fd *fd, struct Stat *stat) 181 | { 182 | struct Pipe *p; 183 | 184 | 185 | 186 | } 187 | 188 | static int 189 | pipeclose(struct Fd *fd) 190 | { 191 | syscall_mem_unmap(0, fd); 192 | syscall_mem_unmap(0, fd2data(fd)); 193 | return 0; 194 | } 195 | 196 | -------------------------------------------------------------------------------- /user/print.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2001 MontaVista Software Inc. 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | */ 11 | 12 | #include 13 | 14 | /* macros */ 15 | #define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') ) 16 | #define Ctod(x) ( (x) - '0') 17 | 18 | /* forward declaration */ 19 | extern int user_PrintChar(char *, char, int, int); 20 | extern int user_PrintString(char *, char *, int, int); 21 | extern int user_PrintNum(char *, unsigned long, int, int, int, int, char, int); 22 | 23 | /* private variable */ 24 | static const char user_theFatalMsg[] = "fatal error in user_lp_Print!"; 25 | 26 | /* -*- 27 | * A low level printf() function. 28 | */ 29 | void 30 | user_lp_Print(void (*output)(void *, char *, int), 31 | void * arg, 32 | char *fmt, 33 | va_list ap) 34 | { 35 | 36 | #define OUTPUT(arg, s, l) \ 37 | { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \ 38 | (*output)(arg, (char*)user_theFatalMsg, sizeof(user_theFatalMsg)-1); for(;;); \ 39 | } else { \ 40 | (*output)(arg, s, l); arg+= l;\ 41 | } \ 42 | } 43 | 44 | char buf[LP_MAX_BUF]; 45 | 46 | char c; 47 | char *s; 48 | long int num; 49 | 50 | int longFlag; 51 | int negFlag; 52 | int width; 53 | int prec; 54 | int ladjust; 55 | char padc; 56 | 57 | int length; 58 | 59 | for(;;) { 60 | { 61 | /* scan for the next '%' */ 62 | char *fmtStart = fmt; 63 | while ( (*fmt != '\0') && (*fmt != '%')) { 64 | fmt ++; 65 | } 66 | 67 | /* flush the string found so far */ 68 | OUTPUT(arg, fmtStart, fmt-fmtStart); 69 | 70 | /* are we hitting the end? */ 71 | if (*fmt == '\0') break; 72 | } 73 | 74 | /* we found a '%' */ 75 | fmt ++; 76 | 77 | /* check for long */ 78 | if (*fmt == 'l') { 79 | longFlag = 1; 80 | fmt ++; 81 | } else { 82 | longFlag = 0; 83 | } 84 | 85 | /* check for other prefixes */ 86 | width = 0; 87 | prec = -1; 88 | ladjust = 0; 89 | padc = ' '; 90 | 91 | if (*fmt == '-') { 92 | ladjust = 1; 93 | fmt ++; 94 | } 95 | 96 | if (*fmt == '0') { 97 | padc = '0'; 98 | fmt++; 99 | } 100 | 101 | if (IsDigit(*fmt)) { 102 | while (IsDigit(*fmt)) { 103 | width = 10 * width + Ctod(*fmt++); 104 | } 105 | } 106 | 107 | if (*fmt == '.') { 108 | fmt ++; 109 | if (IsDigit(*fmt)) { 110 | prec = 0; 111 | while (IsDigit(*fmt)) { 112 | prec = prec*10 + Ctod(*fmt++); 113 | } 114 | } 115 | } 116 | 117 | 118 | /* check format flag */ 119 | negFlag = 0; 120 | switch (*fmt) { 121 | case 'b': 122 | if (longFlag) { 123 | num = va_arg(ap, long int); 124 | } else { 125 | num = va_arg(ap, int); 126 | } 127 | length = user_PrintNum(buf, num, 2, 0, width, ladjust, padc, 0); 128 | OUTPUT(arg, buf, length); 129 | break; 130 | 131 | case 'd': 132 | case 'D': 133 | if (longFlag) { 134 | num = va_arg(ap, long int); 135 | } else { 136 | num = va_arg(ap, int); 137 | } 138 | if (num < 0) { 139 | num = - num; 140 | negFlag = 1; 141 | } 142 | length = user_PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0); 143 | OUTPUT(arg, buf, length); 144 | break; 145 | 146 | case 'o': 147 | case 'O': 148 | if (longFlag) { 149 | num = va_arg(ap, long int); 150 | } else { 151 | num = va_arg(ap, int); 152 | } 153 | length = user_PrintNum(buf, num, 8, 0, width, ladjust, padc, 0); 154 | OUTPUT(arg, buf, length); 155 | break; 156 | 157 | case 'u': 158 | case 'U': 159 | if (longFlag) { 160 | num = va_arg(ap, long int); 161 | } else { 162 | num = va_arg(ap, int); 163 | } 164 | length = user_PrintNum(buf, num, 10, 0, width, ladjust, padc, 0); 165 | OUTPUT(arg, buf, length); 166 | break; 167 | 168 | case 'x': 169 | if (longFlag) { 170 | num = va_arg(ap, long int); 171 | } else { 172 | num = va_arg(ap, int); 173 | } 174 | length = user_PrintNum(buf, num, 16, 0, width, ladjust, padc, 0); 175 | OUTPUT(arg, buf, length); 176 | break; 177 | 178 | case 'X': 179 | if (longFlag) { 180 | num = va_arg(ap, long int); 181 | } else { 182 | num = va_arg(ap, int); 183 | } 184 | length = user_PrintNum(buf, num, 16, 0, width, ladjust, padc, 1); 185 | OUTPUT(arg, buf, length); 186 | break; 187 | 188 | case 'c': 189 | c = (char)va_arg(ap, int); 190 | length = user_PrintChar(buf, c, width, ladjust); 191 | OUTPUT(arg, buf, length); 192 | break; 193 | 194 | case 's': 195 | s = (char*)va_arg(ap, char *); 196 | length = user_PrintString(buf, s, width, ladjust); 197 | OUTPUT(arg, buf, length); 198 | break; 199 | 200 | case '\0': 201 | fmt --; 202 | break; 203 | 204 | default: 205 | /* output this char as it is */ 206 | OUTPUT(arg, fmt, 1); 207 | } /* switch (*fmt) */ 208 | 209 | fmt ++; 210 | } /* for(;;) */ 211 | 212 | /* special termination call */ 213 | OUTPUT(arg, "\0", 1); 214 | } 215 | 216 | 217 | /* --------------- local help functions --------------------- */ 218 | int 219 | user_PrintChar(char * buf, char c, int length, int ladjust) 220 | { 221 | int i; 222 | 223 | if (length < 1) length = 1; 224 | if (ladjust) { 225 | *buf = c; 226 | for (i=1; i< length; i++) buf[i] = ' '; 227 | } else { 228 | for (i=0; i< length-1; i++) buf[i] = ' '; 229 | buf[length - 1] = c; 230 | } 231 | return length; 232 | } 233 | 234 | int 235 | user_PrintString(char * buf, char* s, int length, int ladjust) 236 | { 237 | int i; 238 | int len=0; 239 | char* s1 = s; 240 | while (*s1++) len++; 241 | if (length < len) length = len; 242 | 243 | if (ladjust) { 244 | for (i=0; i< len; i++) buf[i] = s[i]; 245 | for (i=len; i< length; i++) buf[i] = ' '; 246 | } else { 247 | for (i=0; i< length-len; i++) buf[i] = ' '; 248 | for (i=length-len; i < length; i++) buf[i] = s[i-length+len]; 249 | } 250 | return length; 251 | } 252 | 253 | int 254 | user_PrintNum(char * buf, unsigned long u, int base, int negFlag, 255 | int length, int ladjust, char padc, int upcase) 256 | { 257 | /* algorithm : 258 | * 1. prints the number from left to right in reverse form. 259 | * 2. fill the remaining spaces with padc if length is longer than 260 | * the actual length 261 | * TRICKY : if left adjusted, no "0" padding. 262 | * if negtive, insert "0" padding between "0" and number. 263 | * 3. if (!ladjust) we reverse the whole string including paddings 264 | * 4. otherwise we only reverse the actual string representing the num. 265 | */ 266 | 267 | int actualLength =0; 268 | char *p = buf; 269 | int i; 270 | 271 | do { 272 | int tmp = u %base; 273 | if (tmp <= 9) { 274 | *p++ = '0' + tmp; 275 | } else if (upcase) { 276 | *p++ = 'A' + tmp - 10; 277 | } else { 278 | *p++ = 'a' + tmp - 10; 279 | } 280 | u /= base; 281 | } while (u != 0); 282 | 283 | if (negFlag) { 284 | *p++ = '-'; 285 | } 286 | 287 | /* figure out actual length and adjust the maximum length */ 288 | actualLength = p - buf; 289 | if (length < actualLength) length = actualLength; 290 | 291 | /* add padding */ 292 | if (ladjust) { 293 | padc = ' '; 294 | } 295 | if (negFlag && !ladjust && (padc == '0')) { 296 | for (i = actualLength-1; i< length-1; i++) buf[i] = padc; 297 | buf[length -1] = '-'; 298 | } else { 299 | for (i = actualLength; i< length; i++) buf[i] = padc; 300 | } 301 | 302 | 303 | /* prepare to reverse the string */ 304 | { 305 | int begin = 0; 306 | int end; 307 | if (ladjust) { 308 | end = actualLength - 1; 309 | } else { 310 | end = length -1; 311 | } 312 | 313 | while (end > begin) { 314 | char tmp = buf[begin]; 315 | buf[begin] = buf[end]; 316 | buf[end] = tmp; 317 | begin ++; 318 | end --; 319 | } 320 | } 321 | 322 | /* adjust the string pointer */ 323 | return length; 324 | } 325 | -------------------------------------------------------------------------------- /user/printf.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "lib.h" 4 | 5 | 6 | 7 | 8 | void halt(void); 9 | 10 | static void user_myoutput(void *arg, char *s, int l) 11 | { 12 | int i; 13 | 14 | // special termination call 15 | if ((l==1) && (s[0] == '\0')) return; 16 | 17 | for (i=0; i< l; i++) { 18 | syscall_putchar(s[i]); 19 | if (s[i] == '\n') syscall_putchar('\n'); 20 | } 21 | } 22 | 23 | void writef(char *fmt, ...) 24 | { 25 | va_list ap; 26 | va_start(ap, fmt); 27 | user_lp_Print(user_myoutput, 0, fmt, ap); 28 | va_end(ap); 29 | } 30 | 31 | void 32 | _user_panic(const char *file, int line, const char *fmt,...) 33 | { 34 | va_list ap; 35 | 36 | 37 | va_start(ap, fmt); 38 | writef("panic at %s:%d: ", file, line); 39 | user_lp_Print(user_myoutput, 0, (char *)fmt, ap); 40 | writef("\n"); 41 | va_end(ap); 42 | 43 | 44 | for(;;); 45 | } 46 | -------------------------------------------------------------------------------- /user/sh.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | 4 | int debug_ = 0; 5 | 6 | // 7 | // get the next token from string s 8 | // set *p1 to the beginning of the token and 9 | // *p2 just past the token. 10 | // return: 11 | // 0 for end-of-string 12 | // > for > 13 | // | for | 14 | // w for a word 15 | // 16 | // eventually (once we parse the space where the nul will go), 17 | // words get nul-terminated. 18 | #define WHITESPACE " \t\r\n" 19 | #define SYMBOLS "<|>&;()" 20 | 21 | int 22 | _gettoken(char *s, char **p1, char **p2) 23 | { 24 | int t; 25 | 26 | if (s == 0) { 27 | //if (debug_ > 1) writef("GETTOKEN NULL\n"); 28 | return 0; 29 | } 30 | 31 | //if (debug_ > 1) writef("GETTOKEN: %s\n", s); 32 | 33 | *p1 = 0; 34 | *p2 = 0; 35 | 36 | while(strchr(WHITESPACE, *s)) 37 | *s++ = 0; 38 | if(*s == 0) { 39 | // if (debug_ > 1) writef("EOL\n"); 40 | return 0; 41 | } 42 | if(strchr(SYMBOLS, *s)){ 43 | t = *s; 44 | *p1 = s; 45 | *s++ = 0; 46 | *p2 = s; 47 | // if (debug_ > 1) writef("TOK %c\n", t); 48 | return t; 49 | } 50 | *p1 = s; 51 | while(*s && !strchr(WHITESPACE SYMBOLS, *s)) 52 | s++; 53 | *p2 = s; 54 | if (debug_ > 1) { 55 | t = **p2; 56 | **p2 = 0; 57 | // writef("WORD: %s\n", *p1); 58 | **p2 = t; 59 | } 60 | return 'w'; 61 | } 62 | 63 | int 64 | gettoken(char *s, char **p1) 65 | { 66 | static int c, nc; 67 | static char *np1, *np2; 68 | 69 | if (s) { 70 | nc = _gettoken(s, &np1, &np2); 71 | return 0; 72 | } 73 | c = nc; 74 | *p1 = np1; 75 | nc = _gettoken(np2, &np1, &np2); 76 | return c; 77 | } 78 | 79 | #define MAXARGS 16 80 | void 81 | runcmd(char *s) 82 | { 83 | char *argv[MAXARGS], *t; 84 | int argc, c, i, r, p[2], fd, rightpipe; 85 | int fdnum; 86 | rightpipe = 0; 87 | gettoken(s, 0); 88 | again: 89 | argc = 0; 90 | for(;;){ 91 | c = gettoken(0, &t); 92 | switch(c){ 93 | case 0: 94 | goto runit; 95 | case 'w': 96 | if(argc == MAXARGS){ 97 | writef("too many arguments\n"); 98 | exit(); 99 | } 100 | argv[argc++] = t; 101 | break; 102 | case '<': 103 | if(gettoken(0, &t) != 'w'){ 104 | writef("syntax error: < not followed by word\n"); 105 | exit(); 106 | } 107 | // Your code here -- open t for reading, 108 | // dup it onto fd 0, and then close the fd you got. 109 | fdnum = open(t, O_RDONLY); 110 | dup(fdnum, 0); 111 | close(fdnum); 112 | 113 | // user_panic("< redirection not implemented"); 114 | break; 115 | case '>': 116 | if(gettoken(0, &t) != 'w'){ 117 | writef("syntax error: < not followed by word\n"); 118 | exit(); 119 | } 120 | // Your code here -- open t for writing, 121 | // dup it onto fd 1, and then close the fd you got. 122 | fdnum = open(t, O_WRONLY); 123 | dup(fdnum, 1); 124 | close(fdnum); 125 | 126 | // user_panic("> redirection not implemented"); 127 | break; 128 | case '|': 129 | // Your code here. 130 | // First, allocate a pipe. 131 | // Then fork. 132 | // the child runs the right side of the pipe: 133 | // dup the read end of the pipe onto 0 134 | // close the read end of the pipe 135 | // close the write end of the pipe 136 | // goto again, to parse the rest of the command line 137 | // the parent runs the left side of the pipe: 138 | // dup the write end of the pipe onto 1 139 | // close the write end of the pipe 140 | // close the read end of the pipe 141 | // set "rightpipe" to the child envid 142 | // goto runit, to execute this piece of the pipeline 143 | // and then wait for the right side to finish 144 | pipe(p); 145 | rightpipe = fork(); 146 | if (rightpipe == 0) { 147 | dup(p[0], 0); 148 | close(p[0]); 149 | close(p[1]); 150 | goto again; 151 | } 152 | else { 153 | dup(p[1], 1); 154 | close(p[1]); 155 | close(p[0]); 156 | goto runit; 157 | } 158 | // user_panic("| not implemented"); 159 | break; 160 | } 161 | } 162 | 163 | runit: 164 | if(argc == 0) { 165 | if (debug_) writef("EMPTY COMMAND\n"); 166 | return; 167 | } 168 | argv[argc] = 0; 169 | if (1) { 170 | writef("[%08x] SPAWN:", env->env_id); 171 | for (i=0; argv[i]; i++) 172 | writef(" %s", argv[i]); 173 | writef("\n"); 174 | } 175 | 176 | if ((r = spawn(argv[0], argv)) < 0) 177 | writef("spawn %s: %e\n", argv[0], r); 178 | close_all(); 179 | if (r >= 0) { 180 | if (debug_) writef("[%08x] WAIT %s %08x\n", env->env_id, argv[0], r); 181 | wait(r); 182 | } 183 | if (rightpipe) { 184 | if (debug_) writef("[%08x] WAIT right-pipe %08x\n", env->env_id, rightpipe); 185 | wait(rightpipe); 186 | } 187 | 188 | exit(); 189 | } 190 | 191 | void 192 | readline(char *buf, u_int n) 193 | { 194 | int i, r; 195 | 196 | r = 0; 197 | for(i=0; i 0) 205 | i -= 2; 206 | else 207 | i = 0; 208 | } 209 | if(buf[i] == '\r' || buf[i] == '\n'){ 210 | buf[i] = 0; 211 | return; 212 | } 213 | } 214 | writef("line too long\n"); 215 | while((r = read(0, buf, 1)) == 1 && buf[0] != '\n') 216 | ; 217 | buf[0] = 0; 218 | } 219 | 220 | char buf[1024]; 221 | 222 | void 223 | usage(void) 224 | { 225 | writef("usage: sh [-dix] [command-file]\n"); 226 | exit(); 227 | } 228 | 229 | void 230 | umain(int argc, char **argv) 231 | { 232 | int r, interactive, echocmds; 233 | interactive = '?'; 234 | echocmds = 0; 235 | writef("\n:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n"); 236 | writef(":: ::\n"); 237 | writef(":: Super Shell V0.0.0_1 ::\n"); 238 | writef(":: ::\n"); 239 | writef(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n"); 240 | ARGBEGIN{ 241 | case 'd': 242 | debug_++; 243 | break; 244 | case 'i': 245 | interactive = 1; 246 | break; 247 | case 'x': 248 | echocmds = 1; 249 | break; 250 | default: 251 | usage(); 252 | }ARGEND 253 | 254 | if(argc > 1) 255 | usage(); 256 | if(argc == 1){ 257 | close(0); 258 | if ((r = open(argv[1], O_RDONLY)) < 0) 259 | user_panic("open %s: %e", r); 260 | user_assert(r==0); 261 | } 262 | if(interactive == '?') 263 | interactive = iscons(0); 264 | for(;;){ 265 | if (interactive) 266 | fwritef(1, "\n$ "); 267 | readline(buf, sizeof buf); 268 | 269 | if (buf[0] == '#') 270 | continue; 271 | if (echocmds) 272 | fwritef(1, "# %s\n", buf); 273 | if ((r = fork()) < 0) 274 | user_panic("fork: %e", r); 275 | if (r == 0) { 276 | runcmd(buf); 277 | exit(); 278 | return; 279 | } else 280 | wait(r); 281 | } 282 | } 283 | 284 | -------------------------------------------------------------------------------- /user/spawn.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define debug 0 7 | #define TMPPAGE (BY2PG) 8 | #define TMPPAGETOP (TMPPAGE+BY2PG) 9 | 10 | int 11 | init_stack(u_int child, char **argv, u_int *init_esp) 12 | { 13 | int argc, i, r, tot; 14 | char *strings; 15 | u_int *args; 16 | 17 | // Count the number of arguments (argc) 18 | // and the total amount of space needed for strings (tot) 19 | tot = 0; 20 | for (argc=0; argv[argc]; argc++) 21 | tot += strlen(argv[argc])+1; 22 | 23 | // Make sure everything will fit in the initial stack page 24 | if (ROUND(tot, 4)+4*(argc+3) > BY2PG) 25 | return -E_NO_MEM; 26 | 27 | // Determine where to place the strings and the args array 28 | strings = (char*)TMPPAGETOP - tot; 29 | args = (u_int*)(TMPPAGETOP - ROUND(tot, 4) - 4*(argc+1)); 30 | 31 | if ((r = syscall_mem_alloc(0, TMPPAGE, PTE_V|PTE_R)) < 0) 32 | return r; 33 | // Replace this with your code to: 34 | // 35 | // - copy the argument strings into the stack page at 'strings' 36 | char *ctemp,*argv_temp; 37 | u_int j; 38 | ctemp = strings; 39 | for(i = 0;i < argc; i++) 40 | { 41 | argv_temp = argv[i]; 42 | for(j=0;j < strlen(argv[i]);j++) 43 | { 44 | *ctemp = *argv_temp; 45 | ctemp++; 46 | argv_temp++; 47 | } 48 | *ctemp = 0; 49 | ctemp++; 50 | } 51 | // - initialize args[0..argc-1] to be pointers to these strings 52 | // that will be valid addresses for the child environment 53 | // (for whom this page will be at USTACKTOP-BY2PG!). 54 | ctemp = (char *)(USTACKTOP - TMPPAGETOP + (u_int)strings); 55 | for(i = 0;i < argc;i++) 56 | { 57 | args[i] = (u_int)ctemp; 58 | ctemp += strlen(argv[i])+1; 59 | } 60 | // - set args[argc] to 0 to null-terminate the args array. 61 | ctemp--; 62 | args[argc] = ctemp; 63 | // - push two more words onto the child's stack below 'args', 64 | // containing the argc and argv parameters to be passed 65 | // to the child's umain() function. 66 | u_int *pargv_ptr; 67 | pargv_ptr = args - 1; 68 | *pargv_ptr = USTACKTOP - TMPPAGETOP + (u_int)args; 69 | pargv_ptr--; 70 | *pargv_ptr = argc; 71 | // 72 | // - set *init_esp to the initial stack pointer for the child 73 | // 74 | *init_esp = USTACKTOP - TMPPAGETOP + (u_int)pargv_ptr; 75 | // *init_esp = USTACKTOP; // Change this! 76 | 77 | if ((r = syscall_mem_map(0, TMPPAGE, child, USTACKTOP-BY2PG, PTE_V|PTE_R)) < 0) 78 | goto error; 79 | if ((r = syscall_mem_unmap(0, TMPPAGE)) < 0) 80 | goto error; 81 | 82 | return 0; 83 | 84 | error: 85 | syscall_mem_unmap(0, TMPPAGE); 86 | return r; 87 | } 88 | 89 | int usr_is_elf_format(u_char *binary){ 90 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)binary; 91 | if (ehdr->e_ident[0] == ELFMAG0 && 92 | ehdr->e_ident[1] == ELFMAG1 && 93 | ehdr->e_ident[2] == ELFMAG2 && 94 | ehdr->e_ident[3] == ELFMAG3) { 95 | return 1; 96 | } 97 | 98 | return 0; 99 | } 100 | 101 | int 102 | usr_load_elf(int fd , Elf32_Phdr *ph, int child_envid){ 103 | //Hint: maybe this function is useful 104 | // If you want to use this func, you should fill it ,it's not hard 105 | u_long va = ph->p_vaddr; 106 | u_long sgsize = ph->p_memsz; 107 | u_long bin_size = ph->p_filesz; 108 | 109 | u_char *blk; 110 | u_char *tmp = USTACKTOP; 111 | 112 | u_long i; 113 | int r; 114 | int ret; 115 | u_long offset = va - ROUNDDOWN(va, BY2PG); 116 | 117 | r = 0; 118 | 119 | ret = read_map(fd, ph->p_offset, &blk); 120 | if (ret) return ret; 121 | 122 | if (offset) { 123 | ret = syscall_mem_alloc(child_envid, va, PTE_R | PTE_V); 124 | if (ret) return ret; 125 | ret = syscall_mem_map(child_envid, va, 0, tmp, PTE_R | PTE_V); 126 | if (ret) return ret; 127 | r = MIN(BY2PG - offset, bin_size); 128 | user_bcopy(blk, tmp + offset, r); 129 | ret = syscall_mem_unmap(0, tmp); 130 | if (ret) return ret; 131 | } 132 | for (i = r; i < bin_size; i += BY2PG) { 133 | ret = syscall_mem_alloc(child_envid, va + i, PTE_R | PTE_V); 134 | if (ret) return ret; 135 | ret = syscall_mem_map(child_envid, va + i, 0, tmp, PTE_R | PTE_V); 136 | if (ret) return ret; 137 | user_bcopy(blk + i, tmp, MIN(BY2PG, bin_size - i)); 138 | ret = syscall_mem_unmap(0, tmp); 139 | if (ret) return ret; 140 | } 141 | 142 | while (i < sgsize) { 143 | ret = syscall_mem_alloc(child_envid, va + i, PTE_R | PTE_V); 144 | if (ret) return ret; 145 | i += BY2PG; 146 | } 147 | 148 | return 0; 149 | } 150 | 151 | int spawn(char *prog, char **argv) 152 | { 153 | //u_char elfbuf[512]; 154 | int r; 155 | int fd; 156 | u_int child_envid; 157 | int size, text_start; 158 | u_int i, *blk; 159 | u_int esp; 160 | Elf32_Ehdr* elf; 161 | Elf32_Phdr* ph; 162 | 163 | u_char *elfbuf; 164 | 165 | // Note 0: some variable may be not used,you can cancel them as you like 166 | // Step 1: Open the file specified by `prog` (prog is the path of the program) 167 | if((r=open(prog, O_RDONLY))<0){ 168 | user_panic("spawn ::open line 102 RDONLY wrong !\n"); 169 | return r; 170 | } 171 | // Your code begins here 172 | fd = r; 173 | elfbuf = INDEX2DATA(fd); 174 | 175 | // Before Step 2 , You had better check the "target" spawned is a execute bin 176 | if (usr_is_elf_format(elfbuf) == 0) return -E_INVAL; 177 | 178 | // Step 2: Allocate an env (Hint: using syscall_env_alloc()) 179 | r = syscall_env_alloc(); 180 | if (r < 0) return r; 181 | child_envid = r; 182 | 183 | // Step 3: Using init_stack(...) to initialize the stack of the allocated env 184 | init_stack(child_envid, argv, &esp); 185 | 186 | // Step 3: Map file's content to new env's text segment 187 | // Hint 1: what is the offset of the text segment in file? try to use objdump to find out. 188 | // Hint 2: using read_map(...) 189 | // Hint 3: Important!!! sometimes ,its not safe to use read_map ,guess why 190 | // If you understand, you can achieve the "load APP" with any method 191 | // Note1: Step 1 and 2 need sanity check. In other words, you should check whether 192 | // the file is opened successfully, and env is allocated successfully. 193 | // Note2: You can achieve this func in any way ,remember to ensure the correctness 194 | // Maybe you can review lab3 195 | size = ((struct Filefd *)num2fd(fd))->f_file.f_size; 196 | if (size < 4) return -E_INVAL; 197 | elf = elfbuf; 198 | ph = elfbuf + elf->e_phoff; 199 | for (i = 0; i < elf->e_phnum; i++) { 200 | if (ph->p_type == PT_LOAD) { 201 | r = usr_load_elf(fd, ph, child_envid); 202 | if (r) return r; 203 | } 204 | ph++; 205 | } 206 | 207 | // Your code ends here 208 | 209 | struct Trapframe *tf; 210 | writef("\n::::::::::spawn size : %x sp : %x::::::::\n",size,esp); 211 | tf = &(envs[ENVX(child_envid)].env_tf); 212 | tf->pc = UTEXT; 213 | tf->regs[29]=esp; 214 | 215 | 216 | // Share memory 217 | u_int pdeno = 0; 218 | u_int pteno = 0; 219 | u_int pn = 0; 220 | u_int va = 0; 221 | for(pdeno = 0;pdeno0) 42 | *dest++=*src++; 43 | return destaddr; 44 | } 45 | 46 | 47 | int 48 | strcmp(const char *p, const char *q) 49 | { 50 | while (*p && *p == *q) 51 | p++, q++; 52 | if ((u_int)*p < (u_int)*q) 53 | return -1; 54 | if ((u_int)*p > (u_int)*q) 55 | return 1; 56 | return 0; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /user/syscall_lib.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void syscall_putchar(char ch) 8 | { 9 | msyscall(SYS_putchar, (int)ch, 0, 0, 0, 0); 10 | } 11 | 12 | 13 | u_int 14 | syscall_getenvid(void) 15 | { 16 | return msyscall(SYS_getenvid, 0, 0, 0, 0, 0); 17 | } 18 | 19 | void 20 | syscall_yield(void) 21 | { 22 | msyscall(SYS_yield, 0, 0, 0, 0, 0); 23 | } 24 | 25 | 26 | int 27 | syscall_env_destroy(u_int envid) 28 | { 29 | return msyscall(SYS_env_destroy, envid, 0, 0, 0, 0); 30 | } 31 | int 32 | syscall_set_pgfault_handler(u_int envid, void (*func)(void), u_int xstacktop) 33 | { 34 | return msyscall(SYS_set_pgfault_handler, envid, (int)func, xstacktop, 0, 0); 35 | } 36 | 37 | int 38 | syscall_mem_alloc(u_int envid, u_int va, u_int perm) 39 | { 40 | return msyscall(SYS_mem_alloc, envid, va, perm, 0, 0); 41 | } 42 | 43 | int 44 | syscall_mem_map(u_int srcid, u_int srcva, u_int dstid, u_int dstva, u_int perm) 45 | { 46 | return msyscall(SYS_mem_map, srcid, srcva, dstid, dstva, perm); 47 | } 48 | 49 | int 50 | syscall_mem_unmap(u_int envid, u_int va) 51 | { 52 | return msyscall(SYS_mem_unmap, envid, va, 0, 0, 0); 53 | } 54 | 55 | int 56 | syscall_set_env_status(u_int envid, u_int status) 57 | { 58 | return msyscall(SYS_set_env_status, envid, status, 0, 0, 0); 59 | } 60 | 61 | int 62 | syscall_set_trapframe(u_int envid, struct Trapframe *tf) 63 | { 64 | return msyscall(SYS_set_trapframe, envid, (int)tf, 0, 0, 0); 65 | } 66 | 67 | void 68 | syscall_panic(char *msg) 69 | { 70 | msyscall(SYS_panic, (int)msg, 0, 0, 0, 0); 71 | } 72 | 73 | int 74 | syscall_ipc_can_send(u_int envid, u_int value, u_int srcva, u_int perm) 75 | { 76 | return msyscall(SYS_ipc_can_send, envid, value, srcva, perm, 0); 77 | } 78 | 79 | void 80 | syscall_ipc_recv(u_int dstva) 81 | { 82 | msyscall(SYS_ipc_recv, dstva, 0, 0, 0, 0); 83 | } 84 | 85 | int 86 | syscall_cgetc() 87 | { 88 | return msyscall(SYS_cgetc, 0, 0, 0, 0, 0); 89 | } 90 | int syscall_write_dev(u_int va,u_int dev,u_int offset) 91 | { 92 | return msyscall(SYS_write_dev,va,dev,offset,0,0); 93 | } 94 | 95 | int syscall_read_dev(u_int va,u_int dev,u_int offset) 96 | { 97 | return msyscall(SYS_read_dev, va , dev , offset ,0,0); 98 | } 99 | -------------------------------------------------------------------------------- /user/syscall_wrap.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /*** exercise 4.1 ***/ 6 | LEAF(msyscall) 7 | // TODO: you JUST need to execute a `syscall` instruction and return from msyscall 8 | syscall 9 | jr ra 10 | nop 11 | END(msyscall) 12 | 13 | -------------------------------------------------------------------------------- /user/testarg.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | void umain(int argc, char **argv) 4 | { 5 | int i; 6 | for(i=0;ienv_id, p[1]); 20 | close(p[1]); 21 | writef("[%08x] pipereadeof readn %d\n", env->env_id, p[0]); 22 | i = readn(p[0], buf, sizeof buf-1); 23 | if (i < 0) 24 | user_panic("read: %e", i); 25 | buf[i] = 0; 26 | if (strcmp(buf, msg) == 0) 27 | writef("\npipe read closed properly\n"); 28 | else 29 | writef("\ngot %d bytes: %s\n", i, buf); 30 | exit(); 31 | } else { 32 | writef("[%08x] pipereadeof close %d\n", env->env_id, p[0]); 33 | close(p[0]); 34 | writef("[%08x] pipereadeof write %d\n", env->env_id, p[1]); 35 | if ((i=write(p[1], msg, strlen(msg))) != strlen(msg)) 36 | user_panic("write: %e", i); 37 | close(p[1]); 38 | } 39 | wait(pid); 40 | 41 | if ((i=pipe(p)) < 0) 42 | user_panic("pipe: %e", i); 43 | 44 | if ((pid=fork()) < 0) 45 | user_panic("fork: %e", i); 46 | 47 | if (pid == 0) { 48 | close(p[0]); 49 | for(;;){ 50 | writef("."); 51 | if(write(p[1], "x", 1) != 1) 52 | break; 53 | } 54 | writef("\npipe write closed properly\n"); 55 | } 56 | close(p[0]); 57 | close(p[1]); 58 | wait(pid); 59 | 60 | writef("pipe tests passed\n"); 61 | } 62 | -------------------------------------------------------------------------------- /user/testpiperace.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | void 4 | umain(void) 5 | { 6 | int p[2], r, pid, i, max; 7 | u_int va; 8 | struct Fd *fd; 9 | struct Env *kid; 10 | 11 | writef("testing for dup race...\n"); 12 | if ((r = pipe(p)) < 0) 13 | user_panic("pipe: %e", r); 14 | max = 200; 15 | if ((r = fork()) < 0) 16 | user_panic("fork: %e", r); 17 | if (r == 0) { 18 | close(p[1]); 19 | // 20 | // Now the ref count for p[0] will toggle between 2 and 3 21 | // as the parent dups and closes it (there's a close implicit in dup). 22 | // 23 | // The ref count for p[1] is 1. 24 | // Thus the ref count for the underlying pipe structure 25 | // will toggle between 3 and 4. 26 | // 27 | // If a clock interrupt catches close between unmapping 28 | // the pipe structure and unmapping the fd, we'll have 29 | // a ref count for p[0] of 3, a ref count for p[1] of 1, 30 | // and a ref count for the pipe structure of 3, which is 31 | // a no-no. 32 | // 33 | // If a clock interrupt catches dup between mapping the 34 | // fd and mapping the pipe structure, we'll have the same 35 | // ref counts, still a no-no. 36 | // 37 | for (i=0; ienv_status == ENV_RUNNABLE) 54 | dup(p[0], 10); 55 | 56 | writef("child done with loop\n"); 57 | if (pipeisclosed(p[0])) 58 | user_panic("somehow the other end of p[0] got closed!"); 59 | if ((r = fd_lookup(p[0], &fd)) < 0) 60 | user_panic("cannot look up p[0]: %e", r); 61 | va = fd2data(fd); 62 | if (pageref((void*)va) != 3+1) 63 | writef("\nchild detected race\n"); 64 | else 65 | writef("\nrace didn't happen\n", max); 66 | } 67 | -------------------------------------------------------------------------------- /user/testptelibrary.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #define TMPVA ((char *) 0x50005000) 3 | const char *msg = "hello world!\n"; 4 | const char *msg2 = "goodbye ,world!\n"; 5 | 6 | void childofspawn(void); 7 | 8 | 9 | void umain (int argc, char **argv) 10 | { 11 | int r; 12 | if(argc!=0) 13 | childofspawn(); 14 | 15 | if((r=syscall_mem_alloc(0,TMPVA,PTE_R|PTE_V|PTE_LIBRARY))<0) 16 | user_panic("syscall error!"); 17 | if((r=fork())<0) 18 | user_panic("fork: %d",r); 19 | if(r==0){ 20 | strcpy(TMPVA,msg); 21 | exit(); 22 | } 23 | 24 | wait(r); 25 | writef("TMPVAis %s \n",TMPVA); 26 | if(strcmp(TMPVA,msg)==0) 27 | writef("fork solved the problem of PTE_LIBRARY,congratulations!\n"); 28 | else 29 | user_panic("sorry , your fork may be wrong\n"); 30 | if((r=spawnl("testptelibrary.b","testptelibrary","arg",0))<0) 31 | user_panic("spawn wrong: %d",r); 32 | wait(r); 33 | if(strcmp(TMPVA,msg2)==0) 34 | writef("spawn solved the problem of PTE_LIBRARY,congratulations!\n"); 35 | else 36 | user_panic("sorry , your spawn may be wrong\n"); 37 | 38 | 39 | } 40 | 41 | void childofspawn(void){ 42 | strcpy(TMPVA,msg2); 43 | exit(); 44 | } 45 | -------------------------------------------------------------------------------- /user/user.lds: -------------------------------------------------------------------------------- 1 | /* ld script to make i386 Linux kernel 2 | * Written by Martin Mares ; 3 | */ 4 | OUTPUT_ARCH(mips) 5 | ENTRY(_start) 6 | SECTIONS 7 | { 8 | . = 0x00400000; 9 | 10 | _text = .; /* Text and read-only data */ 11 | .text : { 12 | *(.text) 13 | *(.fixup) 14 | *(.gnu.warning) 15 | } 16 | 17 | _etext = .; /* End of text section */ 18 | 19 | .data : { /* Data */ 20 | *(.data) 21 | *(.rodata) 22 | *(.rodata.*) 23 | *(.eh_frame) 24 | CONSTRUCTORS 25 | } 26 | 27 | _edata = .; /* End of data section */ 28 | 29 | 30 | 31 | __bss_start = .; /* BSS */ 32 | .bss : { 33 | *(.bss) 34 | } 35 | /DISCARD/ : { 36 | *(.comment) 37 | *(.debug_*) 38 | } 39 | end = . ; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /user/wait.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | void 4 | wait(u_int envid) 5 | { 6 | struct Env *e; 7 | 8 | //writef("envid:%x wait()~~~~~~~~~",envid); 9 | e = &envs[ENVX(envid)]; 10 | while(e->env_id == envid && e->env_status != ENV_FREE) 11 | syscall_yield(); 12 | } 13 | 14 | 15 | --------------------------------------------------------------------------------