├── .gitignore ├── Makefile ├── Readme.md ├── boot ├── Makefile └── start.S ├── drivers ├── Makefile └── gxconsole │ ├── Makefile │ ├── console.c │ └── dev_cons.h ├── fs ├── Makefile ├── Makefile.bak ├── Makefile625 ├── bintoc ├── fs.bak ├── fs.c ├── fs.h ├── fsformat ├── fsformat.c ├── ide.c ├── ide_asm.S ├── motd ├── newmotd ├── serv.b ├── serv.c ├── serv.out ├── test.c ├── testfdsharing.out └── view ├── gxemul ├── fs.img ├── fs.out ├── fs2.img ├── fs_.img_ ├── fsformat ├── r3000 └── view ├── include.mk ├── include ├── args.h ├── asm-mips3k │ ├── asm.h │ ├── cp0regdef.h │ └── regdef.h ├── asm │ ├── 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 ├── 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 ├── run.sh ├── tools └── scse0_3.lds ├── user ├── Makefile ├── bintoc ├── cat.c ├── console.c ├── date.c ├── entry.S ├── exit.c ├── fd.c ├── fd.h ├── file.c ├── fktest.c ├── fktest.out ├── fork.bak ├── fork.c ├── fprintf.c ├── fsipc.c ├── icode.c ├── idle.c ├── init.c ├── ipc.c ├── lib.h ├── libos.c ├── ls.c ├── out.txt ├── pageref.c ├── pgfault.c ├── pingpong.c ├── pingpong.out ├── pipe.c ├── print.c ├── printf.c ├── pt1.c ├── pt2.c ├── sh.c ├── sh.out ├── spawn.c ├── string.c ├── syscall_lib.c ├── syscall_lib.txt ├── syscall_wrap.S ├── testarg.c ├── testarg.out ├── testfdsharing.c ├── testfdsharing.out ├── testpipe.c ├── testpiperace.c ├── testspawn.c ├── user.lds └── wait.c └── 实验报告 ├── OSLAB1 ├── Gccmakegit.pptx ├── Gxemul.pptx ├── OSLAB1实验报告.docx ├── Shell_v1.1.pptx ├── Vim.pptx └── lab1.pptx ├── OSLAB2 ├── Lab2实验报告 .md ├── Lab2实验报告 .pdf ├── init.c ├── mmu.h ├── pmap.c ├── pmap.h └── queue.h ├── OSLAB3 ├── Lab3实验报告.md ├── Lab3实验报告.pdf ├── code_a.c ├── code_b.c ├── env.c ├── env.h ├── env_asm.S ├── init.c ├── load_icode_mapper.png ├── mmu.h ├── pmap.c ├── sched.c ├── trap.h └── 实验函数调用图.png ├── OSLAB4 ├── OSLAB4.md ├── OSLAB4.pdf ├── env.c ├── fork.c ├── pgfault.png ├── pmap.c ├── sched.c ├── sys_mem_map.png ├── syscall_all.c └── 函数调用关系.png ├── OSLAB5 ├── Lab5.md ├── Lab5.pdf ├── Makefile ├── Makefile1 ├── fd.c ├── file.c ├── fs.c ├── fsformat.c ├── fsipc.c ├── ide.c ├── ide_asm.S ├── serv.c └── 草图.png └── OSLAB6 ├── Lab6实验报告.md ├── Lab6实验报告.pdf ├── OS答辩.pptx ├── fd.c ├── fork.c ├── lib.h ├── ls.c ├── pipe.c ├── sh.c ├── syscall_all.c ├── syscall_lib.c └── 实验难点.png /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.o 3 | vmlinux 4 | *.x 5 | *.b 6 | -------------------------------------------------------------------------------- /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 | 17 | link_script := $(tools_dir)/scse0_3.lds 18 | 19 | modules := boot drivers init lib mm user fs 20 | objects := $(boot_dir)/start.o \ 21 | $(init_dir)/main.o \ 22 | $(init_dir)/init.o \ 23 | $(init_dir)/code.o \ 24 | $(drivers_dir)/gxconsole/console.o \ 25 | $(lib_dir)/*.o \ 26 | $(user_dir)/*.x \ 27 | $(fs_dir)/*.x \ 28 | $(mm_dir)/*.o 29 | 30 | .PHONY: all $(modules) clean 31 | 32 | all: $(modules) vmlinux 33 | 34 | vmlinux: $(modules) 35 | $(LD) -o $(vmlinux_elf) -N -T $(link_script) $(objects) 36 | 37 | $(modules): 38 | $(MAKE) --directory=$@ 39 | 40 | clean: 41 | for d in $(modules); \ 42 | do \ 43 | $(MAKE) --directory=$$d clean; \ 44 | done; \ 45 | rm -rf *.o *~ $(vmlinux_elf) 46 | 47 | include include.mk 48 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ## Readme 2 | --- 3 | This is the backup of my work during the Operating System lab courses. There are 6 branches: lab1 to lab6. You can checkout each branch to see every stage of the whole project. In the last branch lab6, a simple and naive shell is implemented, which is final goal of this project. 4 | 5 | The whole project is in fact based on the MIT JOS project, but instead of using x86 assembly language, it uses the mips assemply language. So the whole project needs the support of cross-platform compiler and can only be running on Gxemul simulator. 6 | -------------------------------------------------------------------------------- /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 | NESTED(except_vec3, 0, sp) 17 | .set noat 18 | .set noreorder 19 | /* 20 | * Register saving is delayed as long as we don't know 21 | * which registers really need to be saved. 22 | */ 23 | 1: 24 | mfc0 k1,CP0_CAUSE 25 | la k0,exception_handlers 26 | /* 27 | * Next lines assumes that the used CPU type has max. 28 | * 32 different types of exceptions. We might use this 29 | * to implement software exceptions in the future. 30 | */ 31 | 32 | andi k1,0x7c 33 | addu k0,k1 34 | lw k0,(k0) 35 | NOP 36 | jr k0 37 | nop 38 | END(except_vec3) 39 | .set at 40 | 41 | 42 | .data 43 | .globl mCONTEXT 44 | mCONTEXT: 45 | .word 0 46 | 47 | .globl delay 48 | delay: 49 | .word 0 50 | 51 | .globl tlbra 52 | tlbra: 53 | .word 0 54 | 55 | .section .data.stk 56 | KERNEL_STACK: 57 | .space 0x8000 58 | 59 | 60 | .text 61 | LEAF(_start) 62 | 63 | .set mips2 64 | .set reorder 65 | 66 | /* Disable interrupts */ 67 | mtc0 zero, CP0_STATUS 68 | 69 | /* Disable watch exception. */ 70 | mtc0 zero, CP0_WATCHLO 71 | mtc0 zero, CP0_WATCHHI 72 | 73 | /* disable kernel mode cache */ 74 | mfc0 t0, CP0_CONFIG 75 | and t0, ~0x7 76 | ori t0, 0x2 77 | mtc0 t0, CP0_CONFIG 78 | 79 | /* set up stack */ 80 | li sp, 0x80400000 81 | 82 | li t0,0x80400000 83 | sw t0,mCONTEXT 84 | 85 | /* jump to main */ 86 | jal main 87 | 88 | loop: 89 | j loop 90 | nop 91 | END(_start) 92 | 93 | -------------------------------------------------------------------------------- /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 | #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 | USERDIR := ../user/ 10 | USERLIB := ../user/printf.o \ 11 | ../user/print.o \ 12 | ../user/libos.o \ 13 | ../user/fork.o \ 14 | ../user/pgfault.o \ 15 | ../user/syscall_lib.o \ 16 | ../user/ipc.o \ 17 | ../user/string.o \ 18 | ../user/fd.o \ 19 | ../user/pageref.o \ 20 | ../user/file.o \ 21 | ../user/fsipc.o \ 22 | ../user/wait.o \ 23 | ../user/spawn.o \ 24 | ../user/pipe.o \ 25 | ../user/console.o \ 26 | ../user/fprintf.o 27 | 28 | FSLIB := fs.o \ 29 | ide.o \ 30 | ide_asm.o \ 31 | test.o 32 | 33 | FSIMGFILES := motd \ 34 | newmotd \ 35 | ../user/testfdsharing.b \ 36 | ../user/testarg.b \ 37 | ../user/init.b \ 38 | ../user/sh.b \ 39 | ../user/cat.b \ 40 | ../user/ls.b \ 41 | ../user/date.b \ 42 | ../user/exit.b 43 | 44 | 45 | CFLAGS += -nostdlib -static 46 | 47 | all: serv.x fs.img serv.b 48 | 49 | %.x: %.b.c 50 | echo cc1 $< 51 | $(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $< 52 | 53 | %.b.c: %.b 54 | echo create $@ 55 | echo bintoc $* $< > $@~ 56 | ./bintoc $* $< > $@~ && mv -f $@~ $@ 57 | # grep \. $@ 58 | 59 | %.b: ../user/entry.o ../user/syscall_wrap.o %.o $(USERLIB) $(FSLIB) 60 | echo ld $@ 61 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T $(USERDIR)user.lds $^ 62 | 63 | %.o: %.c 64 | echo user1 cc $< 65 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 66 | 67 | %.o: %.S 68 | echo as $< 69 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 70 | 71 | 72 | %.o: $(USERDIR)lib.h 73 | 74 | fs.img: $(FSIMGFILES) 75 | dd if=/dev/zero of=../gxemul/fs.img bs=4096 count=1024 2>/dev/null 76 | gcc $(INCLUDES) fsformat.c -o fsformat -m32 77 | chmod +x ./fsformat 78 | ./fsformat ../gxemul/fs.img $(FSIMGFILES) 79 | 80 | .PHONY: clean 81 | 82 | clean: 83 | rm -rf *~ *.o *.b.c *.x 84 | 85 | include ../include.mk 86 | -------------------------------------------------------------------------------- /fs/Makefile.bak: -------------------------------------------------------------------------------- 1 | INCLUDES = -I../include/ -I../user/ 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 | USERDIR := ../user/ 10 | USERLIB := ../user/printf.o \ 11 | ../user/print.o \ 12 | ../user/libos.o \ 13 | ../user/fork.o \ 14 | ../user/pgfault.o \ 15 | ../user/syscall_lib.o \ 16 | ../user/ipc.o \ 17 | ../user/string.o \ 18 | ../user/fd.o \ 19 | ../user/pageref.o \ 20 | ../user/file.o \ 21 | ../user/fsipc.o \ 22 | ../user/wait.o \ 23 | ../user/spawn.o \ 24 | ../user/pipe.o \ 25 | ../user/console.o \ 26 | ../user/fprintf.o 27 | 28 | FSLIB := fs.o \ 29 | ide.o \ 30 | ide_asm.o \ 31 | test.o 32 | 33 | FSIMGFILES := motd \ 34 | newmotd \ 35 | ../user/testfdsharing.b \ 36 | ../user/testarg.b \ 37 | ../user/init.b \ 38 | ../user/sh.b \ 39 | ../user/cat.b \ 40 | ../user/ls.b 41 | 42 | 43 | CFLAGS += -nostdlib -static 44 | 45 | all: serv.x fs.img serv.b 46 | 47 | %.x: %.b.c 48 | echo cc1 $< 49 | $(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $< 50 | 51 | %.b.c: %.b 52 | echo create $@ 53 | echo bintoc $* $< > $@~ 54 | ./bintoc $* $< > $@~ && mv -f $@~ $@ 55 | # grep \. $@ 56 | 57 | %.b: ../user/entry.o ../user/syscall_wrap.o %.o $(USERLIB) $(FSLIB) 58 | echo ld $@ 59 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T $(USERDIR)user.lds $^ 60 | 61 | %.o: %.c 62 | echo user1 cc $< 63 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 64 | 65 | %.o: %.S 66 | echo as $< 67 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 68 | 69 | 70 | %.o: $(USERDIR)lib.h 71 | 72 | fs.img: $(FSIMGFILES) 73 | dd if=/dev/zero of=../gxemul/fs.img bs=4096 count=1024 2>/dev/null 74 | ./fsformat ../gxemul/fs.img $(FSIMGFILES) 75 | 76 | .PHONY: clean 77 | 78 | clean: 79 | rm -rf *~ *.o *.b.c *.x 80 | 81 | include ../include.mk 82 | -------------------------------------------------------------------------------- /fs/Makefile625: -------------------------------------------------------------------------------- 1 | INCLUDES = -I../include/ -I../user/ 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 | USERDIR := ../user/ 10 | USERLIB := ../user/printf.o \ 11 | ../user/print.o \ 12 | ../user/libos.o \ 13 | ../user/fork.o \ 14 | ../user/pgfault.o \ 15 | ../user/syscall_lib.o \ 16 | ../user/ipc.o \ 17 | ../user/string.o \ 18 | ../user/fd.o \ 19 | ../user/pageref.o \ 20 | ../user/file.o \ 21 | ../user/fsipc.o \ 22 | ../user/pipe.o \ 23 | ../user/console.o \ 24 | ../user/fprintf.o 25 | 26 | FSLIB := fs.o \ 27 | ide.o \ 28 | ide_asm.o \ 29 | test.o 30 | 31 | FSIMGFILES := motd newmotd 32 | 33 | CFLAGS += -nostdlib -static 34 | 35 | all: serv.x fs.img serv.b 36 | 37 | %.x: %.b.c 38 | echo cc1 $< 39 | $(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $< 40 | 41 | %.b.c: %.b 42 | echo create $@ 43 | echo bintoc $* $< > $@~ 44 | chmod +x ./bintoc 45 | ./bintoc $* $< > $@~ && mv -f $@~ $@ 46 | # grep \. $@ 47 | 48 | %.b: ../user/entry.o ../user/syscall_wrap.o %.o $(USERLIB) $(FSLIB) 49 | echo ld $@ 50 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T $(USERDIR)user.lds $^ 51 | 52 | %.o: %.c 53 | echo user1 cc $< 54 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 55 | 56 | %.o: %.S 57 | echo as $< 58 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 59 | 60 | 61 | %.o: $(USERDIR)lib.h 62 | 63 | fs.img: $(FSIMGFILES) 64 | dd if=/dev/zero of=../gxemul/fs.img bs=4096 count=1024 2>/dev/null 65 | gcc $(INCLUDES) fsformat.c -o fsformat -m32 66 | chmod +x ./fsformat 67 | ./fsformat ../gxemul/fs.img $(FSIMGFILES) 68 | 69 | .PHONY: clean 70 | 71 | clean: 72 | rm -rf *~ *.o *.b.c *.b *.x 73 | 74 | include ../include.mk 75 | 76 | -------------------------------------------------------------------------------- /fs/bintoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/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 (3GB) */ 16 | #define DISKMAX 0xc0000000 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/fsformat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/fs/fsformat -------------------------------------------------------------------------------- /fs/ide.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Minimal PIO-based (non-interrupt-driven) IDE driver code. 3 | * For information about what all this IDE/ATA magic means, 4 | * see for example "The Guide to ATA/ATAPI documentation" at: 5 | * http://www.stanford.edu/~csapuntz/ide.html 6 | */ 7 | 8 | #include "fs.h" 9 | #include "lib.h" 10 | #include 11 | 12 | void 13 | ide_read(u_int diskno, u_int secno, void *dst, u_int nsecs) 14 | { 15 | int offset_begin = secno * 0x200; 16 | int offset_end = offset_begin + nsecs * 0x200; 17 | int offset = 0; 18 | 19 | while(offset_begin + offset < offset_end) 20 | { 21 | //writef("ide.c: read_sector() offset=%x\n",offset_begin + offset); 22 | if (read_sector(offset_begin + offset)) 23 | { 24 | user_bcopy( 0x93004000,dst + offset, 0x200); 25 | offset += 0x200; 26 | //user_panic("$$$$$$$$$$$$$$$$$$$$$$$"); 27 | 28 | } else { 29 | user_panic("disk I/O error"); 30 | } 31 | } 32 | } 33 | 34 | void 35 | ide_write(u_int diskno, u_int secno, void *src, u_int nsecs) 36 | { 37 | int offset_begin = secno * 0x200; 38 | int offset_end = offset_begin + nsecs * 0x200; 39 | int offset = 0; 40 | 41 | while (offset_begin + offset < offset_end) 42 | { 43 | //writef("ide_write(): offset_begin:%x offset:%x src:%x\n",offset_begin,offset,src); 44 | user_bcopy(src + offset,0x93004000, 0x200); 45 | if (write_sector(offset_begin + offset)) 46 | { 47 | offset += 0x200; 48 | } else { 49 | user_panic("disk I/O error"); 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /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.b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/fs/serv.b -------------------------------------------------------------------------------- /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/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/fs/view -------------------------------------------------------------------------------- /gxemul/fs.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/gxemul/fs.img -------------------------------------------------------------------------------- /gxemul/fs2.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/gxemul/fs2.img -------------------------------------------------------------------------------- /gxemul/fs_.img_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/gxemul/fs_.img_ -------------------------------------------------------------------------------- /gxemul/fsformat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/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/view: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/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 | CROSS_COMPILE := /OSLAB/compiler/usr/bin/mips_4KC- 8 | CC := $(CROSS_COMPILE)gcc 9 | CFLAGS := -O -G 0 -mno-abicalls -fno-builtin -Wa,-xgot -Wall -fPIC 10 | LD := $(CROSS_COMPILE)ld 11 | -------------------------------------------------------------------------------- /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/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/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 | 30 | // Lab 4 IPC 31 | u_int env_ipc_value; // data value sent to us 32 | u_int env_ipc_from; // envid of the sender 33 | u_int env_ipc_recving; // env is blocked receiving 34 | u_int env_ipc_dstva; // va at which to map received page 35 | u_int env_ipc_perm; // perm of page mapping received 36 | 37 | // Lab 4 fault handling 38 | u_int env_pgfault_handler; // page fault state 39 | u_int env_xstacktop; // top of exception stack 40 | 41 | // Lab 6 scheduler counts 42 | u_int env_runs; // number of times been env_run'ed 43 | }; 44 | 45 | LIST_HEAD(Env_list, Env); 46 | extern struct Env *envs; // All environments 47 | extern struct Env *curenv; // the current env 48 | 49 | void env_init(void); 50 | int env_alloc(struct Env **e, u_int parent_id); 51 | void env_free(struct Env *); 52 | void env_create(u_char *binary, int size); 53 | void env_destroy(struct Env *e); 54 | 55 | int envid2env(u_int envid, struct Env **penv, int checkperm); 56 | void env_run(struct Env *e); 57 | 58 | 59 | // for the grading script 60 | #define ENV_CREATE2(x, y) \ 61 | { \ 62 | extern u_char x[], y[]; \ 63 | env_create(x, (int)y); \ 64 | } 65 | 66 | #define ENV_CREATE(x) \ 67 | { \ 68 | extern u_char binary_##x##_start[];\ 69 | extern u_int binary_##x##_size; \ 70 | env_create(binary_##x##_start, \ 71 | (u_int)binary_##x##_size); \ 72 | } 73 | 74 | #endif // !_ENV_H_ 75 | -------------------------------------------------------------------------------- /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/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 | #endif 24 | -------------------------------------------------------------------------------- /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 | extern char aoutcode[]; 8 | extern char boutcode[]; 9 | 10 | void mips_init() 11 | { 12 | printf("init.c:\tmips_init() is called\n"); 13 | mips_detect_memory(); 14 | 15 | mips_vm_init(); 16 | page_init(); 17 | 18 | env_init(); 19 | //count(); 20 | /*you can create some processes(env) here. in terms of binary code, please refer current directory/code_a.c 21 | * code_b.c*/ 22 | //ENV_CREATE(user_pingpong); 23 | //ENV_CREATE(user_fktest); 24 | ENV_CREATE(user_icode); 25 | //ENV_CREATE(user_testfdsharing); 26 | //ENV_CREATE(user_testspawn); 27 | //ENV_CREATE(user_testpipe); 28 | //ENV_CREATE(user_testpiperace); 29 | ENV_CREATE(fs_serv); 30 | 31 | /*you may want to create process by MACRO, please read env.h file, in which you will find it. this MACRO is very 32 | * interesting, have fun please*/ 33 | trap_init(); 34 | kclock_init(); 35 | panic("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); 36 | while(1); 37 | panic("init.c:\tend of mips_init() reached!"); 38 | } 39 | 40 | void bcopy(const void *src, void *dst, size_t len) 41 | { 42 | void *max; 43 | 44 | max = dst + len; 45 | // copy machine words while possible 46 | while (dst + 3 < max) 47 | { 48 | *(int *)dst = *(int *)src; 49 | dst+=4; 50 | src+=4; 51 | } 52 | // finish remaining 0-3 bytes 53 | while (dst < max) 54 | { 55 | *(char *)dst = *(char *)src; 56 | dst+=1; 57 | src+=1; 58 | } 59 | } 60 | 61 | void bzero(void *b, size_t len) 62 | { 63 | void *max; 64 | 65 | max = b + len; 66 | 67 | //printf("init.c:\tzero from %x to %x\n",(int)b,(int)max); 68 | 69 | // zero machine words while possible 70 | 71 | while (b + 3 < max) 72 | { 73 | *(int *)b = 0; 74 | b+=4; 75 | } 76 | 77 | // finish remaining 0-3 bytes 78 | while (b < max) 79 | { 80 | *(char *)b++ = 0; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /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 | int load_elf(u_char *binary, int size, u_long *entry_point, void *user_data, 47 | int (*map)(u_long va, u_int32_t sgsize, 48 | u_char *bin, u_int32_t bin_size, void *user_data)) 49 | { 50 | Elf32_Ehdr *ehdr = (Elf32_Ehdr *)binary; 51 | Elf32_Phdr *phdr = NULL; 52 | /* As a loader, we just care about segment, 53 | * so we just parse program headers. 54 | */ 55 | u_char *ptr_ph_table = NULL; 56 | Elf32_Half ph_entry_count; 57 | Elf32_Half ph_entry_size; 58 | int r; 59 | 60 | // check whether `binary` is a ELF file. 61 | if (size < 4 || !is_elf_format(binary)) { 62 | return -1; 63 | } 64 | 65 | ptr_ph_table = binary + ehdr->e_phoff; 66 | ph_entry_count = ehdr->e_phnum; 67 | ph_entry_size = ehdr->e_phentsize; 68 | 69 | while (ph_entry_count--) { 70 | phdr = (Elf32_Phdr *)ptr_ph_table; 71 | 72 | if (phdr->p_type == PT_LOAD) { 73 | r = map(phdr->p_vaddr, phdr->p_memsz, 74 | binary + phdr->p_offset, phdr->p_filesz, user_data); 75 | 76 | if (r < 0) { 77 | return r; 78 | } 79 | } 80 | 81 | ptr_ph_table += ph_entry_size; 82 | } 83 | 84 | *entry_point = ehdr->e_entry; 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /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 | * Search through 'envs' for a runnable environment , 8 | * in circular fashion statrting after the previously running env, 9 | * and switch to the first such environment found. 10 | * 11 | * Hints: 12 | * The variable which is for counting should be defined as 'static'. 13 | */ 14 | void sched_yield(void) 15 | { 16 | static u_long count = 0; 17 | while (1){ 18 | count = (count+1)%NENV; 19 | if (envs[count].env_status==ENV_RUNNABLE) { 20 | env_run((envs+count)); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /lib/syscall.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | NESTED(handle_sys,TF_SIZE, sp) 9 | 10 | SAVE_ALL 11 | CLI 12 | 13 | //1: j 1b 14 | nop 15 | .set at 16 | lw t1, TF_EPC(sp) 17 | lw v0, TF_REG2(sp) 18 | 19 | subu v0, v0, __SYSCALL_BASE 20 | sltiu t0, v0, __NR_SYSCALLS+1 21 | 22 | addiu t1, 4 23 | sw t1, TF_EPC(sp) 24 | beqz t0, illegal_syscall//undef 25 | nop 26 | sll t0, v0,2 27 | la t1, sys_call_table 28 | addu t1, t0 29 | lw t2, (t1) 30 | beqz t2, illegal_syscall//undef 31 | nop 32 | lw t0,TF_REG29(sp) 33 | 34 | lw t1, (t0) 35 | lw t3, 4(t0) 36 | lw t4, 8(t0) 37 | lw t5, 12(t0) 38 | lw t6, 16(t0) 39 | lw t7, 20(t0) 40 | 41 | subu sp, 20 42 | 43 | sw t1, 0(sp) 44 | sw t3, 4(sp) 45 | sw t4, 8(sp) 46 | sw t5, 12(sp) 47 | sw t6, 16(sp) 48 | sw t7, 20(sp) 49 | 50 | move a0, t1 51 | move a1, t3 52 | move a2, t4 53 | move a3, t5 54 | 55 | jalr t2 56 | nop 57 | 58 | addu sp, 20 59 | 60 | sw v0, TF_REG2(sp) 61 | 62 | j ret_from_exception//extern? 63 | nop 64 | 65 | illegal_syscall: j illegal_syscall 66 | nop 67 | END(handle_sys) 68 | 69 | .extern sys_putchar 70 | .extern sys_getenvid 71 | .extern sys_yield 72 | .extern sys_env_destroy 73 | .extern sys_set_pgfault_handler 74 | .extern sys_mem_alloc 75 | .extern sys_mem_map 76 | .extern sys_mem_unmap 77 | .extern sys_env_alloc 78 | .extern sys_set_env_status 79 | .extern sys_set_trapframe 80 | .extern sys_panic 81 | .extern sys_ipc_can_send 82 | .extern sys_ipc_recv 83 | .extern sys_cgetc 84 | 85 | .macro syscalltable 86 | .word sys_putchar 87 | .word sys_getenvid 88 | .word sys_yield 89 | .word sys_env_destroy 90 | .word sys_set_pgfault_handler 91 | .word sys_mem_alloc 92 | .word sys_mem_map 93 | .word sys_mem_unmap 94 | .word sys_env_alloc 95 | .word sys_set_env_status 96 | .word sys_set_trapframe 97 | .word sys_panic 98 | .word sys_ipc_can_send 99 | .word sys_ipc_recv 100 | .word sys_cgetc 101 | .endm 102 | 103 | 104 | EXPORT(sys_call_table) 105 | syscalltable 106 | .size sys_call_table, . - sys_call_table 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /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 | void trap_init(){ 12 | int i; 13 | for(i=0;i<32;i++) 14 | set_except_vector(i, handle_reserved); 15 | set_except_vector(0, handle_int); 16 | set_except_vector(1, handle_mod); 17 | set_except_vector(2, handle_tlb); 18 | set_except_vector(3, handle_tlb); 19 | set_except_vector(8, handle_sys); 20 | } 21 | void *set_except_vector(int n, void * addr){ 22 | unsigned long handler=(unsigned long)addr; 23 | unsigned long old_handler=exception_handlers[n]; 24 | exception_handlers[n]=handler; 25 | return (void *)old_handler; 26 | } 27 | 28 | 29 | struct pgfault_trap_frame{ 30 | u_int fault_va; 31 | u_int err; 32 | u_int sp; 33 | u_int eflags; 34 | u_int pc; 35 | u_int empty1; 36 | u_int empty2; 37 | u_int empty3; 38 | u_int empty4; 39 | u_int empty5; 40 | }; 41 | 42 | 43 | void 44 | page_fault_handler(struct Trapframe *tf) 45 | { 46 | u_int va; 47 | u_int *tos, d; 48 | struct Trapframe PgTrapFrame; 49 | extern struct Env * curenv; 50 | //printf("^^^^cp0_BadVAddress:%x\n",tf->cp0_badvaddr); 51 | 52 | 53 | bcopy(tf, &PgTrapFrame,sizeof(struct Trapframe)); 54 | if(tf->regs[29] >= (curenv->env_xstacktop - BY2PG) && tf->regs[29] <= (curenv->env_xstacktop - 1)) 55 | { 56 | //panic("fork can't nest!!"); 57 | tf->regs[29] = tf->regs[29] - sizeof(struct Trapframe); 58 | bcopy(&PgTrapFrame, tf->regs[29], sizeof(struct Trapframe)); 59 | } 60 | else 61 | { 62 | 63 | tf->regs[29] = curenv->env_xstacktop - sizeof(struct Trapframe); 64 | // printf("page_fault_handler(): bcopy(): src:%x\tdes:%x\n",(int)&PgTrapFrame,(int)(curenv->env_xstacktop - sizeof(struct Trapframe))); 65 | bcopy(&PgTrapFrame, curenv->env_xstacktop - sizeof(struct Trapframe), sizeof(struct Trapframe)); 66 | } 67 | // printf("^^^^cp0_epc:%x\tcurenv->env_pgfault_handler:%x\n",tf->cp0_epc,curenv->env_pgfault_handler); 68 | 69 | tf->cp0_epc = curenv->env_pgfault_handler; 70 | 71 | 72 | return; 73 | } 74 | -------------------------------------------------------------------------------- /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 | tlbp 12 | nop 13 | nop 14 | nop 15 | nop 16 | mfc0 k0,CP0_INDEX 17 | bltz k0,NOFOUND 18 | nop 19 | mtc0 zero,CP0_ENTRYHI 20 | mtc0 zero,CP0_ENTRYLO0 21 | nop 22 | tlbwi 23 | //add k0, 40 24 | //sb k0, 0x90000000 25 | //li k0, '>' 26 | //sb k0, 0x90000000 27 | NOFOUND: 28 | 29 | mtc0 k1,CP0_ENTRYHI 30 | 31 | j ra 32 | nop 33 | END(tlb_out) 34 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!usr/bin 2 | make clean 3 | make 4 | /OSLAB/gxemul -M 64 -C R3000 -E testmips -d gxemul/fs.img ./gxemul/vmlinux 5 | -------------------------------------------------------------------------------- /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 | . = 0x80010000; 11 | .text : { 12 | *(.text) 13 | } 14 | 15 | .data : { 16 | *(.data) 17 | } 18 | 19 | .bss : { 20 | *(.bss) 21 | } 22 | 23 | .sdata : { 24 | *(.sdata) 25 | } 26 | 27 | . = 0x80400000; 28 | 29 | end = . ; 30 | } 31 | -------------------------------------------------------------------------------- /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 | fsipc.o \ 21 | wait.o \ 22 | spawn.o \ 23 | pipe.o \ 24 | console.o \ 25 | fprintf.o 26 | 27 | CFLAGS += -nostdlib -static 28 | 29 | all: fktest.x fktest.b testfdsharing.x testfdsharing.b pingpong.x pingpong.b idle.x testspawn.x testarg.b testpipe.x testpiperace.x icode.x init.b sh.b cat.b ls.b date.b exit.b $(USERLIB) entry.o syscall_wrap.o 30 | 31 | %.x: %.b.c 32 | echo cc1 $< 33 | $(CC) $(CFLAGS) -c -o $@ $< 34 | 35 | %.b.c: %.b 36 | echo create $@ 37 | echo bintoc $* $< > $@~ 38 | ./bintoc $* $< > $@~ && mv -f $@~ $@ 39 | # grep \. $@ 40 | 41 | %.b: entry.o syscall_wrap.o %.o $(USERLIB) 42 | echo ld $@ 43 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T ./user.lds $^ 44 | 45 | %.o: %.c 46 | echo user1 cc $< 47 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 48 | 49 | %.o: %.S 50 | echo as $< 51 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 52 | 53 | %.o: lib.h 54 | 55 | .PHONY: clean 56 | 57 | clean: 58 | rm -rf *~ *.o *.b.c *.x *.b 59 | 60 | include ../include.mk 61 | -------------------------------------------------------------------------------- /user/bintoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/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/date.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | int isLeapYear(int year) { 3 | if (year%4==0 && year%100!=0) 4 | return 1; 5 | if (year%400==0) 6 | return 1; 7 | return 0; 8 | } 9 | void date(int Cal) { 10 | int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; 11 | long sec = getDate(); 12 | int ss = 1; 13 | int mm = ss*60; 14 | int hh = mm*60; 15 | int dd = hh*24; 16 | int day = sec/dd; 17 | int hour = (sec-day*dd)/hh; 18 | int minute = (sec-day*dd-hour*hh)/mm; 19 | int second = (sec-day*dd-hour*hh-minute*mm)/ss; 20 | int year = 1970; 21 | int origin_day = day; 22 | while (1) { 23 | int old_day = day; 24 | if (isLeapYear(year)) 25 | day-=366; 26 | else 27 | day-=365; 28 | if (day<0) { 29 | day = old_day; 30 | break; 31 | } 32 | year+=1; 33 | } 34 | int month = 1; 35 | if (isLeapYear(year)) 36 | months[2] = 29; 37 | while (1) { 38 | int old_day = day; 39 | day -= months[month]; 40 | if (day<0) { 41 | day = old_day; 42 | break; 43 | } 44 | month++; 45 | } 46 | day++; 47 | if (!Cal) { 48 | int WeekDay = (origin_day+3)%7+1; 49 | switch (WeekDay) { 50 | case 1:writef("Mon\t");break; 51 | case 2:writef("Tues\t");break; 52 | case 3:writef("Wed\t");break; 53 | case 4:writef("Thur\t");break; 54 | case 5:writef("Fri\t");break; 55 | case 6:writef("Sat\t");break; 56 | case 7:writef("Sun\t");break; 57 | default:break; 58 | } 59 | writef("%d/%d/%d %d:%d:%d CST\n",year,month,day,hour+8,minute,second); 60 | } else { 61 | int WeekDay = (origin_day+3)%7+1; 62 | int firstDay; 63 | for (firstDay = 0;firstDay<7;firstDay++) { 64 | if ((firstDay+day-1)%7+1==WeekDay) { 65 | break; 66 | } 67 | } 68 | int cnt = 0,i; 69 | cnt+=firstDay; 70 | writef("%d年%d月\t\n",year,month); 71 | writef("Mon\tTues\tWed\tThur\tFri\tSat\tSun\t\n"); 72 | for (i=0;i 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/exit.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | void umain() { 3 | exitShell(); 4 | } 5 | -------------------------------------------------------------------------------- /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 | 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /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/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 | int i; 22 | for (i=0;i<512;i++) 23 | buf[i]=0; 24 | va_list ap; 25 | va_start(ap, fmt); 26 | user_lp_Print(user_out2string, buf, fmt, ap); 27 | va_end(ap); 28 | return write(fd, buf, strlen(buf)); 29 | } 30 | -------------------------------------------------------------------------------- /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 | // Send an IP request to the file server, and wait for a reply. 10 | // type: request code, passed as the simple integer IPC value. 11 | // fsreq: page to send containing additional request data, usually fsipcbuf. 12 | // Can be modified by server to return additional response info. 13 | // dstva: virtual address at which to receive reply page, 0 if none. 14 | // *perm: permissions of received page. 15 | // Returns 0 if successful, < 0 on failure. 16 | static int 17 | fsipc(u_int type, void *fsreq, u_int dstva, u_int *perm) 18 | { 19 | u_int whom; 20 | int r; 21 | //we file system no. is 000000000000000000 22 | ipc_send(envs[1].env_id, type, (u_int)fsreq, PTE_V|PTE_R); 23 | // writef("fsipc:ending ipc send & recv dst:%x\n",dstva); 24 | r = ipc_recv(&whom, dstva, perm); 25 | //writef("fsipc:r = %d\n",r); 26 | return r; 27 | } 28 | 29 | // Send file-open request to the file server. 30 | // Includes path and omode in request, sets *fileid and *size from reply. 31 | // Returns 0 on success, < 0 on failure. 32 | int 33 | fsipc_open(const char *path, u_int omode, struct Fd *fd) 34 | { 35 | u_int perm; 36 | struct Fsreq_open *req; 37 | //writef("TTTTTTTTTT fsipc_open:enter path:%s\n",path); 38 | req = (struct Fsreq_open*)fsipcbuf; 39 | if (strlen(path) >= MAXPATHLEN) 40 | return -E_BAD_PATH; 41 | strcpy(req->req_path, path); 42 | req->req_omode = omode; 43 | //writef("fsipc_open:will to ipc send\n"); 44 | //writef("fsipcbuf = %x, req->req_path = %x, vpd[req/PDMAP]=%x, vpt[req/BY2PG]=%x\n",fsipcbuf,(u_int)req->req_path,vpd[(u_int)req/PDMAP],vpt[(u_int)req/BY2PG]); 45 | //writef("UTOP = %x, ULIM = %x, UTEXT = %x\n",UTOP,ULIM,UTEXT); 46 | //writef("UUUUUUUUUUUUUUfsipc_open:fd = %x\n",(u_int)fd); 47 | return fsipc(FSREQ_OPEN, req, (u_int)fd, &perm); 48 | } 49 | 50 | // Make a map-block request to the file server. 51 | // We send the fileid and the (byte) offset of the desired block in the file, 52 | // and the server sends us back a mapping for a page containing that block. 53 | // Returns 0 on success, < 0 on failure. 54 | int 55 | fsipc_map(u_int fileid, u_int offset, u_int dstva) 56 | { 57 | int r; 58 | u_int perm; 59 | struct Fsreq_map *req; 60 | 61 | req = (struct Fsreq_map*)fsipcbuf; 62 | req->req_fileid = fileid; 63 | req->req_offset = offset; 64 | if ((r=fsipc(FSREQ_MAP, req, dstva, &perm)) < 0) 65 | return r; 66 | if ((perm&~(PTE_R|PTE_LIBRARY)) != (PTE_V)) 67 | user_panic("fsipc_map: unexpected permissions %08x for dstva %08x", perm, dstva); 68 | return 0; 69 | } 70 | 71 | // Make a set-file-size request to the file server. 72 | int 73 | fsipc_set_size(u_int fileid, u_int size) 74 | { 75 | struct Fsreq_set_size *req; 76 | 77 | req = (struct Fsreq_set_size*)fsipcbuf; 78 | req->req_fileid = fileid; 79 | req->req_size = size; 80 | return fsipc(FSREQ_SET_SIZE, req, 0, 0); 81 | } 82 | 83 | // Make a file-close request to the file server. 84 | // After this the fileid is invalid. 85 | int 86 | fsipc_close(u_int fileid) 87 | { 88 | struct Fsreq_close *req; 89 | 90 | req = (struct Fsreq_close*)fsipcbuf; 91 | req->req_fileid = fileid; 92 | return fsipc(FSREQ_CLOSE, req, 0, 0); 93 | } 94 | 95 | // Ask the file server to mark a particular file block dirty. 96 | int 97 | fsipc_dirty(u_int fileid, u_int offset) 98 | { 99 | struct Fsreq_dirty *req; 100 | 101 | req = (struct Fsreq_dirty*)fsipcbuf; 102 | req->req_fileid = fileid; 103 | req->req_offset = offset; 104 | return fsipc(FSREQ_DIRTY, req, 0, 0); 105 | } 106 | 107 | // Ask the file server to delete a file, given its pathname. 108 | int 109 | fsipc_remove(const char *path) 110 | { 111 | struct Fsreq_remove *req; 112 | 113 | req = (struct Fsreq_remove*)fsipcbuf; 114 | if (strlen(path) >= MAXPATHLEN) 115 | return -E_BAD_PATH; 116 | strcpy(req->req_path, path); 117 | return fsipc(FSREQ_REMOVE, req, 0, 0); 118 | } 119 | 120 | // Ask the file server to update the disk 121 | // by writing any dirty blocks in the buffer cache. 122 | int 123 | fsipc_sync(void) 124 | { 125 | return fsipc(FSREQ_SYNC, fsipcbuf, 0, 0); 126 | } 127 | 128 | -------------------------------------------------------------------------------- /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 | /////////////////////////////////////////////////////head 10 | extern void umain(); 11 | extern void libmain(); 12 | extern void exit(); 13 | 14 | extern struct Env *env; 15 | 16 | 17 | #define USED(x) (void)(x) 18 | //////////////////////////////////////////////////////printf 19 | #include 20 | #define LP_MAX_BUF 80 21 | 22 | void user_lp_Print(void (*output)(void *, char *, int), 23 | void * arg, 24 | char *fmt, 25 | va_list ap); 26 | 27 | void writef(char *fmt, ...); 28 | 29 | void _user_panic(const char *, int, const char *, ...) 30 | __attribute__((noreturn)); 31 | 32 | #define user_panic(...) _user_panic(__FILE__, __LINE__, __VA_ARGS__) 33 | 34 | 35 | /////////////////////////////////////////////////////fork spawn 36 | int spawn(char *prog, char **argv); 37 | int fork(void); 38 | 39 | void user_bcopy(const void *src, void *dst, size_t len); 40 | void user_bzero(void *v, u_int n); 41 | //////////////////////////////////////////////////syscall_lib 42 | void syscall_putchar(char ch); 43 | u_int syscall_getenvid(void); 44 | void syscall_yield(void); 45 | void syscall_env_destroy(u_int envid); 46 | int syscall_set_pgfault_handler(u_int envid, u_int func, u_int xstacktop); 47 | int syscall_mem_alloc(u_int envid, u_int va, u_int perm); 48 | int syscall_mem_map(u_int srcid, u_int srcva, u_int dstid, u_int dstva, u_int perm); 49 | int syscall_mem_unmap(u_int envid, u_int va); 50 | int syscall_env_alloc(int iffork); 51 | int syscall_set_env_status(u_int envid, u_int status); 52 | int syscall_set_trapframe(u_int envid, struct Trapframe *tf); 53 | void syscall_panic(char *msg); 54 | 55 | // ipc.c 56 | void ipc_send(u_int whom, u_int val, u_int srcva, u_int perm); 57 | u_int ipc_recv(u_int *whom, u_int dstva, u_int *perm); 58 | 59 | // pageref.c 60 | int pageref(void*); 61 | 62 | // fsipc.c 63 | int fsipc_open(const char*, u_int, struct Fd*); 64 | int fsipc_map(u_int, u_int, u_int); 65 | int fsipc_set_size(u_int, u_int); 66 | int fsipc_close(u_int); 67 | int fsipc_dirty(u_int, u_int); 68 | int fsipc_remove(const char*); 69 | int fsipc_sync(void); 70 | int fsipc_incref(u_int); 71 | 72 | // fd.c 73 | int close(int fd); 74 | int read(int fd, void *buf, u_int nbytes); 75 | int write(int fd, const void *buf, u_int nbytes); 76 | int seek(int fd, u_int offset); 77 | void close_all(void); 78 | int readn(int fd, void *buf, u_int nbytes); 79 | int dup(int oldfd, int newfd); 80 | int fstat(int fdnum, struct Stat *stat); 81 | int stat(const char *path, struct Stat*); 82 | 83 | // file.c 84 | int open(const char *path, int mode); 85 | int read_map(int fd, u_int offset, void **blk); 86 | int delete(const char *path); 87 | int ftruncate(int fd, u_int size); 88 | int sync(void); 89 | // date.c 90 | int getDate(void); 91 | 92 | #define user_assert(x) \ 93 | do { if (!(x)) user_panic("assertion failed: %s", #x); } while (0) 94 | 95 | /* File open modes */ 96 | #define O_RDONLY 0x0000 /* open for reading only */ 97 | #define O_WRONLY 0x0001 /* open for writing only */ 98 | #define O_RDWR 0x0002 /* open for reading and writing */ 99 | #define O_ACCMODE 0x0003 /* mask for above modes */ 100 | 101 | #define O_CREAT 0x0100 /* create if nonexistent */ 102 | #define O_TRUNC 0x0200 /* truncate to zero length */ 103 | #define O_EXCL 0x0400 /* error if already exists */ 104 | #define O_MKDIR 0x0800 /* create directory, not regular file */ 105 | 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /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 6 | 7 | extern void (*__pgfault_handler)(u_int, 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, u_int err)) 20 | { 21 | int r; 22 | 23 | if (__pgfault_handler == 0) { 24 | // Your code here: 25 | // map one page of exception stack with top at UXSTACKTOP 26 | // register assembly handler and stack with operating system 27 | if(syscall_mem_alloc(0, UXSTACKTOP - BY2PG, PTE_V|PTE_R)<0 || syscall_set_pgfault_handler(0, __asm_pgfault_handler, UXSTACKTOP)<0) 28 | { 29 | writef("cannot set pgfault handler\n"); 30 | return; 31 | } 32 | // panic("set_pgfault_handler not implemented"); 33 | } 34 | 35 | // Save handler pointer for assembly to call. 36 | __pgfault_handler = fn; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /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 | do { 89 | runs = env->env_runs; 90 | pfd = pageref(fd); 91 | pfp = pageref(p); 92 | } while (runs!=(env->env_runs)); 93 | return (pfd==pfp? 1:0); 94 | // panic("_pipeisclosed not implemented"); 95 | // return 0; 96 | } 97 | 98 | int 99 | pipeisclosed(int fdnum) 100 | { 101 | struct Fd *fd; 102 | struct Pipe *p; 103 | int r; 104 | 105 | if ((r = fd_lookup(fdnum, &fd)) < 0) 106 | return r; 107 | p = (struct Pipe*)fd2data(fd); 108 | return _pipeisclosed(fd, p); 109 | } 110 | 111 | static int 112 | piperead(struct Fd *fd, void *vbuf, u_int n, u_int offset) 113 | { 114 | // Your code here. See the lab text for a description of 115 | // what piperead needs to do. Write a loop that 116 | // transfers one byte at a time. If you decide you need 117 | // to yield (because the pipe is empty), only yield if 118 | // you have not yet copied any bytes. (If you have copied 119 | // some bytes, return what you have instead of yielding.) 120 | // If the pipe is empty and closed and you didn't copy any data out, return 0. 121 | // Use _pipeisclosed to check whether the pipe is closed. 122 | int i; 123 | struct Pipe *p; 124 | char *rbuf = vbuf; 125 | 126 | p = (struct Pipe*)fd2data(fd); 127 | if (_pipeisclosed(fd,p)) return 0; 128 | for (i=0;ip_rpos) >= (p->p_wpos) ) { 130 | if (_pipeisclosed(fd,p)) 131 | return i; 132 | syscall_yield(); 133 | } 134 | *rbuf = p->p_buf[(p->p_rpos)%BY2PIPE]; 135 | rbuf++; 136 | (p->p_rpos)++; 137 | } 138 | return i; 139 | // panic("piperead not implemented"); 140 | // return -E_INVAL; 141 | } 142 | 143 | static int 144 | pipewrite(struct Fd *fd, const void *vbuf, u_int n, u_int offset) 145 | { 146 | // Your code here. See the lab text for a description of what 147 | // pipewrite needs to do. Write a loop that transfers one byte 148 | // at a time. Unlike in read, it is not okay to write only some 149 | // of the data. If the pipe fills and you've only copied some of 150 | // the data, wait for the pipe to empty and then keep copying. 151 | // If the pipe is full and closed, return 0. 152 | // Use _pipeisclosed to check whether the pipe is closed. 153 | int i; 154 | struct Pipe *p; 155 | char *wbuf = vbuf; 156 | p = (struct Pipe*)fd2data(fd); 157 | if (_pipeisclosed(fd,p)) return 0; 158 | for (i=0;ip_wpos - p->p_rpos) >= BY2PIPE ) { 160 | if (_pipeisclosed(fd,p)) 161 | return i; 162 | syscall_yield(); 163 | } 164 | 165 | p->p_buf[(p->p_wpos)%BY2PIPE] = (*wbuf); 166 | wbuf++; 167 | (p->p_wpos)++; 168 | } 169 | return n; 170 | } 171 | 172 | static int 173 | pipestat(struct Fd *fd, struct Stat *stat) 174 | { 175 | struct Pipe *p; 176 | p = (struct Pipe*)fd2data(fd); 177 | p = (struct Pipe *)fd2data(fd); 178 | strcpy(stat->st_name, ""); 179 | stat->st_size = p->p_wpos - p->p_rpos; 180 | stat->st_isdir = 0; 181 | stat->st_dev = &devpipe; 182 | return 0; 183 | } 184 | 185 | static int 186 | pipeclose(struct Fd *fd) 187 | { 188 | syscall_mem_unmap(0, fd2data(fd)); 189 | return 0; 190 | } 191 | 192 | -------------------------------------------------------------------------------- /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/pt1.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | umain() 4 | { 5 | int i=0; 6 | 7 | for(i=0;i<100;i++) 8 | writef("1"); 9 | 10 | return ; 11 | } 12 | -------------------------------------------------------------------------------- /user/pt2.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | umain() 4 | { 5 | for(;;) 6 | writef("2"); 7 | 8 | return ; 9 | } 10 | -------------------------------------------------------------------------------- /user/spawn.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | #include 3 | #include 4 | 5 | #define TMPPAGE (BY2PG) 6 | #define TMPPAGETOP (TMPPAGE+BY2PG) 7 | 8 | int 9 | init_stack(u_int child, char **argv, u_int *init_esp) 10 | { 11 | int argc, i, r, tot; 12 | char *strings; 13 | u_int *args; 14 | 15 | // Count the number of arguments (argc) 16 | // and the total amount of space needed for strings (tot) 17 | tot = 0; 18 | for (argc=0; argv[argc]; argc++) 19 | tot += strlen(argv[argc])+1; 20 | 21 | // Make sure everything will fit in the initial stack page 22 | if (ROUND(tot, 4)+4*(argc+3) > BY2PG) 23 | return -E_NO_MEM; 24 | 25 | // Determine where to place the strings and the args array 26 | strings = (char*)TMPPAGETOP - tot; 27 | args = (u_int*)(TMPPAGETOP - ROUND(tot, 4) - 4*(argc+1)); 28 | 29 | if ((r = syscall_mem_alloc(0, TMPPAGE, PTE_V|PTE_R|PTE_LIBRARY)) < 0) 30 | return r; 31 | // Replace this with your code to: 32 | // 33 | // - copy the argument strings into the stack page at 'strings' 34 | //printf("come 1\n"); 35 | char *ctemp,*argv_temp; 36 | u_int j; 37 | ctemp = strings; 38 | //printf("tot=%d\n",tot); 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 | //printf("come 2\n"); 55 | ctemp = (char *)(USTACKTOP - TMPPAGETOP + (u_int)strings); 56 | for(i = 0;i < argc;i++) 57 | { 58 | args[i] = (u_int)ctemp; 59 | //writef("args[i]=%x\n",args[i]); 60 | ctemp += strlen(argv[i])+1; 61 | } 62 | // - set args[argc] to 0 to null-terminate the args array. 63 | //printf("come 3\n"); 64 | ctemp--; 65 | args[argc] = ctemp; 66 | //writef("args[argc]=%x\n",args[argc]); 67 | // - push two more words onto the child's stack below 'args', 68 | // containing the argc and argv parameters to be passed 69 | // to the child's umain() function. 70 | u_int *pargv_ptr; 71 | //printf("come 4 args=%x\n",(u_int)args); 72 | pargv_ptr = args - 1; 73 | *pargv_ptr = USTACKTOP - TMPPAGETOP + (u_int)args; 74 | //writef("*pargv_ptr=%x\n",*pargv_ptr); 75 | pargv_ptr--; 76 | *pargv_ptr = argc; 77 | // 78 | // - set *init_esp to the initial stack pointer for the child 79 | // 80 | //printf("come 5\n"); 81 | //writef("TMPPAGETOP - pargv_ptr =%x, pargv_ptr=%x\n",TMPPAGETOP - (u_int)pargv_ptr,pargv_ptr); 82 | *init_esp = USTACKTOP - TMPPAGETOP + (u_int)pargv_ptr; 83 | // *init_esp = USTACKTOP; // Change this! 84 | 85 | if ((r = syscall_mem_map(0, TMPPAGE, child, USTACKTOP-BY2PG, PTE_V|PTE_R)) < 0) 86 | goto error; 87 | if ((r = syscall_mem_unmap(0, TMPPAGE)) < 0) 88 | goto error; 89 | 90 | return 0; 91 | 92 | error: 93 | syscall_mem_unmap(0, TMPPAGE); 94 | return r; 95 | } 96 | 97 | 98 | int spawn(char *prog, char **argv) 99 | { 100 | int fd; 101 | int r; 102 | int size; 103 | u_int esp; 104 | 105 | if((fd = open(prog, O_RDWR/*O_ACCMODE*/))<0) 106 | user_panic("spawn:open %s:%e",prog,fd); 107 | 108 | u_int child_envid; 109 | child_envid = syscall_env_alloc(0);//syscall_env_alloc(); 110 | if(child_envid < 0) 111 | { 112 | writef("spawn:alloc the new env is wrong\n"); 113 | return child_envid; 114 | } 115 | 116 | init_stack(child_envid, argv,&esp); 117 | 118 | size = ((struct Filefd*)num2fd(fd))->f_file.f_size; 119 | 120 | 121 | u_int i; 122 | u_int *blk; 123 | int text_start; 124 | text_start = 0; 125 | for(i = 0x1000; i < size; i += BY2PG) 126 | { 127 | if((r = read_map(fd, i, &blk))<0) 128 | { 129 | writef("mapping text region is wrong\n"); 130 | return r; 131 | } 132 | 133 | syscall_mem_map(0, blk, child_envid, UTEXT+text_start, PTE_V |PTE_R); 134 | text_start += BY2PG; 135 | } 136 | 137 | struct Trapframe *tf; 138 | writef("\n::::::::::spawn size : %x sp : %x::::::::\n",size,esp); 139 | tf = &(envs[ENVX(child_envid)].env_tf); 140 | tf->pc = UTEXT; 141 | tf->regs[29]=esp; 142 | 143 | 144 | u_int pdeno = 0; 145 | u_int pteno = 0; 146 | u_int pn = 0; 147 | u_int va = 0; 148 | //writef("spawn begin to share \n"); 149 | 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 | void 27 | syscall_env_destroy(u_int envid) 28 | { 29 | msyscall(SYS_env_destroy,envid,0,0,0,0); 30 | } 31 | int 32 | syscall_set_pgfault_handler(u_int envid, u_int func, u_int xstacktop) 33 | { 34 | return msyscall(SYS_set_pgfault_handler,envid,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 syscall_env_alloc(int iffork) 56 | { 57 | 58 | int a= msyscall(SYS_env_alloc,iffork,0,0,0,0); 59 | return a; 60 | } 61 | 62 | int 63 | syscall_set_env_status(u_int envid, u_int status) 64 | { 65 | return msyscall(SYS_set_env_status,envid,status,0,0,0); 66 | } 67 | 68 | int 69 | syscall_set_trapframe(u_int envid, struct Trapframe *tf) 70 | { 71 | return msyscall(SYS_set_trapframe,envid,tf,0,0,0); 72 | } 73 | 74 | void 75 | syscall_panic(char *msg) 76 | { 77 | msyscall(SYS_panic,msg,0,0,0,0); 78 | } 79 | 80 | int 81 | syscall_ipc_can_send(u_int envid, u_int value, u_int srcva, u_int perm) 82 | { 83 | return msyscall(SYS_ipc_can_send, envid, value, srcva, perm, 0); 84 | } 85 | 86 | void 87 | syscall_ipc_recv(u_int dstva) 88 | { 89 | msyscall(SYS_ipc_recv, dstva, 0, 0, 0, 0); 90 | } 91 | 92 | int 93 | syscall_cgetc() 94 | { 95 | msyscall(SYS_cgetc,0,0,0,0,0); 96 | } 97 | -------------------------------------------------------------------------------- /user/syscall_wrap.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Overview: 6 | * `msyscall` push all the arguments into the stack, running 7 | * `syscall` instruction. 8 | * 9 | * Pre-Condition: 10 | * The first, second, third and fourth arguments are passed 11 | * by registers(a0~a3). The remains are stored on the stack. 12 | * 13 | * Post-Condition: 14 | * All arguments should be stored on the stack. Syscall number 15 | * should be passed by register v0. 16 | * 17 | * Hint: 18 | * Interestingly, MIPS 32 ABI(application binary interface) defined that 19 | * allocating space, which shoud be large enough to contain all the arguments, 20 | * on the stack is always required. 21 | * So, we needn't allocate space on the stack again. In another word, 22 | * we shouldn't change the value of $sp. All we need to do is store 23 | * registers(a0~a3) on the stack. 24 | * Remember passing syscall number by register v0 :) 25 | */ 26 | LEAF(msyscall) 27 | 28 | sw a0,0(sp) 29 | sw a1,4(sp) 30 | sw a2,8(sp) 31 | sw a3,12(sp) 32 | move v0, a0 33 | 34 | syscall 35 | 36 | jr ra 37 | 38 | END(msyscall) 39 | 40 | LEAF(getDate) 41 | lw t0,0x95000000 42 | lw v0,0x95000010 43 | jr ra 44 | nop 45 | END(getDate) 46 | 47 | LEAF(exitShell) 48 | lw t0,0x90000010 49 | jr ra 50 | nop 51 | END(exitShell) 52 | 53 | 54 | -------------------------------------------------------------------------------- /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]); 21 | close(p[1]); 22 | writef("[%08x] pipereadeof readn %d\n", env->env_id, p[0]); 23 | i = readn(p[0], buf, sizeof buf-1); 24 | if (i < 0) 25 | user_panic("read: %e", i); 26 | buf[i] = 0; 27 | if (strcmp(buf, msg) == 0) 28 | writef("\npipe read closed properly\n"); 29 | else 30 | writef("\ngot %d bytes: %s\n", i, buf); 31 | exit(); 32 | } else { 33 | writef("[%08x] pipereadeof close %d\n", env->env_id, p[0]); 34 | close(p[0]); 35 | writef("[%08x] pipereadeof write %d\n", env->env_id, p[1]); 36 | if ((i=write(p[1], msg, strlen(msg))) != strlen(msg)) 37 | user_panic("write: %e", i); 38 | close(p[1]); 39 | } 40 | wait(pid); 41 | 42 | if ((i=pipe(p)) < 0) 43 | user_panic("pipe: %e", i); 44 | 45 | if ((pid=fork()) < 0) 46 | user_panic("fork: %e", i); 47 | 48 | if (pid == 0) { 49 | close(p[0]); 50 | for(;;){ 51 | writef("."); 52 | if(write(p[1], "x", 1) != 1) 53 | break; 54 | } 55 | writef("\npipe write closed properly\n"); 56 | } 57 | close(p[0]); 58 | close(p[1]); 59 | wait(pid); 60 | 61 | writef("pipe tests passed\n"); 62 | } 63 | -------------------------------------------------------------------------------- /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/testspawn.c: -------------------------------------------------------------------------------- 1 | #include "lib.h" 2 | 3 | void umain(int argc, char **argv) 4 | { 5 | char a[]={"testfdsharing.b"}; 6 | char *s1[]={{"hello!"},{"world!"},{"haha"},{NULL}}; 7 | 8 | spawn(a, s1); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /实验报告/OSLAB1/Gccmakegit.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB1/Gccmakegit.pptx -------------------------------------------------------------------------------- /实验报告/OSLAB1/Gxemul.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB1/Gxemul.pptx -------------------------------------------------------------------------------- /实验报告/OSLAB1/OSLAB1实验报告.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB1/OSLAB1实验报告.docx -------------------------------------------------------------------------------- /实验报告/OSLAB1/Shell_v1.1.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB1/Shell_v1.1.pptx -------------------------------------------------------------------------------- /实验报告/OSLAB1/Vim.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB1/Vim.pptx -------------------------------------------------------------------------------- /实验报告/OSLAB1/lab1.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB1/lab1.pptx -------------------------------------------------------------------------------- /实验报告/OSLAB2/Lab2实验报告 .md: -------------------------------------------------------------------------------- 1 | # Lab2实验报告 2 | 3 | 150616-14051131-陈登博 4 | [TOC] 5 | 6 | ### 思考题 7 | 1. Thinking 2.1 8 | 这种写法的好处是以后可以通过修改```while()```括号中的条件方便地改变循环的次数,使得程序具有更好的可扩展性。 9 | 10 | 2. Thinking 2.2 11 | 物理内存页具体在0x80000000到0x84000000这64MB空间中,4KB为一页,共计0x4000页。对于一个Page结构体p,我们可以通过```page2kva(&p)```获取它所对应的物理内存页的虚拟地址。观察page2kva函数的实现可知,首先通过```(&p)-pages```得到该Page页的索引,然后将其向左移动12位,就得到了该Page页对应物理页的物理地址,再将该物理地址加ULIM,即得到了相应的虚拟地址。 12 | 13 | 3. Thinking 2.3 14 | 这个b指针是一个虚拟地址。从bzero函数的实现即可看出,其中使用了```*(int*)b=0```等语句。而在整个实验中,物理地址都是需要转换为虚拟地址(+ULIM)之后才可以寻址的,因此b指针是一个虚拟地址。 15 | 16 | 4. Thinking 2.4 17 | 其页目录的起始地址为0xC0000000+(0xC0000000>>10) = 0xc0300000。 18 | 19 | 5. Thinking 2.5 20 | 21 | tlb_out函数跳转到NOFOUND的流程为 22 | ```python 23 | mfc0 k1,CP0_ENTRYHI #先从CP0_ENTRYHI寄存器中取出值保存在k1寄存器中 24 | mtc0 a0,CP0_ENTRYHI #再把参数a0寄存器中保存的值存入CP0_ENTRYHI寄存器 25 | nop 26 | tlbp #然后在TLB的表项中查找是否有与CP0_ENTRYHI寄存器匹配的, 若有则把匹配项Index保 27 | #存到CP0_INDEX寄存器中,没有匹配则置CP0_INDEX的最高位为1 28 | ... 29 | mfc0 k0,CP0_INDEX #取出CP0_INDEX寄存器 30 | bltz k0,NOFOUND #检测CP0_INDEX第一位是否为1(是负数就为1),为1则跳转到NOFOUND 31 | nop 32 | ... 33 | NOFOUND: 34 | mtc0 k1,CP0_ENTRYHI #没找到匹配项,将刚刚保存的ENTRYHI寄存器的值重新赋给它 35 | j ra #函数返回 36 | nop 37 | ``` 38 | 6. Thinking 2.6 39 | 这是因为我们先执行```page_insert```函数,其中会调用```tlb_invalidate```函数,而```tlb_invalidate```函数又会去调用```tlb_out```函数,也就是说在插入页的时候我们就将va对应的页项从tlb中删除了,所以在向*va处写入数据的时候,我们会触发tlb miss,引起异常,没有重填机制的lab2就会在这里陷入死循环。 40 | 41 | ### 实验难点 42 |   在本次实验中,最难的莫过于理解整个页表的分配和管理机制了。示意图如下 43 | 44 | ![未命名文件](C:\Users\Chen Dengbo\Desktop\未命名文件.png) 45 | 46 |   首先让人感到困惑的是,什么是pa,什么是kva,二者的关系是什么。通过查阅宏函数对这两种地址的转换可知,pa是kva-0x80000000得到的。因此通过联系mips_detect_memory函数可知,这个pa是物理地址,kva是内核虚拟地址,由于物理空间只有从0x80000000-0x84000000的64MB,因此将内核虚拟地址转换为物理地址只需要减去一个0x80000000即可。 47 | 48 |   其次的难点在于pgdir_walk和boot_pgdir_walk,从注释的意思可以看出这两个函数都是要获取虚拟地址对应的页表项,同时兼具创建页表的功能。一开始这两个函数让我感到很困惑,在了解了二级页表的机制之后才慢慢明白其含义。因为这两个函数都会给定页目录地址,因此我们通过PDX(va)和页目录地址的配合就能找到页目录项,也就是对应页表的首地址,再通过PTX(va)就能找到对应的页表项,这也符合我们二级页表寻址过程。而create功能无非是其中一个点缀,其作用是创建一个页表,然后将地址传回到页目录项中,这就建立起页目录中项和一个页表的联系,这显然与我们的二级页表思想相吻合。而boot_pgdir_walk和pgdir_walk的区别在于空闲链表是否被初始化,从boot的名字上也可以看出是在启动时分配页表,因此空闲链表还未被初始化。明白了二者的区别,就可以发现二者其实挺相似的,因此解决了一个另一个也变得容易了。 49 | 50 |   而lab2还有一个难点在于页目录的自映射。这可以用数学中的不动点定理加一证明,简而言之,就是页目录跟它所指向的一个页表重合了,因此产生了只要4MB空间即可存储页目录和页表的现象。理解了自映射机制,那么可以得出页目录起始地址计算公式。 51 | $$ 52 | PGDIR_{init\_addr} = PGTABLE_{init\_addr}+PGTABLE_{init\_addr}>>10 53 | $$ 54 | 55 | ### 体会和感想 56 | 57 |   在lab2中我大量的时间花在了理解二级页表机制上,其实真正需要完成的函数不多,而且重要的page_insert函数也没有要求我们实现。从lab2的经历中,我发现阅读那些已经为我们写好的宏函数是非常有用的。因为它们透露出设计者的意图或者整个工程的思想,这对于完成整个任务是很有帮助的。此外,善用宏函数能够让我们需要写的代码非常简洁。 58 |   在lab2中,仍未解决的问题就是TLB重填函数的未实现问题,这导致了无法正确再现之前思考题2.6所提到的现象,程序会在TLB缺失之后陷入死循环。因此我对TLB重填函数的实现机制也不甚了解,这些可能都得在lab3或者更以后的实验中才能解决。 59 | 60 | -------------------------------------------------------------------------------- /实验报告/OSLAB2/Lab2实验报告 .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB2/Lab2实验报告 .pdf -------------------------------------------------------------------------------- /实验报告/OSLAB2/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void mips_init() 8 | { 9 | printf("init.c:\tmips_init() is called\n"); 10 | 11 | // Lab 2 memory management initialization functions 12 | mips_detect_memory(); 13 | mips_vm_init(); 14 | page_init(); 15 | page_check(); 16 | 17 | panic("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); 18 | 19 | while (1); 20 | 21 | panic("init.c:\tend of mips_init() reached!"); 22 | } 23 | 24 | void bcopy(const void *src, void *dst, size_t len) 25 | { 26 | void *max; 27 | 28 | max = dst + len; 29 | 30 | // copy machine words while possible 31 | while (dst + 3 < max) { 32 | *(int *)dst = *(int *)src; 33 | dst += 4; 34 | src += 4; 35 | } 36 | 37 | // finish remaining 0-3 bytes 38 | while (dst < max) { 39 | *(char *)dst = *(char *)src; 40 | dst += 1; 41 | src += 1; 42 | } 43 | } 44 | 45 | void bzero(void *b, size_t len) 46 | { 47 | void *max; 48 | 49 | max = b + len; 50 | 51 | //printf("init.c:\tzero from %x to %x\n",(int)b,(int)max); 52 | 53 | // zero machine words while possible 54 | 55 | while (b + 3 < max) { 56 | *(int *)b = 0; 57 | b += 4; 58 | } 59 | 60 | // finish remaining 0-3 bytes 61 | while (b < max) { 62 | *(char *)b++ = 0; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /实验报告/OSLAB2/mmu.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB2/mmu.h -------------------------------------------------------------------------------- /实验报告/OSLAB2/pmap.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB2/pmap.c -------------------------------------------------------------------------------- /实验报告/OSLAB2/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 | /* 12 | struct Page_list{ 13 | struct Page *lh_first; 14 | } 15 | */ 16 | typedef LIST_ENTRY(Page) Page_LIST_entry_t; 17 | /* 18 | typedef 19 | struct { 20 | struct Page *le_next; 21 | struct Page **le_prev; 22 | } Page_LIST_entry_t; 23 | */ 24 | 25 | struct Page { 26 | Page_LIST_entry_t pp_link; /* free list link */ 27 | 28 | // Ref is the count of pointers (usually in page table entries) 29 | // to this page. This only holds for pages allocated using 30 | // page_alloc. Pages allocated at boot time using pmap.c's "alloc" 31 | // do not have valid reference count fields. 32 | 33 | u_short pp_ref; 34 | }; 35 | 36 | extern struct Page *pages; 37 | 38 | static inline u_long 39 | page2ppn(struct Page *pp) 40 | { 41 | return pp - pages; 42 | } 43 | 44 | /* Get the physical address of Page 'pp'. 45 | */ 46 | static inline u_long 47 | page2pa(struct Page *pp) 48 | { 49 | return page2ppn(pp) << PGSHIFT; 50 | } 51 | 52 | /* Get the Page struct whose physical address is 'pa'. 53 | */ 54 | static inline struct Page * 55 | pa2page(u_long pa) 56 | { 57 | if (PPN(pa) >= npage) { 58 | panic("pa2page called with invalid pa: %x", pa); 59 | } 60 | 61 | return &pages[PPN(pa)]; 62 | } 63 | 64 | /* Get the kernel virtual address of Page 'pp'. 65 | */ 66 | static inline u_long 67 | page2kva(struct Page *pp) 68 | { 69 | return KADDR(page2pa(pp)); 70 | } 71 | 72 | /* Transform the virtual address 'va' to physical address. 73 | */ 74 | static inline u_long 75 | va2pa(Pde *pgdir, u_long va) 76 | { 77 | Pte *p; 78 | 79 | pgdir = &pgdir[PDX(va)]; 80 | 81 | if (!(*pgdir & PTE_V)) { 82 | return ~0; 83 | } 84 | 85 | p = (Pte *)KADDR(PTE_ADDR(*pgdir)); 86 | 87 | if (!(p[PTX(va)]&PTE_V)) { 88 | return ~0; 89 | } 90 | 91 | return PTE_ADDR(p[PTX(va)]); 92 | } 93 | 94 | /********** functions for memory management(see implementation in mm/pmap.c). ***********/ 95 | 96 | void mips_detect_memory(); 97 | 98 | void mips_vm_init(); 99 | 100 | void mips_init(); 101 | void page_init(void); 102 | void page_check(); 103 | int page_alloc(struct Page **pp); 104 | void page_free(struct Page *pp); 105 | void page_decref(struct Page *pp); 106 | int pgdir_walk(Pde *pgdir, u_long va, int create, Pte **ppte); 107 | int page_insert(Pde *pgdir, struct Page *pp, u_long va, u_int perm); 108 | struct Page *page_lookup(Pde *pgdir, u_long va, Pte **ppte); 109 | void page_remove(Pde *pgdir, u_long va) ; 110 | void tlb_invalidate(Pde *pgdir, u_long va); 111 | 112 | void boot_map_segment(Pde *pgdir, u_long va, u_long size, u_long pa, int perm); 113 | 114 | extern struct Page *pages; 115 | 116 | 117 | #endif /* _PMAP_H_ */ 118 | -------------------------------------------------------------------------------- /实验报告/OSLAB3/Lab3实验报告.md: -------------------------------------------------------------------------------- 1 | ### Lab3实验报告 2 | --- 3 | [TOC] 4 | #### 思考题 5 | * Thinking 3.1 6 | 只有使用逆序插入,我们才能保证以从前往后的方式从```env_free_list```中取出PCB块,即第一次调用```env_alloc```能从中取出```envs[0]```。 7 | 8 | * Thinking 3.2 9 | 1. 因为```UTOP```之上的所有映射对于任意一个地址空间都是一样的,只有为每个进程都拷贝一份内核才能使用的虚页表,进程才会有成为临时内核的资格,才可以发出申请变成内核态下运行的进程。 10 | 2. ```ULIM```是0x80000000,是操作系统分配给用户地址空间的最大值,```UTOP```是0x7f400000,是用户能够操控的地址空间的最大值。```UTOP```到```ULIM```这段空间用户不能写只能读,也应属于“内核态”,是在映射过程中留出来给用户进程查看其他进程信息的,用户在此处读取不会陷入异常。 11 | 3. ```UVPT```需要自映射到它在进程的```pgdir```中对应的页目录地址。这样当我们需要将```UVPT```这块区域的虚拟地址转换为物理地址时,就能方便地找到对应的页目录。 12 | 13 | * Thinking 3.3 14 | ```user_data```实际上是在```env_create```中用```env_alloc```分配出来的,在```load_icode_mapper```中需要将其强制转换为```env```。没有该参数是不可以的,因为在我写的代码中,它被作为连接```load_icode```, ```load_elf```, ```load_icode_mapper```的纽带,只有一路传递下去了,我们才能在```load_icode_mapper```中用它找到进程对应的页目录,完成```page_insert```的工作。 15 | 16 | * Thinking 3.4 17 | 1. 指令位置是针对虚拟空间所定义的。 18 | 2. entry_point对于每个进程是一样的,因为elf文件都被加载到了固定位置,因此每个进程运行代码的入口点是相同的。在网上查阅了ELF文件的格式之后得知,ELF文件并不是一开始就是代码,而是要经历一系列的header和magic数据之后才可到达代码区。所以我认为,这种统一来自于ELF的格式统一。 19 | 3. 我认为这个值是UTEXT+0xb0,即0x4000b0。 20 | 21 | * Thinking 3.5 22 | 这个值应该设置为curenv->env_tf.cp0_epc,因为EPC寄存器存放的正是异常发生时,系统正在执行指令的地址,因此要保存的进程上下文中的env_tf.pc应该设置为该值。 23 | 24 | * Thinking 3.6 25 | KERNEL_SP: 0,TIMESTACK: 0x82000000,我认为这里的TIMESTACK实际上是一个在时钟中断后用于从中取出之前存放的进程上下文信息的栈指针,在include/stackframe.h中出现了代码 26 | ```C 27 | .macro get_sp 28 | mfc0 k1, CP0_CAUSE 29 | andi k1, 0x107C 30 | xori k1, 0x1000 31 | bnez k1, 1f 32 | nop 33 | li sp, 0x82000000 34 | j 2f 35 | nop 36 | 1: 37 | bltz sp, 2f 38 | nop 39 | lw sp, KERNEL_SP 40 | nop 41 | 2: 42 | nop 43 | ``` 44 | 这段代码是宏get_sp中的,而get_sp又是宏SAVE_ALL中的,在handle_int函数中又出现了SAVE_ALL宏。通过阅读这一段汇编代码可知,如果CP0_CAUSE寄存器的exception code非0,即当前是中断导致的异常的话,那么获取的sp就是0x82000000,如果exception code非0,那么获取的sp是存储在KERNEL_SP中的值。所以我认为,**TIMESTACK是系统在发生中断异常时保存现场所用的栈顶指针**,联系到本次实验可以认为是在计时器产生中断后,程序保存上下文所用到的栈顶指针,在```env_run```函数中我们可以看到程序做了将TIMESTACK以下的值复制到进程的trapframe中的操作。 45 | ```C 46 | void 47 | env_run(struct Env *e) { 48 | ... 49 | if (curenv!=NULL && curenv!=e) { 50 | curenv->env_tf = *((struct Trapframe *)(TIMESTACK-sizeof(struct Trapframe))); 51 | curenv->env_tf.pc = curenv->env_tf.cp0_epc; 52 | } 53 | ... 54 | } 55 | ``` 56 | 这也就是保存进程的上下文至相应进程的结构体中。 57 | 58 | 至于说到TIMESTACK和KERNEL_SP的区别,我认为KERNEL_SP是产生非中断异常时所用到的栈指针,TIMESTACK则是发生中断异常时用到的栈指针,因为在本实验中,只有当exception code不是0,即不是中断导致的异常时,保存的上下文才是在KERNEL_SP中。 59 | 60 | * Thinking 3.7 61 | 因为在从env[1]之后开始遍历envs的时候,总会遍历多达NENV-2个env,在此期间env[1]还在继续运行,而如果是在env[0]之后遍历就不会出现这种情况,因为我们马上就能找到env[1],因此我们看到的是输出的2比1多。在只有两个进程的情况,要降低这种不公平,只需要将sched.c里面的NENV换成2,使得两个进程之间能不经过遍历其他env而迅速切换即可。 62 | #### 实验难点图示 63 | 64 | ​ 我认为本次实验的难点在于完成函数load_icode_mapper,而要完成该函数,我们需要明白整个实验的函数调用关系。(仅仅包含关键函数) 65 | 66 | ​ ![实验函数调用图](实验函数调用图.png) 67 | 68 | ​ 从上图可以看出,我们的实验整个流程大致为:初始化进程块之后,创建进程块,随后设置相应的中断产生于处理机制,然后gxemul就会根据设定的周期产生中断,中断处理之后根据我们完成的sched.c中的轮转算法就会开始运行新进程。而其中load_icode_mapper最为复杂,从调用关系上来看我们是在进程创建的过程中,将给定的elf文件加载到进程对应的位置,但是这个加载不上简单的一个bcopy就可以了,因为要考虑到一些边角情况。下图是我的二进制文件加载思路: 69 | 70 | ​ ![load_icode_mapper](load_icode_mapper.png) 71 | 72 | ​ 首先需要注意的是va未必对齐了BY2PG,其次在拷贝的末尾需要注意va+bin_size也未必对齐了BY2PG,最后还需要注意sgsize可能大于bin_size,因此bin_size之后的部分需要填充0。 73 | 74 | 75 | #### 体会与感想 76 | 77 | ​ 本次的实验加深我对操作系统进程运行和异常处理机制的理解,特别是PCB块,以前从未听说过它的存在,而在本次实验中这一结构体是记录进程信息的关键。本次实验还让我发现了更多在mmu.h的映射图中的细节,比如明白了UTOP和ULIM是什么,二者之间又是什么。在本次实验的难度方面,我感觉最困难的函数就是load_icode_mapper,其次是env_run,而env_run的坑点来说可能比load_icode_mapper更胜一筹,因为我在env_run中将bcopy的参数写反了,导致src和dst的位置交换,往系统不该写的地方写入了东西,因此陷入莫名的TOO LOW的panic中无法自拔,最终在反复折腾了两个小时之后才解决这个BUG。 78 | 79 | ​ 总的来说,本次实验是一个较为困难的工程,需要花费不少时间才能攻克。 -------------------------------------------------------------------------------- /实验报告/OSLAB3/Lab3实验报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB3/Lab3实验报告.pdf -------------------------------------------------------------------------------- /实验报告/OSLAB3/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 | 30 | // Lab 4 IPC 31 | u_int env_ipc_value; // data value sent to us 32 | u_int env_ipc_from; // envid of the sender 33 | u_int env_ipc_recving; // env is blocked receiving 34 | u_int env_ipc_dstva; // va at which to map received page 35 | u_int env_ipc_perm; // perm of page mapping received 36 | 37 | // Lab 4 fault handling 38 | u_int env_pgfault_handler; // page fault state 39 | u_int env_xstacktop; // top of exception stack 40 | 41 | // Lab 6 scheduler counts 42 | u_int env_runs; // number of times been env_run'ed 43 | }; 44 | 45 | LIST_HEAD(Env_list, Env); 46 | extern struct Env *envs; // All environments 47 | extern struct Env *curenv; // the current env 48 | 49 | void env_init(void); 50 | int env_alloc(struct Env **e, u_int parent_id); 51 | void env_free(struct Env *); 52 | void env_create(u_char *binary, int size); 53 | void env_destroy(struct Env *e); 54 | 55 | int envid2env(u_int envid, struct Env **penv, int checkperm); 56 | void env_run(struct Env *e); 57 | 58 | 59 | // for the grading script 60 | #define ENV_CREATE2(x, y) \ 61 | { \ 62 | extern u_char x[], y[]; \ 63 | env_create(x, (int)y); \ 64 | } 65 | 66 | #define ENV_CREATE(x) \ 67 | { \ 68 | extern u_char binary_##x##_start[];\ 69 | extern u_int binary_##x##_size; \ 70 | env_create(binary_##x##_start, \ 71 | (u_int)binary_##x##_size); \ 72 | } 73 | 74 | #endif // !_ENV_H_ 75 | -------------------------------------------------------------------------------- /实验报告/OSLAB3/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 | -------------------------------------------------------------------------------- /实验报告/OSLAB3/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void mips_init() 9 | { 10 | printf("init.c:\tmips_init() is called\n"); 11 | mips_detect_memory(); 12 | 13 | mips_vm_init(); 14 | page_init(); 15 | 16 | env_init(); 17 | ENV_CREATE(user_A); 18 | ENV_CREATE(user_B); 19 | /*you can create some processes(env) here. in terms of binary code, please refer current directory/code_a.c 20 | * code_b.c*/ 21 | /*you may want to create process by MACRO, please read env.h file, in which you will find it. this MACRO is very 22 | * interesting, have fun please*/ 23 | trap_init(); 24 | kclock_init(); 25 | panic("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); 26 | while(1); 27 | panic("init.c:\tend of mips_init() reached!"); 28 | } 29 | 30 | void bcopy(const void *src, void *dst, size_t len) 31 | { 32 | void *max; 33 | 34 | max = dst + len; 35 | // copy machine words while possible 36 | while (dst + 3 < max) 37 | { 38 | *(int *)dst = *(int *)src; 39 | dst+=4; 40 | src+=4; 41 | } 42 | // finish remaining 0-3 bytes 43 | while (dst < max) 44 | { 45 | *(char *)dst = *(char *)src; 46 | dst+=1; 47 | src+=1; 48 | } 49 | } 50 | 51 | void bzero(void *b, size_t len) 52 | { 53 | void *max; 54 | 55 | max = b + len; 56 | 57 | //printf("init.c:\tzero from %x to %x\n",(int)b,(int)max); 58 | 59 | // zero machine words while possible 60 | 61 | while (b + 3 < max) 62 | { 63 | *(int *)b = 0; 64 | b+=4; 65 | } 66 | 67 | // finish remaining 0-3 bytes 68 | while (b < max) 69 | { 70 | *(char *)b++ = 0; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /实验报告/OSLAB3/load_icode_mapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB3/load_icode_mapper.png -------------------------------------------------------------------------------- /实验报告/OSLAB3/pmap.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB3/pmap.c -------------------------------------------------------------------------------- /实验报告/OSLAB3/sched.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Overview: 6 | * Implement simple round-robin scheduling. 7 | * Search through 'envs' for a runnable environment , 8 | * in circular fashion statrting after the previously running env, 9 | * and switch to the first such environment found. 10 | * 11 | * Hints: 12 | * The variable which is for counting should be defined as 'static'. 13 | */ 14 | void sched_yield(void) 15 | { 16 | static int count = 0; 17 | while (1){ 18 | count = (count+1)%NENV; 19 | if (envs[count].env_status==ENV_RUNNABLE) { 20 | env_run(envs+count); 21 | break; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /实验报告/OSLAB3/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_PCC ((TF_EPC) + 4)4) 105 | /* 106 | * Size of stack frame, word/double word alignment 107 | */ 108 | #define TF_SIZE ((TF_PC)+4) 109 | #endif /* _TRAP_H_ */ -------------------------------------------------------------------------------- /实验报告/OSLAB3/实验函数调用图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB3/实验函数调用图.png -------------------------------------------------------------------------------- /实验报告/OSLAB4/OSLAB4.md: -------------------------------------------------------------------------------- 1 | ### Lab4实验报告 2 | --- 3 | [TOC] 4 | #### 思考题 5 | * Thinking 4.1 6 | ​ 前者说明在fork()之后,子进程的与父进程共享同一段代码。后者说明在fork()中子进程的pc值被设置为父进程调用fork()之后的位置,因此子进程就会只执行fork()之后的代码。 7 | 8 | * Thinking 4.2 9 | 10 | ​ 答案是C,因为fork()是产生子进程的函数,子进程当然不可能调用它。 11 | 12 | ```c 13 | sys_env_alloc -> $v0 14 | $v0 -> envid 15 | ``` 16 | 17 | ​ 而根据对fork()返回进程号的理解,fork()实际上调用了函数sys_env_alloc(),如上述代码所示。在子进程中返回值寄存器(v0)被设置为0而且子进程只能执行sys_env_alloc之后的代码,因此子进程得到的envid是0,而在父进程中能执行完整的代码因此得到的envid是子进程id。所以说fork()在两个进程中各自产生了一个返回值。 18 | 19 | * Thinking 4.3 20 | 21 | ​ 在USTACKTOP以下的页,UTEXT以上的页可以被保护,而在USTACKTOP到UTOP之间的位置不能被保护,即不能被duppage,原因是如果我们将[UXSTACKTOP-BY2PG,UXSTACKTOP]这块区域duppage到子进程,那么父进程与子进程的错误栈就一样了。但是由于两个进程的调度时机不同,子进程应该为其分配一个新的错误栈。所以[UXSTACKTOP-BY2PG,UXSTACKTOP]的区域不应该被保护,而[USTACKTOP,USTACKTOP+BY2PG]的区域是无效内存,因此也不应该被保护。此外,在这个区域中我们对于只读的页不能加上PTE_COW权限,而应该只给可写的页或者原本是PTE_COW权限的页加上PTE_COW权限。因为我们不能将原本不可写的页的权限改成可写。 22 | 23 | * Thinking 4.4 24 | 25 | vpd宏是指向用户页目录的指针,即\*vpd=7fdff000=(UVPT+(UVPT>>12)\*4),vpt宏则是指向用户页表的指针,即\*vpt=7fc00000=UVPT。通过这二者,我们可以得到一个虚拟地址va的页目录项以及其页表项,用法就是(\*vpd)[(VPN(va)>>10)]即得到对应的页目录项,(\*vpt)[VPN(va)]即得到对应的页表项。这两者出现的背景是为了在用户地址空间中实现对内核中相应地址的访问,如果要我在lab2中实现同样的功能,我可以采用UVPT+VPN(va)来代替(*vpt)[VPN(va)]。 26 | 27 | #### 实验难点 28 | 29 | * 首先我认为理清本次实验的函数调用关系对于理解整个函数的过程是非常有帮助的,我所理解的系统调用关系如下: 30 | 31 | ![函数调用关系](函数调用关系.png) 32 | 33 | ​ 从中可以看出,本次实验关键的fork函数的调用是以syscall特权指令为基础的,而在异常处理阶段,handle_sys函数依靠sys_call_table宏以及传入的参数所定位到的sys_x类函数正是我们需要完成的一系列基础但重要的函数。 34 | 35 | * 在本次实验中我认为比较难的函数之一的是sys_env_alloc函数,在这个函数中,我们需要做的是用env_alloc来创建一个子进程,然后将父进程的运行环境复制给它,再设置其相应的PC值、返回值和状态值。这其中最让人疑惑的是为什么它能在父子进程中返回两个不同的结果,阅读其代码我们可以整理出这样的过程。 36 | 37 | ```C 38 | ... syscall_env_alloc()-> $v0 39 | $v0 -> newenvid $v0 -> newenvid 40 | 子进程 父进程 41 | / newenvid=0 newenvid=e->env_id 42 | e->env_tf.pc = e->env_tf.cp0_epc; 43 | e->env_tf.regs[2] = 0; 44 | return e->env_id; 45 | 46 | ... 47 | ``` 48 | 49 | ​ 在调用syscall_env_alloc()之后,子进程实际上得以执行的汇编指令是将\$v0的值赋予newenvid的指令,这是因为其pc值被设置为cp0_epc,即发生异常的时候的pc+4,而在接下来又设置了\$v0=0,因此子进程的newenvid得到的就是0,而父进程得以执行完整的代码,因此其\$v0是sys\_env\_alloc的返回值,即e->env_id; 50 | 51 | * 此外我认为比较难的函数是sys_mem_map函数,这个函数的难点在于它与之后的pgfault函数有着紧密的联系。下面是sys_mem_map的结构: 52 | 53 | ![sys_mem_map](sys_mem_map.png) 54 | 55 | ​ 显然,此函数是将srcid对应的srcenv的srcva对应的那一页再与dstid对应的dstenv的dstva建立映射关系,这个函数再与sys_mem_unmap函数结合,就构成了pgfault函数的主要部分。 56 | 57 | ​ pgfault函数的作用是处理有COW权限位的页缺失,由于COW的性质,父子进程在修改双方共有的页面的时候不能直接修改,而应该将该页面复制一份,然后才能不破坏另一个享有该页的进程的正常功能。下面对pgfault函数进行分析。 58 | 59 | ![pgfault](pgfault.png) 60 | 61 | ​ 首先,我们需要通过```sys_mem_alloc```来为当前进程的tmp(即UXSTACKTOP-2*BY2PG)处分配上一个刚刚分配出的页,这样这个新的页面就与tmp建立起了映射关系,随后将va处那一页的内容用```user_bcopy```拷贝到tmp处,这实际上完成的就是COW中的Copy操作。再利用我们写好的sys_mem_map将tmp对应的那一页与va建立起映射关系,这样刚刚分配出的那一页与tmp和va都建立起了映射关系,最后调用```sys_mem_unmap```将那一页与tmp的映射关系抹除,这样,只有va与那一页存在映射关系。而我们在整个过程中对这新分配的一页给的权限都是PTE_V|PTE_R,这意味着该页是可写的,因此就满足COW中的Write操作。 62 | 63 | #### 感想与体会 64 | 65 | ​ 个人感觉Lab4也许是整个操作系统实验中最为艰难的一个lab,其中各种内核函数的调用关系在最开始不知道的时候感觉分外复杂,而在要完成各种基础sys_x类函数的时候线索的缺失和提示的晦涩也给人带来了不小的麻烦。但是在做完整个Lab4之后又给人一种恍然大悟的感觉,不得不感叹整个机制的精妙与复杂。 66 | 67 | ​ Lab4最大的考察点是fork,虽然fork函数本身不难填,但是它底层的机制与要思考的问题却挺麻烦。例如,fork机制是依靠底层的sys_env_alloc函数,而sys_env_alloc函数返回两个值的关键在于汇编指令执行的顺序以及相应的PC值的设置,这就与我们之前的计组联系了起来。其次,进程之间的通信也非常有意思,通过对本次实验的理解我发现,不同进程之间的通信就是依靠共有区域,即内核空间来实现的,这样就巧妙地利用了操作系统空间划分的特点。最后,本次实验让我看到了以前不起眼的指令syscall的强大作用,它使得进程陷入内核态,能够完成用户程序所无法完成的任务,这种作用也是我们后面的fork与进程间通信的基础。 -------------------------------------------------------------------------------- /实验报告/OSLAB4/OSLAB4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB4/OSLAB4.pdf -------------------------------------------------------------------------------- /实验报告/OSLAB4/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 | static void 82 | pgfault(u_int va) 83 | { 84 | u_int *tmp; 85 | //writef("fork.c:pgfault():\t va:%x\n",va); 86 | 87 | //map the new page at a temporary place 88 | tmp=UXSTACKTOP-2*BY2PG; 89 | va = ROUNDDOWN(va,BY2PG); 90 | if (!((*vpt)[VPN(va)] & PTE_COW)) { 91 | user_panic("no COW\n"); 92 | } 93 | if (syscall_mem_alloc(0,tmp,PTE_V|PTE_R)) { 94 | user_panic("syscall_mem_alloc error!\n"); 95 | } 96 | //copy the content 97 | user_bcopy((void*)va,tmp,BY2PG); 98 | //map the page on the appropriate place 99 | if (syscall_mem_map(0,tmp,0,va,PTE_V|PTE_R)!=0) { 100 | user_panic("syscall_mem_map error!\n"); 101 | } 102 | //unmap the temporary place 103 | if (syscall_mem_unmap(0,tmp)!=0) { 104 | user_panic("syscall_mem_unmap error!\n"); 105 | } 106 | } 107 | 108 | /* Overview: 109 | * Map our virtual page `pn` (address pn*BY2PG) into the target `envid` 110 | * at the same virtual address. 111 | * 112 | * Post-Condition: 113 | * if the page is writable or copy-on-write, the new mapping must be 114 | * created copy on write and then our mapping must be marked 115 | * copy on write as well. In another word, both of the new mapping and 116 | * our mapping should be copy-on-write if the page is writable or 117 | * copy-on-write. 118 | * 119 | * Hint: 120 | * PTE_LIBRARY indicates that the page is shared between processes. 121 | * A page with PTE_LIBRARY may have PTE_R at the same time. You 122 | * should process it correctly. 123 | */ 124 | static void 125 | duppage(u_int envid, u_int pn) 126 | { 127 | /* Note: 128 | * I am afraid I have some bad news for you. There is a ridiculous, 129 | * annoying and awful bug here. I could find another more adjectives 130 | * to qualify it, but you have to reproduce it to understand 131 | * how disturbing it is. 132 | * To reproduce this bug, you should follow the steps bellow: 133 | * 1. uncomment the statement "writef("");" bellow. 134 | * 2. make clean && make 135 | * 3. lauch Gxemul and check the result. 136 | * 4. you can add serveral `writef("");` and repeat step2~3. 137 | * Then, you will find that additional `writef("");` may lead to 138 | * a kernel panic. Interestingly, some students, who faced a strange 139 | * kernel panic problem, found that adding a `writef("");` could solve 140 | * the problem. 141 | * Unfortunately, we cannot find the code which leads to this bug, 142 | * although we have debugged it for serveral weeks. If you face this 143 | * bug, we would like to say "Good luck. God bless." 144 | */ 145 | // writef(""); 146 | //u_int addr; 147 | //u_int perm; 148 | 149 | // user_panic("duppage not implemented"); 150 | } 151 | 152 | /* Overview: 153 | * User-level fork. Create a child and then copy our address space 154 | * and page fault handler setup to the child. 155 | * 156 | * Hint: use vpd, vpt, and duppage. 157 | * Hint: remember to fix "env" in the child process! 158 | * Note: `set_pgfault_handler`(user/pgfault.c) is different from 159 | * `syscall_set_pgfault_handler`. 160 | */ 161 | extern void __asm_pgfault_handler(void); 162 | int 163 | fork(void) 164 | { 165 | // Your code here. 166 | u_int newenvid; 167 | extern struct Env *envs; 168 | extern struct Env *env; 169 | u_int i; 170 | //The parent installs pgfault using set_pgfault_handler 171 | //必须先设置pgfault 172 | set_pgfault_handler(pgfault); 173 | //然后才能调用syscall_env_alloc,否则会在异常中无法自拔 174 | newenvid = syscall_env_alloc(); 175 | if (newenvid==0) { 176 | env=&(envs[ENVX(syscall_getenvid())]); 177 | } else { 178 | syscall_mem_alloc(newenvid, UXSTACKTOP - BY2PG, PTE_V|PTE_R); 179 | syscall_set_pgfault_handler(newenvid, __asm_pgfault_handler, UXSTACKTOP); 180 | syscall_set_env_status(newenvid,ENV_RUNNABLE); 181 | } 182 | 183 | //alloc a new alloc 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 | -------------------------------------------------------------------------------- /实验报告/OSLAB4/pgfault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB4/pgfault.png -------------------------------------------------------------------------------- /实验报告/OSLAB4/sched.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Overview: 6 | * Implement simple round-robin scheduling. 7 | * Search through 'envs' for a runnable environment , 8 | * in circular fashion statrting after the previously running env, 9 | * and switch to the first such environment found. 10 | * 11 | * Hints: 12 | * The variable which is for counting should be defined as 'static'. 13 | */ 14 | void sched_yield(void) 15 | { 16 | static u_long count = 0; 17 | while (1){ 18 | count = count%NENV; 19 | if (envs[count].env_status==ENV_RUNNABLE) { 20 | env_run(&envs[count++]); 21 | } else { 22 | count++; 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /实验报告/OSLAB4/sys_mem_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB4/sys_mem_map.png -------------------------------------------------------------------------------- /实验报告/OSLAB4/函数调用关系.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB4/函数调用关系.png -------------------------------------------------------------------------------- /实验报告/OSLAB5/Lab5.md: -------------------------------------------------------------------------------- 1 | ### Lab5实验报告 2 | --- 3 | [TOC] 4 | #### 思考题 5 | * Thinking 5.1 6 | /proc文件系统是LINUX/UNIX系统上的一种内核和内核模块用来向进程 (process) 发送信息的机制。其作用是提供了一种和内核内部数据结构进行交互、获取有关进程的有用信息、在运行中改变设置(通过改变内核参数)的方式。Windows系统通过Win32 API的函数调用来完成与内核模式的交互。这样的设计将对内核信息的访问交互抽象成了对文件的访问修改,简化了交互过程。 7 | 8 | * Thinking 5.2 9 | 由于diskaddr函数中的return DISKMAP+blockno*BY2BLK语句返回的是对应磁盘块号的虚拟地址,该虚拟地址必须在[DISKMAP,DISKMAP+DISKMAX]之间,因此磁盘上的块与内存中的块一一对应,支持的最大的磁盘大小就是DISKMAX,即3GB。 10 | 11 | * Thinking 5.3 12 | 4KB*1024 = 4MB 13 | 14 | * Thinking 5.4 15 | 一个磁盘块有FILE2BLK=16个文件控制块,由于一个目录最多指向1024个磁盘块,每个磁盘块下面最多有16个文件控制块,因此一个目录最多有1024*16=16384个子文件。 16 | 17 | * Thinking 5.5 18 | 因为在serve函数中对于每种请求,都调用了相关的serve_x函数,而serve_x函数中会调用ipc_send函数,其中ipc_send函数会调用syscall_yield来切换进程并执行,因此serve中的死循环不会一直在CPU中运行,因此也就不会导致整个内核进入panic状态。 19 | 20 | * Thinking 5.6 21 | 22 | 因为一个Filefd的结构体的结构如下: 23 | 24 | ```C 25 | struct Filefd { 26 | struct Fd f_fd; 27 | u_int f_fileid; 28 | struct File f_file; 29 | } 30 | ``` 31 | 32 | 而一个Fd的结构如下 33 | 34 | ```C 35 | struct Fd { 36 | u_int fd_dev_id; 37 | u_int fd_offset; 38 | u_int fd_omode; 39 | } 40 | ``` 41 | 42 | 可以看出,Filefd的结构实际上是包含了Fd的结构的,由于在打开一个文件的时候,该文件描述符被分配了一页的空间,然后fsipc\_open在其中设置了文件的各种信息,其中就有f\_fileid以及struct File结构体所能存放的信息,因此一个Fd\*指针指向的那一页中就既存放着struct Fd中应该有的信息,又存放着struct Filefd中应该有的信息,而且由于结构体的内存位置分配原则,struct Fd中的信息在struct Filefd中信息的前面。因此只需要将Fd强制转换为struct Filefd\*类型,就能通过它获取到文件的其他信息。这也正是file.c中很多代码所做的那样。 43 | 44 | * Thinking 5.7 45 | 46 | 用户进程是将文件内容映射到文件描述符对应的虚地址,然后连续存放文件本身内容,而文件系统进程是将文件内容映射到opentab的一项所对应的一页内存的虚地址处,其中存入的是相应的文件结构体的各种信息。fileid传入的作用是在文件系统服务进程中,部分serve\_x函数可以用open\_lookup函数查找fileid对应的打开的文件,然后进行相应的操作。 47 | 48 | 49 | #### 实验难点 50 | 51 | 我认为本次实验的主要流程如下: 52 | 53 | ![草图](草图.png) 54 | 55 | ```User_fstest```进程主要依靠```IPC```机制与```fs_serv```进程进行通信来完成对文件系统的操作,除去与内存进行交互的```read/write```函数之外(二者主要依靠```user_bcopy```函数操作数据),整个lab5最主要的函数我认为就是```open/close```,以及这二者涉及到的```IPC```通信。通过阅读源代码我们可以发现,```open/close```函数中分别都调用了```fsipc_x```类函数(```open```函数中调用了```fsipc_open```函数,而```close```函数中调用了```fsipc_close```函数),而所有的```fsipc_x```类函数都会调用```fsipc```函数,通过```IPC```机制向```fs_serv```进程发送信息,而```fs_serv```进程中的```serve```函数会根据信息中所包含的请求种类信息调用相应的```serve_x```函数,再通过```IPC```机制向用户进程返回结果信息,从而完成了用户进程所请求的相应的操作。 56 | 57 | 此外,我感觉到本次本次实验的open函数是本次实验最困难的函数,下面从它的源代码解析。 58 | 59 | ```C 60 | int 61 | open(const char *path, int mode) 62 | { 63 | struct Fd *fd; 64 | struct Filefd *ffd; 65 | u_int size, fileid; 66 | int r; 67 | u_int va; 68 | u_int i; 69 | 70 | if ((r = fd_alloc(&fd)) < 0) { 71 | return r; 72 | } 73 | if ((r = fsipc_open(path, mode, fd)) < 0) { 74 | return r; 75 | } 76 | va = fd2data(fd); 77 | ffd = (struct Filefd*)fd; 78 | size = ffd->f_file.f_size; 79 | fileid = ffd->f_fileid; 80 | for (i=0;i $@~ 44 | chmod +x ./bintoc 45 | ./bintoc $* $< > $@~ && mv -f $@~ $@ 46 | # grep \. $@ 47 | 48 | %.b: ../user/entry.o ../user/syscall_wrap.o %.o $(USERLIB) $(FSLIB) 49 | echo ld $@ 50 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T $(USERDIR)user.lds $^ 51 | 52 | %.o: %.c 53 | echo user1 cc $< 54 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 55 | 56 | %.o: %.S 57 | echo as $< 58 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 59 | 60 | 61 | %.o: $(USERDIR)lib.h 62 | 63 | fs.img: $(FSIMGFILES) 64 | dd if=/dev/zero of=../gxemul/fs.img bs=4096 count=1024 2>/dev/null 65 | gcc $(INCLUDES) fsformat.c -o fsformat -m32 66 | chmod +x ./fsformat 67 | ./fsformat ../gxemul/fs.img $(FSIMGFILES) 68 | 69 | .PHONY: clean 70 | 71 | clean: 72 | rm -rf *~ *.o *.b.c *.b *.x 73 | 74 | include ../include.mk 75 | -------------------------------------------------------------------------------- /实验报告/OSLAB5/Makefile1: -------------------------------------------------------------------------------- 1 | INCLUDES = -I../include/ -I../user/ 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 | USERDIR := ../user/ 10 | USERLIB := ../user/printf.o \ 11 | ../user/print.o \ 12 | ../user/libos.o \ 13 | ../user/fork.o \ 14 | ../user/pgfault.o \ 15 | ../user/syscall_lib.o \ 16 | ../user/ipc.o \ 17 | ../user/string.o \ 18 | ../user/fd.o \ 19 | ../user/pageref.o \ 20 | ../user/file.o \ 21 | ../user/fsipc.o \ 22 | ../user/pipe.o \ 23 | ../user/console.o \ 24 | ../user/fprintf.o 25 | 26 | FSLIB := fs.o \ 27 | ide.o \ 28 | ide_asm.o \ 29 | test.o 30 | 31 | FSIMGFILES := motd newmotd 32 | 33 | CFLAGS += -nostdlib -static 34 | 35 | all: serv.x fs.img serv.b 36 | 37 | %.x: %.b.c 38 | echo cc1 $< 39 | $(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $< 40 | 41 | %.b.c: %.b 42 | echo create $@ 43 | echo bintoc $* $< > $@~ 44 | chmod +x ./bintoc 45 | ./bintoc $* $< > $@~ && mv -f $@~ $@ 46 | # grep \. $@ 47 | 48 | %.b: ../user/entry.o ../user/syscall_wrap.o %.o $(USERLIB) $(FSLIB) 49 | echo ld $@ 50 | $(LD) -o $@ $(LDFLAGS) -G 0 -static -n -nostdlib -T $(USERDIR)user.lds $^ 51 | 52 | %.o: %.c 53 | echo user1 cc $< 54 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 55 | 56 | %.o: %.S 57 | echo as $< 58 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 59 | 60 | 61 | %.o: $(USERDIR)lib.h 62 | 63 | fs.img: $(FSIMGFILES) 64 | dd if=/dev/zero of=../gxemul/fs.img bs=4096 count=1024 2>/dev/null 65 | gcc $(INCLUDES) fsformat.c -o fsformat -m32 66 | chmod +x ./fsformat 67 | ./fsformat ../gxemul/fs.img $(FSIMGFILES) 68 | 69 | .PHONY: clean 70 | 71 | clean: 72 | rm -rf *~ *.o *.b.c *.b *.x 73 | 74 | include ../include.mk 75 | -------------------------------------------------------------------------------- /实验报告/OSLAB5/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 | // Step 1: decide if the path is valid. 131 | struct Fsreq_remove * req; 132 | req = (struct Fsreq_remove*)fsipcbuf; 133 | if (strlen(path)>=MAXPATHLEN) { 134 | return -E_BAD_PATH; 135 | } 136 | strcpy((char *)req->req_path, path); 137 | // Step 2: Send request to fs server with IPC. 138 | return fsipc(FSREQ_REMOVE,req,0,0); 139 | } 140 | 141 | // Overview: 142 | // Ask the file server to update the disk by writing any dirty 143 | // blocks in the buffer cache. 144 | int 145 | fsipc_sync(void) 146 | { 147 | return fsipc(FSREQ_SYNC, fsipcbuf, 0, 0); 148 | } 149 | -------------------------------------------------------------------------------- /实验报告/OSLAB5/ide.c: -------------------------------------------------------------------------------- 1 | /* 2 | * operations on IDE disk. 3 | */ 4 | 5 | #include "fs.h" 6 | #include "lib.h" 7 | #include 8 | 9 | extern int read_sector(int diskno, int offset); 10 | extern int write_sector(int diskno, int offset); 11 | 12 | // Overview: 13 | // read data from IDE disk. 14 | // 15 | // Parameters: 16 | // diskno: disk number. 17 | // secno: start sector number. 18 | // dst: destination for data read from IDE disk. 19 | // nsecs: the number of sectors to read. 20 | // 21 | // Post-Condition: 22 | // If error occurred during read the IDE disk, panic. 23 | void 24 | ide_read(u_int diskno, u_int secno, void *dst, u_int nsecs) 25 | { 26 | // 0x200: the size of a sector: 512 bytes. 27 | int offset_begin = secno * 0x200; 28 | int offset_end = offset_begin + nsecs * 0x200; 29 | int offset = 0; 30 | 31 | while (offset_begin + offset < offset_end) { 32 | if (read_sector(diskno, offset_begin + offset)) { 33 | // copy data from disk buffer(512 bytes, a sector) to destination array. 34 | user_bcopy((void *)0x93004000, dst + offset, 0x200); 35 | offset += 0x200; 36 | } else { 37 | // error occurred, then panic. 38 | user_panic("disk I/O error"); 39 | } 40 | } 41 | } 42 | 43 | 44 | // Overview: 45 | // write data to IDE disk. 46 | // 47 | // Parameters: 48 | // diskno: disk number. 49 | // secno: start sector number. 50 | // src: the source data to write into IDE disk. 51 | // nsecs: the number of sectors to write. 52 | // 53 | // Post-Condition: 54 | // If error occurred during read the IDE disk, panic. 55 | void 56 | ide_write(u_int diskno, u_int secno, void *src, u_int nsecs) 57 | { 58 | int offset_begin = secno*0x200; 59 | int offset_end = offset_begin+nsecs*0x200; 60 | int offset = 0; 61 | writef("diskno: %d\n", diskno); 62 | while ( offset_begin+offset < offset_end ) { 63 | user_bcopy(src+offset,(void*)0x93004000,0x200); 64 | if (write_sector(diskno,offset_begin+offset)) { 65 | // copy data from source array to disk buffer. 66 | offset+=0x200; 67 | } 68 | else { 69 | // if error occur, then panic. 70 | user_panic("ide_write error"); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /实验报告/OSLAB5/ide_asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // more info about emulated IDE disks provided by Gexmul, see at http://gxemul.sourceforge.net/gxemul-stable/doc/experiments.html. 6 | 7 | // Default physical address: 0x13000000 8 | // Offset: Effect: 9 | // 0x0000 Write: Set the offset (in bytes) from the beginning of the disk image. This offset will be used for the next read/write operation. 10 | // 0x0008 Write: Set the high 32 bits of the offset (in bytes). (*) 11 | // 0x0010 Write: Select the IDE ID to be used in the next read/write operation. 12 | // 0x0020 Write: Start a read or write operation. (Writing 0 means a Read operation, a 1 means a Write operation.) 13 | // 0x0030 Read: Get status of the last operation. (Status 0 means failure, non-zero means success.) 14 | // 0x4000-0x41ff Read/Write: 512 bytes data buffer. 15 | 16 | // read sector at specified offset from the beginning of the disk image. 17 | LEAF(read_sector) 18 | sw a0, 0x93000010 // select the IDE id. 19 | sw a1, 0x93000000 // offset. 20 | li t0, 0 21 | sb t0, 0x93000020 // start read. 22 | lw v0, 0x93000030 23 | nop 24 | jr ra 25 | nop 26 | END(read_sector) 27 | 28 | // write 29 | LEAF(write_sector) 30 | sw a0, 0x93000010 // select the IDE id. 31 | sw a1, 0x93000000 // offset. 32 | li t0, 1 33 | sb t0, 0x93000020 // start write. 34 | lw v0, 0x93000030 // get status as return value. 35 | jr ra 36 | nop 37 | END(write_sector) 38 | -------------------------------------------------------------------------------- /实验报告/OSLAB5/草图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB5/草图.png -------------------------------------------------------------------------------- /实验报告/OSLAB6/Lab6实验报告.md: -------------------------------------------------------------------------------- 1 | ## Lab6实验报告 2 | 3 | --- 4 | 5 | [TOC] 6 | 7 | #### 实验思考题 8 | 9 | > Thinking 6.1 10 | 11 |     将```case 0```与```default```的内容交换,并且将其中的```child-process```改成```father-process```即可。 12 | 13 | > Thinking 6.2 14 | 15 |     这是因为```pageref(pipe)``` = ```pageref(fd[0])```+```pageref(fd[1])``` ,因此如果```fd[0]```与```fd[1]```都大于0,则pipe的pageref大于二者之中任意一个,当在dup函数中我们先对fd的pageref++,再对pipe的pageref++的时候,可能存在```pageref(pipe)```=```pageref(fd)```的情况,这里的fd是fd[0]或者fd[1],如果此时进程被切换到执行_pipeclosed函数,可能造成该函数的误判,导致无法正常完成读写任务。 16 | 17 | > Thinking 6.3 18 | 19 |     系统调用是原子操作,具体代码是在include/stackframe.h中定义的CLI宏,如下所示 20 | 21 | ```c 22 | .macro CLI 23 | mfc0 t0, CP0_STATUS 24 | li t1, (STATUS_CU0 | 0x1) 25 | or t0, t1 26 | xor t0, 0x1 27 | mtc0 t0, CP0_STATUS 28 | .endm 29 | ``` 30 | 31 |     CLI宏在handle_sys函数中出现,作用是设置CP0_STATUS寄存器,因此后面的中断无法发生,因此就无法发生嵌套中断,导致系统调用也不能被打断,因此系统调用是原子操作。 32 | 33 | > Thinking 6.4 34 | 35 | 1. 可以解决上述竞争问题。这是因为通常pageref(pipe)>pageref(fd),如果先unmap(fd),那么pageref(pipe)>pageref(fd)的关系依然保持,所以不会出现二者相等而导致_pipeclosed误判的情况。 36 | 2. 与close中的情况类似,dup中依然可能有pageref(pipe)>pageref(fd)的情况出现,如果我们先将pipe的pageref++(用syscall_mem_map),再将fd的pageref++,那我们依然能够保持pageref(pipe)>pageref(fd),故不会出现pageref(pipe)=pageref(fd)而导致_pipeclosed误判的情况。 37 | 38 | #### 实验难点图示 39 | 40 | ![实验难点](实验难点.png) 41 | 42 | 本次实验主要分为两个大方面:管道与Shell,管道方面需要注意的地方就是管道的读写与竞争,而shell主要注意与管道的结合,以及如何分析输入的命令(runcmd)。 43 | 44 | * pipe 45 | 46 |  管道的读写都是在一个环形缓冲区中进行,而环形缓冲区大小十分有限,因此读写往往需要父子进程不断切换。那么控制这种切换我们需要借助一些特别的方法,即pageref。通常情况下, 一旦建立起一个管道,两个fd与共享的那个pipe的pageref分别应该是1,1,2。当有一个进程用close函数关闭一个fd时,close实际上做了两个动作,让fd与pipe的pageref都减一,因此两个fd与pipe的pageref变成1,0,1或者0,1,1,我们通过判断某个fd的pageref与pipe的pageref是否相等就可以知道另一个fd是否关闭了。 47 | 48 |  但是这种pageref判断的方法又引起了竞争的问题,在某些特殊情况下,不同的unmap顺序可能导致恰好出现pageref(fd)与pageref(pipe)相等的情况,这种情况就需要调换unmap或者map的顺序,让pageref(fd)与pageref(pipe)的情况不会错误地出现,以此来避免竞争产生的问题。 49 | 50 | * shell 51 | 52 |  shell主要的难点在于runcmd,由于runcmd大部分都补全了,只是pipe相关的内容缺失,因此可以说shell的主要难点还是在pipe的形成。但是由于shell处的注释写得非常详细,因此这个pipe部分也很好填写。简而言之,遇到```|```符号则说明我们需要用父子进程的pipe来完成命令。如果是子进程,我们则需要将管道的输出端重定向到子进程的输入端,而将父进程的输出端重定向到管道的输入端。 53 | 54 | #### 感想与体会 55 | 56 |  感觉Lab6实际上不是很难,虽然号称管道与shell但是做起来才发现实际上主要还是管道,理解了管道的一些概念之后就会很得心应手,不过由于很久没有做过lab了,因此我lab6也花了相当的一段时间。 57 | 58 |  lab6是本学期操作系统最后一个lab了,一路做下来,感觉每个lab都有自己不甚理解的地方,但是可能由于远程评测点手松,于是莫名其妙地过了。最大的体会是如果这个lab仅仅是过了但是没有解决隐患,那么留到下一个lab的将会是各种debug。 59 | 60 |  整个学习操作系统实验课让我对一个操作系统各种功能的最基本的实现有了一定的了解,或许这在以后能派上用场。 -------------------------------------------------------------------------------- /实验报告/OSLAB6/Lab6实验报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB6/Lab6实验报告.pdf -------------------------------------------------------------------------------- /实验报告/OSLAB6/OS答辩.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB6/OS答辩.pptx -------------------------------------------------------------------------------- /实验报告/OSLAB6/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 | static void 82 | pgfault(u_int va) 83 | { 84 | u_int *tmp; 85 | //writef("fork.c:pgfault():\t va:%x\n",va); 86 | 87 | //map the new page at a temporary place 88 | tmp=UXSTACKTOP-2*BY2PG; 89 | va = ROUNDDOWN(va,BY2PG); 90 | if (!((*vpt)[VPN(va)] & PTE_COW)) { 91 | user_panic("no COW\n"); 92 | } 93 | if (syscall_mem_alloc(0,tmp,PTE_V|PTE_R)) { 94 | user_panic("syscall_mem_alloc error!\n"); 95 | } 96 | //copy the content 97 | user_bcopy((void*)va,tmp,BY2PG); 98 | //map the page on the appropriate place 99 | if (syscall_mem_map(0,tmp,0,va,PTE_V|PTE_R)!=0) { 100 | user_panic("syscall_mem_map error!\n"); 101 | } 102 | //unmap the temporary place 103 | if (syscall_mem_unmap(0,tmp)!=0) { 104 | user_panic("syscall_mem_unmap error!\n"); 105 | } 106 | } 107 | 108 | /* Overview: 109 | * Map our virtual page `pn` (address pn*BY2PG) into the target `envid` 110 | * at the same virtual address. 111 | * 112 | * Post-Condition: 113 | * if the page is writable or copy-on-write, the new mapping must be 114 | * created copy on write and then our mapping must be marked 115 | * copy on write as well. In another word, both of the new mapping and 116 | * our mapping should be copy-on-write if the page is writable or 117 | * copy-on-write. 118 | * 119 | * Hint: 120 | * PTE_LIBRARY indicates that the page is shared between processes. 121 | * A page with PTE_LIBRARY may have PTE_R at the same time. You 122 | * should process it correctly. 123 | */ 124 | static void 125 | duppage(u_int envid, u_int pn) 126 | { 127 | /* Note: 128 | * I am afraid I have some bad news for you. There is a ridiculous, 129 | * annoying and awful bug here. I could find another more adjectives 130 | * to qualify it, but you have to reproduce it to understand 131 | * how disturbing it is. 132 | * To reproduce this bug, you should follow the steps bellow: 133 | * 1. uncomment the statement "writef("");" bellow. 134 | * 2. make clean && make 135 | * 3. lauch Gxemul and check the result. 136 | * 4. you can add serveral `writef("");` and repeat step2~3. 137 | * Then, you will find that additional `writef("");` may lead to 138 | * a kernel panic. Interestingly, some students, who faced a strange 139 | * kernel panic problem, found that adding a `writef("");` could solve 140 | * the problem. 141 | * Unfortunately, we cannot find the code which leads to this bug, 142 | * although we have debugged it for serveral weeks. If you face this 143 | * bug, we would like to say "Good luck. God bless." 144 | */ 145 | // writef(""); 146 | //u_int addr; 147 | //u_int perm; 148 | 149 | // user_panic("duppage not implemented"); 150 | } 151 | 152 | /* Overview: 153 | * User-level fork. Create a child and then copy our address space 154 | * and page fault handler setup to the child. 155 | * 156 | * Hint: use vpd, vpt, and duppage. 157 | * Hint: remember to fix "env" in the child process! 158 | * Note: `set_pgfault_handler`(user/pgfault.c) is different from 159 | * `syscall_set_pgfault_handler`. 160 | */ 161 | extern void __asm_pgfault_handler(void); 162 | int 163 | fork(void) 164 | { 165 | // Your code here. 166 | u_int newenvid; 167 | extern struct Env *envs; 168 | extern struct Env *env; 169 | u_int i; 170 | //The parent installs pgfault using set_pgfault_handler 171 | //必须先设置pgfault 172 | set_pgfault_handler(pgfault); 173 | //然后才能调用syscall_env_alloc,否则会在异常中无法自拔 174 | newenvid = syscall_env_alloc(1); 175 | if (newenvid==0) { 176 | env=&(envs[ENVX(syscall_getenvid())]); 177 | } else { 178 | syscall_mem_alloc(newenvid, UXSTACKTOP - BY2PG, PTE_V|PTE_R|PTE_LIBRARY); 179 | syscall_set_pgfault_handler(newenvid, __asm_pgfault_handler, UXSTACKTOP); 180 | syscall_set_env_status(newenvid,ENV_RUNNABLE); 181 | } 182 | 183 | //alloc a new alloc 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 | -------------------------------------------------------------------------------- /实验报告/OSLAB6/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 | /////////////////////////////////////////////////////head 10 | extern void umain(); 11 | extern void libmain(); 12 | extern void exit(); 13 | 14 | extern struct Env *env; 15 | 16 | 17 | #define USED(x) (void)(x) 18 | //////////////////////////////////////////////////////printf 19 | #include 20 | #define LP_MAX_BUF 80 21 | 22 | void user_lp_Print(void (*output)(void *, char *, int), 23 | void * arg, 24 | char *fmt, 25 | va_list ap); 26 | 27 | void writef(char *fmt, ...); 28 | 29 | void _user_panic(const char *, int, const char *, ...) 30 | __attribute__((noreturn)); 31 | 32 | #define user_panic(...) _user_panic(__FILE__, __LINE__, __VA_ARGS__) 33 | 34 | 35 | /////////////////////////////////////////////////////fork spawn 36 | int spawn(char *prog, char **argv); 37 | int fork(void); 38 | 39 | void user_bcopy(const void *src, void *dst, size_t len); 40 | void user_bzero(void *v, u_int n); 41 | //////////////////////////////////////////////////syscall_lib 42 | void syscall_putchar(char ch); 43 | u_int syscall_getenvid(void); 44 | void syscall_yield(void); 45 | void syscall_env_destroy(u_int envid); 46 | int syscall_set_pgfault_handler(u_int envid, u_int func, u_int xstacktop); 47 | int syscall_mem_alloc(u_int envid, u_int va, u_int perm); 48 | int syscall_mem_map(u_int srcid, u_int srcva, u_int dstid, u_int dstva, u_int perm); 49 | int syscall_mem_unmap(u_int envid, u_int va); 50 | int syscall_env_alloc(int iffork); 51 | int syscall_set_env_status(u_int envid, u_int status); 52 | int syscall_set_trapframe(u_int envid, struct Trapframe *tf); 53 | void syscall_panic(char *msg); 54 | 55 | // ipc.c 56 | void ipc_send(u_int whom, u_int val, u_int srcva, u_int perm); 57 | u_int ipc_recv(u_int *whom, u_int dstva, u_int *perm); 58 | 59 | // pageref.c 60 | int pageref(void*); 61 | 62 | // fsipc.c 63 | int fsipc_open(const char*, u_int, struct Fd*); 64 | int fsipc_map(u_int, u_int, u_int); 65 | int fsipc_set_size(u_int, u_int); 66 | int fsipc_close(u_int); 67 | int fsipc_dirty(u_int, u_int); 68 | int fsipc_remove(const char*); 69 | int fsipc_sync(void); 70 | int fsipc_incref(u_int); 71 | 72 | // fd.c 73 | int close(int fd); 74 | int read(int fd, void *buf, u_int nbytes); 75 | int write(int fd, const void *buf, u_int nbytes); 76 | int seek(int fd, u_int offset); 77 | void close_all(void); 78 | int readn(int fd, void *buf, u_int nbytes); 79 | int dup(int oldfd, int newfd); 80 | int fstat(int fdnum, struct Stat *stat); 81 | int stat(const char *path, struct Stat*); 82 | 83 | // file.c 84 | int open(const char *path, int mode); 85 | int read_map(int fd, u_int offset, void **blk); 86 | int delete(const char *path); 87 | int ftruncate(int fd, u_int size); 88 | int sync(void); 89 | 90 | #define user_assert(x) \ 91 | do { if (!(x)) user_panic("assertion failed: %s", #x); } while (0) 92 | 93 | /* File open modes */ 94 | #define O_RDONLY 0x0000 /* open for reading only */ 95 | #define O_WRONLY 0x0001 /* open for writing only */ 96 | #define O_RDWR 0x0002 /* open for reading and writing */ 97 | #define O_ACCMODE 0x0003 /* mask for above modes */ 98 | 99 | #define O_CREAT 0x0100 /* create if nonexistent */ 100 | #define O_TRUNC 0x0200 /* truncate to zero length */ 101 | #define O_EXCL 0x0400 /* error if already exists */ 102 | #define O_MKDIR 0x0800 /* create directory, not regular file */ 103 | 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /实验报告/OSLAB6/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 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 | void 27 | syscall_env_destroy(u_int envid) 28 | { 29 | msyscall(SYS_env_destroy,envid,0,0,0,0); 30 | } 31 | int 32 | syscall_set_pgfault_handler(u_int envid, u_int func, u_int xstacktop) 33 | { 34 | return msyscall(SYS_set_pgfault_handler,envid,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 syscall_env_alloc(int iffork) 56 | { 57 | 58 | int a= msyscall(SYS_env_alloc,iffork,0,0,0,0); 59 | return a; 60 | } 61 | 62 | int 63 | syscall_set_env_status(u_int envid, u_int status) 64 | { 65 | return msyscall(SYS_set_env_status,envid,status,0,0,0); 66 | } 67 | 68 | int 69 | syscall_set_trapframe(u_int envid, struct Trapframe *tf) 70 | { 71 | return msyscall(SYS_set_trapframe,envid,tf,0,0,0); 72 | } 73 | 74 | void 75 | syscall_panic(char *msg) 76 | { 77 | msyscall(SYS_panic,msg,0,0,0,0); 78 | } 79 | 80 | int 81 | syscall_ipc_can_send(u_int envid, u_int value, u_int srcva, u_int perm) 82 | { 83 | return msyscall(SYS_ipc_can_send, envid, value, srcva, perm, 0); 84 | } 85 | 86 | void 87 | syscall_ipc_recv(u_int dstva) 88 | { 89 | msyscall(SYS_ipc_recv, dstva, 0, 0, 0, 0); 90 | } 91 | 92 | int 93 | syscall_cgetc() 94 | { 95 | msyscall(SYS_cgetc,0,0,0,0,0); 96 | } 97 | -------------------------------------------------------------------------------- /实验报告/OSLAB6/实验难点.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JamesDYX/BUAA_OS_Lab/ca050b4a18a643017892deb29ca2fe58ff75dc36/实验报告/OSLAB6/实验难点.png --------------------------------------------------------------------------------