From 3b78acb2cb44d7b2fa53eccbd06dc40d1b9feb73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E9=80=82=E4=B9=8B?= Date: Wed, 28 Mar 2018 20:02:05 +0800 Subject: [PATCH] uCore is migrated to https://github.com/roastduck/ucore-thumips --- ucore-thumips/.gdbinit | 6 - ucore-thumips/.gitignore | 20 - ucore-thumips/Makefile | 200 --- ucore-thumips/Makefile.gcc | 112 -- ucore-thumips/Makefile.thu | 112 -- ucore-thumips/README.md | 2 - ucore-thumips/TODO | 20 - ucore-thumips/boot/bootasm.S | 106 -- ucore-thumips/check_delay_slot.py | 34 - ucore-thumips/debug | 6 - ucore-thumips/disasm.py | 28 - ucore-thumips/doc/book.bib | 78 -- ucore-thumips/doc/reg-sr.png | Bin 17986 -> 0 bytes ucore-thumips/doc/ucore_thumips.tex | 480 ------- ucore-thumips/flash.img | 1 - ucore-thumips/kern/debug/assert.h | 27 - ucore-thumips/kern/debug/kdebug.c | 88 -- ucore-thumips/kern/debug/kdebug.h | 13 - ucore-thumips/kern/debug/monitor.c | 126 -- ucore-thumips/kern/debug/monitor.h | 12 - ucore-thumips/kern/debug/panic.c | 49 - ucore-thumips/kern/driver/clock.c | 35 - ucore-thumips/kern/driver/clock.h | 11 - ucore-thumips/kern/driver/console.c | 215 --- ucore-thumips/kern/driver/console.h | 10 - ucore-thumips/kern/driver/ide.c | 67 - ucore-thumips/kern/driver/ide.h | 30 - ucore-thumips/kern/driver/intr.c | 26 - ucore-thumips/kern/driver/intr.h | 31 - ucore-thumips/kern/driver/picirq.c | 33 - ucore-thumips/kern/driver/picirq.h | 11 - ucore-thumips/kern/driver/ramdisk.c | 84 -- ucore-thumips/kern/driver/ramdisk.h | 31 - ucore-thumips/kern/driver/vga.c | 89 -- ucore-thumips/kern/driver/vga.h | 10 - ucore-thumips/kern/fs/devs/dev.c | 121 -- ucore-thumips/kern/fs/devs/dev.h | 27 - ucore-thumips/kern/fs/devs/dev_disk0.c | 144 -- ucore-thumips/kern/fs/devs/dev_stdin.c | 126 -- ucore-thumips/kern/fs/devs/dev_stdout.c | 64 - ucore-thumips/kern/fs/file.c | 338 ----- ucore-thumips/kern/fs/file.h | 60 - ucore-thumips/kern/fs/fs.c | 99 -- ucore-thumips/kern/fs/fs.h | 56 - ucore-thumips/kern/fs/iobuf.c | 57 - ucore-thumips/kern/fs/iobuf.h | 21 - ucore-thumips/kern/fs/sfs/bitmap.c | 108 -- ucore-thumips/kern/fs/sfs/bitmap.h | 16 - ucore-thumips/kern/fs/sfs/sfs.c | 13 - ucore-thumips/kern/fs/sfs/sfs.h | 142 -- ucore-thumips/kern/fs/sfs/sfs_fs.c | 215 --- ucore-thumips/kern/fs/sfs/sfs_inode.c | 858 ------------ ucore-thumips/kern/fs/sfs/sfs_io.c | 107 -- ucore-thumips/kern/fs/sfs/sfs_lock.c | 34 - ucore-thumips/kern/fs/sysfile.c | 303 ---- ucore-thumips/kern/fs/sysfile.h | 28 - ucore-thumips/kern/fs/vfs/inode.c | 110 -- ucore-thumips/kern/fs/vfs/inode.h | 248 ---- ucore-thumips/kern/fs/vfs/vfs.c | 91 -- ucore-thumips/kern/fs/vfs/vfs.h | 191 --- ucore-thumips/kern/fs/vfs/vfsdev.c | 264 ---- ucore-thumips/kern/fs/vfs/vfsfile.c | 102 -- ucore-thumips/kern/fs/vfs/vfslookup.c | 89 -- ucore-thumips/kern/fs/vfs/vfspath.c | 103 -- ucore-thumips/kern/include/asm/mipsregs.h | 1368 ------------------- ucore-thumips/kern/include/asm/regdef.h | 55 - ucore-thumips/kern/include/atomic.h | 298 ---- ucore-thumips/kern/include/defs.h | 88 -- ucore-thumips/kern/include/dirent.h | 13 - ucore-thumips/kern/include/elf.h | 93 -- ucore-thumips/kern/include/error.h | 33 - ucore-thumips/kern/include/glue_pgmap.h | 162 --- ucore-thumips/kern/include/list.h | 153 --- ucore-thumips/kern/include/mips_vm.h | 76 -- ucore-thumips/kern/include/stat.h | 27 - ucore-thumips/kern/include/stdarg.h | 12 - ucore-thumips/kern/include/thumips.h | 89 -- ucore-thumips/kern/include/thumips_tlb.h | 75 - ucore-thumips/kern/include/unistd.h | 68 - ucore-thumips/kern/init/entry.S | 89 -- ucore-thumips/kern/init/init.c | 61 - ucore-thumips/kern/libs/hash.c | 18 - ucore-thumips/kern/libs/printfmt.c | 360 ----- ucore-thumips/kern/libs/rand.c | 25 - ucore-thumips/kern/libs/rb_tree.c | 530 ------- ucore-thumips/kern/libs/rb_tree.h | 32 - ucore-thumips/kern/libs/readline.c | 50 - ucore-thumips/kern/libs/stdio.c | 134 -- ucore-thumips/kern/libs/stdio.h | 24 - ucore-thumips/kern/libs/stdlib.h | 17 - ucore-thumips/kern/libs/string.c | 392 ------ ucore-thumips/kern/libs/string.h | 27 - ucore-thumips/kern/mm/buddy_pmm.c | 325 ----- ucore-thumips/kern/mm/buddy_pmm.h | 9 - ucore-thumips/kern/mm/kmalloc.c | 659 --------- ucore-thumips/kern/mm/kmalloc.h | 18 - ucore-thumips/kern/mm/memlayout.h | 99 -- ucore-thumips/kern/mm/mmu.h | 69 - ucore-thumips/kern/mm/pmm.c | 576 -------- ucore-thumips/kern/mm/pmm.h | 149 -- ucore-thumips/kern/mm/thumips_tlb.c | 39 - ucore-thumips/kern/mm/vmm.c | 486 ------- ucore-thumips/kern/mm/vmm.h | 109 -- ucore-thumips/kern/process/entry.S | 16 - ucore-thumips/kern/process/proc.c | 1049 -------------- ucore-thumips/kern/process/proc.h | 104 -- ucore-thumips/kern/process/switch.S | 59 - ucore-thumips/kern/schedule/default_sched.c | 58 - ucore-thumips/kern/schedule/default_sched.h | 9 - ucore-thumips/kern/schedule/sched.c | 176 --- ucore-thumips/kern/schedule/sched.h | 67 - ucore-thumips/kern/sync/sem.c | 77 -- ucore-thumips/kern/sync/sem.h | 19 - ucore-thumips/kern/sync/sync.h | 41 - ucore-thumips/kern/sync/wait.c | 122 -- ucore-thumips/kern/sync/wait.h | 48 - ucore-thumips/kern/syscall/syscall.c | 209 --- ucore-thumips/kern/syscall/syscall.h | 7 - ucore-thumips/kern/trap/exception.S | 266 ---- ucore-thumips/kern/trap/mips_trapframe.h | 77 -- ucore-thumips/kern/trap/trap.c | 306 ----- ucore-thumips/kern/trap/trap.h | 12 - ucore-thumips/kern/trap/vectors.S | 159 --- ucore-thumips/run | 4 - ucore-thumips/thumips-cc | 24 - ucore-thumips/thumips_insn.txt | 44 - ucore-thumips/tools/initrd_piggy.S.in | 12 - ucore-thumips/tools/kernel.ld | 68 - ucore-thumips/tools/mksfs.c | 582 -------- ucore-thumips/tools/piggy.S.in | 12 - ucore-thumips/user/_archive/test.txt | 1 - ucore-thumips/user/badarg.c | 22 - ucore-thumips/user/badsegment.c | 11 - ucore-thumips/user/cat.c | 38 - ucore-thumips/user/divzero.c | 11 - ucore-thumips/user/echo.c | 23 - ucore-thumips/user/exit.c | 34 - ucore-thumips/user/faultread.c | 9 - ucore-thumips/user/faultreadkernel.c | 9 - ucore-thumips/user/forktest.c | 34 - ucore-thumips/user/forktree.c | 37 - ucore-thumips/user/hello.c | 11 - ucore-thumips/user/libs/dir.c | 46 - ucore-thumips/user/libs/dir.h | 19 - ucore-thumips/user/libs/file.c | 68 - ucore-thumips/user/libs/file.h | 23 - ucore-thumips/user/libs/initcode.S | 10 - ucore-thumips/user/libs/lock.h | 62 - ucore-thumips/user/libs/panic.c | 28 - ucore-thumips/user/libs/printfmt.c | 358 ----- ucore-thumips/user/libs/stdio.c | 131 -- ucore-thumips/user/libs/stdio.h | 22 - ucore-thumips/user/libs/string.c | 369 ----- ucore-thumips/user/libs/string.h | 25 - ucore-thumips/user/libs/syscall.c | 143 -- ucore-thumips/user/libs/syscall.h | 33 - ucore-thumips/user/libs/ulib.c | 82 -- ucore-thumips/user/libs/ulib.h | 49 - ucore-thumips/user/libs/umain.c | 34 - ucore-thumips/user/libs/user.ld | 57 - ucore-thumips/user/ls.c | 118 -- ucore-thumips/user/pgdir.c | 11 - ucore-thumips/user/pwd.c | 18 - ucore-thumips/user/sh.c | 255 ---- ucore-thumips/user/sleep.c | 28 - ucore-thumips/user/softint.c | 9 - ucore-thumips/user/spin.c | 29 - ucore-thumips/user/testbss.c | 33 - ucore-thumips/user/waitkill.c | 59 - ucore-thumips/user/yield.c | 16 - 170 files changed, 19247 deletions(-) delete mode 100644 ucore-thumips/.gdbinit delete mode 100644 ucore-thumips/.gitignore delete mode 100644 ucore-thumips/Makefile delete mode 100644 ucore-thumips/Makefile.gcc delete mode 100644 ucore-thumips/Makefile.thu delete mode 100644 ucore-thumips/README.md delete mode 100644 ucore-thumips/TODO delete mode 100644 ucore-thumips/boot/bootasm.S delete mode 100644 ucore-thumips/check_delay_slot.py delete mode 100644 ucore-thumips/debug delete mode 100644 ucore-thumips/disasm.py delete mode 100644 ucore-thumips/doc/book.bib delete mode 100644 ucore-thumips/doc/reg-sr.png delete mode 100644 ucore-thumips/doc/ucore_thumips.tex delete mode 120000 ucore-thumips/flash.img delete mode 100644 ucore-thumips/kern/debug/assert.h delete mode 100644 ucore-thumips/kern/debug/kdebug.c delete mode 100644 ucore-thumips/kern/debug/kdebug.h delete mode 100644 ucore-thumips/kern/debug/monitor.c delete mode 100644 ucore-thumips/kern/debug/monitor.h delete mode 100644 ucore-thumips/kern/debug/panic.c delete mode 100644 ucore-thumips/kern/driver/clock.c delete mode 100644 ucore-thumips/kern/driver/clock.h delete mode 100644 ucore-thumips/kern/driver/console.c delete mode 100644 ucore-thumips/kern/driver/console.h delete mode 100644 ucore-thumips/kern/driver/ide.c delete mode 100644 ucore-thumips/kern/driver/ide.h delete mode 100644 ucore-thumips/kern/driver/intr.c delete mode 100644 ucore-thumips/kern/driver/intr.h delete mode 100644 ucore-thumips/kern/driver/picirq.c delete mode 100644 ucore-thumips/kern/driver/picirq.h delete mode 100644 ucore-thumips/kern/driver/ramdisk.c delete mode 100644 ucore-thumips/kern/driver/ramdisk.h delete mode 100644 ucore-thumips/kern/driver/vga.c delete mode 100644 ucore-thumips/kern/driver/vga.h delete mode 100644 ucore-thumips/kern/fs/devs/dev.c delete mode 100644 ucore-thumips/kern/fs/devs/dev.h delete mode 100644 ucore-thumips/kern/fs/devs/dev_disk0.c delete mode 100644 ucore-thumips/kern/fs/devs/dev_stdin.c delete mode 100644 ucore-thumips/kern/fs/devs/dev_stdout.c delete mode 100644 ucore-thumips/kern/fs/file.c delete mode 100644 ucore-thumips/kern/fs/file.h delete mode 100644 ucore-thumips/kern/fs/fs.c delete mode 100644 ucore-thumips/kern/fs/fs.h delete mode 100644 ucore-thumips/kern/fs/iobuf.c delete mode 100644 ucore-thumips/kern/fs/iobuf.h delete mode 100644 ucore-thumips/kern/fs/sfs/bitmap.c delete mode 100644 ucore-thumips/kern/fs/sfs/bitmap.h delete mode 100644 ucore-thumips/kern/fs/sfs/sfs.c delete mode 100644 ucore-thumips/kern/fs/sfs/sfs.h delete mode 100644 ucore-thumips/kern/fs/sfs/sfs_fs.c delete mode 100644 ucore-thumips/kern/fs/sfs/sfs_inode.c delete mode 100644 ucore-thumips/kern/fs/sfs/sfs_io.c delete mode 100644 ucore-thumips/kern/fs/sfs/sfs_lock.c delete mode 100644 ucore-thumips/kern/fs/sysfile.c delete mode 100644 ucore-thumips/kern/fs/sysfile.h delete mode 100644 ucore-thumips/kern/fs/vfs/inode.c delete mode 100644 ucore-thumips/kern/fs/vfs/inode.h delete mode 100644 ucore-thumips/kern/fs/vfs/vfs.c delete mode 100644 ucore-thumips/kern/fs/vfs/vfs.h delete mode 100644 ucore-thumips/kern/fs/vfs/vfsdev.c delete mode 100644 ucore-thumips/kern/fs/vfs/vfsfile.c delete mode 100644 ucore-thumips/kern/fs/vfs/vfslookup.c delete mode 100644 ucore-thumips/kern/fs/vfs/vfspath.c delete mode 100644 ucore-thumips/kern/include/asm/mipsregs.h delete mode 100644 ucore-thumips/kern/include/asm/regdef.h delete mode 100644 ucore-thumips/kern/include/atomic.h delete mode 100644 ucore-thumips/kern/include/defs.h delete mode 100644 ucore-thumips/kern/include/dirent.h delete mode 100644 ucore-thumips/kern/include/elf.h delete mode 100644 ucore-thumips/kern/include/error.h delete mode 100644 ucore-thumips/kern/include/glue_pgmap.h delete mode 100644 ucore-thumips/kern/include/list.h delete mode 100644 ucore-thumips/kern/include/mips_vm.h delete mode 100644 ucore-thumips/kern/include/stat.h delete mode 100644 ucore-thumips/kern/include/stdarg.h delete mode 100644 ucore-thumips/kern/include/thumips.h delete mode 100644 ucore-thumips/kern/include/thumips_tlb.h delete mode 100644 ucore-thumips/kern/include/unistd.h delete mode 100644 ucore-thumips/kern/init/entry.S delete mode 100644 ucore-thumips/kern/init/init.c delete mode 100644 ucore-thumips/kern/libs/hash.c delete mode 100644 ucore-thumips/kern/libs/printfmt.c delete mode 100644 ucore-thumips/kern/libs/rand.c delete mode 100644 ucore-thumips/kern/libs/rb_tree.c delete mode 100644 ucore-thumips/kern/libs/rb_tree.h delete mode 100644 ucore-thumips/kern/libs/readline.c delete mode 100644 ucore-thumips/kern/libs/stdio.c delete mode 100644 ucore-thumips/kern/libs/stdio.h delete mode 100644 ucore-thumips/kern/libs/stdlib.h delete mode 100644 ucore-thumips/kern/libs/string.c delete mode 100644 ucore-thumips/kern/libs/string.h delete mode 100644 ucore-thumips/kern/mm/buddy_pmm.c delete mode 100644 ucore-thumips/kern/mm/buddy_pmm.h delete mode 100644 ucore-thumips/kern/mm/kmalloc.c delete mode 100644 ucore-thumips/kern/mm/kmalloc.h delete mode 100644 ucore-thumips/kern/mm/memlayout.h delete mode 100644 ucore-thumips/kern/mm/mmu.h delete mode 100644 ucore-thumips/kern/mm/pmm.c delete mode 100644 ucore-thumips/kern/mm/pmm.h delete mode 100644 ucore-thumips/kern/mm/thumips_tlb.c delete mode 100644 ucore-thumips/kern/mm/vmm.c delete mode 100644 ucore-thumips/kern/mm/vmm.h delete mode 100644 ucore-thumips/kern/process/entry.S delete mode 100644 ucore-thumips/kern/process/proc.c delete mode 100644 ucore-thumips/kern/process/proc.h delete mode 100644 ucore-thumips/kern/process/switch.S delete mode 100644 ucore-thumips/kern/schedule/default_sched.c delete mode 100644 ucore-thumips/kern/schedule/default_sched.h delete mode 100644 ucore-thumips/kern/schedule/sched.c delete mode 100644 ucore-thumips/kern/schedule/sched.h delete mode 100644 ucore-thumips/kern/sync/sem.c delete mode 100644 ucore-thumips/kern/sync/sem.h delete mode 100644 ucore-thumips/kern/sync/sync.h delete mode 100644 ucore-thumips/kern/sync/wait.c delete mode 100644 ucore-thumips/kern/sync/wait.h delete mode 100644 ucore-thumips/kern/syscall/syscall.c delete mode 100644 ucore-thumips/kern/syscall/syscall.h delete mode 100644 ucore-thumips/kern/trap/exception.S delete mode 100644 ucore-thumips/kern/trap/mips_trapframe.h delete mode 100644 ucore-thumips/kern/trap/trap.c delete mode 100644 ucore-thumips/kern/trap/trap.h delete mode 100644 ucore-thumips/kern/trap/vectors.S delete mode 100644 ucore-thumips/run delete mode 100644 ucore-thumips/thumips-cc delete mode 100644 ucore-thumips/thumips_insn.txt delete mode 100644 ucore-thumips/tools/initrd_piggy.S.in delete mode 100644 ucore-thumips/tools/kernel.ld delete mode 100644 ucore-thumips/tools/mksfs.c delete mode 100644 ucore-thumips/tools/piggy.S.in delete mode 100644 ucore-thumips/user/_archive/test.txt delete mode 100644 ucore-thumips/user/badarg.c delete mode 100644 ucore-thumips/user/badsegment.c delete mode 100644 ucore-thumips/user/cat.c delete mode 100644 ucore-thumips/user/divzero.c delete mode 100644 ucore-thumips/user/echo.c delete mode 100644 ucore-thumips/user/exit.c delete mode 100644 ucore-thumips/user/faultread.c delete mode 100644 ucore-thumips/user/faultreadkernel.c delete mode 100644 ucore-thumips/user/forktest.c delete mode 100644 ucore-thumips/user/forktree.c delete mode 100644 ucore-thumips/user/hello.c delete mode 100644 ucore-thumips/user/libs/dir.c delete mode 100644 ucore-thumips/user/libs/dir.h delete mode 100644 ucore-thumips/user/libs/file.c delete mode 100644 ucore-thumips/user/libs/file.h delete mode 100644 ucore-thumips/user/libs/initcode.S delete mode 100644 ucore-thumips/user/libs/lock.h delete mode 100644 ucore-thumips/user/libs/panic.c delete mode 100644 ucore-thumips/user/libs/printfmt.c delete mode 100644 ucore-thumips/user/libs/stdio.c delete mode 100644 ucore-thumips/user/libs/stdio.h delete mode 100644 ucore-thumips/user/libs/string.c delete mode 100644 ucore-thumips/user/libs/string.h delete mode 100644 ucore-thumips/user/libs/syscall.c delete mode 100644 ucore-thumips/user/libs/syscall.h delete mode 100644 ucore-thumips/user/libs/ulib.c delete mode 100644 ucore-thumips/user/libs/ulib.h delete mode 100644 ucore-thumips/user/libs/umain.c delete mode 100644 ucore-thumips/user/libs/user.ld delete mode 100644 ucore-thumips/user/ls.c delete mode 100644 ucore-thumips/user/pgdir.c delete mode 100644 ucore-thumips/user/pwd.c delete mode 100644 ucore-thumips/user/sh.c delete mode 100644 ucore-thumips/user/sleep.c delete mode 100644 ucore-thumips/user/softint.c delete mode 100644 ucore-thumips/user/spin.c delete mode 100644 ucore-thumips/user/testbss.c delete mode 100644 ucore-thumips/user/waitkill.c delete mode 100644 ucore-thumips/user/yield.c diff --git a/ucore-thumips/.gdbinit b/ucore-thumips/.gdbinit deleted file mode 100644 index 0da8b6d..0000000 --- a/ucore-thumips/.gdbinit +++ /dev/null @@ -1,6 +0,0 @@ -set endian little -set mipsfpu none -target remote 127.0.0.1:1234 -file obj/ucore-kernel-initrd -#file boot/loader - diff --git a/ucore-thumips/.gitignore b/ucore-thumips/.gitignore deleted file mode 100644 index 230c241..0000000 --- a/ucore-thumips/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -/obj/ucore-kernel-initrd -/boot/loader -/boot/loader.bin -/boot/loader.o -/dep -/obj/debug/ -/obj/driver/ -/obj/fs/ -/obj/init/ -/obj/libs/ -/obj/mm/ -/obj/process/ -/obj/schedule/ -/obj/sync/ -/obj/syscall/ -/obj/trap/ -/obj/ucore.bin -/obj/ucore.ub -/obj/user/ -/tools/mksfs diff --git a/ucore-thumips/Makefile b/ucore-thumips/Makefile deleted file mode 100644 index c9a6976..0000000 --- a/ucore-thumips/Makefile +++ /dev/null @@ -1,200 +0,0 @@ -EMPTY := -SPACE := $(EMPTY) $(EMPTY) -SLASH := / - -ON_FPGA :=y - -V := @ - -GCCPREFIX ?= mips-sde-elf- - -# eliminate default suffix rules -.SUFFIXES: .c .S .h - -# define compiler and flags - -HOSTCC := gcc -HOSTCFLAGS := -g -Wall -O2 - -GDB := $(GCCPREFIX)gdb - -THUMIPSCC := ./thumips-cc -CLANG := clang -CC :=$(GCCPREFIX)gcc -CFLAGS := -fno-builtin -nostdlib -nostdinc -g -EL -G0 -fno-delayed-branch -Wa,-O0 -CTYPE := c S - -LD := $(GCCPREFIX)ld -AS := $(GCCPREFIX)as -EL -g -mips32 -AR := $(GCCPREFIX)ar -LDFLAGS += -nostdlib - -OBJCOPY := $(GCCPREFIX)objcopy -OBJDUMP := $(GCCPREFIX)objdump - -COPY := cp -MKDIR := mkdir -p -MV := mv -RM := rm -f -AWK := awk -SED := sed -SH := sh -TR := tr -TOUCH := touch -c - -TAR := tar -ZIP := gzip - -OBJDIR := obj -BINDIR := bin -SRCDIR := kern -DEPDIR := dep - - -MODULES := init libs debug driver trap mm sync process schedule syscall fs fs/vfs fs/sfs fs/devs -SRC_DIR := $(addprefix $(SRCDIR)/,$(MODULES)) -BUILD_DIR := $(addprefix $(OBJDIR)/,$(MODULES)) -DEP_DIR := $(addprefix $(DEPDIR)/,$(MODULES)) -VPATH += $(SRC_DIR) - -SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) -OBJ := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SRC)) -ASMSRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.S)) -OBJ += $(patsubst $(SRCDIR)/%.S, $(OBJDIR)/%.o, $(ASMSRC)) -INCLUDES := $(addprefix -I,$(SRC_DIR)) -INCLUDES += -I$(SRCDIR)/include - -ifeq ($(ON_FPGA), y) -USER_APPLIST:= pwd cat sh ls forktest yield hello faultreadkernel faultread badarg pgdir exit sleep -INITRD_BLOCK_CNT:=4000 -FPGA_LD_FLAGS += -S -MACH_DEF := -DMACH_FPGA -else -USER_APPLIST:= pwd cat sh ls forktest yield hello faultreadkernel faultread badarg waitkill pgdir exit sleep -# 2M -INITRD_BLOCK_CNT:=4000 -MACH_DEF := -DMACH_QEMU -endif - -USER_SRCDIR := user -USER_OBJDIR := $(OBJDIR)/$(USER_SRCDIR) -USER_LIB_OBJDIR := $(USER_OBJDIR)/libs -USER_INCLUDE := -I$(USER_SRCDIR)/libs - -USER_APP_BINS:= $(addprefix $(USER_OBJDIR)/, $(USER_APPLIST)) - -USER_LIB_SRCDIR := $(USER_SRCDIR)/libs -USER_LIB_SRC := $(foreach sdir,$(USER_LIB_SRCDIR),$(wildcard $(sdir)/*.c)) -USER_LIB_OBJ := $(patsubst $(USER_LIB_SRCDIR)/%.c, $(USER_LIB_OBJDIR)/%.o, $(USER_LIB_SRC)) -USER_LIB_OBJ += $(USER_LIB_OBJDIR)/initcode.o -USER_LIB := $(USER_OBJDIR)/libuser.a - -BUILD_DIR += $(USER_LIB_OBJDIR) -BUILD_DIR += $(USER_OBJDIR) - - -DEPENDS := $(patsubst $(SRCDIR)/%.c, $(DEPDIR)/%.d, $(SRC)) - -MAKEDEPEND = $(CLANG) -M $(CFLAGS) $(INCLUDES) -o $(DEPDIR)/$*.d $< -#vpath %.c $(SRC_DIR) -#vpath %.S $(SRC_DIR) - -.PHONY: all checkdirs clean - -all: checkdirs boot/loader.bin obj/ucore-kernel-initrd obj/ucore.ub - -$(shell mkdir -p $(DEP_DIR)) - - -obj/ucore-kernel: $(OBJ) tools/kernel.ld - @echo LINK $@ - $(LD) -nostdlib -n -G 0 -static -T tools/kernel.ld $(OBJ) -o $@ - -obj/ucore-kernel-piggy: $(BUILD_DIR) $(OBJ) $(USER_APP_BINS) tools/kernel.ld - @echo LINK $@ - $(LD) -nostdlib -n -G 0 -static -T tools/kernel.ld $(OBJ) \ - $(addsuffix .piggy.o, $(USER_APP_BINS)) -o $@ - -$(DEPDIR)/%.d: $(SRCDIR)/%.c - @echo DEP $< - @set -e; rm -f $@; \ - $(CC) -MM -MT "$(OBJDIR)/$*.o $@" $(CFLAGS) $(INCLUDES) $< > $@; - -$(OBJDIR)/%.o: $(SRCDIR)/%.c - $(CC) -c -mips1 $(INCLUDES) $(CFLAGS) $(MACH_DEF) $< -o $@ - -$(OBJDIR)/%.o: $(SRCDIR)/%.S - $(CC) -mips32 -c -D__ASSEMBLY__ $(MACH_DEF) $(INCLUDES) -g -EL -G0 $< -o $@ - -checkdirs: $(BUILD_DIR) $(DEP_DIR) - -$(BUILD_DIR): - @mkdir -p $@ - -$(DEP_DIR): - @mkdir -p $@ - -clean: - -rm -rf $(BUILD_DIR) - -rm -rf $(DEPDIR) - -rm -rf boot/loader.o boot/loader boot/loader.bin - - -ifneq ($(MAKECMDGOALS),clean) --include $(DEPENDS) -endif - -#user lib - -$(USER_LIB): $(BUILD_DIR) $(USER_LIB_OBJ) - @echo "Building USERLIB" - $(AR) rcs $@ $(USER_LIB_OBJ) - -#user applications -define make-user-app -$1: $(BUILD_DIR) $(addsuffix .o,$1) $(USER_LIB) - @echo LINK $$@ - $(LD) $(FPGA_LD_FLAGS) -T $(USER_LIB_SRCDIR)/user.ld $(addsuffix .o,$1) $(USER_LIB) -o $$@ - $(SED) 's/$$$$FILE/$(notdir $1)/g' tools/piggy.S.in > $(USER_OBJDIR)/piggy.S - $(AS) $(USER_OBJDIR)/piggy.S -o $$@.piggy.o -endef - -$(foreach bdir,$(USER_APP_BINS),$(eval $(call make-user-app,$(bdir)))) - -$(USER_OBJDIR)/%.o: $(USER_SRCDIR)/%.c - $(CC) -c -mips1 $(USER_INCLUDE) -I$(SRCDIR)/include $(CFLAGS) $< -o $@ - -$(USER_OBJDIR)/%.o: $(USER_SRCDIR)/%.S - $(CC) -mips32 -c -D__ASSEMBLY__ $(USER_INCLUDE) -I$(SRCDIR)/include -g -EL -G0 $< -o $@ - - -# filesystem -TOOL_MKSFS := tools/mksfs -ROOTFS_DIR:= $(USER_OBJDIR)/rootfs -ROOTFS_IMG:= $(USER_OBJDIR)/initrd.img -$(TOOL_MKSFS): tools/mksfs.c - $(HOSTCC) $(HOSTCFLAGS) -o $@ $^ - -$(OBJDIR)/ucore-kernel-initrd: $(BUILD_DIR) $(TOOL_MKSFS) $(OBJ) $(USER_APP_BINS) tools/kernel.ld - rm -rf $(ROOTFS_DIR) $(ROOTFS_IMG) - mkdir $(ROOTFS_DIR) - cp $(USER_APP_BINS) $(ROOTFS_DIR) - cp -r $(USER_SRCDIR)/_archive/* $(ROOTFS_DIR)/ - dd if=/dev/zero of=$(ROOTFS_IMG) count=$(INITRD_BLOCK_CNT) - #touch $(ROOTFS_IMG) - $(TOOL_MKSFS) $(ROOTFS_IMG) $(ROOTFS_DIR) - $(SED) 's%_FILE_%$(ROOTFS_IMG)%g' tools/initrd_piggy.S.in > $(USER_OBJDIR)/initrd_piggy.S - $(AS) $(USER_OBJDIR)/initrd_piggy.S -o $(USER_OBJDIR)/initrd.img.o - @echo LINK $@ - $(LD) $(FPGA_LD_FLAGS) -nostdlib -n -G 0 -static -T tools/kernel.ld $(OBJ) \ - $(USER_OBJDIR)/initrd.img.o -o $@ - rm -rf $(ROOTFS_DIR) - -$(OBJDIR)/ucore.ub: $(OBJDIR)/ucore-kernel-initrd - $(OBJCOPY) -O binary -v $^ $(OBJDIR)/ucore.bin - mkimage -A mips -O u-boot -T kernel -C none -a 0x80000040 -e 0x80000040 -n ucore-thumips -d $(OBJDIR)/ucore.bin $@ - -boot/loader.bin: boot/bootasm.S - $(CC) $(CFLAGS) -g -c -o boot/loader.o $^ - $(LD) -EL -n -G0 -Ttext 0xbfc00000 -o boot/loader boot/loader.o - $(OBJCOPY) -O binary -j .text -S boot/loader $@ diff --git a/ucore-thumips/Makefile.gcc b/ucore-thumips/Makefile.gcc deleted file mode 100644 index 7b035d8..0000000 --- a/ucore-thumips/Makefile.gcc +++ /dev/null @@ -1,112 +0,0 @@ -PROJ := 5 -EMPTY := -SPACE := $(EMPTY) $(EMPTY) -SLASH := / - -V := @ - -GCCPREFIX:=mips-sde-elf- - -# eliminate default suffix rules -.SUFFIXES: .c .S .h - -# define compiler and flags - -HOSTCC := gcc -HOSTCFLAGS := -g -Wall -O2 - -GDB := $(GCCPREFIX)gdb - -THUMIPSCC := ./thumips-cc -CLANG := clang -#CC :=$(GCCPREFIX)gcc -CFLAGS := -fno-builtin -nostdlib -nostdinc -CTYPE := c S - -LD := $(GCCPREFIX)ld -AS := $(GCCPREFIX)as -EL -g -mips32 -LDFLAGS += -nostdlib - -OBJCOPY := $(GCCPREFIX)objcopy -OBJDUMP := $(GCCPREFIX)objdump - -COPY := cp -MKDIR := mkdir -p -MV := mv -RM := rm -f -AWK := awk -SED := sed -SH := sh -TR := tr -TOUCH := touch -c - -TAR := tar -ZIP := gzip - -OBJDIR := obj -BINDIR := bin -SRCDIR := kern -DEPDIR := dep - - -MODULES := init libs debug driver trap mm sync -SRC_DIR := $(addprefix $(SRCDIR)/,$(MODULES)) -BUILD_DIR := $(addprefix $(OBJDIR)/,$(MODULES)) -DEP_DIR := $(addprefix $(DEPDIR)/,$(MODULES)) -VPATH += $(SRC_DIR) - -SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) -OBJ := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SRC)) -ASMSRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.S)) -OBJ += $(patsubst $(SRCDIR)/%.S, $(OBJDIR)/%.o, $(ASMSRC)) -INCLUDES := $(addprefix -I,$(SRC_DIR)) -INCLUDES += -I$(SRCDIR)/include - -DEPENDS := $(patsubst $(SRCDIR)/%.c, $(DEPDIR)/%.d, $(SRC)) - -MAKEDEPEND = $(CLANG) -M $(CFLAGS) $(INCLUDES) -o $(DEPDIR)/$*.d $< -#vpath %.c $(SRC_DIR) -#vpath %.S $(SRC_DIR) - -.PHONY: all checkdirs clean - -all: checkdirs obj/ucore-kernel - -$(shell mkdir -p $(DEP_DIR)) - - -obj/ucore-kernel: $(OBJ) tools/kernel.ld - @echo LINK - $(LD) -nostdlib -n -G 0 -static -T tools/kernel.ld $(OBJ) -o $@ - -$(DEPDIR)/%.d: $(SRCDIR)/%.c - @echo DEP $< - @set -e; rm -f $@; \ - $(CLANG) -MM -MT "$(OBJDIR)/$*.o $@" $(CFLAGS) $(INCLUDES) $< > $@; - -$(OBJDIR)/%.o: $(SRCDIR)/%.c - /opt/CodeSourcery/Sourcery_CodeBench_Lite_for_MIPS_ELF/bin/mips-sde-elf-gcc -c -EL -G0 $(INCLUDES) $(CFLAGS) $< -o $@ - -$(OBJDIR)/%.o: $(SRCDIR)/%.S - $(CLANG) $(INCLUDES) -D__ASSEMBLY__ -E $< | $(AS) -o $@ - -checkdirs: $(BUILD_DIR) $(DEP_DIR) - -$(BUILD_DIR): - @mkdir -p $@ - -$(DEP_DIR): - @mkdir -p $@ - -clean: - -rm -rf $(BUILD_DIR) - -rm -rf $(DEPDIR) - - -ifneq ($(MAKECMDGOALS),clean) --include $(DEPENDS) -endif - - - - diff --git a/ucore-thumips/Makefile.thu b/ucore-thumips/Makefile.thu deleted file mode 100644 index d4db8d4..0000000 --- a/ucore-thumips/Makefile.thu +++ /dev/null @@ -1,112 +0,0 @@ -PROJ := 5 -EMPTY := -SPACE := $(EMPTY) $(EMPTY) -SLASH := / - -V := @ - -GCCPREFIX:=mips-sde-elf- - -# eliminate default suffix rules -.SUFFIXES: .c .S .h - -# define compiler and flags - -HOSTCC := gcc -HOSTCFLAGS := -g -Wall -O2 - -GDB := $(GCCPREFIX)gdb - -THUMIPSCC := ./thumips-cc -CLANG := clang -#CC :=$(GCCPREFIX)gcc -CFLAGS := -fno-builtin -nostdlib -nostdinc -CTYPE := c S - -LD := $(GCCPREFIX)ld -AS := $(GCCPREFIX)as -EL -g -mips32 -LDFLAGS += -nostdlib - -OBJCOPY := $(GCCPREFIX)objcopy -OBJDUMP := $(GCCPREFIX)objdump - -COPY := cp -MKDIR := mkdir -p -MV := mv -RM := rm -f -AWK := awk -SED := sed -SH := sh -TR := tr -TOUCH := touch -c - -TAR := tar -ZIP := gzip - -OBJDIR := obj -BINDIR := bin -SRCDIR := kern -DEPDIR := dep - - -MODULES := init libs debug driver trap mm sync -SRC_DIR := $(addprefix $(SRCDIR)/,$(MODULES)) -BUILD_DIR := $(addprefix $(OBJDIR)/,$(MODULES)) -DEP_DIR := $(addprefix $(DEPDIR)/,$(MODULES)) -VPATH += $(SRC_DIR) - -SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) -OBJ := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SRC)) -ASMSRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.S)) -OBJ += $(patsubst $(SRCDIR)/%.S, $(OBJDIR)/%.o, $(ASMSRC)) -INCLUDES := $(addprefix -I,$(SRC_DIR)) -INCLUDES += -I$(SRCDIR)/include - -DEPENDS := $(patsubst $(SRCDIR)/%.c, $(DEPDIR)/%.d, $(SRC)) - -MAKEDEPEND = $(CLANG) -M $(CFLAGS) $(INCLUDES) -o $(DEPDIR)/$*.d $< -#vpath %.c $(SRC_DIR) -#vpath %.S $(SRC_DIR) - -.PHONY: all checkdirs clean - -all: checkdirs obj/ucore-kernel - -$(shell mkdir -p $(DEP_DIR)) - - -obj/ucore-kernel: $(OBJ) tools/kernel.ld - @echo LINK - $(LD) -nostdlib -n -G 0 -static -T tools/kernel.ld $(OBJ) -o $@ - -$(DEPDIR)/%.d: $(SRCDIR)/%.c - @echo DEP $< - @set -e; rm -f $@; \ - $(CLANG) -MM -MT "$(OBJDIR)/$*.o $@" $(CFLAGS) $(INCLUDES) $< > $@; - -$(OBJDIR)/%.o: $(SRCDIR)/%.c - $(THUMIPSCC) "$(INCLUDES) $(CFLAGS)" $< $@ - -$(OBJDIR)/%.o: $(SRCDIR)/%.S - $(CLANG) $(INCLUDES) -D__ASSEMBLY__ -E $< | $(AS) -o $@ - -checkdirs: $(BUILD_DIR) $(DEP_DIR) - -$(BUILD_DIR): - @mkdir -p $@ - -$(DEP_DIR): - @mkdir -p $@ - -clean: - -rm -rf $(BUILD_DIR) - -rm -rf $(DEPDIR) - - -ifneq ($(MAKECMDGOALS),clean) --include $(DEPENDS) -endif - - - - diff --git a/ucore-thumips/README.md b/ucore-thumips/README.md deleted file mode 100644 index 980a928..0000000 --- a/ucore-thumips/README.md +++ /dev/null @@ -1,2 +0,0 @@ -ucore-thumips -============= \ No newline at end of file diff --git a/ucore-thumips/TODO b/ucore-thumips/TODO deleted file mode 100644 index bff63c6..0000000 --- a/ucore-thumips/TODO +++ /dev/null @@ -1,20 +0,0 @@ -2012/07/02 - -Compiler: -1. distinct MACRO Instr (ulw, ulb, etc) from machine instr -2. mul: - mips1: multu, mflo - mips32: mul $r1, $r2, $r3 (mul is MACRO in mips1) - -OS: -1. OS/161? -2. va_list -3. makefile header depend -4. trapframe - -save hi,lo!! - -use? - -fno-delayed-branch - - gcc use mult... diff --git a/ucore-thumips/boot/bootasm.S b/ucore-thumips/boot/bootasm.S deleted file mode 100644 index 235d45d..0000000 --- a/ucore-thumips/boot/bootasm.S +++ /dev/null @@ -1,106 +0,0 @@ -/* - Bootloader for MIPS32S - Chen Yuheng - 2012/07/16 - */ - -#define FLASH_START 0xBE000000 -#define FLASH_SIZE 0x01000000 -#define ELF_MAGIC 0x464C457F - -/* off = offset from s0 */ -/* load a 32bit word from Flash, - * off is byte-addressed */ -#define LOAD_WORD_I(dst, off) \ - la $t7, ((off) << 1); \ - addu $t7, $s0, $t7; \ - lw dst, 0($t7); \ - lw $t7, 4($t7); \ - sll $t7, $t7, 16; \ - or dst, dst, $t7 - -#define LOAD_WORD_R(dst, off, base) \ - addiu $t7, base, off;\ - sll $t7, $t7, 1; \ - addu $t7, $s0, $t7; \ - lw dst, 0($t7); \ - lw $t7, 4($t7); \ - sll $t7, $t7, 16; \ - or dst, dst, $t7; - -#assume file base == FLASH_START - -.set noreorder -.set noat -.globl __start -__start: - nop - b load_elf - nop - -load_elf: - #dirty hack - la $t0, (FLASH_START+FLASH_SIZE - 8) - la $t1, 0x00FF - sw $t1, 0($t0) - - #addr of elfheader, s0 - la $s0, FLASH_START - #e_magic - LOAD_WORD_I($t1, 0) - la $t0, ELF_MAGIC - beq $t0, $t1, 1f - nop - b bad - nop -1: - #e_phoff - LOAD_WORD_I($s1, 28) - #e_phnum - LOAD_WORD_I($s2, 44) - andi $s2, $s2, 0xFFFF - - #e_entry - LOAD_WORD_I($s3, 24) - -next_sec: - #s1, addr proghdr - #s4, p_va - LOAD_WORD_R($s4, 8, $s1) - #s5, p_filesz - LOAD_WORD_R($s5, 16, $s1) - #s6, p_offset - LOAD_WORD_R($s6, 4, $s1) - - beq $s4, $zero, 3f - nop - beq $s5, $zero, 3f - nop - -#copy from file_base+p_offset to p_va -copy_sec: - LOAD_WORD_R($t0, 0, $s6) - sw $t0, 0($s4) - addiu $s6, $s6, 4 - addiu $s4, $s4, 4 - addiu $s5, $s5, -4 - bgtz $s5, copy_sec - nop - -3: - addiu $s1, $s1, 32 - addiu $s2, $s2, -1 - bgtz $s2, next_sec - nop - -done: -#jump to kernel - jr $s3 - nop - b . - nop - -bad: - b bad - nop - diff --git a/ucore-thumips/check_delay_slot.py b/ucore-thumips/check_delay_slot.py deleted file mode 100644 index 8d31cea..0000000 --- a/ucore-thumips/check_delay_slot.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/python -import sys, os, tempfile, struct - -def isjump(line): - jmp = ['jal', 'j', 'jr', 'b', 'bne','beq', - 'bneg'] - for x in jmp: - if line.find('\t'+x+'\t') != -1: - return True - return False - -OBJDUMP='mips-sde-elf-objdump' - -if len(sys.argv) < 2: - print 'usage: check_delay_slot.py [file]' - exit(0) - -print 'checking...' -f = os.popen(OBJDUMP+' -d '+sys.argv[1]) -while(True): - line = f.readline() - if not line: break - if isjump(line): - line1 = f.readline() - if line1.find('nop')== -1: - print 'Error: ', line.replace('\n','') - print '\t->', line1.replace('\n','') - print '' - -ret = f.close() -if ret: - print 'Error: code=', ret -else: - print 'Done' diff --git a/ucore-thumips/debug b/ucore-thumips/debug deleted file mode 100644 index 2eb48d7..0000000 --- a/ucore-thumips/debug +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -../qemu-thumips/bin/qemu-system-mipsel -M mipssim -m 32M -serial stdio -bios boot/loader.bin -S -s & -sleep 1 -gnome-terminal -e "mips-sde-elf-gdb" - diff --git a/ucore-thumips/disasm.py b/ucore-thumips/disasm.py deleted file mode 100644 index bc8fd67..0000000 --- a/ucore-thumips/disasm.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/python - -import sys, os, tempfile, struct - -if len(sys.argv) < 2: - print 'usage: disasm.py [hex] [hex]...' - exit(0) - -OBJDUMP='mips-sde-elf-objdump' - -temp = tempfile.NamedTemporaryFile() -#print temp.name -#temp = open('temp.bin', 'wb') -try: - for arg in sys.argv[1:]: - x = int(arg, 16) - temp.write(struct.pack("I", x)) - - temp.flush() - - out = os.popen(OBJDUMP+ ' -D -b binary -EL -m mips '+temp.name) - print out.read() -except: - print 'Error: invalid input or "'+OBJDUMP+'" not found!' - -temp.close() - #print '%08x' % (x) - diff --git a/ucore-thumips/doc/book.bib b/ucore-thumips/doc/book.bib deleted file mode 100644 index b6e2bae..0000000 --- a/ucore-thumips/doc/book.bib +++ /dev/null @@ -1,78 +0,0 @@ -@Book{TESTBOOK, - author = {Lai, M.; Wong, D.F.}, - title = {Slicing tree is a complete floorplan representation}, - year = 2001, - publisher = {Oxford University Press}, - address = {New York} -} - -@Article{LW2001, - author = {Lai, M.; Wong, D.F.}, - title = {Slicing tree is a complete floorplan representation}, - year = 2001 -}; - -@Article{BSG1996, - author = {Nakatake, S.; Fujiyoshi, K.; Murata, H.; Kajitani, Y.}, - title = {Module placement on BSG-structure and IC layout applications}, - year = 1996 -}; - - -@Article{USIMM, - author = {University of Utah and Intel Corp.}, - title = {USIMM: the Utah SImulated Memory Module}, - year = 2012 -}; - -@Article{WIKI_NAND, - author = {Wikipedia}, - title = {Flash memory}, - url = {http://en.wikipedia.org/wiki/Flash\_memory}, - year = 2011 -}; - -@Article{NAND_DATASHEET, - author = {Sumsung Inc.}, - title = {K9F2G08U0M Datasheet}, - year = 2011 -}; - - -@article{OS161, - author = {Holland, David A. and Lim, Ada T. and Seltzer, Margo I.}, - title = {A new instructional operating system}, - journal = {SIGCSE Bull.}, - issue_date = {March 2002}, - volume = {34}, - number = {1}, - month = feb, - year = {2002}, - issn = {0097-8418}, - pages = {111--115}, - numpages = {5}, - url = {http://doi.acm.org/10.1145/563517.563383}, - doi = {10.1145/563517.563383}, - acmid = {563383}, - publisher = {ACM}, - address = {New York, NY, USA}, -} - -@book{Sweetman:2006:SMR:1210986, - author = {Sweetman, Dominic}, - title = {See MIPS Run, Second Edition}, - year = {2006}, - isbn = {0120884216}, - publisher = {Morgan Kaufmann Publishers Inc.}, - address = {San Francisco, CA, USA}, -} - -@book{Warren:2002:HD:515297, - author = {Warren, Henry S.}, - title = {Hacker's Delight}, - year = {2002}, - isbn = {0201914654}, - publisher = {Addison-Wesley Longman Publishing Co., Inc.}, - address = {Boston, MA, USA}, -} - diff --git a/ucore-thumips/doc/reg-sr.png b/ucore-thumips/doc/reg-sr.png deleted file mode 100644 index 32e9642508c9b447cef82be2dab4bb192492f1ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17986 zcmb?@g`}H6SA|)V=fQlg9T_VyYAxP)YAt0TKbl1==-Q6J#Lw6$$14wuMo^!tU z{0HB@E=OT5Hhb@Rp8H;F-D?^6NnQf;8ObvU1cE6g`B4c1L1qL0)_M8}ygCKebc4T; z?3E-wKuU(lcEA^CUnSM;ArNf+fBqol3Fn%DZ=!yak`qH+K*f4O$vyHmH4=P__?y_5 zZ=yCrC-~KSZj9=BG{VVq7?t?NP%kS@KSXz9)vq>%Yf6i{B%aK_Y>&_^lGTE|7 zJ${Qr9h%P3@+sze9)nKAa2b$^Q;c_|BlL#AO9VR z&=>zZCK$5P|2vF{|993d;YkL10Y;2Dl)=UUZEbD0OTiQ2VGHsA-SDJkwpyLKwtVj{ zgB=8d?SSn7=bWmPrjPNW$GUQMVR91cGS7C=u>kuOH68tHfFKy!E2QGA0r6&f^LXe9 zf;QD}^K^Qgl<_O)67%VsYQclQziq0=9%(l=T>E;CJ^Id$WR)=d7(r__UBbk$zdjv( zZIapgv9X~ckpYq5eZ|O5kfXaDt{ZN1&BXPjmF9+J{_)Y}8P6*N7mKWXbcJVz6rn3l z;HnV^H37HL0y|nKnwzg~KCMWJjHen`*6(PH%C zO2L5&G#|D;Am}p=KJ>@4B{ioxCs7x!)b3HJ!{?u6H3&P}%+{zDewO?Fm1v4SEcFG) z1P5}N?)LPl_T3rZHqVS!{@jy;TpbT=jbc?J=Usl)!Ns{x7oHDpceBD3#c?cd!ZQ7p z&}o}MRi5A8q`!+ST@N-6%E0YJlgr_AM}z3 z|9#0wZ-YGL1JyEtTNYQe&GvOIqo(=1s-hWL%^laWqV8Xj5~X}u5B4XJ6^agL3w15W zmv)?T>X=(~(Yq_S)3}mT_MOO(@@0cq>9@CrUx=QwU9iPUL(gv+AU~P?EFyxs3?YB` zH#G_3=wqe#G(wgKPnw(VrH1vxM`&I=&{?Ys2+F~rFFV4dvvKQRAbIE8IR{ zP0*a8?OP$ud&?1-dK-t1;WFH|v^iD|IwV^xbe)$48f7ZwgEP2dxj`uHcqurW zPx#33oejR2?%JH&RZcC_u^*vllU>H7g|JCYM(}7reYS9RxIA>pgFONuVy2R;r4aq{80x>Mi~m4( z9d-?&BnYoo`gPdF0!f!$Lb((=`JRv2uTtE2wRqcpfd1~srB3ShU&jh-f$p=fE5Z8B zMHbAkt_^VNBvs8bFJFD4tvozbjdi=9`^NnJ$b%|=`tbuk11M;*42BKFEZ+~oToseV_{9)pAeY{<2^cNa$oint$V>XnW`kTH6iFCPE{{%{I)b<#B zoRF_!{JS)tv#Llt<@6rfmb7}lOBD`B(Er%-fuyg%!~@^pbRdWvEigTn--i~kW56pQ znCvd08ebcEr|V<}{WXU;YDUDH1t2UKhVv%MwJ1HdH6C2Y2L`SG=Is}3@ zb3T8XtnOAv`($Pi$=j;6xH}$vMimU2aU!356IsgoczOkUC;#TpohjKL)F1`_IuN-* zb*#3`SD_2jmq;nf-0^Vdwxb>Ej?9dsD{f=mV@Vd6MjOTnPmE;4W-CTVUAOusWr++) zjO&~H7L=&TkyxeuG!@&tTM;v1M9HCn_%#yWG&;|qGU;iUzQ6IiYQn+CtniHrkJgtE zDyhU!N(VisB#yH9 zesrgL0LhBXNu`g_KR*bQ&fb)< z`EeM&VpqTCSPy50lcq39Sx<|{_p$D^l}<~=va*7*5gUiUl{emGp*-Qe#zPi3W>4$L zXgqJi{!4GCX5gMD*fGlQQK00IPP|yOlgyU}M(`u9=7nPgyJhqa?D*j3JP2`vGjld} zi>5ns@i02TwtSY1HsHZcc*ogbRW8F2)q>h(lG*Y1lkg6aZLfvHS$fVzvkbLbCNY$Og9Rbk;Iv;;%jQFADwD(z!S{ljMJE^CM;1@ zTeo}s_WhQ(VW)L%A!RntT;s}{c$@+5JU9z1{QvdJ37QD0tu3h?}<~&@qQng zfF$nK9D5u$&29SnjxFZ*L=D$(0!mKKqye_xO>N^ZHr0aoMYTQY`6$FjDDjTf;#)j} z&y87}R)e2il)y=>Cv?qJ^51M6!z;S46?ZSiHSK&Z923sIMPTDI6@O6HW=4Kys#GeP z;-KawCKp;o2Q!y3pG0JbL^`k>u)!&lc-P1|h(i{x-9C+PZffuUL7WZVSs2VI zdnuE?duQj_oPz6f3gg1*I)UsT zGFwD6>D*tH)0Zca3_+{9Vj;Q_Bch_eVC2lUg2`I}5*|3YB65T_J4d*1x+CLLfsFZ$70F>xLL26q!ZmjZ4@>UC zp|Dj~o^{yV%4Wke-7f~}YatYOPV+yq+i~YRK>eHRT}Nna?`*G4%k^kYe7n@q5&QyL z)u6A#X?b{pjY)verlXBuSb@j1edqYc*ExP9-JF*?o|~s3_6vO#mMIPs6T!=a>=!ROi$Jr#3GonP)ijSfHN6(j7^zSpYL$$mlIRzPl76%7M+ zzy7j`P>Fx#K`mi0qXWhG;8(%qgLr0Vu5BX6uYy{K?qzs)f61Ke8tb99_06{WxUVJ5 z7*5d~sHq(#4Qg5E=0{oc28DSk_O=N%--ZSboMZ33w8{aU%Ftkf0e*2z^ycE_31@+Z zB{G)>7V-QbS4?qsu2grfIJ+;iFK?Jd^AmHbJYI1!%-NWB?{pY-jYrMwN##DGZl;>3 zgN3s$JC;nxV+BpiUwg7;{`F6!-z@X_u{F3TKS`{XN-%gsQ@*3YO?8d`LRq9r&~6kA z=|LkW##<9!>2c?5iCbn%sF-u&tY^n zvw-;G7<&F0!N|wmNl>+?65jmC_I04lPI)lX(ZbR8*WTYL+U;wb{@#}Vp3~YEAfA*g zWoM0TuTqLBB*N?h)~hR{Yt@E1C(YmMThV1$fk}amI8@bNU)n~-8|E66CS}>(Lg*_mSIJMDQT7al^KKn#M@;hR31}INt@EQ(hL3Swp!eZ z$_^OZc5f?aZwgv&c|8WykhcOVPct9SKb6B~!^jGko~~C6KKKb%Q+!k89s*$(#^=98 zVFxa8^v3-05b7SqOoy-^t1_cID+B!a)@w_%=xoNTyC@moUP%+ppg^p_Z9?w&=bUf( zXgLA2@zthR>P5=oWYAeHTHtPA7{a=_$PF)pLKl>uDDx&|J2(KY@t*Pq1cTY!R%l1{ z+xIj3!haQX6o%XzSLm2yrH2%^{OYbc)rR$gb;H9$!|H`?nekzJs9czrzWnG6aMv(b z62^=~>cB!fG8zK0j^s-5SAua(6mA|p9teWorD2qz$5c{tWOuM6`hC!cvX#t+8{K*d zM9%hp7=Kccvh&(I_u2{94vnl6zqaQ4#zZBwY>EkR54)(k%^_IkEeh^3zHhb60(yl9 z8igGRvsV$zg^Zggh}Js)W#yP4@MaH^M58If;`ezO0`q6g+n0h?y%Cc$!~l-FGq+w} zm}e`|K4@<)ZzSDBbgMp33kG06(hJqf2T}%Q-aQ*^FMjf{b)RD)?O7>kng4}tfZQTa z2egUHNxAty#r=gTl^MG`BKoBflGcf@ep%-rWOKTgm>;xDROkx5N~xm)KeUXzPLhiH zH6%shZu1-xWYGodyk}>1pqb>Lc|L<;S!hvc&b#31^mE8}f}a_-VMlZM%7LEqVZ6yz zx608<|2(5`t3N@+ODoG zGFx+1pXf)Xs)g1&Qdp^&Y}7e(Ih^jy%bg{3lcszUDTsKrb){cB(4`@qT%k#ntsKN+ zz2%K%4U#53Kb=`U7x}(NSevNW}?d`R=+L zG&TRsA~JyHR4&(;NLK4hUGvEK09A&9#n~S4nN+zO8!;v^k~!fDMw}|u^jRuELh51}CCx3E zAjs+$)F`aBJ+B?kxjI;sb>$rX1`jeg9lbo0OG}ntlASxBjpB~-HSwL<_%grW6}X0% z&rdt7sPIP?Vp0y){|!>3;mpd-z}CY8#ob!~N~t^*UXbJGw4@Zge2f9mBpJOB-sD7p zefDK$UU;w-@s}cTc4r|_4M9*LK1iWz*PJ(YK)heZg8PrB59^@%#-w*i6+BcZVsK+%# zS9s}7!yC9qHI0S!YAMPT(h`R@?A<9ST5)Ut)=VXES9>f~NN2C!4EU!uo7?+N6{~fO zMb#G_#4CBbMtv=`6{XK!jH2$AQiq*+Z0>$S*K=-6_07|S)pUiiQ^^}&wG78(a&cD{ z8S`6TE!I@((p!DbA_$VmjZ-7qj4#!$WbzQY1mugTcGc0|*-vEmpWhbc7V*YyW=h#p z)JA>$Lq`NjcM7TbFv*#@t<)z{H*N z+SO@8-;82I04XFG#+bRE8i763e%b0@U@}~*c7tZ77%T_}APqhh}4t>ay zd;kAU&yg2LZoGwC9FO>mR`va-7;!vJMytcBc7HB;$3HyeDJ(;p@;`m(1NOAO+Ur?_ zRQkxs70Q27(F?y%6voSBBydJUx0!yp^cB1ghh<_9)SysOS{Z%R~ zZ|0-PGUgon-6^mk_sqBZ*-e1=6F9G&w_B``3AoRBwk@zaD77_c+ zrow*Pr+`vYJn||xgYbc_MTd5Uf3pLzCyO@K-TD*xP26k#3;_VMAY~C6+mG)+?ILwh z26#Tn+QFfEKYP%KJt)dGVn@q@zCYXF>W$oV9e}BX?el%S!50LYal)Zfqr9t@iR}|= z%8<7Bcmhm*Wl;t8Hg7Z{y_jYG9p-##;{F*Xt1KH=u~rX9%W>ka9gQr&u^)MO^ zx&1X4OKxSF`3%E5B|kPuo2w?=<`Lvw2|=y>UX|EA2VK6AsZImki>VEQ!HVuCC@HQZ zs-dA)HJWtsH2n_&wBoZ(#z(vR3Av`Wn%M7m&5~-7O`(pdc7yeCh-G1|Wsgrt z;Yj_bE9h(!yyQ;%Iyn23`7ro6N?x5V ze!I4wYk~^^rtnqe5u`S$!#ltHh3gq1EzxTiL3L-1Hjx#+s#n1pRVtr`A`TF6V;A@; zkppPA*T?JRTVx$!av!>%Uin|0Hdi%K`=9|h{X#d9_@$?ssGJtgn%de%#p}UKr^{^{ z#S

9$T=%yF>1AW2y2%b-wBJ=f!s|e$h(KEW}(=Qj+MDkYL@-`S-O#&cUzoi!snX z<~>Ojkw_AaRGEE3V#=$Ch*c_)&iQr1?@92*Mw{S!e5<(EF++3$^i-wPfH?~c<9Uw2 z`8uXXbZPk74QgaP_{GTK_mOhTQZ{3ccIRx>!aWuFuEi@3t3ENsF%rPRo;$yDboidl znU5lOObEB^y=sFDAD!#-wTe4dDlCoRoX>!A0_3gG9-uVb+%e?8(X*aaH7XR+ zdjx~-Q_RG5LEVkt)E05c;XNKkoh(%mJ+%C!t-%nIc+y+@{1^OiaYHzcHw+ol5=S!( zE)fF6KJ;2bI{eSpv-Cs={F}XMB~t4qIvEoExcGhSkCH z?i?I+|Kz5u$zwjGQ?2q~J-n@lI@Ek!)%bC+QI156=kxl#T&tGq2JACktaSDl23Mfs zkztuL2gN*fHa_TFERhzfO z7Oll|k{GF2bT4G}mTlB7utZ*8(bX1x;dt@rvbaW++2xbcbe_B*rIwnTO2wk(rcMsI zZHCBSkuXz+*TDgYW>wcfv;Sc%tzH_8vrdm8Z`6O8G$jXm<&-Sjb*}4RMIJN-K7Bc## zk;gK2@M}5(3&$f?y34-PNA%4JW#woT1QOvEF>m+6w4{(en;^C&ODHs?-H5-$f8Mn| zRk{_3sn3vqxKj7U#{(7iu;k$<1w=qX@QeXTMFv;&u(?V6AxeI^)A@qU8$4ChwgQ0; zON8#=nor@?=1NtGj%^DS)Z!L0v=50cQrrF`0MGm8K2cX45S5C`6qaaobbub1 z?9%W*z;6L@>fd|*K8osqW@&qP)O=XMQz*eJz9$@rO6!B`;B8kM^?lld_Cen{<=dU; z@uR|{^UJiU3>7-)L$ACi?`(Xf-OGT4&z|aqI&+QGkbyW?U#0w*hS=AY;$zTDrsW>O zV6pB_Ajwa!bzRwB%acHI6y*6OlKqz0IPXHSi(^;S)?l@a{fG1fwsd>Q1MNgufL?CVKI4f;TOgFh;i4=knU7eqtd?Svhg_D{SS;4{TM z;S90Te$DmJ`A6@!8$bQgdY@5-HS4eLa4>PeSh%Ih-=mpBYsHyLTO8Z#zWCe~`4Ov! zorXJ;ISGpcJ$@_hGPy!AgAK074*yODwtv}Z&0hXh+9u~9|HZf#r~D`7Bpx9}XH|%I z#>%Tqo<)fT=`))g2&D^q;ETfs9d0qN&`pXB%);oV)P;}As;1XrHyj+3OBL4}#a69@ z03BZCoX=-qEFAKFj=PuW0_&h#am7|h}w0k_8cPg{zT6Fj;-BU&4_=2i=}pwAL#XaF80#9>o+Mjj?K;05 zX7KNL>6#9F$&1q5Byya= zo;gd^KSK`FN7W$|W3?3opG?M;&GS|_s4ZS3m0+BKn&CK2t`slYT>}@rI`^O4Ocknq zJ)R(N9boOPhZ?OYzH$^4H+Y9wQad5bpb#MKOvELB*ZfY*D=^denCz&tv|E{5`AXu- zcNe{vopk5~Q4eL$HIba}US;K2IKe*Iwi)-*9w#gjEtx2eX=0+Wp^{<*6y!KD#EIMX zOor%Yn5cZX;-b=2KZ5PgqGyIK3|fQ^N~CNO-3e- z@onU()@z-h9p+s7E5Iypi(TYc3}kN7$@8a&lD|(GY$T2$B%s&UuB*|2^9Sq~5f`5b z4=Q*H?vOaV^;94l8x|bOpy&4BX57OEgau63?&6CJD|Q{so{EmDx$8Xk_IcpV+Z>(~ zjBSc!D2|1+ISmljlS%2wxrV!KaJsCHqlwDDH(w3nadBt!pc#yh&sfQr*&uRhv+u;a z<4kOc#`2{27Qz#;O!fw=3q5;WI_g(I{}%zj;h!z&PvoDlq)M8i$Uo`CXT9|JdUo)+ zihY7(cYtv`yvTQ%@chuN6Wkq~KFN>_KSvNfN!*p?epA|KG>-)N601t= zC$fet^O>=>sKzs}%W!)`&Sbm>Dd_^w=2p5%g)ZAVCwWaiXP&3Fh#dOMliHIrY}^y9 z>>3!?a28_J+fSh5;+XVKGsVA9N=v-k{FRK8%8YpWkQr}rw!)zrERYoonu(gl1u;ZE{JB41K2R+bx?MWA% zW`Y5gRhrd(t_z30Zd~mE>s}f5d>4J@+^galBVo{Oc>7pn|G1}<+<~Dp1010L_=$g5 zfjO7C91u)KwVVNfgIBz}R(;SBQv?*jptZnFMp9H@e88t<2vv=>lG znKH_G3aM+*qai=)|D3Jz*&R`RhAz#e|Ned79{;8&s@016Z#4M|+)6Q@EQYw+36ElD z_^E);ol>|_;kc%1aQm)yU_yP;@0JVlBlA>sItKg)H7!}@DFw%?;f=}3&kM_@$CpNX z<^vHGY+bsvkG#)b(%;iR4H_-e(BM3UJsEo3pp&7yjh(FW__fr)grD({??RR}8)rUO z>#UMZ{tcT8yIHk{qQ_J`yDw0*#KcO;M=Q+tvn8x-h>Z&)0&T8!5_eYyY!WzQu7t=P zAXtii`V(|Dezlg$sDWaG+8GLM4e5J&MAUY)29z1*2zYsTcg%HQ zE;yKB8Xf92BgowH7?f+3z@8ALz{)Gju5& ze_mTBPMKTD=lu8Wo41A{uCH9eT{vw9ADmiFGk>1Do`)CRl-*Q2!zYe-LLla-{A~*t z_CzfcTN8M)9-N#f`xr+&xKnQ}muEs6aY#8%wYUG|wcDu%zaN~`} zvyd1|0{nD-f?3Y=n%En^ef>hYl215)J{^;vPmRb?sm3=XB=QKcp013Ldnz0oE7^D$ zphSJ}Vjl#TDd}Qp+s$|A(WKv&i*Ex)0vf#Z5WQcTXk^XwmUOXw&I^-M%sh5I$%aOb z87H7meK|wra7Ae7nXbsN5zjqml$- zc`!dmWK`B-mGS`9(TVoxaZlo?ovS|opu~=8X4}rHxd|(0AiWg|Q05cdeLVDdWNpx~ z67eL7#H{3i6w@TH$NT0DHy;%jPLZf6%OXbL-`Z71Qg^S25F^MJkMjPDBct~PwEPk& zzf?$SB`|H&fdtn~2tF-Ve+-DTr)XqeI9jky5Q)q?ZHv4lZU^=!)bV$oumPc6;%p%Q zLcB9|t)}qQi1RKO3q_^DAh9d~1eM@7hJv8^+1)v;et*4|FDxj@FHYi2dYT^X-sUI=HX zuMymF2KlPdv`>kjdlK-@vKECdOs+8&p7ez(+S8>INipzqusw!!87MN+SlIjCmuv?4 z;cd1gy}>#g3y$*S+5Q|dXkD0*MD`{uzcgn8A5_y)IKL_B1jaC?Mc=RNSuN`XeY1T> zw>$j;zGkQ_w@=_R-<~I+ZJ*hNH%?|32-nIM>lRGP)EmsL-#`sNpTY`=tSohA>#JiR7TfcqlmR^ zqmy2?9$Nq@aO2s}D^9-}`gaFtf7xn*RznGTYypJgWH5*?g|);E3HQTy+4`7AN7PKT zB3rAQq4ChSB>@1f0`i`(a_rhfI_q2zMMzF4nGdiy!eNoK37TP_gu6uSmmnxy=*b;D zoOd=(-Q#(811lCibdNaLu$7!dX)PpKZ#b$>wVN9XSH6VdT9^;)rQd@72pVnm^NyO zb9!k9meX=xt)~Y7reIgUf$B&`t9-} zaP~vZpVs)Fk)NyHBsctZ%?(&u%pMG$8$kO~16IYD(>Q>gJEgf-PA&!;HdTRi-1N?L zM2!T61+frg<^ixJ6?25k<^hB_s^OuX4N=>eMj@#69qo4+`qs4gvg?x>NE6Zjp`2h1sgC>R;qhAOH3wi z+6y<%%u`?S)>(3sHj_=x7=^mRPf0#S_m*rD*TPf!jC-FYO*KOkG4!hMJr-|Z30#}@ zXSwG#XjMOdHvhOWbUOFsvSrU0y*QhBPhvy7xjT@Yigx$>Su%!X)VknmSCa;(xe*S@ zCTz0zMpi|~J0q~sA5~~Vh7U;{h&JMU2PnBAfbrC*;>BLA| zygf?D)2UDcVDz?v0pn@Qusg7RB;DAC#Y0^atoN%Qy+>F-^GFE8K^`s3r8Tu{IMPh@K1$#%d+BYu`81ur`z+wol-%Y2cLLqf24Qme^XrduS?PZMz zm!9hS_G6fs;xp_@B8ASgOR}ENC$HI(n;Z7_u`mRK)mme-9Yp6Gp4VHf-QnuC9)cwra+Pel`HMkLLF8N z2S{3xF0*#tVMeT9o&O)0{o4VVY7}b7{KPn`?fU1zT;mI~RMu7~Q*rD9MWf-g!So($MK9f7ZVV?U6$a)mx#Ej4*KwLutf$@q3BYJqNi{^EF8|UA#;SUwqmG4@? zW}HdwcO58hf+7UfU=LbTrc<{a0vfMc@PulTo_J4$s$?xy{JEn1JK|%}iMU`~Gf4Jb ze{@B9$6Bz3aJ7SvU5pbIc6nAE)UGWVnyyDq>Ll8d|Lfj~e2EGaWiYF(fJrm%lwl0n zZXq62M>9xUNw8DUtac85kAY3RapQcHFPXFFn(&vziIrO1{q^RFi|jGGmU0DjUW0+a zz^Kq`8?Qh^E3iJBP^7gX4W72OF5pPfI$O>~!elsXFm-Ue@;S(!b7G2ZNbPLgP_n z^J)!D!t8!Z&83RG%D4$tp-7F@pn!Q--kub|6W_4snIW2??$ojNRBD^>73flo!4`s?Hkj%I&*Nz|WK4D^`yFGD{>z=CADE`PiJ;Yd8towC6 z>iM&)?+vNY89ozrP8J6{X~yWJbJ(Q!t6`uaa$na%ZPXc`m2%e>El=5))^?Zn03s1Z z6)7)9aOBZq*6n@o-aa0!t03pNlR<)7{5~1mF?SQ zGrnG%E1Vd7F}q(RZ<9d2jcFh&yKeCKL^hf`nsi_Hg6Sdt1$28cA8Gm(VUO)quFDHi zE$l76)iHYqLBrArW<7$G9Ew<@Er&H*^5C9FCXbYLt%Gz4AJmEj*;55ePjB`VDoJ=h z8wzosodLlBFD_)o+EH~#LxcXUHPsAxjfR``Y)$7aZdwq60!A(a#&+V(Pj}qRRtrZ4 zMrr`oC#~C_oHOJ+&5v$9M?T-XE1KVc=}3OB{0?J;5oM6|K=et0-D+zjtfxjtURXr;`#RH(>OQf=bL8EwNcbw9)dBE8E;wIn! zEe9*^mf&9Xeyx63MPiOnErvRu2e;tq%5xpwZJq#Ee|>I}*?n8MMTJA{q*wdF&49_W zP3>RRer3(1ba6bjkMMbd^_7Xin1eb6_K^u~@00fnK(gOprJ$(k|7Rfp4{uC_DNg3m zGb)9?D*Xqp&_6rrtHdtx)7#6A#ho1M#4d76+sj^u(y}+6{I0rGQvcX*DX;+j0KMy8 z;qIg0A8ajqAo83yRiX-F*3}2|U3(AzYuCj}LBDD}waCOx+Ke*+V(S|zrPdJ&9z067 zT+BIC3pe;zd2uq{NjBNSsRrNJ_|deici%WX6G=Gk(ykPZ)+sh^lP7cn^FzY3PL*VlY9j6#g}ra6LvAb5HWGX?$SH?q#^rwGM#Gli`>Jo_1$Y}{GtZ}6*R zw*`R8uLVE8NTlGEI*^It;1bB03IqM5TfDoBHfLDYf5>+PsKj!Pi(JldgVt_PuA-=L z!p7oOz(A2jjl@C8Dk1{<$0)r!D05SKUK}j>b7V)dq*ZoB^({wiF}F|LFMwX+8%DcONeWE=Gp{kVZSG_+Y|SY&Q4A){|vT*--T33Vp(3C zg()!`p$?^;R0(0OslT1C#UBt;+m;%ir}m^}CwQ#*)5#>AsRl>~s-$^MkCV%Gsv;JRi&Gv)=23JX?X7Yj4_5 zDJ!Dxm(}5dqwY?xs=ck=Vmu}FXFe;dHsizQl~S~jIO=QcFBzmBNqhc*fb}Dj1jq7Q zR?f4PSHNSu&a(GOYfRv5Ql%PC5<`C2Ih|}ilUn9Ap(Md5jb1(9EkZvdkny1QYmF{>-4`aRr&P5j`^cMRYs>hVpsrfF2Lq z{LW`IG%!zI$kYkR=dBmBZ^EEWz1~GES7YmHG&M^mKkpYXe^1#HoL?_#`&^aRUCO>j zD%AFur}t@#c+;iAWg&UX&&k>8u@xDT)KXg*9LDzh`J|S|SyLej^|{ub6Qd zv{!Jb9;?3BMGJV!1(18rzhgoOl+dg5SBT{p;7mD$w*JC{-fxR!ToW*!O~{oy%Mv{g zP&FXxzW@G`mf^1cm+(`0h3NIQKIjoU-_3NllRneJw^H~=WROJ${2RZoS5)o1)-}NI;^o& zqwGYAqRuhOn0zx@AMY()=2Bk`16OPn6Hl1twY?d%e9a z61d{ZWA{^cYpBy*+1s2n{FnRwNOIt;PTp{*<;!b!*7>I$-~|iZO|g$`>e)%jkcd6C zac+h%UZrByuIzxZnnBAC;Ip2ieQiE*A`9$Ab2?B=L9OA0_`$ZSjDy;5?@34}t{HRX zMrh+-6c?qErElnenJ}jgyWYlc_E!~M{^KyHuPi>z4fBbwu@)UnE-Der*X+{8u!ny= zv#wSnu$ivbtY|2nDC|IN5kn}&Q}wMAR)UjsMg=!{{^WI|fFOea*}c*7_c>zHvx$cD z)T0bn<8jfCRJy#~x>j7(QhYlr-PpVt8_!Q{ zbpa#(t64L?CHpdcp~k)292dd4BLga@V-9&ijm@mQxIcqW_j$0(OQn0xVR>K=c#i$e zRD2q#SY?apfnV)dbnSuKNjU*D_@@i=}Eynx8gZ4=BxL{d zt{^3;E!)7QW$}#2jr6pSc7LF4+gvBz=d>=zECYGw&?pt~;-Z5u53`6@uCyA?8i!;@ zvYxzBE_(jAIoDCa;@qry8L|I6NgUaj*wEl> zhZZo;1aV_gaWCAJCt3DhD2QFlHyl>!?UdiHSzM!hUytVXds!E}l=P#0{81vbUFW-< zO74+Y6&mov+~Z5zYTws>z8aj9+0cEA_mcm`zrmS8W~h5bl~0;Gci^4LJ^Up03Vo^dR!Uk&A&j@D#{F2X{3ET#hsvdj5vPoaloyag5BI$a zJNL_UD;5_)TEVzOU0bo_8~vfX$VSimU*~tErd7(HszUZUEU#68pXM)-gzGXN$@glAGZ##Qn34>cfiI%W#|B=`_YC3eyf8=DAic23pjRswySTLUdLh*PRnR7`Y}32nBK_7Q51He-dAR_FR z!JFV@EiYiHGJQ#X+suk*?LSoO!sagKgPuL0Bcdbewp74nCtM4k`O@la2`6H2`L7x|8AM9<6g z!1NySX{}HGJ<;QILv)@H%GaJ$B;v4ChSNup($RjeV>Y| z4k@z>-6wo2M0mB>v=uM0&$#PVo3`+l0}PyhRV}A;uhvSVla<;CE;@M%1NDxTWgT{?&ImMVoVT3 zZ_%pj>f5!BE5F)(sdV8r*X*k$HirSpKfWXiN;br2ut`5YN8et6^viWl)?&S}1h(Bb)xb2{IlFaM2t8=@Ov;@?9B<9PsU` z&}|p!H-h)ek6g{a>l3xaO}CQXFrq+)6lv}oo!v$qdb?OKAcu`EtH`2pK3f5(!aZkS zA%FPx#;`M?w!F?gEcSI!7!l1L{Q#HdVkb6AOc_C6mgSN+rhG9?P zVBOz&oxpTQ3cO4xOQl&tV;_mi&(aQo(#!yV1exvt&5tfNh`KZ1N(!7;$adnnzT|k#u=oeFNemuAU;&r9v^zS_^lXT_)Mh>S0u!^qMejH- z1AZCS<~-U;&tNeOLIW-QPz)7d{O(}6ZZHgux2ASyC95ZT#h7Cz$jK6kp7fMdL^Pq- zKvsG@*x13{DC>F}mug5R#Ho;oLg@p8 zbuU-yzqRN$d*tje7ua$qg>C)OureVm5t^t zk9GO-C&uyaT*(s+LLH`HT0qzpAD;;@c=N8QWU z%x6rqWH#M1^UwSp8?S}UeKLsA!gF_4wOL}=sd(Q=)<|%Yc8Korh;@_$H@2knmx%1M zXOjya3sOz$%FD7yKm%-C?Qo7@H4?Ma4j*X7$e7)(DpktYdtrCpzUL>50fLD6g2YC~ z33aef5=Swg)_m1h^WHo(bZcLmy>qpdga(>mS+U76vNUawIDs~5DxBdjyXbnIN5+?T z8Z){qzF_#S=uC*})DR~;jzpUCVt#^Lq#C)K7onoCY;pSIT6@((tEo9J|4E`Z;yG1D zei5Uy1A504(TrG}el@wf_7a#DjfFp$VahqLZvPjrr{siC-w)tC0K!IU!g5U+~c%x;AYGp{JlDd3P02Ma?g% z9VdgWZc2{x40w;bXv(RP-ya)CU7kq(#Nx)A%i9YI;Cg;E8Tn5j`0S;{A6ZHd=4P6vF}(XW;6Il%)PjP25Oss9vK&ch)+s@KEH2vrFr>iL2Q`iTB;dZO8D(9byrP1l>W71tuM`!X2eSpayIwuZfX-C_Tjvb;Rm^i zYl|356w}Yajq)6G(t=sLXIS2)(N6AH)0F$J^7bK8?GY z>uo!N$_Qz5&NQ6JIH!$58CZfp^0sQr;WmQrLLp^e7$KjWRV8&4Di(_#(1r7J294i1 z9Fd)wK1wfn!{p%gS<{SOh)`K$R7BV1abU8Oa%@Pi2Tij+QZvJC8f3*!fV zQDAD?X*2`Mw@Vyvr0hBvq^O{J89np{(XWzwVhiCllYPz!aNCu>O+OdJG*G(D@;>4` zbz8BirXbhWy~gY=(3a3Np$&#Wp2Yq0{{rYy#Vm9Y5swdE3ZH52r%;8i&M0Mf1!OeJokO4iV<~J*N-LeMegw%@hsDY2 zwn-Nw59I6bK!-(46_$TR()9jle8d>#9WEZOFNvP@ohYJf26efoa4q#8-(_q+urr%q zld9=BAi~dYy#w!sTdOn8wz!}rs`A1q4_xEqPqyS(4k7a*nd;o1<^tp~_ZVK~& zbL5q;NQTxXJ~bEve1{`o_Ob;^;v(kf2+B}mq{QocklrR~og|jere`&K9=%GjO}9&U zJxYNLfsqGqmKcYU*9!rsTl9fV`Ii9tfF=-y5r9`5Cki~k-PP38PUG?z;O*Xeb-8iW zBU~=-xDX|7Wgztc(?z>9lE?j0cykn$ZDTzMAZ?dPElbgVZ>`3KeDn%6e&~JFHgic- zn-r}h3G_i1!6l{qpZankjaEF9kj|~lhQA1nugzq9eZWN2;OOw`2`K6fXQz=OALM4+ zi+jvx3XGJ?N1R?^;`HSC>=*-U75KFPPWkEoFnN)MwD_}J*AQg#fdtFx!C^h|xBM`h z1wv$fRO+Ip%(YYBStcF+C)MOjJkUCun4+sT{uRbSE(4rplwNV~uZV3qy=@QZ0-Pu!9728Lldq-&PFRCeLp;daYBRBI)gA zm9uUU=>+Nq$_&5V%2USMpqf-^E!?qnU<66^zu^lrgcu#b@F0E6<_)r`&wm0PpRfB6 zb*yT?c7tNwP|ff-5d)*HTiY)qVQBVU?4TR5O2I*-NP&8X{*?H?+-(U%_y0C=Wp~=~ zXI0;(l*yL8G>-xHpU$~lpC;7O^hmx9I3N4`pY`?$Q3^jFi>!^lw|Z&lo#y1@O26I3 z!ZTAgN&dA<|8LM^c^tTB1-LtD<@AhzJ#i;C^=JoraJ`(}^k?#)2i3qWXfxt+lHVz} zDrNxlNqqZF?#;j%{-2*j)*gQSQEZ+_LHWkHJ@pTJ=2x9A)3|nj!zW-$DQjXg)cn`m z5!X{><9>S~@8uWmmHYbn<9V)Eny7CLTw%7f;<1SS*7us_0RbgqZJGfhz6ZA5Z+oq{ zqStAwrt9C!PMhjp^fKrbEm{CRy2JH%?vyWczW~P#(+s9B{Nw*OT1TuAXrCN#H}1swwNcq(LZZ@s*Jba*Iv1cB$fFnGH9 KxvXtf_vaddr; - int ret = 0; - pte_t *pte = get_pte(current_pgdir, tf->tf_vaddr, 0); - if(pte==NULL || ptep_invalid(pte)){ //PTE miss, pgfault - //tlb will not be refill in do_pgfault, - //so a vmm pgfault will trigger 2 exception - //permission check in tlb miss - ret = pgfault_handler(tf, badaddr, get_error_code(write, pte)); - }else{ //tlb miss only, reload it - /* refill two slot */ - /* check permission */ - if(in_kernel){ - tlb_refill(badaddr, pte); - return; - }else{ - if(!ptep_u_read(pte)){ - ret = -1; - goto exit; - } - if(write && !ptep_u_write(pte)){ - ret = -2; - goto exit; - } - tlb_refill(badaddr, pte); - return ; - } - } - -exit: - if(ret){ - print_trapframe(tf); - if(in_kernel){ - panic("unhandled pgfault"); - }else{ - do_exit(-E_KILLED); - } - } - return ; -} - -\end{lstlisting} -\caption{User Mode System Calling Convetion} -\label{alg:tlbmiss} -\end{algorithm} - -\subsection{Context Switch} -According to MIPS32 O32 ABI, we must save the following registers -during the context switching: - -\begin{algorithm}[H] - \begin{lstlisting}[language={C++}] -struct context { - uint32_t sf_s0; - uint32_t sf_s1; - uint32_t sf_s2; - uint32_t sf_s3; - uint32_t sf_s4; - uint32_t sf_s5; - uint32_t sf_s6; - uint32_t sf_s7; - uint32_t sf_s8; - uint32_t sf_gp; - uint32_t sf_ra; - uint32_t sf_sp; -}; - -\end{lstlisting} -\caption{Context} -\label{alg:context} -\end{algorithm} - -According to O32 ABI, \emph{s0-s8} must be reserved by the callee, -\emph{gp} is a global pointer, \emph{ra} is the interrupted PC. -In addition, we must switch the kernel stack, which is saved in \emph{sf\_sp}. - - -\subsection{System Call} -The syscall mechanism is borrowed from Linux2.6. In MIPS, a special -instruction \emph{syscall} handles user mode to supervisor mode transition. - -In ucore, we employ the following system calling convention: -\begin{enumerate} - \item \emph{a0 - a3}, arguments(from left to right) - \item \emph{v0}, syscall number - \item \emph{syscall} - \item return value in \emph{v0} -\end{enumerate} - -Syscall is wrapped in user mode library and can be called as a normal -C function. - -\subsection{User Library and Application} -The code in \emph{user} -should works without modification. However, since \emph{libs-user-ucore/syscall.c} is not compatible with MIPS's -system calling convetion, we use some macros from Linux -to create our own system call entries. See Alg. \ref{alg:syscall}. - -\begin{algorithm}[h] - \begin{lstlisting}[language={C++}] -static inline int -syscall(int num, ...) { - va_list ap; - va_start(ap, num); - uint32_t arg[MAX_ARGS]; - int i, ret; - for (i = 0; i < MAX_ARGS; i ++) { - arg[i] = va_arg(ap, uint32_t); - } - va_end(ap); - - num += SYSCALL_BASE; - - asm volatile( - ".set noreorder;\n" - "move $v0, %1;\n" /* syscall no. */ - "move $a0, %2;\n" - "move $a1, %3;\n" - "move $a2, %4;\n" - "move $a3, %5;\n" - "syscall;\n" - "nop;\n" - "move %0, $v0;\n" - : "=r"(ret) - : "r"(num), "r"(arg[0]), "r"(arg[1]), "r"(arg[2]), "r"(arg[3]) - : "a0", "a1", "a2", "a3", "v0" - ); - return ret; -} - -\end{lstlisting} -\caption{User Mode System Calling Convetion} -\label{alg:syscall} -\end{algorithm} - -Another modification is \emph{user/libs/user.ld}. -The .text section of user application is located at 0x10000000. - - -\section{Conclusion} -In our project, we work out a basically working version of ucore for MIPS32S. -However, just as what items listed on the TODO list imply, -much work remains for making ucore for MIPS32S pratically usable -operating system. - - - -\bibliographystyle{plain} -\bibliography{book} -\end{document} - - diff --git a/ucore-thumips/flash.img b/ucore-thumips/flash.img deleted file mode 120000 index 29a99ae..0000000 --- a/ucore-thumips/flash.img +++ /dev/null @@ -1 +0,0 @@ -obj/ucore-kernel-initrd \ No newline at end of file diff --git a/ucore-thumips/kern/debug/assert.h b/ucore-thumips/kern/debug/assert.h deleted file mode 100644 index b81f95d..0000000 --- a/ucore-thumips/kern/debug/assert.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __KERN_DEBUG_ASSERT_H__ -#define __KERN_DEBUG_ASSERT_H__ - -#include - -void __warn(const char *file, int line, const char *fmt, ...); -void __noreturn __panic(const char *file, int line, const char *fmt, ...); - -#define warn(...) \ - __warn(__FILE__, __LINE__, __VA_ARGS__) - -#define panic(...) \ - __panic(__FILE__, __LINE__, __VA_ARGS__) - -#define assert(x) \ - do { \ - if (!(x)) { \ - panic("assertion failed: "#x); \ - } \ - } while (0) - -// static_assert(x) will generate a compile-time error if 'x' is false. -#define static_assert(x) \ - switch (x) { case 0: case (x): ; } - -#endif /* !__KERN_DEBUG_ASSERT_H__ */ - diff --git a/ucore-thumips/kern/debug/kdebug.c b/ucore-thumips/kern/debug/kdebug.c deleted file mode 100644 index b657886..0000000 --- a/ucore-thumips/kern/debug/kdebug.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define STACKFRAME_DEPTH 20 - - - -/* * - * print_kerninfo - print the information about kernel, including the location - * of kernel entry, the start addresses of data and text segements, the start - * address of free memory and how many memory that kernel has used. - * */ -void -print_kerninfo(void) { - extern char etext[], edata[], end[], kern_init[]; - kprintf("Special kernel symbols:\n"); - kprintf(" entry 0x"); - printhex((unsigned int)kern_init); - kprintf(" (phys)\n"); - kprintf(" etext\t0x"); - printhex((unsigned int)etext); - kprintf(" (phys)\n"); - kprintf(" edata\t0x"); - printhex((unsigned int)edata); - kprintf(" (phys)\n"); - kprintf(" end\t0x"); - printhex((unsigned int)end); - kprintf(" (phys)\n"); - kprintf("Kernel executable memory footprint: "); - printbase10( (end - etext + 1023)>>10 ); - kprintf("KB\n"); -} - -/* * - * print_debuginfo - read and print the stat information for the address @eip, - * and info.eip_fn_addr should be the first address of the related function. - * */ -void -print_debuginfo(uintptr_t eip) { - panic("Unimpl"); - -} - -/* * - * print_stackframe - print a list of the saved eip values from the nested 'call' - * instructions that led to the current point of execution - * - * The x86 stack pointer, namely esp, points to the lowest location on the stack - * that is currently in use. Everything below that location in stack is free. Pushing - * a value onto the stack will invole decreasing the stack pointer and then writing - * the value to the place that stack pointer pointes to. And popping a value do the - * opposite. - * - * The ebp (base pointer) register, in contrast, is associated with the stack - * primarily by software convention. On entry to a C function, the function's - * prologue code normally saves the previous function's base pointer by pushing - * it onto the stack, and then copies the current esp value into ebp for the duration - * of the function. If all the functions in a program obey this convention, - * then at any given point during the program's execution, it is possible to trace - * back through the stack by following the chain of saved ebp pointers and determining - * exactly what nested sequence of function calls caused this particular point in the - * program to be reached. This capability can be particularly useful, for example, - * when a particular function causes an assert failure or panic because bad arguments - * were passed to it, but you aren't sure who passed the bad arguments. A stack - * backtrace lets you find the offending function. - * - * The inline function read_ebp() can tell us the value of current ebp. And the - * non-inline function read_eip() is useful, it can read the value of current eip, - * since while calling this function, read_eip() can read the caller's eip from - * stack easily. - * - * In print_debuginfo(), the function debuginfo_eip() can get enough information about - * calling-chain. Finally print_stackframe() will trace and print them for debugging. - * - * Note that, the length of ebp-chain is limited. In boot/bootasm.S, before jumping - * to the kernel entry, the value of ebp has been set to zero, that's the boundary. - * */ -void -print_stackframe(void) { - panic("Unimpl"); -} - diff --git a/ucore-thumips/kern/debug/kdebug.h b/ucore-thumips/kern/debug/kdebug.h deleted file mode 100644 index aedc06d..0000000 --- a/ucore-thumips/kern/debug/kdebug.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __KERN_DEBUG_KDEBUG_H__ -#define __KERN_DEBUG_KDEBUG_H__ - -#include -#include - -void print_kerninfo(void); -void print_stackframe(void); -void print_debuginfo(uintptr_t eip); - - -#endif /* !__KERN_DEBUG_KDEBUG_H__ */ - diff --git a/ucore-thumips/kern/debug/monitor.c b/ucore-thumips/kern/debug/monitor.c deleted file mode 100644 index 5d2106b..0000000 --- a/ucore-thumips/kern/debug/monitor.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* * - * Simple command-line kernel monitor useful for controlling the - * kernel and exploring the system interactively. - * */ - -struct command { - const char *name; - const char *desc; - // return -1 to force monitor to exit - int(*func)(int argc, char **argv, struct trapframe *tf); -}; - -static struct command commands[] = { - {"help", "Display this list of commands.", mon_help}, - {"kerninfo", "Display information about the kernel.", mon_kerninfo}, -}; - -/* return if kernel is panic, in kern/debug/panic.c */ -bool is_kernel_panic(void); - -#define NCOMMANDS (sizeof(commands)/sizeof(struct command)) - -/***** Kernel monitor command interpreter *****/ - -#define MAXARGS 16 -#define WHITESPACE " \t\n\r" - -/* parse - parse the command buffer into whitespace-separated arguments */ -static int -parse(char *buf, char **argv) { - int argc = 0; - while (1) { - // find global whitespace - while (*buf != '\0' && strchr(WHITESPACE, *buf) != NULL) { - *buf ++ = '\0'; - } - if (*buf == '\0') { - break; - } - - // save and scan past next arg - if (argc == MAXARGS - 1) { - kprintf("Too many arguments.\n" ); - } - argv[argc ++] = buf; - while (*buf != '\0' && strchr(WHITESPACE, *buf) == NULL) { - buf ++; - } - } - return argc; -} - -/* * - * runcmd - parse the input string, split it into separated arguments - * and then lookup and invoke some related commands/ - * */ -static int -runcmd(char *buf, struct trapframe *tf) { - char *argv[MAXARGS]; - int argc = parse(buf, argv); - if (!argc) { - return 0; - } - int i; - for (i = 0; i < NCOMMANDS; i ++) { - if (!strcmp(commands[i].name, argv[0])) { - return commands[i].func(argc - 1, argv + 1, tf); - } - } - kprintf("Unknown command '"); - kprintf(argv[0]); - kprintf("'\n"); - return 0; -} - -/***** Implementations of basic kernel monitor commands *****/ - -void -monitor(struct trapframe *tf) { - kprintf("Welcome to the kernel debug monitor!!\n"); - kprintf("Type 'help' for a list of commands.\n"); - - if (tf != NULL) { - print_trapframe(tf); - } - - char *buf; - while (1) { - if ((buf = readline("K> ")) != NULL) { - if (runcmd(buf, tf) < 0) { - break; - } - } - } -} - -/* mon_help - print the information about mon_* functions */ -int -mon_help(int argc, char **argv, struct trapframe *tf) { - int i; - for (i = 0; i < NCOMMANDS; i ++) { - kprintf(commands[i].name); - kprintf(" - "); - kprintf(commands[i].desc); - kprintf("\n"); - } - return 0; -} - -/* * - * mon_kerninfo - call print_kerninfo in kern/debug/kdebug.c to - * print the memory occupancy in kernel. - * */ -int -mon_kerninfo(int argc, char **argv, struct trapframe *tf) { - print_kerninfo(); - return 0; -} - diff --git a/ucore-thumips/kern/debug/monitor.h b/ucore-thumips/kern/debug/monitor.h deleted file mode 100644 index 53f1e96..0000000 --- a/ucore-thumips/kern/debug/monitor.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __KERN_DEBUG_MONITOR_H__ -#define __KERN_DEBUG_MONITOR_H__ - -#include - -void monitor(struct trapframe *tf); - -int mon_help(int argc, char **argv, struct trapframe *tf); -int mon_kerninfo(int argc, char **argv, struct trapframe *tf); - -#endif /* !__KERN_DEBUG_MONITOR_H__ */ - diff --git a/ucore-thumips/kern/debug/panic.c b/ucore-thumips/kern/debug/panic.c deleted file mode 100644 index 2f49570..0000000 --- a/ucore-thumips/kern/debug/panic.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include - -static bool is_panic = 0; - -/* * - * __panic - __panic is called on unresolvable fatal errors. it prints - * "panic: 'message'", and then enters the kernel monitor. - * */ -void -__panic(const char *file, int line, const char *fmt, ...) { - if (is_panic) { - goto panic_dead; - } - is_panic = 1; - - // print the 'message' - va_list ap; - va_start(ap, fmt); - kprintf("kernel panic at %s:%d:\n ", file, line); - vkprintf(fmt, ap); - kprintf("\n"); - va_end(ap); - -panic_dead: - intr_disable(); - while (1) { - monitor(NULL); - } -} - -/* __warn - like panic, but don't */ -void -__warn(const char *file, int line, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - kprintf("kernel warning at %s:%d:\n ", file, line); - vkprintf(fmt, ap); - kprintf("\n"); - va_end(ap); -} - -bool -is_kernel_panic(void) { - return is_panic; -} - diff --git a/ucore-thumips/kern/driver/clock.c b/ucore-thumips/kern/driver/clock.c deleted file mode 100644 index 30b8a0a..0000000 --- a/ucore-thumips/kern/driver/clock.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include -#include -#include - -volatile size_t ticks; - -#define TIMER0_INTERVAL 1000000 - -static void reload_timer() -{ - uint32_t counter = read_c0_count(); - counter += TIMER0_INTERVAL; - write_c0_compare(counter); -} - -int clock_int_handler(void * data) -{ - ticks++; -// if( (ticks & 0x1F) == 0) -// cons_putc('A'); - run_timer_list(); - reload_timer(); - return 0; -} - -void -clock_init(void) { - reload_timer(); - pic_enable(TIMER0_IRQ); - kprintf("++setup timer interrupts\n"); -} - diff --git a/ucore-thumips/kern/driver/clock.h b/ucore-thumips/kern/driver/clock.h deleted file mode 100644 index e22f393..0000000 --- a/ucore-thumips/kern/driver/clock.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __KERN_DRIVER_CLOCK_H__ -#define __KERN_DRIVER_CLOCK_H__ - -#include - -extern volatile size_t ticks; - -void clock_init(void); - -#endif /* !__KERN_DRIVER_CLOCK_H__ */ - diff --git a/ucore-thumips/kern/driver/console.c b/ucore-thumips/kern/driver/console.c deleted file mode 100644 index 7bf299b..0000000 --- a/ucore-thumips/kern/driver/console.c +++ /dev/null @@ -1,215 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "vga.h" - -/* stupid I/O delay routine necessitated by historical PC design flaws */ -static void -delay(void) { -} - -/***** Serial I/O code *****/ - -#define COM_RX 0 // In: Receive buffer (DLAB=0) -#define COM_TX 0 // Out: Transmit buffer (DLAB=0) -#define COM_DLL 0 // Out: Divisor Latch Low (DLAB=1) -#define COM_DLM 1 // Out: Divisor Latch High (DLAB=1) -#define COM_IER 1 // Out: Interrupt Enable Register -#define COM_IER_RDI 0x01 // Enable receiver data interrupt -#define COM_IIR 2 // In: Interrupt ID Register -#define COM_FCR 2 // Out: FIFO Control Register -#define COM_LCR 3 // Out: Line Control Register -#define COM_LCR_DLAB 0x80 // Divisor latch access bit -#define COM_LCR_WLEN8 0x03 // Wordlength: 8 bits -#define COM_MCR 4 // Out: Modem Control Register -#define COM_MCR_RTS 0x02 // RTS complement -#define COM_MCR_DTR 0x01 // DTR complement -#define COM_MCR_OUT2 0x08 // Out2 complement -#define COM_LSR 5 // In: Line Status Register -#define COM_LSR_DATA 0x01 // Data available -#define COM_LSR_TXRDY 0x20 // Transmit buffer avail -#define COM_LSR_TSRE 0x40 // Transmitter off - - -static bool serial_exists = 0; - -static void -serial_init(void) { - volatile unsigned char *uart = (unsigned char*)COM1; - if(serial_exists) - return ; - serial_exists = 1; -#ifdef MACH_QEMU - // Turn off the FIFO - outb(COM1 + COM_FCR, 0); - // Set speed; requires DLAB latch - outb(COM1 + COM_LCR, COM_LCR_DLAB); - outb(COM1 + COM_DLL, (uint8_t) (115200 / 9600)); - outb(COM1 + COM_DLM, 0); - - // 8 data bits, 1 stop bit, parity off; turn off DLAB latch - outb(COM1 + COM_LCR, COM_LCR_WLEN8 & ~COM_LCR_DLAB); - - // No modem controls - outb(COM1 + COM_MCR, 0); - // Enable rcv interrupts - outb(COM1 + COM_IER, COM_IER_RDI); -#elif defined MACH_FPGA - //TODO -#endif - - pic_enable(COM1_IRQ); -} - - -static void -serial_putc_sub(int c) { -#ifdef MACH_QEMU - outb(COM1 + COM_TX, c); -#elif defined MACH_FPGA - //TODO - while( (inw(COM1 + 0x04) & 0x01) == 0 ); - outw(COM1 + 0x00, c & 0xFF); -#endif -} - -/* serial_putc - print character to serial port */ -static void -serial_putc(int c) { - if (c == '\b') { - serial_putc_sub('\b'); - serial_putc_sub(' '); - serial_putc_sub('\b'); - }else { - serial_putc_sub(c); - } -} - -/* serial_proc_data - get data from serial port */ -static int -serial_proc_data(void) { - int c; -#ifdef MACH_QEMU - if (!(inb(COM1 + COM_LSR) & COM_LSR_DATA)) { - return -1; - } - c = inb(COM1 + COM_RX); -#elif defined MACH_FPGA - //TODO - if( (inw(COM1 + 0x04) & 0x02) == 0) - return -1; - c = inw(COM1 + 0x00) & 0xFF; -#endif - if (c == 127) { - c = '\b'; - } - return c; -} - - -void serial_int_handler(void *opaque) -{ -#ifdef MACH_QEMU - unsigned char id = inb(COM1+COM_IIR); - if(id & 0x01) - return ; -#endif - //int c = serial_proc_data(); - int c = cons_getc(c); - extern void dev_stdin_write(char c); - dev_stdin_write(c); -} - -/* * - * Here we manage the console input buffer, where we stash characters - * received from the keyboard or serial port whenever the corresponding - * interrupt occurs. - * */ - -#define CONSBUFSIZE 512 - -static struct { - uint8_t buf[CONSBUFSIZE]; - uint32_t rpos; - uint32_t wpos; -} cons; - -/* * - * cons_intr - called by device interrupt routines to feed input - * characters into the circular console input buffer. - * */ -static void -cons_intr(int (*proc)(void)) { - int c; - while ((c = (*proc)()) != -1) { - if (c != 0) { - cons.buf[cons.wpos ++] = c; - if (cons.wpos == CONSBUFSIZE) { - cons.wpos = 0; - } - } - } -} - -/* serial_intr - try to feed input characters from serial port */ -void -serial_intr(void) { - if (serial_exists) { - cons_intr(serial_proc_data); - } -} - -/* cons_init - initializes the console devices */ -void -cons_init(void) { - serial_init(); - //cons.rpos = cons.wpos = 0; - if (!serial_exists) { - kprintf("serial port does not exist!!\n"); - } -} - -/* cons_putc - print a single character @c to console devices */ -void -cons_putc(int c) { - bool intr_flag; - local_intr_save(intr_flag); - { - serial_putc(c); - vga_putc(c); - } - local_intr_restore(intr_flag); -} - -/* * - * cons_getc - return the next input character from console, - * or 0 if none waiting. - * */ -int -cons_getc(void) { - int c = 0; - bool intr_flag; - local_intr_save(intr_flag); - { - // poll for any pending input characters, - // so that this function works even when interrupts are disabled - // (e.g., when called from the kernel monitor). - serial_intr(); - - // grab the next character from the input buffer. - if (cons.rpos != cons.wpos) { - c = cons.buf[cons.rpos ++]; - if (cons.rpos == CONSBUFSIZE) { - cons.rpos = 0; - } - } - } - local_intr_restore(intr_flag); - return c; -} - diff --git a/ucore-thumips/kern/driver/console.h b/ucore-thumips/kern/driver/console.h deleted file mode 100644 index 9e485ea..0000000 --- a/ucore-thumips/kern/driver/console.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __KERN_DRIVER_CONSOLE_H__ -#define __KERN_DRIVER_CONSOLE_H__ - -void cons_init(void); -void cons_putc(int c); -int cons_getc(void); -void serial_intr(void); - -#endif /* !__KERN_DRIVER_CONSOLE_H__ */ - diff --git a/ucore-thumips/kern/driver/ide.c b/ucore-thumips/kern/driver/ide.c deleted file mode 100644 index 112a2c6..0000000 --- a/ucore-thumips/kern/driver/ide.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VALID_IDE(ideno) (((ideno) >= 0) && ((ideno) < MAX_IDE) && (ide_devices[ideno].valid)) - -#define MAX_IDE 4 - -#define CHECK_CALL(ideno, func) (VALID_IDE(ideno) && ide_devices[ideno].func) - - -//#define _CHECK_NANDFLASH - -static struct ide_device ide_devices[MAX_IDE]; - - -static int -ide_wait_ready(unsigned int iobase, bool check_error) { - return 0; -} - -// TODO: check if ramdisk are there -void -ide_init(void) { - int i; - for(i=0;i - - -void ide_init(void); -bool ide_device_valid(unsigned int ideno); -size_t ide_device_size(unsigned int ideno); - -int ide_read_secs(unsigned int ideno, uint32_t secno, void *dst, size_t nsecs); -int ide_write_secs(unsigned int ideno, uint32_t secno, const void *src, size_t nsecs); - -struct ide_device { - unsigned int valid; // 0 or 1 (If Device Really Exists) - unsigned int sets; // Commend Sets Supported - unsigned int size; // Size in Sectors - uintptr_t iobase; - void * dev_data; - char model[32]; // Model in String - - void (*init)(struct ide_device *dev); - /* return 0 if succeed */ - int (*read_secs)(struct ide_device *dev, size_t secno, void *dst, size_t nsecs); - int (*write_secs)(struct ide_device *dev, size_t secno, const void *src, size_t nsecs); - -}; - -#endif /* !__KERN_DRIVER_RAMDISK_H__ */ - diff --git a/ucore-thumips/kern/driver/intr.c b/ucore-thumips/kern/driver/intr.c deleted file mode 100644 index 313eec2..0000000 --- a/ucore-thumips/kern/driver/intr.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include - -#define get_status(x) __asm volatile("mfc0 %0,$12" : "=r" (x)) -#define set_status(x) __asm volatile("mtc0 %0,$12" :: "r" (x)) - -/* intr_enable - enable irq interrupt */ -void -intr_enable(void) { - uint32_t x; - get_status(x); - x |= ST0_IE; - set_status(x); - -} - -/* intr_disable - disable irq interrupt */ -void -intr_disable(void) { - uint32_t x; - get_status(x); - x &= ~ST0_IE; - set_status(x); -} - diff --git a/ucore-thumips/kern/driver/intr.h b/ucore-thumips/kern/driver/intr.h deleted file mode 100644 index afbdf1f..0000000 --- a/ucore-thumips/kern/driver/intr.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __KERN_DRIVER_INTR_H__ -#define __KERN_DRIVER_INTR_H__ - -#include -#include - -void intr_enable(void); -void intr_disable(void); - - -static inline bool -__intr_save(void) { - if (!(read_c0_status() & ST0_IE)) { - return 0; - } - intr_disable(); - return 1; -} - -static inline void -__intr_restore(bool flag) { - if (flag) { - intr_enable(); - } -} - -#define local_intr_save(x) do { x = __intr_save(); } while (0) -#define local_intr_restore(x) __intr_restore(x); - -#endif /* !__KERN_DRIVER_INTR_H__ */ - diff --git a/ucore-thumips/kern/driver/picirq.c b/ucore-thumips/kern/driver/picirq.c deleted file mode 100644 index 9aa0024..0000000 --- a/ucore-thumips/kern/driver/picirq.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include - -static bool did_init = 0; - - -void -pic_enable(unsigned int irq) { - assert(irq < 8); - uint32_t sr = read_c0_status(); - sr |= 1<<(irq + STATUSB_IP0); - write_c0_status(sr); -} - -void pic_disable(unsigned int irq){ - assert(irq < 8); - uint32_t sr = read_c0_status(); - sr &= ~(1<<(irq + STATUSB_IP0)); - write_c0_status(sr); -} - -void -pic_init(void) { - uint32_t sr = read_c0_status(); - /* disable all */ - sr &= ~ST0_IM; - write_c0_status(sr); - did_init = 1; -} - diff --git a/ucore-thumips/kern/driver/picirq.h b/ucore-thumips/kern/driver/picirq.h deleted file mode 100644 index 42aa217..0000000 --- a/ucore-thumips/kern/driver/picirq.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __KERN_DRIVER_PICIRQ_H__ -#define __KERN_DRIVER_PICIRQ_H__ - -void pic_init(void); -void pic_enable(unsigned int irq); -void pic_disable(unsigned int irq); - -#define IRQ_OFFSET 32 - -#endif /* !__KERN_DRIVER_PICIRQ_H__ */ - diff --git a/ucore-thumips/kern/driver/ramdisk.c b/ucore-thumips/kern/driver/ramdisk.c deleted file mode 100644 index 692f9d1..0000000 --- a/ucore-thumips/kern/driver/ramdisk.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * ===================================================================================== - * - * Filename: ramdisk.c - * - * Description: - * - * Version: 1.0 - * Created: 03/26/2012 06:16:29 PM - * Revision: none - * Compiler: gcc - * - * Author: Chen Yuheng (Chen Yuheng), chyh1990@163.com - * Organization: Tsinghua Unv. - * - * ===================================================================================== - */ - -#include -#include -#include -#include -#include -#include -#include - -#define MIN(x,y) (((x)<(y))?(x):(y)) - -//char initrd_begin[], initrd_end[]; - -bool check_initrd(){ - if(_initrd_begin == _initrd_end){ - kprintf("Warning: No Initrd!\n"); - return 0; - } - kprintf("Initrd: 0x%08x - 0x%08x, size: 0x%08x, magic: 0x%02x%02x%02x%02x\n", - _initrd_begin, _initrd_end-1, _initrd_end - _initrd_begin, - *(uint8_t*)(_initrd_begin+3), *(uint8_t*)(_initrd_begin+2), - *(uint8_t*)(_initrd_begin+1), *(uint8_t*)_initrd_begin); - return 1; -} - - -static int ramdisk_read(struct ide_device* dev, size_t secno, void *dst, size_t nsecs) -{ - nsecs = MIN(nsecs, dev->size-secno); - if(nsecs<0) - return -1; - memcpy(dst, (void*)(dev->iobase+secno*SECTSIZE), nsecs*SECTSIZE); - return 0; -} - -static int ramdisk_write(struct ide_device* dev, size_t secno,const void *src, size_t nsecs) -{ - //kprintf("%08x(%d) %08x(%d)\n", dev->size, dev->size, secno, secno); - nsecs = MIN(nsecs, dev->size-secno); - if(nsecs<0) - return -1; - memcpy( (void*)(dev->iobase+secno*SECTSIZE),src, nsecs*SECTSIZE); - return 0; -} - -static void ramdisk_init(struct ide_device* dev){ - kprintf("ramdisk_init(): initrd found, magic: 0x%08x, 0x%08x secs\n", *(uint32_t*)(dev->iobase), dev->size); - -} - - -void ramdisk_init_struct(struct ide_device* dev) -{ - memset(dev, 0, sizeof(struct ide_device)); - assert(INITRD_SIZE()%SECTSIZE == 0); - if(CHECK_INITRD_EXIST()){ - dev->valid = 1; - dev->sets = ~0; - dev->size = INITRD_SIZE()/SECTSIZE; - dev->iobase = (uintptr_t)_initrd_begin; - strcpy(dev->model, "KERN_INITRD"); - dev->init = ramdisk_init; - dev->read_secs = ramdisk_read; - dev->write_secs = ramdisk_write; - } -} - diff --git a/ucore-thumips/kern/driver/ramdisk.h b/ucore-thumips/kern/driver/ramdisk.h deleted file mode 100644 index 2eb3823..0000000 --- a/ucore-thumips/kern/driver/ramdisk.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ===================================================================================== - * - * Filename: ramdisk.h - * - * Description: - * - * Version: 1.0 - * Created: 03/26/2012 03:35:39 PM - * Revision: none - * Compiler: gcc - * - * Author: Chen Yuheng (Chen Yuheng), chyh1990@163.com - * Organization: Tsinghua Unv. - * - * ===================================================================================== - */ - -#include -#include - -/* defined in ldscript */ -extern char _initrd_begin[], _initrd_end[]; - -bool check_initrd(); - -#define CHECK_INITRD_EXIST() (_initrd_end != _initrd_begin) -#define INITRD_SIZE() (_initrd_end - _initrd_begin) - -void ramdisk_init_struct(struct ide_device* dev); - diff --git a/ucore-thumips/kern/driver/vga.c b/ucore-thumips/kern/driver/vga.c deleted file mode 100644 index 3c382b3..0000000 --- a/ucore-thumips/kern/driver/vga.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "vga.h" -#include -#include - -#define LINES 24 -#define COLUMNS 64 // COLUMNS should be multiple of 4 -#define CHAR_HEIGHT 16 -#define CHAR_WIDTH 8 -#define LINE_OFFSET 2 -#define COLUMN_OFFSET 1 - -static int lineSt, lineEn; // Circulative, [lineSt, lineEn] -static int offset; // Horizontal position of current char -static uint8_t lines[LINES][COLUMNS]; -// Prefetched lattice, because main memory (1 period read) is faster -// than lattice memory (2 periods read) -static uint32_t lattice[128][CHAR_HEIGHT * CHAR_WIDTH / 32]; - -void _vga_put_one_char(int ltrn, int ltcn, uint8_t ch) { - const int ltr = ltrn * CHAR_HEIGHT, ltc = ltcn * CHAR_WIDTH; - int r, c; - int latBit = 31, latWord = 0; - uint32_t latc; - for (r = 0; r < CHAR_HEIGHT; ++r) { - if ((r & 3) == 0) { - latc = lattice[ch][latWord]; - latWord++; - latBit = 31; - } - for (c = 0; c < CHAR_WIDTH; ++c) { - if ((latc >> latBit) % 2 == 1) - outb(VGA_BASE + (ltr + r + LINE_OFFSET) * 640 + ltc + c + COLUMN_OFFSET, 0xff); - else - outb(VGA_BASE + (ltr + r + LINE_OFFSET) * 640 + ltc + c + COLUMN_OFFSET, 0); - latBit--; - } - } -} - -void _vga_flush() { - int ltrn, ltcn; - for (ltrn = 0; ltrn < LINES; ltrn++) { - const int lineID = (lineSt + ltrn) % LINES; - const int lastID = (lineID + LINES - 1) % LINES; - for (ltcn = 0; ltcn < COLUMNS; ltcn++) - if (lines[lineID][ltcn] != lines[lastID][ltcn]) - _vga_put_one_char(ltrn, ltcn, lines[lineID][ltcn]); - } -} - -void _vga_nextline() { - offset = 0; - lineEn = (lineEn + 1) % LINES; - if (lineEn == lineSt) { - int i = 0; - for (i = 0; i < COLUMNS; i += 4) - *((uint32_t *)(lines[lineSt] + i)) = 0; - lineSt = (lineSt + 1) % LINES; - _vga_flush(); - } -} - -void vga_init() { - lineSt = lineEn = 0; - offset = 0; - int i; - for (i = 0; i < LINES * COLUMNS; i += 4) { - *((uint32_t *)(lines + i)) = 0; - } - for (i = 0; i < 128 * CHAR_HEIGHT * CHAR_WIDTH / 32; i++) - *((uint32_t *)lattice + i) = *((uint32_t *)LATTICE_BASE + i); - uint32_t addr; - for (addr = VGA_BASE; addr < VGA_TOP; ++addr) { - outb(addr, 0); - } -} - -void vga_putc(uint8_t ch) { - if (ch == '\n') { - _vga_nextline(); - return; - } - if (offset == COLUMNS) - _vga_nextline(); - lines[lineEn][offset] = ch; - _vga_put_one_char((lineEn - lineSt + LINES) % LINES, offset, ch); - offset++; -} - diff --git a/ucore-thumips/kern/driver/vga.h b/ucore-thumips/kern/driver/vga.h deleted file mode 100644 index 555c90f..0000000 --- a/ucore-thumips/kern/driver/vga.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __KERN_DRIVER_VGA_H__ -#define __KERN_DRIVER_VGA_H__ - -#include -#include - -void vga_init(); -void vga_putc(uint8_t ch); - -#endif \ No newline at end of file diff --git a/ucore-thumips/kern/fs/devs/dev.c b/ucore-thumips/kern/fs/devs/dev.c deleted file mode 100644 index 757ce10..0000000 --- a/ucore-thumips/kern/fs/devs/dev.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static int -dev_open(struct inode *node, uint32_t open_flags) { - if (open_flags & (O_CREAT | O_TRUNC | O_EXCL | O_APPEND)) { - return -E_INVAL; - } - struct device *dev = vop_info(node, device); - return dop_open(dev, open_flags); -} - -static int -dev_close(struct inode *node) { - struct device *dev = vop_info(node, device); - return dop_close(dev); -} - -static int -dev_read(struct inode *node, struct iobuf *iob) { - struct device *dev = vop_info(node, device); - return dop_io(dev, iob, 0); -} - -static int -dev_write(struct inode *node, struct iobuf *iob) { - struct device *dev = vop_info(node, device); - return dop_io(dev, iob, 1); -} - -static int -dev_ioctl(struct inode *node, int op, void *data) { - struct device *dev = vop_info(node, device); - return dop_ioctl(dev, op, data); -} - -static int -dev_fstat(struct inode *node, struct stat *stat) { - int ret; - memset(stat, 0, sizeof(struct stat)); - if ((ret = vop_gettype(node, &(stat->st_mode))) != 0) { - return ret; - } - struct device *dev = vop_info(node, device); - stat->st_nlinks = 1; - stat->st_blocks = dev->d_blocks; - stat->st_size = stat->st_blocks * dev->d_blocksize; - return 0; -} - -static int -dev_gettype(struct inode *node, uint32_t *type_store) { - struct device *dev = vop_info(node, device); - *type_store = (dev->d_blocks > 0) ? S_IFBLK : S_IFCHR; - return 0; -} - -static int -dev_tryseek(struct inode *node, off_t pos) { - struct device *dev = vop_info(node, device); - if (dev->d_blocks > 0) { - if ((pos % dev->d_blocksize) == 0) { - if (pos >= 0 && pos < dev->d_blocks * dev->d_blocksize) { - return 0; - } - } - } - return -E_INVAL; -} - -static int -dev_lookup(struct inode *node, char *path, struct inode **node_store) { - if (*path != '\0') { - return -E_NOENT; - } - vop_ref_inc(node); - *node_store = node; - return 0; -} - -static const struct inode_ops dev_node_ops = { - .vop_magic = VOP_MAGIC, - .vop_open = dev_open, - .vop_close = dev_close, - .vop_read = dev_read, - .vop_write = dev_write, - .vop_fstat = dev_fstat, - .vop_ioctl = dev_ioctl, - .vop_gettype = dev_gettype, - .vop_tryseek = dev_tryseek, - .vop_lookup = dev_lookup, -}; - -#define init_device(x) \ - do { \ - extern void dev_init_##x(void); \ - dev_init_##x(); \ - } while (0) - -void -dev_init(void) { - // init_device(null); - init_device(stdin); - init_device(stdout); - init_device(disk0); -} - -struct inode * -dev_create_inode(void) { - struct inode *node; - if ((node = alloc_inode(device)) != NULL) { - vop_init(node, &dev_node_ops, NULL); - } - return node; -} - diff --git a/ucore-thumips/kern/fs/devs/dev.h b/ucore-thumips/kern/fs/devs/dev.h deleted file mode 100644 index cc6952f..0000000 --- a/ucore-thumips/kern/fs/devs/dev.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __KERN_FS_DEVS_DEV_H__ -#define __KERN_FS_DEVS_DEV_H__ - -#include - -struct inode; -struct iobuf; - -struct device { - size_t d_blocks; - size_t d_blocksize; - int (*d_open)(struct device *dev, uint32_t open_flags); - int (*d_close)(struct device *dev); - int (*d_io)(struct device *dev, struct iobuf *iob, bool write); - int (*d_ioctl)(struct device *dev, int op, void *data); -}; - -#define dop_open(dev, open_flags) ((dev)->d_open(dev, open_flags)) -#define dop_close(dev) ((dev)->d_close(dev)) -#define dop_io(dev, iob, write) ((dev)->d_io(dev, iob, write)) -#define dop_ioctl(dev, op, data) ((dev)->d_ioctl(dev, op, data)) - -void dev_init(void); -struct inode *dev_create_inode(void); - -#endif /* !__KERN_FS_DEVS_DEV_H__ */ - diff --git a/ucore-thumips/kern/fs/devs/dev_disk0.c b/ucore-thumips/kern/fs/devs/dev_disk0.c deleted file mode 100644 index 3d6fc1d..0000000 --- a/ucore-thumips/kern/fs/devs/dev_disk0.c +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DISK0_BLKSIZE PGSIZE -#define DISK0_BUFSIZE (4 * DISK0_BLKSIZE) -#define DISK0_BLK_NSECT (DISK0_BLKSIZE / SECTSIZE) - -static char *disk0_buffer; -static semaphore_t disk0_sem; - -static void -lock_disk0(void) { - down(&(disk0_sem)); -} - -static void -unlock_disk0(void) { - up(&(disk0_sem)); -} - -static int -disk0_open(struct device *dev, uint32_t open_flags) { - return 0; -} - -static int -disk0_close(struct device *dev) { - return 0; -} - -static void -disk0_read_blks_nolock(uint32_t blkno, uint32_t nblks) { - int ret; - uint32_t sectno = blkno * DISK0_BLK_NSECT, nsecs = nblks * DISK0_BLK_NSECT; - if ((ret = ide_read_secs(DISK0_DEV_NO, sectno, disk0_buffer, nsecs)) != 0) { - panic("disk0: read blkno = %d (sectno = %d), nblks = %d (nsecs = %d): 0x%08x.\n", - blkno, sectno, nblks, nsecs, ret); - } -} - -static void -disk0_write_blks_nolock(uint32_t blkno, uint32_t nblks) { - int ret; - uint32_t sectno = blkno * DISK0_BLK_NSECT, nsecs = nblks * DISK0_BLK_NSECT; - if ((ret = ide_write_secs(DISK0_DEV_NO, sectno, disk0_buffer, nsecs)) != 0) { - panic("disk0: write blkno = %d (sectno = %d), nblks = %d (nsecs = %d): 0x%08x.\n", - blkno, sectno, nblks, nsecs, ret); - } -} - -static int -disk0_io(struct device *dev, struct iobuf *iob, bool write) { - off_t offset = iob->io_offset; - size_t resid = iob->io_resid; - uint32_t blkno = offset / DISK0_BLKSIZE; - uint32_t nblks = resid / DISK0_BLKSIZE; - - /* don't allow I/O that isn't block-aligned */ - if ((offset % DISK0_BLKSIZE) != 0 || (resid % DISK0_BLKSIZE) != 0) { - return -E_INVAL; - } - - /* don't allow I/O past the end of disk0 */ - if (blkno + nblks > dev->d_blocks) { - return -E_INVAL; - } - - /* read/write nothing ? */ - if (nblks == 0) { - return 0; - } - - lock_disk0(); - while (resid != 0) { - size_t copied, alen = DISK0_BUFSIZE; - if (write) { - iobuf_move(iob, disk0_buffer, alen, 0, &copied); - assert(copied != 0 && copied <= resid && copied % DISK0_BLKSIZE == 0); - nblks = copied / DISK0_BLKSIZE; - disk0_write_blks_nolock(blkno, nblks); - } - else { - if (alen > resid) { - alen = resid; - } - nblks = alen / DISK0_BLKSIZE; - disk0_read_blks_nolock(blkno, nblks); - iobuf_move(iob, disk0_buffer, alen, 1, &copied); - assert(copied == alen && copied % DISK0_BLKSIZE == 0); - } - resid -= copied, blkno += nblks; - } - unlock_disk0(); - return 0; -} - -static int -disk0_ioctl(struct device *dev, int op, void *data) { - return -E_UNIMP; -} - -static void -disk0_device_init(struct device *dev) { - static_assert(DISK0_BLKSIZE % SECTSIZE == 0); - if (!ide_device_valid(DISK0_DEV_NO)) { - panic("disk0 device isn't available.\n"); - } - dev->d_blocks = ide_device_size(DISK0_DEV_NO) / DISK0_BLK_NSECT; - dev->d_blocksize = DISK0_BLKSIZE; - dev->d_open = disk0_open; - dev->d_close = disk0_close; - dev->d_io = disk0_io; - dev->d_ioctl = disk0_ioctl; - sem_init(&(disk0_sem), 1); - - static_assert(DISK0_BUFSIZE % DISK0_BLKSIZE == 0); - if ((disk0_buffer = kmalloc(DISK0_BUFSIZE)) == NULL) { - panic("disk0 alloc buffer failed.\n"); - } -} - -void -dev_init_disk0(void) { - struct inode *node; - if ((node = dev_create_inode()) == NULL) { - panic("disk0: dev_create_node.\n"); - } - disk0_device_init(vop_info(node, device)); - - int ret; - if ((ret = vfs_add_dev("disk0", node, 1)) != 0) { - panic("disk0: vfs_add_dev: %e.\n", ret); - } -} - diff --git a/ucore-thumips/kern/fs/devs/dev_stdin.c b/ucore-thumips/kern/fs/devs/dev_stdin.c deleted file mode 100644 index 17af004..0000000 --- a/ucore-thumips/kern/fs/devs/dev_stdin.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define STDIN_BUFSIZE 2048 - -static char stdin_buffer[STDIN_BUFSIZE]; -static off_t p_rpos, p_wpos; -static wait_queue_t __wait_queue, *wait_queue = &__wait_queue; - -void -dev_stdin_write(char c) { - bool intr_flag; - if (c != '\0') { - local_intr_save(intr_flag); - { - stdin_buffer[p_wpos % STDIN_BUFSIZE] = c; - if (p_wpos - p_rpos < STDIN_BUFSIZE) { - p_wpos ++; - } - if (!wait_queue_empty(wait_queue)) { - wakeup_queue(wait_queue, WT_KBD, 1); - } - } - local_intr_restore(intr_flag); - } -} - -static int -dev_stdin_read(char *buf, size_t len) { - int ret = 0; - bool intr_flag; - local_intr_save(intr_flag); - { - for (; ret < len; ret ++, p_rpos ++) { - try_again: - if (p_rpos < p_wpos) { - *buf ++ = stdin_buffer[p_rpos % STDIN_BUFSIZE]; - } - else { - wait_t __wait, *wait = &__wait; - wait_current_set(wait_queue, wait, WT_KBD); - local_intr_restore(intr_flag); - - schedule(); - - local_intr_save(intr_flag); - wait_current_del(wait_queue, wait); - if (wait->wakeup_flags == WT_KBD) { - goto try_again; - } - break; - } - } - } - local_intr_restore(intr_flag); - return ret; -} - -static int -stdin_open(struct device *dev, uint32_t open_flags) { - if (open_flags != O_RDONLY) { - return -E_INVAL; - } - return 0; -} - -static int -stdin_close(struct device *dev) { - return 0; -} - -static int -stdin_io(struct device *dev, struct iobuf *iob, bool write) { - if (!write) { - int ret; - if ((ret = dev_stdin_read(iob->io_base, iob->io_resid)) > 0) { - iob->io_resid -= ret; - } - return ret; - } - return -E_INVAL; -} - -static int -stdin_ioctl(struct device *dev, int op, void *data) { - return -E_INVAL; -} - -static void -stdin_device_init(struct device *dev) { - dev->d_blocks = 0; - dev->d_blocksize = 1; - dev->d_open = stdin_open; - dev->d_close = stdin_close; - dev->d_io = stdin_io; - dev->d_ioctl = stdin_ioctl; - - p_rpos = p_wpos = 0; - wait_queue_init(wait_queue); -} - -void -dev_init_stdin(void) { - struct inode *node; - if ((node = dev_create_inode()) == NULL) { - panic("stdin: dev_create_node.\n"); - } - stdin_device_init(vop_info(node, device)); - - int ret; - if ((ret = vfs_add_dev("stdin", node, 0)) != 0) { - panic("stdin: vfs_add_dev: %e.\n", ret); - } -} - diff --git a/ucore-thumips/kern/fs/devs/dev_stdout.c b/ucore-thumips/kern/fs/devs/dev_stdout.c deleted file mode 100644 index 86dc4be..0000000 --- a/ucore-thumips/kern/fs/devs/dev_stdout.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int -stdout_open(struct device *dev, uint32_t open_flags) { - if (open_flags != O_WRONLY) { - return -E_INVAL; - } - return 0; -} - -static int -stdout_close(struct device *dev) { - return 0; -} - -static int -stdout_io(struct device *dev, struct iobuf *iob, bool write) { - if (write) { - char *data = iob->io_base; - for (; iob->io_resid != 0; iob->io_resid --) { - kputchar(*data ++); - } - return 0; - } - return -E_INVAL; -} - -static int -stdout_ioctl(struct device *dev, int op, void *data) { - return -E_INVAL; -} - -static void -stdout_device_init(struct device *dev) { - dev->d_blocks = 0; - dev->d_blocksize = 1; - dev->d_open = stdout_open; - dev->d_close = stdout_close; - dev->d_io = stdout_io; - dev->d_ioctl = stdout_ioctl; -} - -void -dev_init_stdout(void) { - struct inode *node; - if ((node = dev_create_inode()) == NULL) { - panic("stdout: dev_create_node.\n"); - } - stdout_device_init(vop_info(node, device)); - - int ret; - if ((ret = vfs_add_dev("stdout", node, 0)) != 0) { - panic("stdout: vfs_add_dev: %e.\n", ret); - } -} - diff --git a/ucore-thumips/kern/fs/file.c b/ucore-thumips/kern/fs/file.c deleted file mode 100644 index 952b1d0..0000000 --- a/ucore-thumips/kern/fs/file.c +++ /dev/null @@ -1,338 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define testfd(fd) ((fd) >= 0 && (fd) < FS_STRUCT_NENTRY) - -static struct file * -get_filemap(void) { - struct fs_struct *fs_struct = current->fs_struct; - assert(fs_struct != NULL); - assert(fs_count(fs_struct) > 0); - return fs_struct->filemap; -} - -void -filemap_init(struct file *filemap) { - int fd; - struct file *file = filemap; - for (fd = 0; fd < FS_STRUCT_NENTRY; fd ++, file ++) { - atomic_set(&(file->open_count), 0); - file->status = FD_NONE, file->fd = fd; - } -} - -static int -filemap_alloc(int fd, struct file **file_store) { -// panic("debug"); - struct file *file = get_filemap(); - if (fd == NO_FD) { - for (fd = 0; fd < FS_STRUCT_NENTRY; fd ++, file ++) { - if (file->status == FD_NONE) { - goto found; - } - } - return -E_MAX_OPEN; - } - else { - if (testfd(fd)) { - file += fd; - if (file->status == FD_NONE) { - goto found; - } - return -E_BUSY; - } - return -E_INVAL; - } -found: - assert(fopen_count(file) == 0); - file->status = FD_INIT, file->node = NULL; - *file_store = file; - return 0; -} - -static void -filemap_free(struct file *file) { - assert(file->status == FD_INIT || file->status == FD_CLOSED); - assert(fopen_count(file) == 0); - if (file->status == FD_CLOSED) { - vfs_close(file->node); - } - file->status = FD_NONE; -} - -static void -filemap_acquire(struct file *file) { - assert(file->status == FD_OPENED); - fopen_count_inc(file); -} - -static void -filemap_release(struct file *file) { - assert(file->status == FD_OPENED || file->status == FD_CLOSED); - assert(fopen_count(file) > 0); - if (fopen_count_dec(file) == 0) { - filemap_free(file); - } -} - -void -filemap_open(struct file *file) { - assert(file->status == FD_INIT && file->node != NULL); - file->status = FD_OPENED; - fopen_count_inc(file); -} - -void -filemap_close(struct file *file) { - assert(file->status == FD_OPENED); - assert(fopen_count(file) > 0); - file->status = FD_CLOSED; - if (fopen_count_dec(file) == 0) { - filemap_free(file); - } -} - -void -filemap_dup(struct file *to, struct file *from) { - //kprintf("[filemap_dup]from fd=%d, to fd=%d\n",from->fd, to->fd); - assert(to->status == FD_INIT && from->status == FD_OPENED); - to->pos = from->pos; - to->readable = from->readable; - to->writable = from->writable; - struct inode *node = from->node; - vop_ref_inc(node), vop_open_inc(node); - to->node = node; - filemap_open(to); -} - -static inline int -fd2file(int fd, struct file **file_store) { - if (testfd(fd)) { - struct file *file = get_filemap() + fd; - if (file->status == FD_OPENED && file->fd == fd) { - *file_store = file; - return 0; - } - } - return -E_INVAL; -} - -bool -file_testfd(int fd, bool readable, bool writable) { - int ret; - struct file *file; - if ((ret = fd2file(fd, &file)) != 0) { - return 0; - } - if (readable && !file->readable) { - return 0; - } - if (writable && !file->writable) { - return 0; - } - return 1; -} - -int -file_open(char *path, uint32_t open_flags) { - bool readable = 0, writable = 0; - switch (open_flags & O_ACCMODE) { - case O_RDONLY: readable = 1; break; - case O_WRONLY: writable = 1; break; - case O_RDWR: - readable = writable = 1; - break; - default: - return -E_INVAL; - } - - int ret; - struct file *file; - if ((ret = filemap_alloc(NO_FD, &file)) != 0) { - return ret; - } - - struct inode *node; - if ((ret = vfs_open(path, open_flags, &node)) != 0) { - filemap_free(file); - return ret; - } - - file->pos = 0; - if (open_flags & O_APPEND) { - struct stat __stat, *stat = &__stat; - if ((ret = vop_fstat(node, stat)) != 0) { - vfs_close(node); - filemap_free(file); - return ret; - } - file->pos = stat->st_size; - } - - file->node = node; - file->readable = readable; - file->writable = writable; - filemap_open(file); - return file->fd; -} - -int -file_close(int fd) { - int ret; - struct file *file; - if ((ret = fd2file(fd, &file)) != 0) { - return ret; - } - filemap_close(file); - return 0; -} - -int -file_read(int fd, void *base, size_t len, size_t *copied_store) { - int ret; - struct file *file; - *copied_store = 0; - if ((ret = fd2file(fd, &file)) != 0) { - return ret; - } - if (!file->readable) { - return -E_INVAL; - } - filemap_acquire(file); - - struct iobuf __iob, *iob = iobuf_init(&__iob, base, len, file->pos); - ret = vop_read(file->node, iob); - - size_t copied = iobuf_used(iob); - if (file->status == FD_OPENED) { - file->pos += copied; - } - *copied_store = copied; - filemap_release(file); - return ret; -} - -int -file_write(int fd, void *base, size_t len, size_t *copied_store) { - int ret; - struct file *file; - *copied_store = 0; - if ((ret = fd2file(fd, &file)) != 0) { - return ret; - } - if (!file->writable) { - return -E_INVAL; - } - filemap_acquire(file); - - struct iobuf __iob, *iob = iobuf_init(&__iob, base, len, file->pos); - ret = vop_write(file->node, iob); - - size_t copied = iobuf_used(iob); - if (file->status == FD_OPENED) { - file->pos += copied; - } - *copied_store = copied; - filemap_release(file); - return ret; -} - -int -file_seek(int fd, off_t pos, int whence) { - struct stat __stat, *stat = &__stat; - int ret; - struct file *file; - if ((ret = fd2file(fd, &file)) != 0) { - return ret; - } - filemap_acquire(file); - - switch (whence) { - case LSEEK_SET: break; - case LSEEK_CUR: pos += file->pos; break; - case LSEEK_END: - if ((ret = vop_fstat(file->node, stat)) == 0) { - pos += stat->st_size; - } - break; - default: ret = -E_INVAL; - } - - if (ret == 0) { - if ((ret = vop_tryseek(file->node, pos)) == 0) { - file->pos = pos; - } -// kprintf("file_seek, pos=%d, whence=%d, ret=%d\n", pos, whence, ret); - } - filemap_release(file); - return ret; -} - -int -file_fstat(int fd, struct stat *stat) { - int ret; - struct file *file; - if ((ret = fd2file(fd, &file)) != 0) { - return ret; - } - filemap_acquire(file); - ret = vop_fstat(file->node, stat); - filemap_release(file); - return ret; -} - -int -file_fsync(int fd) { - int ret; - struct file *file; - if ((ret = fd2file(fd, &file)) != 0) { - return ret; - } - filemap_acquire(file); - ret = vop_fsync(file->node); - filemap_release(file); - return ret; -} - -int -file_getdirentry(int fd, struct dirent *direntp) { - int ret; - struct file *file; - if ((ret = fd2file(fd, &file)) != 0) { - return ret; - } - filemap_acquire(file); - - struct iobuf __iob, *iob = iobuf_init(&__iob, direntp->name, sizeof(direntp->name), direntp->offset); - if ((ret = vop_getdirentry(file->node, iob)) == 0) { - direntp->offset += iobuf_used(iob); - } - filemap_release(file); - return ret; -} - -int -file_dup(int fd1, int fd2) { - int ret; - struct file *file1, *file2; - if ((ret = fd2file(fd1, &file1)) != 0) { - return ret; - } - if ((ret = filemap_alloc(fd2, &file2)) != 0) { - return ret; - } - filemap_dup(file2, file1); - return file2->fd; -} - - diff --git a/ucore-thumips/kern/fs/file.h b/ucore-thumips/kern/fs/file.h deleted file mode 100644 index 41a999b..0000000 --- a/ucore-thumips/kern/fs/file.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __KERN_FS_FILE_H__ -#define __KERN_FS_FILE_H__ - -//#include -#include -#include -#include -#include - -struct inode; -struct stat; -struct dirent; - -struct file { - enum { - FD_NONE, FD_INIT, FD_OPENED, FD_CLOSED, - } status; - bool readable; - bool writable; - int fd; - off_t pos; - struct inode *node; - atomic_t open_count; -}; - -void filemap_init(struct file *filemap); -void filemap_open(struct file *file); -void filemap_close(struct file *file); -void filemap_dup(struct file *to, struct file *from); -bool file_testfd(int fd, bool readable, bool writable); - -int file_open(char *path, uint32_t open_flags); -int file_close(int fd); -int file_read(int fd, void *base, size_t len, size_t *copied_store); -int file_write(int fd, void *base, size_t len, size_t *copied_store); -int file_seek(int fd, off_t pos, int whence); -int file_fstat(int fd, struct stat *stat); -int file_fsync(int fd); -int file_getdirentry(int fd, struct dirent *dirent); -int file_dup(int fd1, int fd2); -int file_pipe(int fd[]); -int file_mkfifo(const char *name, uint32_t open_flags); - -static inline int -fopen_count(struct file *file) { - return atomic_read(&(file->open_count)); -} - -static inline int -fopen_count_inc(struct file *file) { - return atomic_add_return(&(file->open_count), 1); -} - -static inline int -fopen_count_dec(struct file *file) { - return atomic_sub_return(&(file->open_count), 1); -} - -#endif /* !__KERN_FS_FILE_H__ */ - diff --git a/ucore-thumips/kern/fs/fs.c b/ucore-thumips/kern/fs/fs.c deleted file mode 100644 index 87f2a8c..0000000 --- a/ucore-thumips/kern/fs/fs.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -//called when init_main proc start -void -fs_init(void) { - vfs_init(); - dev_init(); - sfs_init(); -} - -void -fs_cleanup(void) { - vfs_cleanup(); -} - -void -lock_fs(struct fs_struct *fs_struct) { - down(&(fs_struct->fs_sem)); -} - -void -unlock_fs(struct fs_struct *fs_struct) { - up(&(fs_struct->fs_sem)); -} -//Called when a new proc init -struct fs_struct * -fs_create(void) { - //kprintf("[fs_create]\n"); - static_assert((int)FS_STRUCT_NENTRY > 128); - struct fs_struct *fs_struct; - if ((fs_struct = kmalloc(sizeof(struct fs_struct) + FS_STRUCT_BUFSIZE)) != NULL) { - fs_struct->pwd = NULL; - fs_struct->filemap = (void *)(fs_struct + 1); - atomic_set(&(fs_struct->fs_count), 0); - sem_init(&(fs_struct->fs_sem), 1); - filemap_init(fs_struct->filemap); - } - return fs_struct; -} -//Called when a proc exit -void -fs_destroy(struct fs_struct *fs_struct) { -// kprintf("[fs_destroy]\n"); - assert(fs_struct != NULL && fs_count(fs_struct) == 0); - if (fs_struct->pwd != NULL) { - vop_ref_dec(fs_struct->pwd); - } - int i; - struct file *file = fs_struct->filemap; - for (i = 0; i < FS_STRUCT_NENTRY; i ++, file ++) { - if (file->status == FD_OPENED) { - filemap_close(file); - } - assert(file->status == FD_NONE); - } - kfree(fs_struct); -} - -void -fs_closeall(struct fs_struct *fs_struct) { -// kprintf("[fs_closeall]\n"); - assert(fs_struct != NULL && fs_count(fs_struct) > 0); - int i; - struct file *file = fs_struct->filemap; - //skip the stdin & stdout - for (i = 2, file += 2; i < FS_STRUCT_NENTRY; i ++, file ++) { - if (file->status == FD_OPENED) { - filemap_close(file); - } - } -} - -int -dup_fs(struct fs_struct *to, struct fs_struct *from) { -// kprintf("[dup_fs]\n"); - assert(to != NULL && from != NULL); - assert(fs_count(to) == 0 && fs_count(from) > 0); - if ((to->pwd = from->pwd) != NULL) { - vop_ref_inc(to->pwd); - } - int i; - struct file *to_file = to->filemap, *from_file = from->filemap; - for (i = 0; i < FS_STRUCT_NENTRY; i ++, to_file ++, from_file ++) { - if (from_file->status == FD_OPENED) { - /* alloc_fd first */ - to_file->status = FD_INIT; - filemap_dup(to_file, from_file); - } - } - return 0; -} - diff --git a/ucore-thumips/kern/fs/fs.h b/ucore-thumips/kern/fs/fs.h deleted file mode 100644 index dba0648..0000000 --- a/ucore-thumips/kern/fs/fs.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __KERN_FS_FS_H__ -#define __KERN_FS_FS_H__ - -#include -#include -#include -#include - -#define SECTSIZE 512 -#define PAGE_NSECT (PGSIZE / SECTSIZE) - -#define SWAP_DEV_NO 1 -#define DISK0_DEV_NO 2 -#define DISK1_DEV_NO 3 - -void fs_init(void); -void fs_cleanup(void); - -struct inode; -struct file; - -struct fs_struct { - struct inode *pwd; - struct file *filemap; - atomic_t fs_count; - semaphore_t fs_sem; -}; - -#define FS_STRUCT_BUFSIZE (PGSIZE - sizeof(struct fs_struct)) -#define FS_STRUCT_NENTRY (FS_STRUCT_BUFSIZE / sizeof(struct file)) - -void lock_fs(struct fs_struct *fs_struct); -void unlock_fs(struct fs_struct *fs_struct); - -struct fs_struct *fs_create(void); -void fs_destroy(struct fs_struct *fs_struct); -void fs_closeall(struct fs_struct *fs_struct); -int dup_fs(struct fs_struct *to, struct fs_struct *from); - -static inline int -fs_count(struct fs_struct *fs_struct) { - return atomic_read(&(fs_struct->fs_count)); -} - -static inline int -fs_count_inc(struct fs_struct *fs_struct) { - return atomic_add_return(&(fs_struct->fs_count), 1); -} - -static inline int -fs_count_dec(struct fs_struct *fs_struct) { - return atomic_sub_return(&(fs_struct->fs_count), 1); -} - -#endif /* !__KERN_FS_FS_H__ */ - diff --git a/ucore-thumips/kern/fs/iobuf.c b/ucore-thumips/kern/fs/iobuf.c deleted file mode 100644 index 7f51fc3..0000000 --- a/ucore-thumips/kern/fs/iobuf.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include - -struct iobuf * -iobuf_init(struct iobuf *iob, void *base, size_t len, off_t offset) { - iob->io_base = base; - iob->io_offset = offset; - iob->io_len = iob->io_resid = len; - return iob; -} - -int -iobuf_move(struct iobuf *iob, void *data, size_t len, bool m2b, size_t *copiedp) { - size_t alen; - if ((alen = iob->io_resid) > len) { - alen = len; - } - if (alen > 0) { - void *src = iob->io_base, *dst = data; - if (m2b) { - void *tmp = src; - src = dst, dst = tmp; - } - memmove(dst, src, alen); - iobuf_skip(iob, alen), len -= alen; - } - if (copiedp != NULL) { - *copiedp = alen; - } - return (len == 0) ? 0 : -E_NO_MEM; -} - -int -iobuf_move_zeros(struct iobuf *iob, size_t len, size_t *copiedp) { - size_t alen; - if ((alen = iob->io_resid) > len) { - alen = len; - } - if (alen > 0) { - memset(iob->io_base, 0, alen); - iobuf_skip(iob, alen), len -= alen; - } - if (copiedp != NULL) { - *copiedp = alen; - } - return (len == 0) ? 0 : -E_NO_MEM; -} - -void -iobuf_skip(struct iobuf *iob, size_t n) { - assert(iob->io_resid >= n); - iob->io_base += n, iob->io_offset += n, iob->io_resid -= n; -} - diff --git a/ucore-thumips/kern/fs/iobuf.h b/ucore-thumips/kern/fs/iobuf.h deleted file mode 100644 index fe7a29f..0000000 --- a/ucore-thumips/kern/fs/iobuf.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __KERN_FS_IOBUF_H__ -#define __KERN_FS_IOBUF_H__ - -#include - -struct iobuf { - void *io_base; - off_t io_offset; - size_t io_len; - size_t io_resid; -}; - -#define iobuf_used(iob) ((size_t)((iob)->io_len - (iob)->io_resid)) - -struct iobuf *iobuf_init(struct iobuf *iob, void *base, size_t len, off_t offset); -int iobuf_move(struct iobuf *iob, void *data, size_t len, bool m2b, size_t *copiedp); -int iobuf_move_zeros(struct iobuf *iob, size_t len, size_t *copiedp); -void iobuf_skip(struct iobuf *iob, size_t n); - -#endif /* !__KERN_FS_IOBUF_H__ */ - diff --git a/ucore-thumips/kern/fs/sfs/bitmap.c b/ucore-thumips/kern/fs/sfs/bitmap.c deleted file mode 100644 index 3522c78..0000000 --- a/ucore-thumips/kern/fs/sfs/bitmap.c +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define WORD_TYPE uint32_t -#define WORD_BITS (sizeof(WORD_TYPE) * CHAR_BIT) -#define WORD_BITS_SHIFT (2+3) - -struct bitmap { - uint32_t nbits; - uint32_t nwords; - WORD_TYPE *map; -}; - -struct bitmap * -bitmap_create(uint32_t nbits) { - static_assert(WORD_BITS != 0); - assert(nbits != 0 && nbits + WORD_BITS > nbits); - - struct bitmap *bitmap; - if ((bitmap = kmalloc(sizeof(struct bitmap))) == NULL) { - return NULL; - } - - uint32_t nwords = ROUNDUP_DIV_2N(nbits, WORD_BITS_SHIFT); - WORD_TYPE *map; - if ((map = kmalloc(sizeof(WORD_TYPE) * nwords)) == NULL) { - kfree(bitmap); - return NULL; - } - - bitmap->nbits = nbits, bitmap->nwords = nwords; - bitmap->map = memset(map, 0xFF, sizeof(WORD_TYPE) * nwords); - - /* mark any leftover bits at the end in use(0) */ - if (nbits != nwords * WORD_BITS) { - uint32_t ix = nwords - 1, overbits = nbits - ix * WORD_BITS; - - assert(nbits / WORD_BITS == ix); - assert(overbits > 0 && overbits < WORD_BITS); - - for (; overbits < WORD_BITS; overbits ++) { - bitmap->map[ix] ^= (1 << overbits); - } - } - return bitmap; -} - -int -bitmap_alloc(struct bitmap *bitmap, uint32_t *index_store) { - WORD_TYPE *map = bitmap->map; - uint32_t ix, offset, nwords = bitmap->nwords; - for (ix = 0; ix < nwords; ix ++) { - if (map[ix] != 0) { - for (offset = 0; offset < WORD_BITS; offset ++) { - WORD_TYPE mask = (1 << offset); - if (map[ix] & mask) { - map[ix] ^= mask; - *index_store = ix * WORD_BITS + offset; - return 0; - } - } - assert(0); - } - } - return -E_NO_MEM; -} - -static void -bitmap_translate(struct bitmap *bitmap, uint32_t index, WORD_TYPE **word, WORD_TYPE *mask) { - assert(index < bitmap->nbits); - uint32_t ix = index / WORD_BITS, offset = index % WORD_BITS; - *word = bitmap->map + ix; - *mask = (1 << offset); -} - -bool -bitmap_test(struct bitmap *bitmap, uint32_t index) { - WORD_TYPE *word, mask; - bitmap_translate(bitmap, index, &word, &mask); - return (*word & mask); -} - -void -bitmap_free(struct bitmap *bitmap, uint32_t index) { - WORD_TYPE *word, mask; - bitmap_translate(bitmap, index, &word, &mask); - assert(!(*word & mask)); - *word |= mask; -} - -void -bitmap_destroy(struct bitmap *bitmap) { - kfree(bitmap->map); - kfree(bitmap); -} - -void * -bitmap_getdata(struct bitmap *bitmap, size_t *len_store) { - if (len_store != NULL) { - *len_store = sizeof(WORD_TYPE) * bitmap->nwords; - } - return bitmap->map; -} - diff --git a/ucore-thumips/kern/fs/sfs/bitmap.h b/ucore-thumips/kern/fs/sfs/bitmap.h deleted file mode 100644 index d9078e6..0000000 --- a/ucore-thumips/kern/fs/sfs/bitmap.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __KERN_FS_SFS_BITMAP_H__ -#define __KERN_FS_SFS_BITMAP_H__ - -#include - -struct bitmap; - -struct bitmap *bitmap_create(uint32_t nbits); -int bitmap_alloc(struct bitmap *bitmap, uint32_t *index_store); -bool bitmap_test(struct bitmap *bitmap, uint32_t index); -void bitmap_free(struct bitmap *bitmap, uint32_t index); -void bitmap_destroy(struct bitmap *bitmap); -void *bitmap_getdata(struct bitmap *bitmap, size_t *len_store); - -#endif /* !__KERN_FS_SFS_BITMAP_H__ */ - diff --git a/ucore-thumips/kern/fs/sfs/sfs.c b/ucore-thumips/kern/fs/sfs/sfs.c deleted file mode 100644 index b674395..0000000 --- a/ucore-thumips/kern/fs/sfs/sfs.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include -#include - -void -sfs_init(void) { - int ret; - if ((ret = sfs_mount("disk0")) != 0) { - panic("failed: sfs: sfs_mount: %e.\n", ret); - } -} - diff --git a/ucore-thumips/kern/fs/sfs/sfs.h b/ucore-thumips/kern/fs/sfs/sfs.h deleted file mode 100644 index fff1462..0000000 --- a/ucore-thumips/kern/fs/sfs/sfs.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef __KERN_FS_SFS_SFS_H__ -#define __KERN_FS_SFS_SFS_H__ - -#include -#include -#include -#include -#include - -#define SFS_MAGIC 0x2f8dbe2a /* magic number for sfs */ -#define SFS_BLKSIZE PGSIZE /* size of block */ -#define SFS_BLKSIZE_SHIFT PGSHIFT -#define SFS_NDIRECT 12 /* # of direct blocks in inode */ -#define SFS_MAX_INFO_LEN 31 /* max length of infomation */ -#define SFS_MAX_FNAME_LEN FS_MAX_FNAME_LEN /* max length of filename */ -#define SFS_MAX_FILE_SIZE (1024UL * 1024 * 128) /* max file size (128M) */ -#define SFS_BLKN_SUPER 0 /* block the superblock lives in */ -#define SFS_BLKN_ROOT 1 /* location of the root dir inode */ -#define SFS_BLKN_FREEMAP 2 /* 1st block of the freemap */ - -/* # of bits in a block */ -#define SFS_BLKBITS (SFS_BLKSIZE * CHAR_BIT) -#define SFS_BLKBITS_SHIFT (PGSHIFT + 3) - -/* # of entries in a block */ -#define SFS_BLK_NENTRY (SFS_BLKSIZE / sizeof(uint32_t)) - -/* file types */ -#define SFS_TYPE_INVAL 0 /* Should not appear on disk */ -#define SFS_TYPE_FILE 1 -#define SFS_TYPE_DIR 2 -#define SFS_TYPE_LINK 3 - -/* - * On-disk superblock - */ -struct sfs_super { - uint32_t magic; /* magic number, should be SFS_MAGIC */ - uint32_t blocks; /* # of blocks in fs */ - uint32_t unused_blocks; /* # of unused blocks in fs */ - char info[SFS_MAX_INFO_LEN + 1]; /* infomation for sfs */ -}; - -/* inode (on disk) */ -struct sfs_disk_inode { - uint32_t size; /* size of the file (in bytes) */ - unsigned short __type__; /* one of SYS_TYPE_* above */ - unsigned short __nlinks__; /* # of hard links to this file */ - uint32_t blocks; /* # of blocks */ - uint32_t direct[SFS_NDIRECT]; /* direct blocks */ - uint32_t indirect; /* indirect blocks */ -// uint32_t db_indirect; /* double indirect blocks */ -// unused -}; - -#define _SFS_INODE_GET_TYPE(din) ({\ - uint32_t t = *(uint32_t*)&((din)->__type__);\ - t &= 0xFFFF; \ - t; \ - }) - -#define _SFS_INODE_GET_NLINKS(din) ({\ - uint32_t t = *(uint32_t*)&((din)->__type__);\ - t = t >> 16; \ - t; \ - }) - - -/* file entry (on disk) */ -struct sfs_disk_entry { - uint32_t ino; /* inode number */ - char name[SFS_MAX_FNAME_LEN + 1]; /* file name */ -}; - -#define sfs_dentry_size \ - sizeof(((struct sfs_disk_entry *)0)->name) - -/* inode for sfs */ -struct sfs_inode { - struct sfs_disk_inode *din; /* on-disk inode */ - uint32_t ino; /* inode number */ - bool dirty; /* true if inode modified */ - int reclaim_count; /* kill inode if it hits zero */ - semaphore_t sem; /* semaphore for din */ - list_entry_t inode_link; /* entry for linked-list in sfs_fs */ - list_entry_t hash_link; /* entry for hash linked-list in sfs_fs */ -}; - -#define le2sin(le, member) \ - to_struct((le), struct sfs_inode, member) - -/* filesystem for sfs */ -struct sfs_fs { - struct sfs_super super; /* on-disk superblock */ - struct device *dev; /* device mounted on */ - struct bitmap *freemap; /* blocks in use are mared 0 */ - bool super_dirty; /* true if super/freemap modified */ - void *sfs_buffer; /* buffer for non-block aligned io */ - semaphore_t fs_sem; /* semaphore for fs */ - semaphore_t io_sem; /* semaphore for io */ - semaphore_t mutex_sem; /* semaphore for link/unlink and rename */ - list_entry_t inode_list; /* inode linked-list */ - list_entry_t *hash_list; /* inode hash linked-list */ -}; - -/* hash for sfs */ -#define SFS_HLIST_SHIFT 10 -#define SFS_HLIST_SIZE (1 << SFS_HLIST_SHIFT) -#define sin_hashfn(x) (hash32(x, SFS_HLIST_SHIFT)) - -/* size of freemap (in bits) */ -#define sfs_freemap_bits(super) ROUNDUP_2N((super)->blocks, SFS_BLKBITS_SHIFT) - - -/* size of freemap (in blocks) */ -#define sfs_freemap_blocks(super) ROUNDUP_DIV_2N((super)->blocks, SFS_BLKBITS_SHIFT) - -struct fs; -struct inode; - -void sfs_init(void); -int sfs_mount(const char *devname); - -void lock_sfs_fs(struct sfs_fs *sfs); -void lock_sfs_io(struct sfs_fs *sfs); -void lock_sfs_mutex(struct sfs_fs *sfs); -void unlock_sfs_fs(struct sfs_fs *sfs); -void unlock_sfs_io(struct sfs_fs *sfs); -void unlock_sfs_mutex(struct sfs_fs *sfs); - -int sfs_rblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); -int sfs_wblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); -int sfs_rbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); -int sfs_wbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); -int sfs_sync_super(struct sfs_fs *sfs); -int sfs_sync_freemap(struct sfs_fs *sfs); -int sfs_clear_block(struct sfs_fs *sfs, uint32_t blkno, uint32_t nblks); - -int sfs_load_inode(struct sfs_fs *sfs, struct inode **node_store, uint32_t ino); - -#endif /* !__KERN_FS_SFS_SFS_H__ */ - diff --git a/ucore-thumips/kern/fs/sfs/sfs_fs.c b/ucore-thumips/kern/fs/sfs/sfs_fs.c deleted file mode 100644 index 92e1a48..0000000 --- a/ucore-thumips/kern/fs/sfs/sfs_fs.c +++ /dev/null @@ -1,215 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int -sfs_sync(struct fs *fs) { - struct sfs_fs *sfs = fsop_info(fs, sfs); - lock_sfs_fs(sfs); - { - list_entry_t *list = &(sfs->inode_list), *le = list; - while ((le = list_next(le)) != list) { - struct sfs_inode *sin = le2sin(le, inode_link); - vop_fsync(info2node(sin, sfs_inode)); - } - } - unlock_sfs_fs(sfs); - - int ret; - if (sfs->super_dirty) { - sfs->super_dirty = 0; - if ((ret = sfs_sync_super(sfs)) != 0) { - sfs->super_dirty = 1; - return ret; - } - if ((ret = sfs_sync_freemap(sfs)) != 0) { - sfs->super_dirty = 1; - return ret; - } - } - return 0; -} - -static struct inode * -sfs_get_root(struct fs *fs) { - struct inode *node; - int ret; - if ((ret = sfs_load_inode(fsop_info(fs, sfs), &node, SFS_BLKN_ROOT)) != 0) { - panic("load sfs root failed: %e", ret); - } - return node; -} - -static int -sfs_unmount(struct fs *fs) { - struct sfs_fs *sfs = fsop_info(fs, sfs); - if (!list_empty(&(sfs->inode_list))) { - return -E_BUSY; - } - assert(!sfs->super_dirty); - bitmap_destroy(sfs->freemap); - kfree(sfs->sfs_buffer); - kfree(sfs->hash_list); - kfree(sfs); - return 0; -} - -static void -sfs_cleanup(struct fs *fs) { - struct sfs_fs *sfs = fsop_info(fs, sfs); - uint32_t blocks = sfs->super.blocks, unused_blocks = sfs->super.unused_blocks; - kprintf("sfs: cleanup: '%s' (%d/%d/%d)\n", sfs->super.info, - blocks - unused_blocks, unused_blocks, blocks); - int i, ret; - for (i = 0; i < 32; i ++) { - if ((ret = fsop_sync(fs)) == 0) { - break; - } - } - if (ret != 0) { - warn("sfs: sync error: '%s': %e.\n", sfs->super.info, ret); - } -} - -static int -sfs_init_read(struct device *dev, uint32_t blkno, void *blk_buffer) { - struct iobuf __iob, *iob = iobuf_init(&__iob, blk_buffer, SFS_BLKSIZE, blkno * SFS_BLKSIZE); - return dop_io(dev, iob, 0); -} - -static int -sfs_init_freemap(struct device *dev, struct bitmap *freemap, uint32_t blkno, uint32_t nblks, void *blk_buffer) { - size_t len; - void *data = bitmap_getdata(freemap, &len); - assert(data != NULL && len == nblks * SFS_BLKSIZE); - while (nblks != 0) { - int ret; - if ((ret = sfs_init_read(dev, blkno, data)) != 0) { - return ret; - } - blkno ++, nblks --, data += SFS_BLKSIZE; - } - return 0; -} - -static int -sfs_do_mount(struct device *dev, struct fs **fs_store) { - static_assert(SFS_BLKSIZE >= sizeof(struct sfs_super)); - static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_inode)); - static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_entry)); - - if (dev->d_blocksize != SFS_BLKSIZE) { - return -E_NA_DEV; - } - - /* allocate fs structure */ - struct fs *fs; - if ((fs = alloc_fs(sfs)) == NULL) { - return -E_NO_MEM; - } - struct sfs_fs *sfs = fsop_info(fs, sfs); - sfs->dev = dev; - - int ret = -E_NO_MEM; - - void *sfs_buffer; - if ((sfs->sfs_buffer = sfs_buffer = kmalloc(SFS_BLKSIZE)) == NULL) { - goto failed_cleanup_fs; - } - - /* load and check superblock */ - if ((ret = sfs_init_read(dev, SFS_BLKN_SUPER, sfs_buffer)) != 0) { - goto failed_cleanup_sfs_buffer; - } - - ret = -E_INVAL; - - struct sfs_super *super = sfs_buffer; - if (super->magic != SFS_MAGIC) { - kprintf("sfs: wrong magic in superblock. (%08x should be %08x).\n", - super->magic, SFS_MAGIC); - goto failed_cleanup_sfs_buffer; - } - if (super->blocks > dev->d_blocks) { - kprintf("sfs: fs has %d blocks, device has %d blocks.\n", - super->blocks, dev->d_blocks); - goto failed_cleanup_sfs_buffer; - } - super->info[SFS_MAX_INFO_LEN] = '\0'; - sfs->super = *super; - - ret = -E_NO_MEM; - - uint32_t i; - - /* alloc and initialize hash list */ - list_entry_t *hash_list; - if ((sfs->hash_list = hash_list = kmalloc(sizeof(list_entry_t) * SFS_HLIST_SIZE)) == NULL) { - goto failed_cleanup_sfs_buffer; - } - for (i = 0; i < SFS_HLIST_SIZE; i ++) { - list_init(hash_list + i); - } - - /* load and check freemap */ - struct bitmap *freemap; - uint32_t freemap_size_nbits = sfs_freemap_bits(super); - if ((sfs->freemap = freemap = bitmap_create(freemap_size_nbits)) == NULL) { - goto failed_cleanup_hash_list; - } - uint32_t freemap_size_nblks = sfs_freemap_blocks(super); - if ((ret = sfs_init_freemap(dev, freemap, SFS_BLKN_FREEMAP, freemap_size_nblks, sfs_buffer)) != 0) { - goto failed_cleanup_freemap; - } - - uint32_t blocks = sfs->super.blocks, unused_blocks = 0; - for (i = 0; i < freemap_size_nbits; i ++) { - if (bitmap_test(freemap, i)) { - unused_blocks ++; - } - } - // assert(unused_blocks == sfs->super.unused_blocks); - - /* and other fields */ - sfs->super_dirty = 0; - sem_init(&(sfs->fs_sem), 1); - sem_init(&(sfs->io_sem), 1); - sem_init(&(sfs->mutex_sem), 1); - list_init(&(sfs->inode_list)); - kprintf("sfs: mount: '%s' (%d/%d/%d)\n", sfs->super.info, - blocks - unused_blocks, unused_blocks, blocks); - - fs->fs_sync = sfs_sync; - fs->fs_get_root = sfs_get_root; - fs->fs_unmount = sfs_unmount; - fs->fs_cleanup = sfs_cleanup; - *fs_store = fs; - return 0; - -failed_cleanup_freemap: - bitmap_destroy(freemap); -failed_cleanup_hash_list: - kfree(hash_list); -failed_cleanup_sfs_buffer: - kfree(sfs_buffer); -failed_cleanup_fs: - kfree(fs); - return ret; -} - -int -sfs_mount(const char *devname) { - return vfs_mount(devname, sfs_do_mount); -} - diff --git a/ucore-thumips/kern/fs/sfs/sfs_inode.c b/ucore-thumips/kern/fs/sfs/sfs_inode.c deleted file mode 100644 index 815cd18..0000000 --- a/ucore-thumips/kern/fs/sfs/sfs_inode.c +++ /dev/null @@ -1,858 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const struct inode_ops sfs_node_dirops; -static const struct inode_ops sfs_node_fileops; - -static void -lock_sin(struct sfs_inode *sin) { - down(&(sin->sem)); -} - -static void -unlock_sin(struct sfs_inode *sin) { - up(&(sin->sem)); -} - -static const struct inode_ops * -sfs_get_ops(uint32_t type) { - switch (type) { - case SFS_TYPE_DIR: - return &sfs_node_dirops; - case SFS_TYPE_FILE: - return &sfs_node_fileops; - } - panic("invalid file type %d.\n", type); -} - -static list_entry_t * -sfs_hash_list(struct sfs_fs *sfs, uint32_t ino) { - return sfs->hash_list + sin_hashfn(ino); -} - -static void -sfs_set_links(struct sfs_fs *sfs, struct sfs_inode *sin) { - list_add(&(sfs->inode_list), &(sin->inode_link)); - list_add(sfs_hash_list(sfs, sin->ino), &(sin->hash_link)); -} - -static void -sfs_remove_links(struct sfs_inode *sin) { - list_del(&(sin->inode_link)); - list_del(&(sin->hash_link)); -} - -static bool -sfs_block_inuse(struct sfs_fs *sfs, uint32_t ino) { - if (ino != 0 && ino < sfs->super.blocks) { - return !bitmap_test(sfs->freemap, ino); - } - panic("sfs_block_inuse: called out of range (0, %d) %d.\n", sfs->super.blocks, ino); -} - -static int -sfs_block_alloc(struct sfs_fs *sfs, uint32_t *ino_store) { - int ret; - if ((ret = bitmap_alloc(sfs->freemap, ino_store)) != 0) { - return ret; - } - assert(sfs->super.unused_blocks > 0); - sfs->super.unused_blocks --, sfs->super_dirty = 1; - assert(sfs_block_inuse(sfs, *ino_store)); - return sfs_clear_block(sfs, *ino_store, 1); -} - -static void -sfs_block_free(struct sfs_fs *sfs, uint32_t ino) { - assert(sfs_block_inuse(sfs, ino)); - bitmap_free(sfs->freemap, ino); - sfs->super.unused_blocks ++, sfs->super_dirty = 1; -} - -static int -sfs_create_inode(struct sfs_fs *sfs, struct sfs_disk_inode *din, uint32_t ino, struct inode **node_store) { - struct inode *node; - if ((node = alloc_inode(sfs_inode)) != NULL) { - vop_init(node, sfs_get_ops(_SFS_INODE_GET_TYPE(din)), info2fs(sfs, sfs)); - struct sfs_inode *sin = vop_info(node, sfs_inode); - sin->din = din, sin->ino = ino, sin->dirty = 0, sin->reclaim_count = 1; - sem_init(&(sin->sem), 1); - *node_store = node; - return 0; - } - return -E_NO_MEM; -} - -static struct inode * -lookup_sfs_nolock(struct sfs_fs *sfs, uint32_t ino) { - struct inode *node; - list_entry_t *list = sfs_hash_list(sfs, ino), *le = list; - while ((le = list_next(le)) != list) { - struct sfs_inode *sin = le2sin(le, hash_link); - if (sin->ino == ino) { - node = info2node(sin, sfs_inode); - if (vop_ref_inc(node) == 1) { - sin->reclaim_count ++; - } - return node; - } - } - return NULL; -} - -int -sfs_load_inode(struct sfs_fs *sfs, struct inode **node_store, uint32_t ino) { - lock_sfs_fs(sfs); - struct inode *node; - if ((node = lookup_sfs_nolock(sfs, ino)) != NULL) { - goto out_unlock; - } - - int ret = -E_NO_MEM; - struct sfs_disk_inode *din; - if ((din = kmalloc(sizeof(struct sfs_disk_inode))) == NULL) { - goto failed_unlock; - } - - assert(sfs_block_inuse(sfs, ino)); - if ((ret = sfs_rbuf(sfs, din, sizeof(struct sfs_disk_inode), ino, 0)) != 0) { - goto failed_cleanup_din; - } - - assert(_SFS_INODE_GET_NLINKS(din) != 0); - if ((ret = sfs_create_inode(sfs, din, ino, &node)) != 0) { - goto failed_cleanup_din; - } - sfs_set_links(sfs, vop_info(node, sfs_inode)); - -out_unlock: - unlock_sfs_fs(sfs); - *node_store = node; - return 0; - -failed_cleanup_din: - kfree(din); -failed_unlock: - unlock_sfs_fs(sfs); - return ret; -} - -static int -sfs_bmap_get_sub_nolock(struct sfs_fs *sfs, uint32_t *entp, uint32_t index, bool create, uint32_t *ino_store) { - assert(index < SFS_BLK_NENTRY); - int ret; - uint32_t ent, ino = 0; - off_t offset = index * sizeof(uint32_t); - if ((ent = *entp) != 0) { - if ((ret = sfs_rbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { - return ret; - } - if (ino != 0 || !create) { - goto out; - } - } - else { - if (!create) { - goto out; - } - if ((ret = sfs_block_alloc(sfs, &ent)) != 0) { - return ret; - } - } - - if ((ret = sfs_block_alloc(sfs, &ino)) != 0) { - goto failed_cleanup; - } - if ((ret = sfs_wbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { - sfs_block_free(sfs, ino); - goto failed_cleanup; - } - -out: - if (ent != *entp) { - *entp = ent; - } - *ino_store = ino; - return 0; - -failed_cleanup: - if (ent != *entp) { - sfs_block_free(sfs, ent); - } - return ret; -} - -static int -sfs_bmap_get_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, uint32_t index, bool create, uint32_t *ino_store) { - struct sfs_disk_inode *din = sin->din; - int ret; - uint32_t ent, ino; - if (index < SFS_NDIRECT) { - if ((ino = din->direct[index]) == 0 && create) { - if ((ret = sfs_block_alloc(sfs, &ino)) != 0) { - return ret; - } - din->direct[index] = ino; - sin->dirty = 1; - } - goto out; - } - - index -= SFS_NDIRECT; - if (index < SFS_BLK_NENTRY) { - ent = din->indirect; - if ((ret = sfs_bmap_get_sub_nolock(sfs, &ent, index, create, &ino)) != 0) { - return ret; - } - if (ent != din->indirect) { - assert(din->indirect == 0); - din->indirect = ent; - sin->dirty = 1; - } - goto out; - } - - index -= SFS_BLK_NENTRY; - if ((ent = ino) != 0) { - if ((ret = sfs_bmap_get_sub_nolock(sfs, &ent, index % SFS_BLK_NENTRY, create, &ino)) != 0) { - return ret; - } - } - -out: - assert(ino == 0 || sfs_block_inuse(sfs, ino)); - *ino_store = ino; - return 0; -} - -static int -sfs_bmap_free_sub_nolock(struct sfs_fs *sfs, uint32_t ent, uint32_t index) { - assert(sfs_block_inuse(sfs, ent) && index < SFS_BLK_NENTRY); - int ret; - uint32_t ino, zero = 0; - off_t offset = index * sizeof(uint32_t); - if ((ret = sfs_rbuf(sfs, &ino, sizeof(uint32_t), ent, offset)) != 0) { - return ret; - } - if (ino != 0) { - if ((ret = sfs_wbuf(sfs, &zero, sizeof(uint32_t), ent, offset)) != 0) { - return ret; - } - sfs_block_free(sfs, ino); - } - return 0; -} - -static int -sfs_bmap_free_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, uint32_t index) { - struct sfs_disk_inode *din = sin->din; - int ret; - uint32_t ent, ino; - if (index < SFS_NDIRECT) { - if ((ino = din->direct[index]) != 0) { - sfs_block_free(sfs, ino); - din->direct[index] = 0; - sin->dirty = 1; - } - return 0; - } - - index -= SFS_NDIRECT; - if (index < SFS_BLK_NENTRY) { - if ((ent = din->indirect) != 0) { - if ((ret = sfs_bmap_free_sub_nolock(sfs, ent, index)) != 0) { - return ret; - } - } - return 0; - } - - index -= SFS_BLK_NENTRY; - return 0; -} - -static int -sfs_bmap_load_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, uint32_t index, uint32_t *ino_store) { - struct sfs_disk_inode *din = sin->din; - assert(index <= din->blocks); - int ret; - uint32_t ino; - bool create = (index == din->blocks); - if ((ret = sfs_bmap_get_nolock(sfs, sin, index, create, &ino)) != 0) { - return ret; - } - assert(sfs_block_inuse(sfs, ino)); - if (create) { - din->blocks ++; - } - if (ino_store != NULL) { - *ino_store = ino; - } - return 0; -} - -static int -sfs_bmap_truncate_nolock(struct sfs_fs *sfs, struct sfs_inode *sin) { - struct sfs_disk_inode *din = sin->din; - assert(din->blocks != 0); - int ret; - if ((ret = sfs_bmap_free_nolock(sfs, sin, din->blocks - 1)) != 0) { - return ret; - } - din->blocks --; - sin->dirty = 1; - return 0; -} - -static int -sfs_dirent_read_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, int slot, struct sfs_disk_entry *entry) { - assert(_SFS_INODE_GET_TYPE(sin->din) == SFS_TYPE_DIR && (slot >= 0 && slot < sin->din->blocks)); - int ret; - uint32_t ino; - if ((ret = sfs_bmap_load_nolock(sfs, sin, slot, &ino)) != 0) { - return ret; - } - assert(sfs_block_inuse(sfs, ino)); - if ((ret = sfs_rbuf(sfs, entry, sizeof(struct sfs_disk_entry), ino, 0)) != 0) { - return ret; - } - entry->name[SFS_MAX_FNAME_LEN] = '\0'; - return 0; -} - - -#define sfs_dirent_link_nolock_check(sfs, sin, slot, lnksin, name) \ - do { \ - int err; \ - if ((err = sfs_dirent_link_nolock(sfs, sin, slot, lnksin, name)) != 0) { \ - warn("sfs_dirent_link error: %e.\n", err); \ - } \ - } while (0) - -#define sfs_dirent_unlink_nolock_check(sfs, sin, slot, lnksin) \ - do { \ - int err; \ - if ((err = sfs_dirent_unlink_nolock(sfs, sin, slot, lnksin)) != 0) { \ - warn("sfs_dirent_unlink error: %e.\n", err); \ - } \ - } while (0) - -static int -sfs_dirent_search_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, uint32_t *ino_store, int *slot, int *empty_slot) { - assert(strlen(name) <= SFS_MAX_FNAME_LEN); - struct sfs_disk_entry *entry; - if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { - return -E_NO_MEM; - } - -#define set_pvalue(x, v) do { if ((x) != NULL) { *(x) = (v); } } while (0) - int ret, i, nslots = sin->din->blocks; - set_pvalue(empty_slot, nslots); - for (i = 0; i < nslots; i ++) { - if ((ret = sfs_dirent_read_nolock(sfs, sin, i, entry)) != 0) { - goto out; - } - if (entry->ino == 0) { - set_pvalue(empty_slot, i); - continue ; - } - if (strcmp(name, entry->name) == 0) { - set_pvalue(slot, i); - set_pvalue(ino_store, entry->ino); - goto out; - } - } -#undef set_pvalue - ret = -E_NOENT; -out: - kfree(entry); - return ret; -} - -static int -sfs_dirent_findino_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, uint32_t ino, struct sfs_disk_entry *entry) { - int ret, i, nslots = sin->din->blocks; - for (i = 0; i < nslots; i ++) { - if ((ret = sfs_dirent_read_nolock(sfs, sin, i, entry)) != 0) { - return ret; - } - if (entry->ino == ino) { - return 0; - } - } - return -E_NOENT; -} - -static int -sfs_lookup_once(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, struct inode **node_store, int *slot) { - int ret; - uint32_t ino; - lock_sin(sin); - { - ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, slot, NULL); - } - unlock_sin(sin); - if (ret == 0) { - ret = sfs_load_inode(sfs, node_store, ino); - } - return ret; -} - -static int -sfs_opendir(struct inode *node, uint32_t open_flags) { - switch (open_flags & O_ACCMODE) { - case O_RDONLY: - break; - case O_WRONLY: - case O_RDWR: - default: - return -E_ISDIR; - } - if (open_flags & O_APPEND) { - return -E_ISDIR; - } - return 0; -} - -static int -sfs_openfile(struct inode *node, uint32_t open_flags) { - return 0; -} - -static int -sfs_close(struct inode *node) { - return vop_fsync(node); -} - -static int -sfs_io_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, void *buf, off_t offset, size_t *alenp, bool write) { - struct sfs_disk_inode *din = sin->din; - assert(_SFS_INODE_GET_TYPE(din) != SFS_TYPE_DIR); - off_t endpos = offset + *alenp, blkoff; - *alenp = 0; - if (offset < 0 || offset >= SFS_MAX_FILE_SIZE || offset > endpos) { - return -E_INVAL; - } - if (offset == endpos) { - return 0; - } - if (endpos > SFS_MAX_FILE_SIZE) { - endpos = SFS_MAX_FILE_SIZE; - } - if (!write) { - if (offset >= din->size) { - return 0; - } - if (endpos > din->size) { - endpos = din->size; - } - } - - int (*sfs_buf_op)(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset); - int (*sfs_block_op)(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks); - if (write) { - sfs_buf_op = sfs_wbuf, sfs_block_op = sfs_wblock; - } - else { - sfs_buf_op = sfs_rbuf, sfs_block_op = sfs_rblock; - } - - int ret = 0; - size_t size, alen = 0; - uint32_t ino; - uint32_t blkno = offset / SFS_BLKSIZE; - uint32_t nblks = endpos / SFS_BLKSIZE - blkno; - - //LAB8:EXERCISE1 2009010989 HINT: call sfs_bmap_load_nolock, sfs_rbuf, sfs_rblock,etc. read different kind of blocks in file - - if((blkoff = offset % SFS_BLKSIZE)!= 0) { - if(nblks){ - size = SFS_BLKSIZE - blkoff; - }else{ - size = endpos - offset; - } - if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { - goto out; - } - if ((ret = sfs_buf_op(sfs, buf, size, ino, blkoff)) != 0) { - goto out; - } - alen += size; - if (nblks == 0) { - goto out; - } - buf += size, blkno ++, nblks --; - } - - size = SFS_BLKSIZE; - while(nblks != 0){ - if((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { - goto out; - } - if((ret = sfs_block_op(sfs, buf, ino, 1)) != 0) { - goto out; - } - alen += size, buf += size, blkno ++, nblks --; - } - - if((size = endpos % SFS_BLKSIZE) != 0) { - if ((ret = sfs_bmap_load_nolock(sfs, sin, blkno, &ino)) != 0) { - goto out; - } - if ((ret = sfs_buf_op(sfs, buf, size, ino, 0)) != 0) { - goto out; - } - alen += size; - } -out: - *alenp = alen; - if (offset + alen > sin->din->size) { - sin->din->size = offset + alen; - sin->dirty = 1; - } - return ret; -} - -static inline int -sfs_io(struct inode *node, struct iobuf *iob, bool write) { - struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); - struct sfs_inode *sin = vop_info(node, sfs_inode); - int ret; - lock_sin(sin); - { - size_t alen = iob->io_resid; - ret = sfs_io_nolock(sfs, sin, iob->io_base, iob->io_offset, &alen, write); - if (alen != 0) { - iobuf_skip(iob, alen); - } - } - unlock_sin(sin); - return ret; -} - -static int -sfs_read(struct inode *node, struct iobuf *iob) { - return sfs_io(node, iob, 0); -} - -static int -sfs_write(struct inode *node, struct iobuf *iob) { - return sfs_io(node, iob, 1); -} - -static int -sfs_fstat(struct inode *node, struct stat *stat) { - int ret; - memset(stat, 0, sizeof(struct stat)); - if ((ret = vop_gettype(node, &(stat->st_mode))) != 0) { - return ret; - } - struct sfs_disk_inode *din = vop_info(node, sfs_inode)->din; - stat->st_nlinks = _SFS_INODE_GET_NLINKS(din); - stat->st_blocks = din->blocks; - stat->st_size = din->size; - return 0; -} - -static int -sfs_fsync(struct inode *node) { - struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); - struct sfs_inode *sin = vop_info(node, sfs_inode); - int ret = 0; - if (sin->dirty) { - lock_sin(sin); - { - if (sin->dirty) { - sin->dirty = 0; - if ((ret = sfs_wbuf(sfs, sin->din, sizeof(struct sfs_disk_inode), sin->ino, 0)) != 0) { - sin->dirty = 1; - } - } - } - unlock_sin(sin); - } - return ret; -} - -static int -sfs_namefile(struct inode *node, struct iobuf *iob) { - struct sfs_disk_entry *entry; - if (iob->io_resid <= 2 || (entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { - return -E_NO_MEM; - } - - struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); - struct sfs_inode *sin = vop_info(node, sfs_inode); - - int ret; - char *ptr = iob->io_base + iob->io_resid; - size_t alen, resid = iob->io_resid - 2; - vop_ref_inc(node); - while (1) { - struct inode *parent; - if ((ret = sfs_lookup_once(sfs, sin, "..", &parent, NULL)) != 0) { - goto failed; - } - - uint32_t ino = sin->ino; - vop_ref_dec(node); - if (node == parent) { - vop_ref_dec(node); - break; - } - - node = parent, sin = vop_info(node, sfs_inode); - assert(ino != sin->ino && _SFS_INODE_GET_TYPE(sin->din) == SFS_TYPE_DIR); - - lock_sin(sin); - { - ret = sfs_dirent_findino_nolock(sfs, sin, ino, entry); - } - unlock_sin(sin); - - if (ret != 0) { - goto failed; - } - - if ((alen = strlen(entry->name) + 1) > resid) { - goto failed_nomem; - } - resid -= alen, ptr -= alen; - memcpy(ptr, entry->name, alen - 1); - ptr[alen - 1] = '/'; - } - alen = iob->io_resid - resid - 2; - ptr = memmove(iob->io_base + 1, ptr, alen); - ptr[-1] = '/', ptr[alen] = '\0'; - iobuf_skip(iob, alen); - kfree(entry); - return 0; - -failed_nomem: - ret = -E_NO_MEM; -failed: - vop_ref_dec(node); - kfree(entry); - return ret; -} - -static int -sfs_getdirentry_sub_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, int slot, struct sfs_disk_entry *entry) { - int ret, i, nslots = sin->din->blocks; - for (i = 0; i < nslots; i ++) { - if ((ret = sfs_dirent_read_nolock(sfs, sin, i, entry)) != 0) { - return ret; - } - if (entry->ino != 0) { - if (slot == 0) { - return 0; - } - slot --; - } - } - return -E_NOENT; -} - -static int -sfs_getdirentry(struct inode *node, struct iobuf *iob) { - struct sfs_disk_entry *entry; - if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) { - return -E_NO_MEM; - } - - struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); - struct sfs_inode *sin = vop_info(node, sfs_inode); - - int ret, slot; - off_t offset = iob->io_offset; - if (offset < 0 || offset % sfs_dentry_size != 0) { - kfree(entry); - return -E_INVAL; - } - if ((slot = offset / sfs_dentry_size) > sin->din->blocks) { - kfree(entry); - return -E_NOENT; - } - lock_sin(sin); - if ((ret = sfs_getdirentry_sub_nolock(sfs, sin, slot, entry)) != 0) { - unlock_sin(sin); - goto out; - } - unlock_sin(sin); - ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL); -out: - kfree(entry); - return ret; -} - -static int -sfs_reclaim(struct inode *node) { - struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); - struct sfs_inode *sin = vop_info(node, sfs_inode); - - int ret = -E_BUSY; - uint32_t ent; - lock_sfs_fs(sfs); - assert(sin->reclaim_count > 0); - if ((-- sin->reclaim_count) != 0 || inode_ref_count(node) != 0) { - goto failed_unlock; - } - if (_SFS_INODE_GET_NLINKS(sin->din) == 0) { - if ((ret = vop_truncate(node, 0)) != 0) { - goto failed_unlock; - } - } - if (sin->dirty) { - if ((ret = vop_fsync(node)) != 0) { - goto failed_unlock; - } - } - sfs_remove_links(sin); - unlock_sfs_fs(sfs); - - if (_SFS_INODE_GET_NLINKS(sin->din) == 0) { - sfs_block_free(sfs, sin->ino); - if ((ent = sin->din->indirect) != 0) { - sfs_block_free(sfs, ent); - } - } - kfree(sin->din); - vop_kill(node); - return 0; - -failed_unlock: - unlock_sfs_fs(sfs); - return ret; -} - -static int -sfs_gettype(struct inode *node, uint32_t *type_store) { - struct sfs_disk_inode *din = vop_info(node, sfs_inode)->din; - switch (_SFS_INODE_GET_TYPE(din)) { - case SFS_TYPE_DIR: - *type_store = S_IFDIR; - return 0; - case SFS_TYPE_FILE: - *type_store = S_IFREG; - return 0; - case SFS_TYPE_LINK: - *type_store = S_IFLNK; - return 0; - } - panic("invalid file type %d.\n", _SFS_INODE_GET_TYPE(din)); -} - -static int -sfs_tryseek(struct inode *node, off_t pos) { - if (pos < 0 || pos >= SFS_MAX_FILE_SIZE) { - return -E_INVAL; - } - struct sfs_inode *sin = vop_info(node, sfs_inode); - if (pos > sin->din->size) { - return vop_truncate(node, pos); - } - return 0; -} -static int -sfs_truncfile(struct inode *node, off_t len) { - if (len < 0 || len > SFS_MAX_FILE_SIZE) { - return -E_INVAL; - } - struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); - struct sfs_inode *sin = vop_info(node, sfs_inode); - struct sfs_disk_inode *din = sin->din; - - int ret = 0; - uint32_t nblks, tblks = ROUNDUP_DIV_2N(len, SFS_BLKSIZE_SHIFT); - if (din->size == len) { - assert(tblks == din->blocks); - return 0; - } - - lock_sin(sin); - nblks = din->blocks; - if (nblks < tblks) { - while (nblks != tblks) { - if ((ret = sfs_bmap_load_nolock(sfs, sin, nblks, NULL)) != 0) { - goto out_unlock; - } - nblks ++; - } - } - else if (tblks < nblks) { - while (tblks != nblks) { - if ((ret = sfs_bmap_truncate_nolock(sfs, sin)) != 0) { - goto out_unlock; - } - nblks --; - } - } - assert(din->blocks == tblks); - din->size = len; - sin->dirty = 1; - -out_unlock: - unlock_sin(sin); - return ret; -} - -static int -sfs_lookup(struct inode *node, char *path, struct inode **node_store) { - struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); - assert(*path != '\0' && *path != '/'); - vop_ref_inc(node); - struct sfs_inode *sin = vop_info(node, sfs_inode); - if (_SFS_INODE_GET_TYPE(sin->din) != SFS_TYPE_DIR) { - vop_ref_dec(node); - return -E_NOTDIR; - } - struct inode *subnode; - int ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL); - - vop_ref_dec(node); - if (ret != 0) { - return ret; - } - *node_store = subnode; - return 0; -} - -static const struct inode_ops sfs_node_dirops = { - .vop_magic = VOP_MAGIC, - .vop_open = sfs_opendir, - .vop_close = sfs_close, - .vop_fstat = sfs_fstat, - .vop_fsync = sfs_fsync, - .vop_namefile = sfs_namefile, - .vop_getdirentry = sfs_getdirentry, - .vop_reclaim = sfs_reclaim, - .vop_gettype = sfs_gettype, - .vop_lookup = sfs_lookup, -}; - -static const struct inode_ops sfs_node_fileops = { - .vop_magic = VOP_MAGIC, - .vop_open = sfs_openfile, - .vop_close = sfs_close, - .vop_read = sfs_read, - .vop_write = sfs_write, - .vop_fstat = sfs_fstat, - .vop_fsync = sfs_fsync, - .vop_reclaim = sfs_reclaim, - .vop_gettype = sfs_gettype, - .vop_tryseek = sfs_tryseek, - .vop_truncate = sfs_truncfile, -}; - diff --git a/ucore-thumips/kern/fs/sfs/sfs_io.c b/ucore-thumips/kern/fs/sfs/sfs_io.c deleted file mode 100644 index 77cbe41..0000000 --- a/ucore-thumips/kern/fs/sfs/sfs_io.c +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static int -sfs_rwblock_nolock(struct sfs_fs *sfs, void *buf, uint32_t blkno, bool write, bool check) { - assert((blkno != 0 || !check) && blkno < sfs->super.blocks); - struct iobuf __iob, *iob = iobuf_init(&__iob, buf, SFS_BLKSIZE, blkno * SFS_BLKSIZE); - return dop_io(sfs->dev, iob, write); -} - -static int -sfs_rwblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks, bool write) { - int ret = 0; - lock_sfs_io(sfs); - { - while (nblks != 0) { - if ((ret = sfs_rwblock_nolock(sfs, buf, blkno, write, 1)) != 0) { - break; - } - blkno ++, nblks --; - buf += SFS_BLKSIZE; - } - } - unlock_sfs_io(sfs); - return ret; -} - -int -sfs_rblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks) { - return sfs_rwblock(sfs, buf, blkno, nblks, 0); -} - -int -sfs_wblock(struct sfs_fs *sfs, void *buf, uint32_t blkno, uint32_t nblks) { - return sfs_rwblock(sfs, buf, blkno, nblks, 1); -} - -int -sfs_rbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset) { - assert(offset >= 0 && offset < SFS_BLKSIZE && offset + len <= SFS_BLKSIZE); - int ret; - lock_sfs_io(sfs); - { - if ((ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 0, 1)) == 0) { - memcpy(buf, sfs->sfs_buffer + offset, len); - } - } - unlock_sfs_io(sfs); - return ret; -} - -int -sfs_wbuf(struct sfs_fs *sfs, void *buf, size_t len, uint32_t blkno, off_t offset) { - assert(offset >= 0 && offset < SFS_BLKSIZE && offset + len <= SFS_BLKSIZE); - int ret; - lock_sfs_io(sfs); - { - if ((ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 0, 1)) == 0) { - memcpy(sfs->sfs_buffer + offset, buf, len); - ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 1, 1); - } - } - unlock_sfs_io(sfs); - return ret; -} - -int -sfs_sync_super(struct sfs_fs *sfs) { - int ret; - lock_sfs_io(sfs); - { - memset(sfs->sfs_buffer, 0, SFS_BLKSIZE); - memcpy(sfs->sfs_buffer, &(sfs->super), sizeof(sfs->super)); - ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, SFS_BLKN_SUPER, 1, 0); - } - unlock_sfs_io(sfs); - return ret; -} - -int -sfs_sync_freemap(struct sfs_fs *sfs) { - uint32_t nblks = sfs_freemap_blocks(&(sfs->super)); - return sfs_wblock(sfs, bitmap_getdata(sfs->freemap, NULL), SFS_BLKN_FREEMAP, nblks); -} - -int -sfs_clear_block(struct sfs_fs *sfs, uint32_t blkno, uint32_t nblks) { - int ret; - lock_sfs_io(sfs); - { - memset(sfs->sfs_buffer, 0, SFS_BLKSIZE); - while (nblks != 0) { - if ((ret = sfs_rwblock_nolock(sfs, sfs->sfs_buffer, blkno, 1, 1)) != 0) { - break; - } - blkno ++, nblks --; - } - } - unlock_sfs_io(sfs); - return ret; -} - diff --git a/ucore-thumips/kern/fs/sfs/sfs_lock.c b/ucore-thumips/kern/fs/sfs/sfs_lock.c deleted file mode 100644 index 9e24939..0000000 --- a/ucore-thumips/kern/fs/sfs/sfs_lock.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -void -lock_sfs_fs(struct sfs_fs *sfs) { - down(&(sfs->fs_sem)); -} - -void -lock_sfs_io(struct sfs_fs *sfs) { - down(&(sfs->io_sem)); -} - -void -lock_sfs_mutex(struct sfs_fs *sfs) { - down(&(sfs->mutex_sem)); -} - -void -unlock_sfs_fs(struct sfs_fs *sfs) { - up(&(sfs->fs_sem)); -} - -void -unlock_sfs_io(struct sfs_fs *sfs) { - up(&(sfs->io_sem)); -} - -void -unlock_sfs_mutex(struct sfs_fs *sfs) { - up(&(sfs->mutex_sem)); -} - diff --git a/ucore-thumips/kern/fs/sysfile.c b/ucore-thumips/kern/fs/sysfile.c deleted file mode 100644 index 37ca42b..0000000 --- a/ucore-thumips/kern/fs/sysfile.c +++ /dev/null @@ -1,303 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IOBUF_SIZE 4096 - -static int -copy_path(char **to, const char *from) { - struct mm_struct *mm = current->mm; - char *buffer; - if ((buffer = kmalloc(FS_MAX_FPATH_LEN + 1)) == NULL) { - return -E_NO_MEM; - } - lock_mm(mm); - if (!copy_string(mm, buffer, from, FS_MAX_FPATH_LEN + 1)) { - unlock_mm(mm); - goto failed_cleanup; - } - unlock_mm(mm); - *to = buffer; - return 0; - -failed_cleanup: - kfree(buffer); - return -E_INVAL; -} - -int -sysfile_open(const char *__path, uint32_t open_flags) { - int ret; - char *path; - if ((ret = copy_path(&path, __path)) != 0) { - return ret; - } - ret = file_open(path, open_flags); - kfree(path); - return ret; -} - -int -sysfile_close(int fd) { - return file_close(fd); -} - -int -sysfile_read(int fd, void *base, size_t len) { - struct mm_struct *mm = current->mm; - //kprintf("&& %08x %08x %d\n",current->fs_struct,current->fs_struct->pwd, current->fs_struct->fs_count.counter); - if (len == 0) { - return 0; - } - if (!file_testfd(fd, 1, 0)) { - return -E_INVAL; - } - void *buffer; - if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) { - return -E_NO_MEM; - } - - int ret = 0; - size_t copied = 0, alen; - while (len != 0) { - if ((alen = IOBUF_SIZE) > len) { - alen = len; - } - ret = file_read(fd, buffer, alen, &alen); - if (alen != 0) { - lock_mm(mm); - { - if (copy_to_user(mm, base, buffer, alen)) { - assert(len >= alen); - base += alen, len -= alen, copied += alen; - } - else if (ret == 0) { - ret = -E_INVAL; - } - } - unlock_mm(mm); - } - if (ret != 0 || alen == 0) { - goto out; - } - } - -out: - kfree(buffer); - if (copied != 0) { - return copied; - } - return ret; -} - -int -sysfile_write(int fd, void *base, size_t len) { - struct mm_struct *mm = current->mm; - if (len == 0) { - return 0; - } - if (!file_testfd(fd, 0, 1)) { - return -E_INVAL; - } - void *buffer; - if ((buffer = kmalloc(IOBUF_SIZE)) == NULL) { - return -E_NO_MEM; - } - - int ret = 0; - size_t copied = 0, alen; - while (len != 0) { - if ((alen = IOBUF_SIZE) > len) { - alen = len; - } - lock_mm(mm); - { - if (!copy_from_user(mm, buffer, base, alen, 0)) { - ret = -E_INVAL; - } - } - unlock_mm(mm); - if (ret == 0) { - ret = file_write(fd, buffer, alen, &alen); - if (alen != 0) { - assert(len >= alen); - base += alen, len -= alen, copied += alen; - } - } - if (ret != 0 || alen == 0) { - goto out; - } - } - -out: - kfree(buffer); - if (copied != 0) { - return copied; - } - return ret; -} - -int -sysfile_seek(int fd, off_t pos, int whence) { - return file_seek(fd, pos, whence); -} - -int -sysfile_fstat(int fd, struct stat *__stat) { - struct mm_struct *mm = current->mm; - int ret; - struct stat __local_stat, *stat = &__local_stat; - if ((ret = file_fstat(fd, stat)) != 0) { - return ret; - } - - lock_mm(mm); - { - if (!copy_to_user(mm, __stat, stat, sizeof(struct stat))) { - ret = -E_INVAL; - } - } - unlock_mm(mm); - return ret; -} - -int -sysfile_fsync(int fd) { - return file_fsync(fd); -} - -int -sysfile_chdir(const char *__path) { - int ret; - char *path; - if ((ret = copy_path(&path, __path)) != 0) { - return ret; - } - ret = vfs_chdir(path); - kfree(path); - return ret; -} - -int -sysfile_link(const char *__path1, const char *__path2) { - int ret; - char *old_path, *new_path; - if ((ret = copy_path(&old_path, __path1)) != 0) { - return ret; - } - if ((ret = copy_path(&new_path, __path2)) != 0) { - kfree(old_path); - return ret; - } - ret = vfs_link(old_path, new_path); - kfree(old_path), kfree(new_path); - return ret; -} - -int -sysfile_rename(const char *__path1, const char *__path2) { - int ret; - char *old_path, *new_path; - if ((ret = copy_path(&old_path, __path1)) != 0) { - return ret; - } - if ((ret = copy_path(&new_path, __path2)) != 0) { - kfree(old_path); - return ret; - } - ret = vfs_rename(old_path, new_path); - kfree(old_path), kfree(new_path); - return ret; -} - -int -sysfile_unlink(const char *__path) { - int ret; - char *path; - if ((ret = copy_path(&path, __path)) != 0) { - return ret; - } - ret = vfs_unlink(path); - kfree(path); - return ret; -} - -int -sysfile_getcwd(char *buf, size_t len) { - struct mm_struct *mm = current->mm; - if (len == 0) { - return -E_INVAL; - } - - int ret = -E_INVAL; - lock_mm(mm); - { - if (user_mem_check(mm, (uintptr_t)buf, len, 1)) { - struct iobuf __iob, *iob = iobuf_init(&__iob, buf, len, 0); - ret = vfs_getcwd(iob); - } - } - unlock_mm(mm); - return ret; -} - -int -sysfile_getdirentry(int fd, struct dirent *__direntp) { - struct mm_struct *mm = current->mm; - struct dirent *direntp; - if ((direntp = kmalloc(sizeof(struct dirent))) == NULL) { - return -E_NO_MEM; - } - - int ret = 0; - lock_mm(mm); - { - if (!copy_from_user(mm, &(direntp->offset), &(__direntp->offset), sizeof(direntp->offset), 1)) { - ret = -E_INVAL; - } - } - unlock_mm(mm); - - if (ret != 0 || (ret = file_getdirentry(fd, direntp)) != 0) { - goto out; - } - - lock_mm(mm); - { - if (!copy_to_user(mm, __direntp, direntp, sizeof(struct dirent))) { - ret = -E_INVAL; - } - } - unlock_mm(mm); - -out: - kfree(direntp); - return ret; -} - -int -sysfile_dup(int fd1, int fd2) { - return file_dup(fd1, fd2); -} - -int -sysfile_pipe(int *fd_store) { - return -E_UNIMP; -} - -int -sysfile_mkfifo(const char *__name, uint32_t open_flags) { - return -E_UNIMP; -} - diff --git a/ucore-thumips/kern/fs/sysfile.h b/ucore-thumips/kern/fs/sysfile.h deleted file mode 100644 index 57bac93..0000000 --- a/ucore-thumips/kern/fs/sysfile.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __KERN_FS_SYSFILE_H__ -#define __KERN_FS_SYSFILE_H__ - -#include - -struct stat; -struct dirent; - -int sysfile_open(const char *path, uint32_t open_flags); -int sysfile_close(int fd); -int sysfile_read(int fd, void *base, size_t len); -int sysfile_write(int fd, void *base, size_t len); -int sysfile_seek(int fd, off_t pos, int whence); -int sysfile_fstat(int fd, struct stat *stat); -int sysfile_fsync(int fd); -int sysfile_chdir(const char *path); -int sysfile_mkdir(const char *path); -int sysfile_link(const char *path1, const char *path2); -int sysfile_rename(const char *path1, const char *path2); -int sysfile_unlink(const char *path); -int sysfile_getcwd(char *buf, size_t len); -int sysfile_getdirentry(int fd, struct dirent *direntp); -int sysfile_dup(int fd1, int fd2); -int sysfile_pipe(int *fd_store); -int sysfile_mkfifo(const char *name, uint32_t open_flags); - -#endif /* !__KERN_FS_SYSFILE_H__ */ - diff --git a/ucore-thumips/kern/fs/vfs/inode.c b/ucore-thumips/kern/fs/vfs/inode.c deleted file mode 100644 index 39b7d01..0000000 --- a/ucore-thumips/kern/fs/vfs/inode.c +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* * - * __alloc_inode - alloc a inode structure and initialize in_type - * */ -struct inode * -__alloc_inode(int type) { - struct inode *node; - if ((node = kmalloc(sizeof(struct inode))) != NULL) { - node->in_type = type; - } - return node; -} - -/* * - * inode_init - initialize a inode structure - * invoked by vop_init - * */ -void -inode_init(struct inode *node, const struct inode_ops *ops, struct fs *fs) { - atomic_set(&(node->ref_count), 0); - atomic_set(&(node->open_count), 0); - node->in_ops = ops, node->in_fs = fs; - vop_ref_inc(node); -} - -/* * - * inode_kill - kill a inode structure - * invoked by vop_kill - * */ -void -inode_kill(struct inode *node) { - assert(inode_ref_count(node) == 0); - assert(inode_open_count(node) == 0); - kfree(node); -} - -/* * - * inode_ref_inc - increment ref_count - * invoked by vop_ref_inc - * */ -int -inode_ref_inc(struct inode *node) { - return atomic_add_return(&(node->ref_count), 1); -} - -/* * - * inode_ref_dec - decrement ref_count - * invoked by vop_ref_dec - * calls vop_reclaim if the ref_count hits zero - * */ -int -inode_ref_dec(struct inode *node) { - assert(inode_ref_count(node) > 0); - int ref_count, ret; - if ((ref_count = atomic_sub_return(&(node->ref_count), 1)) == 0) { - if ((ret = vop_reclaim(node)) != 0 && ret != -E_BUSY) { - kprintf("vfs: warning: vop_reclaim: %e.\n", ret); - } - } - return ref_count; -} - -/* * - * inode_open_inc - increment the open_count - * invoked by vop_open_inc - * */ -int -inode_open_inc(struct inode *node) { - return atomic_add_return(&(node->open_count), 1); -} - -/* * - * inode_open_dec - decrement the open_count - * invoked by vop_open_dec - * calls vop_close if the open_count hits zero - * */ -int -inode_open_dec(struct inode *node) { - assert(inode_open_count(node) > 0); - int open_count, ret; - if ((open_count = atomic_sub_return(&(node->open_count), 1)) == 0) { - if ((ret = vop_close(node)) != 0) { - kprintf("vfs: warning: vop_close: %e.\n", ret); - } - } - return open_count; -} - -/* * - * inode_check - check the various things being valid - * called before all vop_* calls - * */ -void -inode_check(struct inode *node, const char *opstr) { - assert(node != NULL && node->in_ops != NULL); - assert(node->in_ops->vop_magic == VOP_MAGIC); - int ref_count = inode_ref_count(node), open_count = inode_open_count(node); - assert(ref_count >= open_count && open_count >= 0); - assert(ref_count < MAX_INODE_COUNT && open_count < MAX_INODE_COUNT); -} - diff --git a/ucore-thumips/kern/fs/vfs/inode.h b/ucore-thumips/kern/fs/vfs/inode.h deleted file mode 100644 index 61f6fbe..0000000 --- a/ucore-thumips/kern/fs/vfs/inode.h +++ /dev/null @@ -1,248 +0,0 @@ -#ifndef __KERN_FS_VFS_INODE_H__ -#define __KERN_FS_VFS_INODE_H__ - -#include -#include -#include -#include -#include - -struct stat; -struct iobuf; - -/* - * A struct inode is an abstract representation of a file. - * - * It is an interface that allows the kernel's filesystem-independent - * code to interact usefully with multiple sets of filesystem code. - */ - -/* - * Abstract low-level file. - * - * Note: in_info is Filesystem-specific data, in_type is the inode type - * - * open_count is managed using VOP_INCOPEN and VOP_DECOPEN by - * vfs_open() and vfs_close(). Code above the VFS layer should not - * need to worry about it. - */ -struct inode { - union { - struct device __device_info; - struct sfs_inode __sfs_inode_info; - } in_info; - enum { - inode_type_device_info = 0x1234, - inode_type_sfs_inode_info, - } in_type; - atomic_t ref_count; - atomic_t open_count; - struct fs *in_fs; - const struct inode_ops *in_ops; -}; - -#define __in_type(type) inode_type_##type##_info - -#define check_inode_type(node, type) ((node)->in_type == __in_type(type)) - -#define __vop_info(node, type) \ - ({ \ - struct inode *__node = (node); \ - assert(__node != NULL && check_inode_type(__node, type)); \ - &(__node->in_info.__##type##_info); \ - }) - -#define vop_info(node, type) __vop_info(node, type) - -#define info2node(info, type) \ - to_struct((info), struct inode, in_info.__##type##_info) - -struct inode *__alloc_inode(int type); - -#define alloc_inode(type) __alloc_inode(__in_type(type)) - -#define MAX_INODE_COUNT 0x10000 - -int inode_ref_inc(struct inode *node); -int inode_ref_dec(struct inode *node); -int inode_open_inc(struct inode *node); -int inode_open_dec(struct inode *node); - -void inode_init(struct inode *node, const struct inode_ops *ops, struct fs *fs); -void inode_kill(struct inode *node); - -#define VOP_MAGIC 0x8c4ba476 - -/* - * Abstract operations on a inode. - * - * These are used in the form VOP_FOO(inode, args), which are macros - * that expands to inode->inode_ops->vop_foo(inode, args). The operations - * "foo" are: - * - * vop_open - Called on open() of a file. Can be used to - * reject illegal or undesired open modes. Note that - * various operations can be performed without the - * file actually being opened. - * The inode need not look at O_CREAT, O_EXCL, or - * O_TRUNC, as these are handled in the VFS layer. - * - * VOP_EACHOPEN should not be called directly from - * above the VFS layer - use vfs_open() to open inodes. - * This maintains the open count so VOP_LASTCLOSE can - * be called at the right time. - * - * vop_close - To be called on *last* close() of a file. - * - * VOP_LASTCLOSE should not be called directly from - * above the VFS layer - use vfs_close() to close - * inodes opened with vfs_open(). - * - * vop_reclaim - Called when inode is no longer in use. Note that - * this may be substantially after vop_lastclose is - * called. - * - ***************************************** - * - * vop_read - Read data from file to uio, at offset specified - * in the uio, updating uio_resid to reflect the - * amount read, and updating uio_offset to match. - * Not allowed on directories or symlinks. - * - * vop_getdirentry - Read a single filename from a directory into a - * uio, choosing what name based on the offset - * field in the uio, and updating that field. - * Unlike with I/O on regular files, the value of - * the offset field is not interpreted outside - * the filesystem and thus need not be a byte - * count. However, the uio_resid field should be - * handled in the normal fashion. - * On non-directory objects, return ENOTDIR. - * - * vop_write - Write data from uio to file at offset specified - * in the uio, updating uio_resid to reflect the - * amount written, and updating uio_offset to match. - * Not allowed on directories or symlinks. - * - * vop_ioctl - Perform ioctl operation OP on file using data - * DATA. The interpretation of the data is specific - * to each ioctl. - * - * vop_stat - Return info about a file. The pointer is a - * pointer to struct stat; see kern/stat.h. - * - * vop_gettype - Return type of file. The values for file types - * are in kern/stattypes.h. - * - * vop_tryseek - Check if seeking to the specified position within - * the file is legal. (For instance, all seeks - * are illegal on serial port devices, and seeks - * past EOF on files whose sizes are fixed may be - * as well.) - * - * vop_fsync - Force any dirty buffers associated with this file - * to stable storage. - * - * vop_truncate - Forcibly set size of file to the length passed - * in, discarding any excess blocks. - * - * vop_namefile - Compute pathname relative to filesystem root - * of the file and copy to the specified - * uio. Need not work on objects that are not - * directories. - * - ***************************************** - * - * vop_creat - Create a regular file named NAME in the passed - * directory DIR. If boolean EXCL is true, fail if - * the file already exists; otherwise, use the - * existing file if there is one. Hand back the - * inode for the file as per vop_lookup. - * - ***************************************** - * - * vop_lookup - Parse PATHNAME relative to the passed directory - * DIR, and hand back the inode for the file it - * refers to. May destroy PATHNAME. Should increment - * refcount on inode handed back. - */ -struct inode_ops { - unsigned long vop_magic; - int (*vop_open)(struct inode *node, uint32_t open_flags); - int (*vop_close)(struct inode *node); - int (*vop_read)(struct inode *node, struct iobuf *iob); - int (*vop_write)(struct inode *node, struct iobuf *iob); - int (*vop_fstat)(struct inode *node, struct stat *stat); - int (*vop_fsync)(struct inode *node); - int (*vop_namefile)(struct inode *node, struct iobuf *iob); - int (*vop_getdirentry)(struct inode *node, struct iobuf *iob); - int (*vop_reclaim)(struct inode *node); - int (*vop_gettype)(struct inode *node, uint32_t *type_store); - int (*vop_tryseek)(struct inode *node, off_t pos); - int (*vop_truncate)(struct inode *node, off_t len); - int (*vop_create)(struct inode *node, const char *name, bool excl, struct inode **node_store); - int (*vop_lookup)(struct inode *node, char *path, struct inode **node_store); - int (*vop_ioctl)(struct inode *node, int op, void *data); -}; - -/* - * Consistency check - */ -void inode_check(struct inode *node, const char *opstr); - -#define __vop_op(node, sym) \ - ({ \ - struct inode *__node = (node); \ - assert(__node != NULL && __node->in_ops != NULL && __node->in_ops->vop_##sym != NULL); \ - inode_check(__node, #sym); \ - __node->in_ops->vop_##sym; \ - }) - -#define vop_open(node, open_flags) (__vop_op(node, open)(node, open_flags)) -#define vop_close(node) (__vop_op(node, close)(node)) -#define vop_read(node, iob) (__vop_op(node, read)(node, iob)) -#define vop_write(node, iob) (__vop_op(node, write)(node, iob)) -#define vop_fstat(node, stat) (__vop_op(node, fstat)(node, stat)) -#define vop_fsync(node) (__vop_op(node, fsync)(node)) -#define vop_namefile(node, iob) (__vop_op(node, namefile)(node, iob)) -#define vop_getdirentry(node, iob) (__vop_op(node, getdirentry)(node, iob)) -#define vop_reclaim(node) (__vop_op(node, reclaim)(node)) -#define vop_ioctl(node, op, data) (__vop_op(node, ioctl)(node, op, data)) -#define vop_gettype(node, type_store) (__vop_op(node, gettype)(node, type_store)) -#define vop_tryseek(node, pos) (__vop_op(node, tryseek)(node, pos)) -#define vop_truncate(node, len) (__vop_op(node, truncate)(node, len)) -#define vop_create(node, name, excl, node_store) (__vop_op(node, create)(node, name, excl, node_store)) -#define vop_lookup(node, path, node_store) (__vop_op(node, lookup)(node, path, node_store)) - - -#define vop_fs(node) ((node)->in_fs) -#define vop_init(node, ops, fs) inode_init(node, ops, fs) -#define vop_kill(node) inode_kill(node) - -/* - * Reference count manipulation (handled above filesystem level) - */ -#define vop_ref_inc(node) inode_ref_inc(node) -#define vop_ref_dec(node) inode_ref_dec(node) -/* - * Open count manipulation (handled above filesystem level) - * - * VOP_INCOPEN is called by vfs_open. VOP_DECOPEN is called by vfs_close. - * Neither of these should need to be called from above the vfs layer. - */ -#define vop_open_inc(node) inode_open_inc(node) -#define vop_open_dec(node) inode_open_dec(node) - - -static inline int -inode_ref_count(struct inode *node) { - return atomic_read(&(node->ref_count)); -} - -static inline int -inode_open_count(struct inode *node) { - return atomic_read(&(node->open_count)); -} - -#endif /* !__KERN_FS_VFS_INODE_H__ */ - diff --git a/ucore-thumips/kern/fs/vfs/vfs.c b/ucore-thumips/kern/fs/vfs/vfs.c deleted file mode 100644 index 9f0dd1e..0000000 --- a/ucore-thumips/kern/fs/vfs/vfs.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -static semaphore_t bootfs_sem; -static struct inode *bootfs_node = NULL; - -extern void vfs_devlist_init(void); - -struct fs * -__alloc_fs(int type) { - struct fs *fs; - if ((fs = kmalloc(sizeof(struct fs))) != NULL) { - fs->fs_type = type; - } - return fs; -} - -void -vfs_init(void) { - sem_init(&bootfs_sem, 1); - vfs_devlist_init(); -} - -static void -lock_bootfs(void) { - down(&bootfs_sem); -} - -static void -unlock_bootfs(void) { - up(&bootfs_sem); -} - -static void -change_bootfs(struct inode *node) { - struct inode *old; - lock_bootfs(); - { - old = bootfs_node, bootfs_node = node; - } - unlock_bootfs(); - if (old != NULL) { - vop_ref_dec(old); - } -} - -int -vfs_set_bootfs(char *fsname) { - struct inode *node = NULL; - if (fsname != NULL) { - char *s; - if ((s = strchr(fsname, ':')) == NULL || s[1] != '\0') { - return -E_INVAL; - } - int ret; - if ((ret = vfs_chdir(fsname)) != 0) { - return ret; - } - if ((ret = vfs_get_curdir(&node)) != 0) { - return ret; - } - } - change_bootfs(node); - return 0; -} - -int -vfs_get_bootfs(struct inode **node_store) { - struct inode *node = NULL; - if (bootfs_node != NULL) { - lock_bootfs(); - { - if ((node = bootfs_node) != NULL) { - vop_ref_inc(bootfs_node); - } - } - unlock_bootfs(); - } - if (node == NULL) { - return -E_NOENT; - } - *node_store = node; - return 0; -} - diff --git a/ucore-thumips/kern/fs/vfs/vfs.h b/ucore-thumips/kern/fs/vfs/vfs.h deleted file mode 100644 index 02489b6..0000000 --- a/ucore-thumips/kern/fs/vfs/vfs.h +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef __KERN_FS_VFS_VFS_H__ -#define __KERN_FS_VFS_VFS_H__ - -#include -#include -#include - -struct inode; // abstract structure for an on-disk file (inode.h) -struct device; // abstract structure for a device (dev.h) -struct iobuf; // kernel or userspace I/O buffer (iobuf.h) - -/* - * Abstract filesystem. (Or device accessible as a file.) - * - * Information: - * fs_info : filesystem-specific data (pipe_fs/sfs_fs) - * fs_type : filesystem type - * Operations: - * - * fs_sync - Flush all dirty buffers to disk. - * fs_get_root - Return root inode of filesystem. - * fs_unmount - Attempt unmount of filesystem. - * fs_cleanup - Cleanup of filesystem.??? - * - * - * fs_get_root should increment the refcount of the inode returned. - * It should not ever return NULL. - * - * If fs_unmount returns an error, the filesystem stays mounted, and - * consequently the struct fs instance should remain valid. On success, - * however, the filesystem object and all storage associated with the - * filesystem should have been discarded/released. - * - */ -struct fs { - union { - struct sfs_fs __sfs_info; - } fs_info; - enum { - fs_type_sfs_info, - } fs_type; - int (*fs_sync)(struct fs *fs); - struct inode *(*fs_get_root)(struct fs *fs); - int (*fs_unmount)(struct fs *fs); - void (*fs_cleanup)(struct fs *fs); -}; - -#define __fs_type(type) fs_type_##type##_info - -#define check_fs_type(fs, type) ((fs)->fs_type == __fs_type(type)) - -#define __fsop_info(_fs, type) ({ \ - struct fs *__fs = (_fs); \ - assert(__fs != NULL && check_fs_type(__fs, type)); \ - &(__fs->fs_info.__##type##_info); \ - }) - -#define fsop_info(fs, type) __fsop_info(fs, type) - -#define info2fs(info, type) \ - to_struct((info), struct fs, fs_info.__##type##_info) - -struct fs *__alloc_fs(int type); - -#define alloc_fs(type) __alloc_fs(__fs_type(type)) - -// Macros to shorten the calling sequences. -#define fsop_sync(fs) ((fs)->fs_sync(fs)) -#define fsop_get_root(fs) ((fs)->fs_get_root(fs)) -#define fsop_unmount(fs) ((fs)->fs_unmount(fs)) -#define fsop_cleanup(fs) ((fs)->fs_cleanup(fs)) - -/* - * Virtual File System layer functions. - * - * The VFS layer translates operations on abstract on-disk files or - * pathnames to operations on specific files on specific filesystems. - */ -void vfs_init(void); -void vfs_cleanup(void); -void vfs_devlist_init(void); - -/* - * VFS layer low-level operations. - * See inode.h for direct operations on inodes. - * See fs.h for direct operations on filesystems/devices. - * - * vfs_set_curdir - change current directory of current thread by inode - * vfs_get_curdir - retrieve inode of current directory of current thread - * vfs_get_root - get root inode for the filesystem named DEVNAME - * vfs_get_devname - get mounted device name for the filesystem passed in - */ -int vfs_set_curdir(struct inode *dir); -int vfs_get_curdir(struct inode **dir_store); -int vfs_get_root(const char *devname, struct inode **root_store); -const char *vfs_get_devname(struct fs *fs); - - -/* - * VFS layer high-level operations on pathnames - * Because namei may destroy pathnames, these all may too. - * - * vfs_open - Open or create a file. FLAGS/MODE per the syscall. - * vfs_close - Close a inode opened with vfs_open. Does not fail. - * (See vfspath.c for a discussion of why.) - * vfs_link - Create a hard link to a file. - * vfs_symlink - Create a symlink PATH containing contents CONTENTS. - * vfs_readlink - Read contents of a symlink into a uio. - * vfs_mkdir - Create a directory. MODE per the syscall. - * vfs_unlink - Delete a file/directory. - * vfs_rename - rename a file. - * vfs_chdir - Change current directory of current thread by name. - * vfs_getcwd - Retrieve name of current directory of current thread. - * - */ -int vfs_open(char *path, uint32_t open_flags, struct inode **inode_store); -int vfs_close(struct inode *node); -int vfs_link(char *old_path, char *new_path); -int vfs_symlink(char *old_path, char *new_path); -int vfs_readlink(char *path, struct iobuf *iob); -int vfs_mkdir(char *path); -int vfs_unlink(char *path); -int vfs_rename(char *old_path, char *new_path); -int vfs_chdir(char *path); -int vfs_getcwd(struct iobuf *iob); - - -/* - * VFS layer mid-level operations. - * - * vfs_lookup - Like VOP_LOOKUP, but takes a full device:path name, - * or a name relative to the current directory, and - * goes to the correct filesystem. - * vfs_lookparent - Likewise, for VOP_LOOKPARENT. - * - * Both of these may destroy the path passed in. - */ -int vfs_lookup(char *path, struct inode **node_store); -int vfs_lookup_parent(char *path, struct inode **node_store, char **endp); - -/* - * Misc - * - * vfs_set_bootfs - Set the filesystem that paths beginning with a - * slash are sent to. If not set, these paths fail - * with ENOENT. The argument should be the device - * name or volume name for the filesystem (such as - * "lhd0:") but need not have the trailing colon. - * - * vfs_get_bootfs - return the inode of the bootfs filesystem. - * - * vfs_add_fs - Add a hardwired filesystem to the VFS named device - * list. It will be accessible as "devname:". This is - * intended for filesystem-devices like emufs, and - * gizmos like Linux procfs or BSD kernfs, not for - * mounting filesystems on disk devices. - * - * vfs_add_dev - Add a device to the VFS named device list. If - * MOUNTABLE is zero, the device will be accessible - * as "DEVNAME:". If the mountable flag is set, the - * device will be accessible as "DEVNAMEraw:" and - * mountable under the name "DEVNAME". Thus, the - * console, added with MOUNTABLE not set, would be - * accessed by pathname as "con:", and lhd0, added - * with mountable set, would be accessed by - * pathname as "lhd0raw:" and mounted by passing - * "lhd0" to vfs_mount. - * - * vfs_mount - Attempt to mount a filesystem on a device. The - * device named by DEVNAME will be looked up and - * passed, along with DATA, to the supplied function - * MOUNTFUNC, which should create a struct fs and - * return it in RESULT. - * - * vfs_unmount - Unmount the filesystem presently mounted on the - * specified device. - * - * vfs_unmountall - Unmount all mounted filesystems. - */ -int vfs_set_bootfs(char *fsname); -int vfs_get_bootfs(struct inode **node_store); - -int vfs_add_fs(const char *devname, struct fs *fs); -int vfs_add_dev(const char *devname, struct inode *devnode, bool mountable); - -int vfs_mount(const char *devname, int (*mountfunc)(struct device *dev, struct fs **fs_store)); -int vfs_unmount(const char *devname); -int vfs_unmount_all(void); - -#endif /* !__KERN_FS_VFS_VFS_H__ */ - diff --git a/ucore-thumips/kern/fs/vfs/vfsdev.c b/ucore-thumips/kern/fs/vfs/vfsdev.c deleted file mode 100644 index 5321aa7..0000000 --- a/ucore-thumips/kern/fs/vfs/vfsdev.c +++ /dev/null @@ -1,264 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - const char *devname; - struct inode *devnode; - struct fs *fs; - bool mountable; - list_entry_t vdev_link; -} vfs_dev_t; - -#define le2vdev(le, member) \ - to_struct((le), vfs_dev_t, member) - -static list_entry_t vdev_list; -static semaphore_t vdev_list_sem; - -static void -lock_vdev_list(void) { - down(&vdev_list_sem); -} - -static void -unlock_vdev_list(void) { - up(&vdev_list_sem); -} - -void -vfs_devlist_init(void) { - list_init(&vdev_list); - sem_init(&vdev_list_sem, 1); -} - -void -vfs_cleanup(void) { - if (!list_empty(&vdev_list)) { - lock_vdev_list(); - { - list_entry_t *list = &vdev_list, *le = list; - while ((le = list_next(le)) != list) { - vfs_dev_t *vdev = le2vdev(le, vdev_link); - if (vdev->fs != NULL) { - fsop_cleanup(vdev->fs); - } - } - } - unlock_vdev_list(); - } -} - -int -vfs_get_root(const char *devname, struct inode **node_store) { - assert(devname != NULL); - int ret = -E_NO_DEV; - if (!list_empty(&vdev_list)) { - lock_vdev_list(); - { - list_entry_t *list = &vdev_list, *le = list; - while ((le = list_next(le)) != list) { - vfs_dev_t *vdev = le2vdev(le, vdev_link); - if (strcmp(devname, vdev->devname) == 0) { - struct inode *found = NULL; - if (vdev->fs != NULL) { - found = fsop_get_root(vdev->fs); - } - else if (!vdev->mountable) { - vop_ref_inc(vdev->devnode); - found = vdev->devnode; - } - if (found != NULL) { - ret = 0, *node_store = found; - } - else { - ret = -E_NA_DEV; - } - break; - } - } - } - unlock_vdev_list(); - } - return ret; -} - -const char * -vfs_get_devname(struct fs *fs) { - assert(fs != NULL); - list_entry_t *list = &vdev_list, *le = list; - while ((le = list_next(le)) != list) { - vfs_dev_t *vdev = le2vdev(le, vdev_link); - if (vdev->fs == fs) { - return vdev->devname; - } - } - return NULL; -} - -static bool -check_devname_conflict(const char *devname) { - list_entry_t *list = &vdev_list, *le = list; - while ((le = list_next(le)) != list) { - vfs_dev_t *vdev = le2vdev(le, vdev_link); - if (strcmp(vdev->devname, devname) == 0) { - return 0; - } - } - return 1; -} - -static int -vfs_do_add(const char *devname, struct inode *devnode, struct fs *fs, bool mountable) { - assert(devname != NULL); - assert((devnode == NULL && !mountable) || (devnode != NULL && check_inode_type(devnode, device))); - if (strlen(devname) > FS_MAX_DNAME_LEN) { - return -E_TOO_BIG; - } - - int ret = -E_NO_MEM; - char *s_devname; - if ((s_devname = strdup(devname)) == NULL) { - return ret; - } - - vfs_dev_t *vdev; - if ((vdev = kmalloc(sizeof(vfs_dev_t))) == NULL) { - goto failed_cleanup_name; - } - - ret = -E_EXISTS; - lock_vdev_list(); - if (!check_devname_conflict(s_devname)) { - unlock_vdev_list(); - goto failed_cleanup_vdev; - } - vdev->devname = s_devname; - vdev->devnode = devnode; - vdev->mountable = mountable; - vdev->fs = fs; - - list_add(&vdev_list, &(vdev->vdev_link)); - unlock_vdev_list(); - return 0; - -failed_cleanup_vdev: - kfree(vdev); -failed_cleanup_name: - kfree(s_devname); - return ret; -} - -int -vfs_add_fs(const char *devname, struct fs *fs) { - return vfs_do_add(devname, NULL, fs, 0); -} - -int -vfs_add_dev(const char *devname, struct inode *devnode, bool mountable) { - return vfs_do_add(devname, devnode, NULL, mountable); -} - -static int -find_mount(const char *devname, vfs_dev_t **vdev_store) { - assert(devname != NULL); - list_entry_t *list = &vdev_list, *le = list; - while ((le = list_next(le)) != list) { - vfs_dev_t *vdev = le2vdev(le, vdev_link); - if (vdev->mountable && strcmp(vdev->devname, devname) == 0) { - *vdev_store = vdev; - return 0; - } - } - return -E_NO_DEV; -} - -int -vfs_mount(const char *devname, int (*mountfunc)(struct device *dev, struct fs **fs_store)) { - int ret; - lock_vdev_list(); - vfs_dev_t *vdev; - if ((ret = find_mount(devname, &vdev)) != 0) { - goto out; - } - if (vdev->fs != NULL) { - ret = -E_BUSY; - goto out; - } - assert(vdev->devname != NULL && vdev->mountable); - - struct device *dev = vop_info(vdev->devnode, device); - if ((ret = mountfunc(dev, &(vdev->fs))) == 0) { - assert(vdev->fs != NULL); - kprintf("vfs: mount %s.\n", vdev->devname); - } - -out: - unlock_vdev_list(); - return ret; -} - -int -vfs_unmount(const char *devname) { - int ret; - lock_vdev_list(); - vfs_dev_t *vdev; - if ((ret = find_mount(devname, &vdev)) != 0) { - goto out; - } - if (vdev->fs == NULL) { - ret = -E_INVAL; - goto out; - } - assert(vdev->devname != NULL && vdev->mountable); - - if ((ret = fsop_sync(vdev->fs)) != 0) { - goto out; - } - if ((ret = fsop_unmount(vdev->fs)) == 0) { - vdev->fs = NULL; - kprintf("vfs: unmount %s.\n", vdev->devname); - } - -out: - unlock_vdev_list(); - return ret; -} - -int -vfs_unmount_all(void) { - if (!list_empty(&vdev_list)) { - lock_vdev_list(); - { - list_entry_t *list = &vdev_list, *le = list; - while ((le = list_next(le)) != list) { - vfs_dev_t *vdev = le2vdev(le, vdev_link); - if (vdev->mountable && vdev->fs != NULL) { - int ret; - if ((ret = fsop_sync(vdev->fs)) != 0) { - kprintf("vfs: warning: sync failed for %s: %e.\n", vdev->devname, ret); - continue ; - } - if ((ret = fsop_unmount(vdev->fs)) != 0) { - kprintf("vfs: warning: unmount failed for %s: %e.\n", vdev->devname, ret); - continue ; - } - vdev->fs = NULL; - kprintf("vfs: unmount %s.\n", vdev->devname); - } - } - } - unlock_vdev_list(); - } - return 0; -} - diff --git a/ucore-thumips/kern/fs/vfs/vfsfile.c b/ucore-thumips/kern/fs/vfs/vfsfile.c deleted file mode 100644 index 85fe8da..0000000 --- a/ucore-thumips/kern/fs/vfs/vfsfile.c +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -int -vfs_open(char *path, uint32_t open_flags, struct inode **node_store) { - bool can_write = 0; - switch (open_flags & O_ACCMODE) { - case O_RDONLY: - break; - case O_WRONLY: - case O_RDWR: - can_write = 1; - break; - default: - return -E_INVAL; - } - - if (open_flags & O_TRUNC) { - if (!can_write) { - return -E_INVAL; - } - } - - int ret; - struct inode *node; - bool excl = (open_flags & O_EXCL) != 0; - bool create = (open_flags & O_CREAT) != 0; - ret = vfs_lookup(path, &node); - - if (ret != 0) { - if (ret == -16 && (create)) { - char *name; - struct inode *dir; - if ((ret = vfs_lookup_parent(path, &dir, &name)) != 0) { - return ret; - } - ret = vop_create(dir, name, excl, &node); - } else return ret; - } else if (excl && create) { - return -E_EXISTS; - } - assert(node != NULL); - - if ((ret = vop_open(node, open_flags)) != 0) { - vop_ref_dec(node); - return ret; - } - - vop_open_inc(node); - if (open_flags & O_TRUNC || create) { - if ((ret = vop_truncate(node, 0)) != 0) { - vop_open_dec(node); - vop_ref_dec(node); - return ret; - } - } - *node_store = node; - return 0; -} - -int -vfs_close(struct inode *node) { - vop_open_dec(node); - vop_ref_dec(node); - return 0; -} - -int -vfs_unlink(char *path) { - return -E_UNIMP; -} - - -int -vfs_rename(char *old_path, char *new_path) { - return -E_UNIMP; -} - -int -vfs_link(char *old_path, char *new_path) { - return -E_UNIMP; -} - -int -vfs_symlink(char *old_path, char *new_path) { - return -E_UNIMP; -} - -int -vfs_readlink(char *path, struct iobuf *iob) { - return -E_UNIMP; -} - -int -vfs_mkdir(char *path){ - return -E_UNIMP; -} diff --git a/ucore-thumips/kern/fs/vfs/vfslookup.c b/ucore-thumips/kern/fs/vfs/vfslookup.c deleted file mode 100644 index f619f92..0000000 --- a/ucore-thumips/kern/fs/vfs/vfslookup.c +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include -#include -#include - -static int -get_device(char *path, char **subpath, struct inode **node_store) { - int i, slash = -1, colon = -1; - for (i = 0; path[i] != '\0'; i ++) { - if (path[i] == ':') { colon = i; break; } - if (path[i] == '/') { slash = i; break; } - } - if (colon < 0 && slash != 0) { - /* * - * No colon before a slash, so no device name specified, and the slash isn't leading - * or is also absent, so this is a relative path or just a bare filename. Start from - * the current directory, and use the whole thing as the subpath. - * */ - *subpath = path; - return vfs_get_curdir(node_store); - } - if (colon > 0) { - /* device:path - get root of device's filesystem */ - path[colon] = '\0'; - - /* device:/path - skip slash, treat as device:path */ - while (path[++ colon] == '/'); - *subpath = path + colon; - return vfs_get_root(path, node_store); - } - - /* * - * we have either /path or :path - * /path is a path relative to the root of the "boot filesystem" - * :path is a path relative to the root of the current filesystem - * */ - int ret; - if (*path == '/') { - if ((ret = vfs_get_bootfs(node_store)) != 0) { - return ret; - } - } - else { - assert(*path == ':'); - struct inode *node; - if ((ret = vfs_get_curdir(&node)) != 0) { - return ret; - } - /* The current directory may not be a device, so it must have a fs. */ - assert(node->in_fs != NULL); - *node_store = fsop_get_root(node->in_fs); - vop_ref_dec(node); - } - - /* ///... or :/... */ - while (*(++ path) == '/'); - *subpath = path; - return 0; -} - -int -vfs_lookup(char *path, struct inode **node_store) { - int ret; - struct inode *node; - if ((ret = get_device(path, &path, &node)) != 0) { - return ret; - } - if (*path != '\0') { - ret = vop_lookup(node, path, node_store); - vop_ref_dec(node); - return ret; - } - *node_store = node; - return 0; -} - -int -vfs_lookup_parent(char *path, struct inode **node_store, char **endp){ - int ret; - struct inode *node; - if ((ret = get_device(path, &path, &node)) != 0) { - return ret; - } - *endp = path; - *node_store = node; - return 0; -} diff --git a/ucore-thumips/kern/fs/vfs/vfspath.c b/ucore-thumips/kern/fs/vfs/vfspath.c deleted file mode 100644 index 53f331c..0000000 --- a/ucore-thumips/kern/fs/vfs/vfspath.c +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct inode * -get_cwd_nolock(void) { - return current->fs_struct->pwd; -} - -static void -set_cwd_nolock(struct inode *pwd) { - current->fs_struct->pwd = pwd; -} - -static void -lock_cfs(void) { - lock_fs(current->fs_struct); -} - -static void -unlock_cfs(void) { - unlock_fs(current->fs_struct); -} - -int -vfs_get_curdir(struct inode **dir_store) { - struct inode *node; - if ((node = get_cwd_nolock()) != NULL) { - vop_ref_inc(node); - *dir_store = node; - return 0; - } - return -E_NOENT; -} - -int -vfs_set_curdir(struct inode *dir) { - int ret = 0; - lock_cfs(); - struct inode *old_dir; - if ((old_dir = get_cwd_nolock()) != dir) { - if (dir != NULL) { - uint32_t type; - if ((ret = vop_gettype(dir, &type)) != 0) { - goto out; - } - if (!S_ISDIR(type)) { - ret = -E_NOTDIR; - goto out; - } - vop_ref_inc(dir); - } - set_cwd_nolock(dir); - if (old_dir != NULL) { - vop_ref_dec(old_dir); - } - } -out: - unlock_cfs(); - return ret; -} - -int -vfs_chdir(char *path) { - int ret; - struct inode *node; - if ((ret = vfs_lookup(path, &node)) == 0) { - ret = vfs_set_curdir(node); - vop_ref_dec(node); - } - return ret; -} - -int -vfs_getcwd(struct iobuf *iob) { - int ret; - struct inode *node; - if ((ret = vfs_get_curdir(&node)) != 0) { - return ret; - } - assert(node->in_fs != NULL); - - const char *devname = vfs_get_devname(node->in_fs); - if ((ret = iobuf_move(iob, (char *)devname, strlen(devname), 1, NULL)) != 0) { - goto out; - } - char colon = ':'; - if ((ret = iobuf_move(iob, &colon, sizeof(colon), 1, NULL)) != 0) { - goto out; - } - ret = vop_namefile(node, iob); - -out: - vop_ref_dec(node); - return ret; -} - diff --git a/ucore-thumips/kern/include/asm/mipsregs.h b/ucore-thumips/kern/include/asm/mipsregs.h deleted file mode 100644 index 4d23ab5..0000000 --- a/ucore-thumips/kern/include/asm/mipsregs.h +++ /dev/null @@ -1,1368 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle - * Copyright (C) 2000 Silicon Graphics, Inc. - * Modified for further R[236]000 support by Paul M. Antoine, 1996. - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000, 07 MIPS Technologies, Inc. - * Copyright (C) 2003, 2004 Maciej W. Rozycki - */ -#ifndef _ASM_MIPSREGS_H -#define _ASM_MIPSREGS_H - -#if 0 -#include -#endif - -/* - * The following macros are especially useful for __asm__ - * inline assembler. - */ -#ifndef __STR -#define __STR(x) #x -#endif -#ifndef STR -#define STR(x) __STR(x) -#endif - -/* - * Configure language - */ -#ifdef __ASSEMBLY__ -#define _ULCAST_ -#else -#define _ULCAST_ (unsigned long) -#endif - -/* - * Coprocessor 0 register names - */ -#define CP0_INDEX $0 -#define CP0_RANDOM $1 -#define CP0_ENTRYLO0 $2 -#define CP0_ENTRYLO1 $3 -#define CP0_CONF $3 -#define CP0_CONTEXT $4 -#define CP0_PAGEMASK $5 -#define CP0_WIRED $6 -#define CP0_INFO $7 -#define CP0_BADVADDR $8 -#define CP0_COUNT $9 -#define CP0_ENTRYHI $10 -#define CP0_COMPARE $11 -#define CP0_STATUS $12 -#define CP0_CAUSE $13 -#define CP0_EPC $14 -#define CP0_PRID $15 -#define CP0_CONFIG $16 -#define CP0_LLADDR $17 -#define CP0_WATCHLO $18 -#define CP0_WATCHHI $19 -#define CP0_XCONTEXT $20 -#define CP0_FRAMEMASK $21 -#define CP0_DIAGNOSTIC $22 -#define CP0_DEBUG $23 -#define CP0_DEPC $24 -#define CP0_PERFORMANCE $25 -#define CP0_ECC $26 -#define CP0_CACHEERR $27 -#define CP0_TAGLO $28 -#define CP0_TAGHI $29 -#define CP0_ERROREPC $30 -#define CP0_DESAVE $31 - -/* - * R4640/R4650 cp0 register names. These registers are listed - * here only for completeness; without MMU these CPUs are not useable - * by Linux. A future ELKS port might take make Linux run on them - * though ... - */ -#define CP0_IBASE $0 -#define CP0_IBOUND $1 -#define CP0_DBASE $2 -#define CP0_DBOUND $3 -#define CP0_CALG $17 -#define CP0_IWATCH $18 -#define CP0_DWATCH $19 - -/* - * Coprocessor 0 Set 1 register names - */ -#define CP0_S1_DERRADDR0 $26 -#define CP0_S1_DERRADDR1 $27 -#define CP0_S1_INTCONTROL $20 - -/* - * Coprocessor 0 Set 2 register names - */ -#define CP0_S2_SRSCTL $12 /* MIPSR2 */ - -/* - * Coprocessor 0 Set 3 register names - */ -#define CP0_S3_SRSMAP $12 /* MIPSR2 */ - -/* - * TX39 Series - */ -#define CP0_TX39_CACHE $7 - -/* - * Coprocessor 1 (FPU) register names - */ -#define CP1_REVISION $0 -#define CP1_STATUS $31 - -/* - * FPU Status Register Values - */ -/* - * Status Register Values - */ - -#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */ -#define FPU_CSR_COND 0x00800000 /* $fcc0 */ -#define FPU_CSR_COND0 0x00800000 /* $fcc0 */ -#define FPU_CSR_COND1 0x02000000 /* $fcc1 */ -#define FPU_CSR_COND2 0x04000000 /* $fcc2 */ -#define FPU_CSR_COND3 0x08000000 /* $fcc3 */ -#define FPU_CSR_COND4 0x10000000 /* $fcc4 */ -#define FPU_CSR_COND5 0x20000000 /* $fcc5 */ -#define FPU_CSR_COND6 0x40000000 /* $fcc6 */ -#define FPU_CSR_COND7 0x80000000 /* $fcc7 */ - -/* - * X the exception cause indicator - * E the exception enable - * S the sticky/flag bit - */ -#define FPU_CSR_ALL_X 0x0003f000 -#define FPU_CSR_UNI_X 0x00020000 -#define FPU_CSR_INV_X 0x00010000 -#define FPU_CSR_DIV_X 0x00008000 -#define FPU_CSR_OVF_X 0x00004000 -#define FPU_CSR_UDF_X 0x00002000 -#define FPU_CSR_INE_X 0x00001000 - -#define FPU_CSR_ALL_E 0x00000f80 -#define FPU_CSR_INV_E 0x00000800 -#define FPU_CSR_DIV_E 0x00000400 -#define FPU_CSR_OVF_E 0x00000200 -#define FPU_CSR_UDF_E 0x00000100 -#define FPU_CSR_INE_E 0x00000080 - -#define FPU_CSR_ALL_S 0x0000007c -#define FPU_CSR_INV_S 0x00000040 -#define FPU_CSR_DIV_S 0x00000020 -#define FPU_CSR_OVF_S 0x00000010 -#define FPU_CSR_UDF_S 0x00000008 -#define FPU_CSR_INE_S 0x00000004 - -/* rounding mode */ -#define FPU_CSR_RN 0x0 /* nearest */ -#define FPU_CSR_RZ 0x1 /* towards zero */ -#define FPU_CSR_RU 0x2 /* towards +Infinity */ -#define FPU_CSR_RD 0x3 /* towards -Infinity */ - -/* - * Values for PageMask register - */ -#ifdef CONFIG_CPU_VR41XX - -/* Why doesn't stupidity hurt ... */ - -#define PM_1K 0x00000000 -#define PM_4K 0x00001800 -#define PM_16K 0x00007800 -#define PM_64K 0x0001f800 -#define PM_256K 0x0007f800 - -#else - -#define PM_4K 0x00000000 -#define PM_16K 0x00006000 -#define PM_64K 0x0001e000 -#define PM_256K 0x0007e000 -#define PM_1M 0x001fe000 -#define PM_4M 0x007fe000 -#define PM_16M 0x01ffe000 -#define PM_64M 0x07ffe000 -#define PM_256M 0x1fffe000 - -#endif - -/* - * Values used for computation of new tlb entries - */ -#define PL_4K 12 -#define PL_16K 14 -#define PL_64K 16 -#define PL_256K 18 -#define PL_1M 20 -#define PL_4M 22 -#define PL_16M 24 -#define PL_64M 26 -#define PL_256M 28 - -/* - * R4x00 interrupt enable / cause bits - */ -#define IE_SW0 (_ULCAST_(1) << 8) -#define IE_SW1 (_ULCAST_(1) << 9) -#define IE_IRQ0 (_ULCAST_(1) << 10) -#define IE_IRQ1 (_ULCAST_(1) << 11) -#define IE_IRQ2 (_ULCAST_(1) << 12) -#define IE_IRQ3 (_ULCAST_(1) << 13) -#define IE_IRQ4 (_ULCAST_(1) << 14) -#define IE_IRQ5 (_ULCAST_(1) << 15) - -/* - * R4x00 interrupt cause bits - */ -#define C_SW0 (_ULCAST_(1) << 8) -#define C_SW1 (_ULCAST_(1) << 9) -#define C_IRQ0 (_ULCAST_(1) << 10) -#define C_IRQ1 (_ULCAST_(1) << 11) -#define C_IRQ2 (_ULCAST_(1) << 12) -#define C_IRQ3 (_ULCAST_(1) << 13) -#define C_IRQ4 (_ULCAST_(1) << 14) -#define C_IRQ5 (_ULCAST_(1) << 15) - -/* - * Bitfields in the R4xx0 cp0 status register - */ -#define ST0_IE 0x00000001 -#define ST0_EXL 0x00000002 -#define ST0_ERL 0x00000004 -#define ST0_KSU 0x00000018 -# define KSU_USER 0x00000010 -# define KSU_SUPERVISOR 0x00000008 -# define KSU_KERNEL 0x00000000 -#define ST0_UX 0x00000020 -#define ST0_SX 0x00000040 -#define ST0_KX 0x00000080 -#define ST0_DE 0x00010000 -#define ST0_CE 0x00020000 - -/* - * Setting c0_status.co enables Hit_Writeback and Hit_Writeback_Invalidate - * cacheops in userspace. This bit exists only on RM7000 and RM9000 - * processors. - */ -#define ST0_CO 0x08000000 - -#if 0 -/* - * Bitfields in the R[23]000 cp0 status register. - */ -#define ST0_IEC 0x00000001 -#define ST0_KUC 0x00000002 -#define ST0_IEP 0x00000004 -#define ST0_KUP 0x00000008 -#define ST0_IEO 0x00000010 -#define ST0_KUO 0x00000020 -/* bits 6 & 7 are reserved on R[23]000 */ -#define ST0_ISC 0x00010000 -#define ST0_SWC 0x00020000 -#define ST0_CM 0x00080000 -#endif - -/* - * Bits specific to the R4640/R4650 - */ -#define ST0_UM (_ULCAST_(1) << 4) -#define ST0_IL (_ULCAST_(1) << 23) -#define ST0_DL (_ULCAST_(1) << 24) - -/* - * Enable the MIPS MDMX and DSP ASEs - */ -#define ST0_MX 0x01000000 - -/* - * Bitfields in the TX39 family CP0 Configuration Register 3 - */ -#define TX39_CONF_ICS_SHIFT 19 -#define TX39_CONF_ICS_MASK 0x00380000 -#define TX39_CONF_ICS_1KB 0x00000000 -#define TX39_CONF_ICS_2KB 0x00080000 -#define TX39_CONF_ICS_4KB 0x00100000 -#define TX39_CONF_ICS_8KB 0x00180000 -#define TX39_CONF_ICS_16KB 0x00200000 - -#define TX39_CONF_DCS_SHIFT 16 -#define TX39_CONF_DCS_MASK 0x00070000 -#define TX39_CONF_DCS_1KB 0x00000000 -#define TX39_CONF_DCS_2KB 0x00010000 -#define TX39_CONF_DCS_4KB 0x00020000 -#define TX39_CONF_DCS_8KB 0x00030000 -#define TX39_CONF_DCS_16KB 0x00040000 - -#define TX39_CONF_CWFON 0x00004000 -#define TX39_CONF_WBON 0x00002000 -#define TX39_CONF_RF_SHIFT 10 -#define TX39_CONF_RF_MASK 0x00000c00 -#define TX39_CONF_DOZE 0x00000200 -#define TX39_CONF_HALT 0x00000100 -#define TX39_CONF_LOCK 0x00000080 -#define TX39_CONF_ICE 0x00000020 -#define TX39_CONF_DCE 0x00000010 -#define TX39_CONF_IRSIZE_SHIFT 2 -#define TX39_CONF_IRSIZE_MASK 0x0000000c -#define TX39_CONF_DRSIZE_SHIFT 0 -#define TX39_CONF_DRSIZE_MASK 0x00000003 - -/* - * Status register bits available in all MIPS CPUs. - */ -#define ST0_IM 0x0000ff00 -#define STATUSB_IP0 8 -#define STATUSF_IP0 (_ULCAST_(1) << 8) -#define STATUSB_IP1 9 -#define STATUSF_IP1 (_ULCAST_(1) << 9) -#define STATUSB_IP2 10 -#define STATUSF_IP2 (_ULCAST_(1) << 10) -#define STATUSB_IP3 11 -#define STATUSF_IP3 (_ULCAST_(1) << 11) -#define STATUSB_IP4 12 -#define STATUSF_IP4 (_ULCAST_(1) << 12) -#define STATUSB_IP5 13 -#define STATUSF_IP5 (_ULCAST_(1) << 13) -#define STATUSB_IP6 14 -#define STATUSF_IP6 (_ULCAST_(1) << 14) -#define STATUSB_IP7 15 -#define STATUSF_IP7 (_ULCAST_(1) << 15) -#define STATUSB_IP8 0 -#define STATUSF_IP8 (_ULCAST_(1) << 0) -#define STATUSB_IP9 1 -#define STATUSF_IP9 (_ULCAST_(1) << 1) -#define STATUSB_IP10 2 -#define STATUSF_IP10 (_ULCAST_(1) << 2) -#define STATUSB_IP11 3 -#define STATUSF_IP11 (_ULCAST_(1) << 3) -#define STATUSB_IP12 4 -#define STATUSF_IP12 (_ULCAST_(1) << 4) -#define STATUSB_IP13 5 -#define STATUSF_IP13 (_ULCAST_(1) << 5) -#define STATUSB_IP14 6 -#define STATUSF_IP14 (_ULCAST_(1) << 6) -#define STATUSB_IP15 7 -#define STATUSF_IP15 (_ULCAST_(1) << 7) -#define ST0_CH 0x00040000 -#define ST0_SR 0x00100000 -#define ST0_TS 0x00200000 -#define ST0_BEV 0x00400000 -#define ST0_RE 0x02000000 -#define ST0_FR 0x04000000 -#define ST0_CU 0xf0000000 -#define ST0_CU0 0x10000000 -#define ST0_CU1 0x20000000 -#define ST0_CU2 0x40000000 -#define ST0_CU3 0x80000000 -#define ST0_XX 0x80000000 /* MIPS IV naming */ - -/* - * Bitfields and bit numbers in the coprocessor 0 cause register. - * - * Refer to your MIPS R4xx0 manual, chapter 5 for explanation. - */ -#define CAUSEB_EXCCODE 2 -#define CAUSEF_EXCCODE (_ULCAST_(31) << 2) -#define CAUSEB_IP 8 -#define CAUSEF_IP (_ULCAST_(255) << 8) -#define CAUSEB_IP0 8 -#define CAUSEF_IP0 (_ULCAST_(1) << 8) -#define CAUSEB_IP1 9 -#define CAUSEF_IP1 (_ULCAST_(1) << 9) -#define CAUSEB_IP2 10 -#define CAUSEF_IP2 (_ULCAST_(1) << 10) -#define CAUSEB_IP3 11 -#define CAUSEF_IP3 (_ULCAST_(1) << 11) -#define CAUSEB_IP4 12 -#define CAUSEF_IP4 (_ULCAST_(1) << 12) -#define CAUSEB_IP5 13 -#define CAUSEF_IP5 (_ULCAST_(1) << 13) -#define CAUSEB_IP6 14 -#define CAUSEF_IP6 (_ULCAST_(1) << 14) -#define CAUSEB_IP7 15 -#define CAUSEF_IP7 (_ULCAST_(1) << 15) -#define CAUSEB_IV 23 -#define CAUSEF_IV (_ULCAST_(1) << 23) -#define CAUSEB_CE 28 -#define CAUSEF_CE (_ULCAST_(3) << 28) -#define CAUSEB_BD 31 -#define CAUSEF_BD (_ULCAST_(1) << 31) - -/* - * Bits in the coprocessor 0 config register. - */ -/* Generic bits. */ -#define CONF_CM_CACHABLE_NO_WA 0 -#define CONF_CM_CACHABLE_WA 1 -#define CONF_CM_UNCACHED 2 -#define CONF_CM_CACHABLE_NONCOHERENT 3 -#define CONF_CM_CACHABLE_CE 4 -#define CONF_CM_CACHABLE_COW 5 -#define CONF_CM_CACHABLE_CUW 6 -#define CONF_CM_CACHABLE_ACCELERATED 7 -#define CONF_CM_CMASK 7 -#define CONF_BE (_ULCAST_(1) << 15) - -/* Bits common to various processors. */ -#define CONF_CU (_ULCAST_(1) << 3) -#define CONF_DB (_ULCAST_(1) << 4) -#define CONF_IB (_ULCAST_(1) << 5) -#define CONF_DC (_ULCAST_(7) << 6) -#define CONF_IC (_ULCAST_(7) << 9) -#define CONF_EB (_ULCAST_(1) << 13) -#define CONF_EM (_ULCAST_(1) << 14) -#define CONF_SM (_ULCAST_(1) << 16) -#define CONF_SC (_ULCAST_(1) << 17) -#define CONF_EW (_ULCAST_(3) << 18) -#define CONF_EP (_ULCAST_(15)<< 24) -#define CONF_EC (_ULCAST_(7) << 28) -#define CONF_CM (_ULCAST_(1) << 31) - -/* Bits specific to the R4xx0. */ -#define R4K_CONF_SW (_ULCAST_(1) << 20) -#define R4K_CONF_SS (_ULCAST_(1) << 21) -#define R4K_CONF_SB (_ULCAST_(3) << 22) - -/* Bits specific to the R5000. */ -#define R5K_CONF_SE (_ULCAST_(1) << 12) -#define R5K_CONF_SS (_ULCAST_(3) << 20) - -/* Bits specific to the RM7000. */ -#define RM7K_CONF_SE (_ULCAST_(1) << 3) -#define RM7K_CONF_TE (_ULCAST_(1) << 12) -#define RM7K_CONF_CLK (_ULCAST_(1) << 16) -#define RM7K_CONF_TC (_ULCAST_(1) << 17) -#define RM7K_CONF_SI (_ULCAST_(3) << 20) -#define RM7K_CONF_SC (_ULCAST_(1) << 31) - -/* Bits specific to the R10000. */ -#define R10K_CONF_DN (_ULCAST_(3) << 3) -#define R10K_CONF_CT (_ULCAST_(1) << 5) -#define R10K_CONF_PE (_ULCAST_(1) << 6) -#define R10K_CONF_PM (_ULCAST_(3) << 7) -#define R10K_CONF_EC (_ULCAST_(15)<< 9) -#define R10K_CONF_SB (_ULCAST_(1) << 13) -#define R10K_CONF_SK (_ULCAST_(1) << 14) -#define R10K_CONF_SS (_ULCAST_(7) << 16) -#define R10K_CONF_SC (_ULCAST_(7) << 19) -#define R10K_CONF_DC (_ULCAST_(7) << 26) -#define R10K_CONF_IC (_ULCAST_(7) << 29) - -/* Bits specific to the VR41xx. */ -#define VR41_CONF_CS (_ULCAST_(1) << 12) -#define VR41_CONF_P4K (_ULCAST_(1) << 13) -#define VR41_CONF_BP (_ULCAST_(1) << 16) -#define VR41_CONF_M16 (_ULCAST_(1) << 20) -#define VR41_CONF_AD (_ULCAST_(1) << 23) - -/* Bits specific to the R30xx. */ -#define R30XX_CONF_FDM (_ULCAST_(1) << 19) -#define R30XX_CONF_REV (_ULCAST_(1) << 22) -#define R30XX_CONF_AC (_ULCAST_(1) << 23) -#define R30XX_CONF_RF (_ULCAST_(1) << 24) -#define R30XX_CONF_HALT (_ULCAST_(1) << 25) -#define R30XX_CONF_FPINT (_ULCAST_(7) << 26) -#define R30XX_CONF_DBR (_ULCAST_(1) << 29) -#define R30XX_CONF_SB (_ULCAST_(1) << 30) -#define R30XX_CONF_LOCK (_ULCAST_(1) << 31) - -/* Bits specific to the TX49. */ -#define TX49_CONF_DC (_ULCAST_(1) << 16) -#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */ -#define TX49_CONF_HALT (_ULCAST_(1) << 18) -#define TX49_CONF_CWFON (_ULCAST_(1) << 27) - -/* Bits specific to the MIPS32/64 PRA. */ -#define MIPS_CONF_MT (_ULCAST_(7) << 7) -#define MIPS_CONF_AR (_ULCAST_(7) << 10) -#define MIPS_CONF_AT (_ULCAST_(3) << 13) -#define MIPS_CONF_M (_ULCAST_(1) << 31) - -/* - * Bits in the MIPS32/64 PRA coprocessor 0 config registers 1 and above. - */ -#define MIPS_CONF1_FP (_ULCAST_(1) << 0) -#define MIPS_CONF1_EP (_ULCAST_(1) << 1) -#define MIPS_CONF1_CA (_ULCAST_(1) << 2) -#define MIPS_CONF1_WR (_ULCAST_(1) << 3) -#define MIPS_CONF1_PC (_ULCAST_(1) << 4) -#define MIPS_CONF1_MD (_ULCAST_(1) << 5) -#define MIPS_CONF1_C2 (_ULCAST_(1) << 6) -#define MIPS_CONF1_DA (_ULCAST_(7) << 7) -#define MIPS_CONF1_DL (_ULCAST_(7) << 10) -#define MIPS_CONF1_DS (_ULCAST_(7) << 13) -#define MIPS_CONF1_IA (_ULCAST_(7) << 16) -#define MIPS_CONF1_IL (_ULCAST_(7) << 19) -#define MIPS_CONF1_IS (_ULCAST_(7) << 22) -#define MIPS_CONF1_TLBS (_ULCAST_(63)<< 25) - -#define MIPS_CONF2_SA (_ULCAST_(15)<< 0) -#define MIPS_CONF2_SL (_ULCAST_(15)<< 4) -#define MIPS_CONF2_SS (_ULCAST_(15)<< 8) -#define MIPS_CONF2_SU (_ULCAST_(15)<< 12) -#define MIPS_CONF2_TA (_ULCAST_(15)<< 16) -#define MIPS_CONF2_TL (_ULCAST_(15)<< 20) -#define MIPS_CONF2_TS (_ULCAST_(15)<< 24) -#define MIPS_CONF2_TU (_ULCAST_(7) << 28) - -#define MIPS_CONF3_TL (_ULCAST_(1) << 0) -#define MIPS_CONF3_SM (_ULCAST_(1) << 1) -#define MIPS_CONF3_MT (_ULCAST_(1) << 2) -#define MIPS_CONF3_SP (_ULCAST_(1) << 4) -#define MIPS_CONF3_VINT (_ULCAST_(1) << 5) -#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6) -#define MIPS_CONF3_LPA (_ULCAST_(1) << 7) -#define MIPS_CONF3_DSP (_ULCAST_(1) << 10) -#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13) - -#define MIPS_CONF7_WII (_ULCAST_(1) << 31) - -#define MIPS_CONF7_RPS (_ULCAST_(1) << 2) - -/* - * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register. - */ -#define MIPS_FPIR_S (_ULCAST_(1) << 16) -#define MIPS_FPIR_D (_ULCAST_(1) << 17) -#define MIPS_FPIR_PS (_ULCAST_(1) << 18) -#define MIPS_FPIR_3D (_ULCAST_(1) << 19) -#define MIPS_FPIR_W (_ULCAST_(1) << 20) -#define MIPS_FPIR_L (_ULCAST_(1) << 21) -#define MIPS_FPIR_F64 (_ULCAST_(1) << 22) - -#ifndef __ASSEMBLY__ - -/* - * Functions to access the R10000 performance counters. These are basically - * mfc0 and mtc0 instructions from and to coprocessor register with a 5-bit - * performance counter number encoded into bits 1 ... 5 of the instruction. - * Only performance counters 0 to 1 actually exist, so for a non-R10000 aware - * disassembler these will look like an access to sel 0 or 1. - */ -#define read_r10k_perf_cntr(counter) \ -({ \ - unsigned int __res; \ - __asm__ __volatile__( \ - "mfpc\t%0, %1" \ - : "=r" (__res) \ - : "i" (counter)); \ - \ - __res; \ -}) - -#define write_r10k_perf_cntr(counter,val) \ -do { \ - __asm__ __volatile__( \ - "mtpc\t%0, %1" \ - : \ - : "r" (val), "i" (counter)); \ -} while (0) - -#define read_r10k_perf_event(counter) \ -({ \ - unsigned int __res; \ - __asm__ __volatile__( \ - "mfps\t%0, %1" \ - : "=r" (__res) \ - : "i" (counter)); \ - \ - __res; \ -}) - -#define write_r10k_perf_cntl(counter,val) \ -do { \ - __asm__ __volatile__( \ - "mtps\t%0, %1" \ - : \ - : "r" (val), "i" (counter)); \ -} while (0) - -/* - * Macros to access the system control coprocessor - */ - -#define __read_32bit_c0_register(source, sel) \ -({ int __res; \ - if (sel == 0) \ - __asm__ __volatile__( \ - "mfc0\t%0, " #source "\n\t" \ - : "=r" (__res)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips32\n\t" \ - "mfc0\t%0, " #source ", " #sel "\n\t" \ - ".set\tmips0\n\t" \ - : "=r" (__res)); \ - __res; \ -}) - -#define __read_64bit_c0_register(source, sel) \ -({ unsigned long long __res; \ - if (sizeof(unsigned long) == 4) \ - __res = __read_64bit_c0_split(source, sel); \ - else if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips3\n\t" \ - "dmfc0\t%0, " #source "\n\t" \ - ".set\tmips0" \ - : "=r" (__res)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmfc0\t%0, " #source ", " #sel "\n\t" \ - ".set\tmips0" \ - : "=r" (__res)); \ - __res; \ -}) - -#define __write_32bit_c0_register(register, sel, value) \ -do { \ - if (sel == 0) \ - __asm__ __volatile__( \ - "mtc0\t%z0, " #register "\n\t" \ - : : "Jr" ((unsigned int)(value))); \ - else \ - __asm__ __volatile__( \ - ".set\tmips32\n\t" \ - "mtc0\t%z0, " #register ", " #sel "\n\t" \ - ".set\tmips0" \ - : : "Jr" ((unsigned int)(value))); \ -} while (0) - -#define __write_64bit_c0_register(register, sel, value) \ -do { \ - if (sizeof(unsigned long) == 4) \ - __write_64bit_c0_split(register, sel, value); \ - else if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips3\n\t" \ - "dmtc0\t%z0, " #register "\n\t" \ - ".set\tmips0" \ - : : "Jr" (value)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmtc0\t%z0, " #register ", " #sel "\n\t" \ - ".set\tmips0" \ - : : "Jr" (value)); \ -} while (0) - -#define __read_ulong_c0_register(reg, sel) \ - ((sizeof(unsigned long) == 4) ? \ - (unsigned long) __read_32bit_c0_register(reg, sel) : \ - (unsigned long) __read_64bit_c0_register(reg, sel)) - -#define __write_ulong_c0_register(reg, sel, val) \ -do { \ - if (sizeof(unsigned long) == 4) \ - __write_32bit_c0_register(reg, sel, val); \ - else \ - __write_64bit_c0_register(reg, sel, val); \ -} while (0) - -/* - * On RM7000/RM9000 these are uses to access cop0 set 1 registers - */ -#define __read_32bit_c0_ctrl_register(source) \ -({ int __res; \ - __asm__ __volatile__( \ - "cfc0\t%0, " #source "\n\t" \ - : "=r" (__res)); \ - __res; \ -}) - -#define __write_32bit_c0_ctrl_register(register, value) \ -do { \ - __asm__ __volatile__( \ - "ctc0\t%z0, " #register "\n\t" \ - : : "Jr" ((unsigned int)(value))); \ -} while (0) - -/* - * These versions are only needed for systems with more than 38 bits of - * physical address space running the 32-bit kernel. That's none atm :-) - */ -#define __read_64bit_c0_split(source, sel) \ -({ \ - unsigned long long __val; \ - unsigned long __flags; \ - \ - local_irq_save(__flags); \ - if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmfc0\t%M0, " #source "\n\t" \ - "dsll\t%L0, %M0, 32\n\t" \ - "dsrl\t%M0, %M0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - ".set\tmips0" \ - : "=r" (__val)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dmfc0\t%M0, " #source ", " #sel "\n\t" \ - "dsll\t%L0, %M0, 32\n\t" \ - "dsrl\t%M0, %M0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - ".set\tmips0" \ - : "=r" (__val)); \ - local_irq_restore(__flags); \ - \ - __val; \ -}) - -#define __write_64bit_c0_split(source, sel, val) \ -do { \ - unsigned long __flags; \ - \ - local_irq_save(__flags); \ - if (sel == 0) \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dsll\t%L0, %L0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - "dsll\t%M0, %M0, 32\n\t" \ - "or\t%L0, %L0, %M0\n\t" \ - "dmtc0\t%L0, " #source "\n\t" \ - ".set\tmips0" \ - : : "r" (val)); \ - else \ - __asm__ __volatile__( \ - ".set\tmips64\n\t" \ - "dsll\t%L0, %L0, 32\n\t" \ - "dsrl\t%L0, %L0, 32\n\t" \ - "dsll\t%M0, %M0, 32\n\t" \ - "or\t%L0, %L0, %M0\n\t" \ - "dmtc0\t%L0, " #source ", " #sel "\n\t" \ - ".set\tmips0" \ - : : "r" (val)); \ - local_irq_restore(__flags); \ -} while (0) - -#define read_c0_index() __read_32bit_c0_register($0, 0) -#define write_c0_index(val) __write_32bit_c0_register($0, 0, val) - -#define read_c0_entrylo0() __read_ulong_c0_register($2, 0) -#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) - -#define read_c0_entrylo1() __read_ulong_c0_register($3, 0) -#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) - -#define read_c0_conf() __read_32bit_c0_register($3, 0) -#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) - -#define read_c0_context() __read_ulong_c0_register($4, 0) -#define write_c0_context(val) __write_ulong_c0_register($4, 0, val) - -#define read_c0_userlocal() __read_ulong_c0_register($4, 2) -#define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val) - -#define read_c0_pagemask() __read_32bit_c0_register($5, 0) -#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val) - -#define read_c0_wired() __read_32bit_c0_register($6, 0) -#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val) - -#define read_c0_info() __read_32bit_c0_register($7, 0) - -#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */ -#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val) - -#define read_c0_badvaddr() __read_ulong_c0_register($8, 0) -#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val) - -#define read_c0_count() __read_32bit_c0_register($9, 0) -#define write_c0_count(val) __write_32bit_c0_register($9, 0, val) - -#define read_c0_count2() __read_32bit_c0_register($9, 6) /* pnx8550 */ -#define write_c0_count2(val) __write_32bit_c0_register($9, 6, val) - -#define read_c0_count3() __read_32bit_c0_register($9, 7) /* pnx8550 */ -#define write_c0_count3(val) __write_32bit_c0_register($9, 7, val) - -#define read_c0_entryhi() __read_ulong_c0_register($10, 0) -#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val) - -#define read_c0_compare() __read_32bit_c0_register($11, 0) -#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val) - -#define read_c0_compare2() __read_32bit_c0_register($11, 6) /* pnx8550 */ -#define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val) - -#define read_c0_compare3() __read_32bit_c0_register($11, 7) /* pnx8550 */ -#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) - -#define read_c0_status() __read_32bit_c0_register($12, 0) -#ifdef CONFIG_MIPS_MT_SMTC -#define write_c0_status(val) \ -do { \ - __write_32bit_c0_register($12, 0, val); \ - __ehb(); \ -} while (0) -#else -/* - * Legacy non-SMTC code, which may be hazardous - * but which might not support EHB - */ -#define write_c0_status(val) __write_32bit_c0_register($12, 0, val) -#endif /* CONFIG_MIPS_MT_SMTC */ - -#define read_c0_cause() __read_32bit_c0_register($13, 0) -#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) - -#define read_c0_epc() __read_ulong_c0_register($14, 0) -#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) - -#define read_c0_prid() __read_32bit_c0_register($15, 0) - -#define read_c0_config() __read_32bit_c0_register($16, 0) -#define read_c0_config1() __read_32bit_c0_register($16, 1) -#define read_c0_config2() __read_32bit_c0_register($16, 2) -#define read_c0_config3() __read_32bit_c0_register($16, 3) -#define read_c0_config4() __read_32bit_c0_register($16, 4) -#define read_c0_config5() __read_32bit_c0_register($16, 5) -#define read_c0_config6() __read_32bit_c0_register($16, 6) -#define read_c0_config7() __read_32bit_c0_register($16, 7) -#define write_c0_config(val) __write_32bit_c0_register($16, 0, val) -#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val) -#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val) -#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val) -#define write_c0_config4(val) __write_32bit_c0_register($16, 4, val) -#define write_c0_config5(val) __write_32bit_c0_register($16, 5, val) -#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val) -#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val) - -/* - * The WatchLo register. There may be upto 8 of them. - */ -#define read_c0_watchlo0() __read_ulong_c0_register($18, 0) -#define read_c0_watchlo1() __read_ulong_c0_register($18, 1) -#define read_c0_watchlo2() __read_ulong_c0_register($18, 2) -#define read_c0_watchlo3() __read_ulong_c0_register($18, 3) -#define read_c0_watchlo4() __read_ulong_c0_register($18, 4) -#define read_c0_watchlo5() __read_ulong_c0_register($18, 5) -#define read_c0_watchlo6() __read_ulong_c0_register($18, 6) -#define read_c0_watchlo7() __read_ulong_c0_register($18, 7) -#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val) -#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val) -#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val) -#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val) -#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val) -#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val) -#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val) -#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val) - -/* - * The WatchHi register. There may be upto 8 of them. - */ -#define read_c0_watchhi0() __read_32bit_c0_register($19, 0) -#define read_c0_watchhi1() __read_32bit_c0_register($19, 1) -#define read_c0_watchhi2() __read_32bit_c0_register($19, 2) -#define read_c0_watchhi3() __read_32bit_c0_register($19, 3) -#define read_c0_watchhi4() __read_32bit_c0_register($19, 4) -#define read_c0_watchhi5() __read_32bit_c0_register($19, 5) -#define read_c0_watchhi6() __read_32bit_c0_register($19, 6) -#define read_c0_watchhi7() __read_32bit_c0_register($19, 7) - -#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val) -#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val) -#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val) -#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val) -#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val) -#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val) -#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val) -#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val) - -#define read_c0_xcontext() __read_ulong_c0_register($20, 0) -#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val) - -#define read_c0_intcontrol() __read_32bit_c0_ctrl_register($20) -#define write_c0_intcontrol(val) __write_32bit_c0_ctrl_register($20, val) - -#define read_c0_framemask() __read_32bit_c0_register($21, 0) -#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val) - -/* RM9000 PerfControl performance counter control register */ -#define read_c0_perfcontrol() __read_32bit_c0_register($22, 0) -#define write_c0_perfcontrol(val) __write_32bit_c0_register($22, 0, val) - -#define read_c0_diag() __read_32bit_c0_register($22, 0) -#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val) - -#define read_c0_diag1() __read_32bit_c0_register($22, 1) -#define write_c0_diag1(val) __write_32bit_c0_register($22, 1, val) - -#define read_c0_diag2() __read_32bit_c0_register($22, 2) -#define write_c0_diag2(val) __write_32bit_c0_register($22, 2, val) - -#define read_c0_diag3() __read_32bit_c0_register($22, 3) -#define write_c0_diag3(val) __write_32bit_c0_register($22, 3, val) - -#define read_c0_diag4() __read_32bit_c0_register($22, 4) -#define write_c0_diag4(val) __write_32bit_c0_register($22, 4, val) - -#define read_c0_diag5() __read_32bit_c0_register($22, 5) -#define write_c0_diag5(val) __write_32bit_c0_register($22, 5, val) - -#define read_c0_debug() __read_32bit_c0_register($23, 0) -#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val) - -#define read_c0_depc() __read_ulong_c0_register($24, 0) -#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val) - -/* - * MIPS32 / MIPS64 performance counters - */ -#define read_c0_perfctrl0() __read_32bit_c0_register($25, 0) -#define write_c0_perfctrl0(val) __write_32bit_c0_register($25, 0, val) -#define read_c0_perfcntr0() __read_32bit_c0_register($25, 1) -#define write_c0_perfcntr0(val) __write_32bit_c0_register($25, 1, val) -#define read_c0_perfctrl1() __read_32bit_c0_register($25, 2) -#define write_c0_perfctrl1(val) __write_32bit_c0_register($25, 2, val) -#define read_c0_perfcntr1() __read_32bit_c0_register($25, 3) -#define write_c0_perfcntr1(val) __write_32bit_c0_register($25, 3, val) -#define read_c0_perfctrl2() __read_32bit_c0_register($25, 4) -#define write_c0_perfctrl2(val) __write_32bit_c0_register($25, 4, val) -#define read_c0_perfcntr2() __read_32bit_c0_register($25, 5) -#define write_c0_perfcntr2(val) __write_32bit_c0_register($25, 5, val) -#define read_c0_perfctrl3() __read_32bit_c0_register($25, 6) -#define write_c0_perfctrl3(val) __write_32bit_c0_register($25, 6, val) -#define read_c0_perfcntr3() __read_32bit_c0_register($25, 7) -#define write_c0_perfcntr3(val) __write_32bit_c0_register($25, 7, val) - -/* RM9000 PerfCount performance counter register */ -#define read_c0_perfcount() __read_64bit_c0_register($25, 0) -#define write_c0_perfcount(val) __write_64bit_c0_register($25, 0, val) - -#define read_c0_ecc() __read_32bit_c0_register($26, 0) -#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val) - -#define read_c0_derraddr0() __read_ulong_c0_register($26, 1) -#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val) - -#define read_c0_cacheerr() __read_32bit_c0_register($27, 0) - -#define read_c0_derraddr1() __read_ulong_c0_register($27, 1) -#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val) - -#define read_c0_taglo() __read_32bit_c0_register($28, 0) -#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val) - -#define read_c0_dtaglo() __read_32bit_c0_register($28, 2) -#define write_c0_dtaglo(val) __write_32bit_c0_register($28, 2, val) - -#define read_c0_taghi() __read_32bit_c0_register($29, 0) -#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val) - -#define read_c0_errorepc() __read_ulong_c0_register($30, 0) -#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val) - -/* MIPSR2 */ -#define read_c0_hwrena() __read_32bit_c0_register($7, 0) -#define write_c0_hwrena(val) __write_32bit_c0_register($7, 0, val) - -#define read_c0_intctl() __read_32bit_c0_register($12, 1) -#define write_c0_intctl(val) __write_32bit_c0_register($12, 1, val) - -#define read_c0_srsctl() __read_32bit_c0_register($12, 2) -#define write_c0_srsctl(val) __write_32bit_c0_register($12, 2, val) - -#define read_c0_srsmap() __read_32bit_c0_register($12, 3) -#define write_c0_srsmap(val) __write_32bit_c0_register($12, 3, val) - -#define read_c0_ebase() __read_32bit_c0_register($15, 1) -#define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val) - -/* - * Macros to access the floating point coprocessor control registers - */ -#define read_32bit_cp1_register(source) \ -({ int __res; \ - __asm__ __volatile__( \ - ".set\tpush\n\t" \ - ".set\treorder\n\t" \ - "cfc1\t%0,"STR(source)"\n\t" \ - ".set\tpop" \ - : "=r" (__res)); \ - __res;}) - -#define rddsp(mask) \ -({ \ - unsigned int __res; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # rddsp $1, %x1 \n" \ - " .word 0x7c000cb8 | (%x1 << 16) \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__res) \ - : "i" (mask)); \ - __res; \ -}) - -#define wrdsp(val, mask) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # wrdsp $1, %x1 \n" \ - " .word 0x7c2004f8 | (%x1 << 11) \n" \ - " .set pop \n" \ - : \ - : "r" (val), "i" (mask)); \ -} while (0) - -#define mfhi0() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mfhi %0, $ac0 \n" \ - " .word 0x00000810 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mfhi1() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mfhi %0, $ac1 \n" \ - " .word 0x00200810 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mfhi2() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mfhi %0, $ac2 \n" \ - " .word 0x00400810 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mfhi3() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mfhi %0, $ac3 \n" \ - " .word 0x00600810 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mflo0() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mflo %0, $ac0 \n" \ - " .word 0x00000812 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mflo1() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mflo %0, $ac1 \n" \ - " .word 0x00200812 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mflo2() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mflo %0, $ac2 \n" \ - " .word 0x00400812 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mflo3() \ -({ \ - unsigned long __treg; \ - \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " # mflo %0, $ac3 \n" \ - " .word 0x00600812 \n" \ - " move %0, $1 \n" \ - " .set pop \n" \ - : "=r" (__treg)); \ - __treg; \ -}) - -#define mthi0(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mthi $1, $ac0 \n" \ - " .word 0x00200011 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -#define mthi1(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mthi $1, $ac1 \n" \ - " .word 0x00200811 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -#define mthi2(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mthi $1, $ac2 \n" \ - " .word 0x00201011 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -#define mthi3(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mthi $1, $ac3 \n" \ - " .word 0x00201811 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -#define mtlo0(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mtlo $1, $ac0 \n" \ - " .word 0x00200013 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -#define mtlo1(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mtlo $1, $ac1 \n" \ - " .word 0x00200813 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -#define mtlo2(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mtlo $1, $ac2 \n" \ - " .word 0x00201013 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -#define mtlo3(x) \ -do { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " move $1, %0 \n" \ - " # mtlo $1, $ac3 \n" \ - " .word 0x00201813 \n" \ - " .set pop \n" \ - : \ - : "r" (x)); \ -} while (0) - -/* - * TLB operations. - * - * It is responsibility of the caller to take care of any TLB hazards. - */ -static inline void tlb_probe(void) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - "tlbp\n\t" - ".set reorder"); -} - -static inline void tlb_read(void) -{ -#if MIPS34K_MISSED_ITLB_WAR - int res = 0; - - __asm__ __volatile__( - " .set push \n" - " .set noreorder \n" - " .set noat \n" - " .set mips32r2 \n" - " .word 0x41610001 # dvpe $1 \n" - " move %0, $1 \n" - " ehb \n" - " .set pop \n" - : "=r" (res)); - - instruction_hazard(); -#endif - - __asm__ __volatile__( - ".set noreorder\n\t" - "tlbr\n\t" - ".set reorder"); - -#if MIPS34K_MISSED_ITLB_WAR - if ((res & _ULCAST_(1))) - __asm__ __volatile__( - " .set push \n" - " .set noreorder \n" - " .set noat \n" - " .set mips32r2 \n" - " .word 0x41600021 # evpe \n" - " ehb \n" - " .set pop \n"); -#endif -} - -static inline void tlb_write_indexed(void) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - "ehb\n\t" - "tlbwi\n\t" - ".set reorder"); -} - -static inline void tlb_write_random(void) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - "ehb\n\t" - "tlbwr\n\t" - ".set reorder"); -} - -/* - * Manipulate bits in a c0 register. - */ -#define __BUILD_SET_C0(name) \ -static inline unsigned int \ -set_c0_##name(unsigned int set) \ -{ \ - unsigned int res; \ - \ - res = read_c0_##name(); \ - res |= set; \ - write_c0_##name(res); \ - \ - return res; \ -} \ - \ -static inline unsigned int \ -clear_c0_##name(unsigned int clear) \ -{ \ - unsigned int res; \ - \ - res = read_c0_##name(); \ - res &= ~clear; \ - write_c0_##name(res); \ - \ - return res; \ -} \ - \ -static inline unsigned int \ -change_c0_##name(unsigned int change, unsigned int new) \ -{ \ - unsigned int res; \ - \ - res = read_c0_##name(); \ - res &= ~change; \ - res |= (new & change); \ - write_c0_##name(res); \ - \ - return res; \ -} - -__BUILD_SET_C0(status) -__BUILD_SET_C0(cause) -__BUILD_SET_C0(config) -__BUILD_SET_C0(intcontrol) -__BUILD_SET_C0(intctl) -__BUILD_SET_C0(srsmap) - -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_MIPSREGS_H */ diff --git a/ucore-thumips/kern/include/asm/regdef.h b/ucore-thumips/kern/include/asm/regdef.h deleted file mode 100644 index 14721cb..0000000 --- a/ucore-thumips/kern/include/asm/regdef.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1985 MIPS Computer Systems, Inc. - * Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle - * Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc. - */ -#ifndef _ASM_REGDEF_H -#define _ASM_REGDEF_H - - - -/* - * Symbolic register names for 32 bit ABI - */ -#define zero $0 /* wired zero */ -#define AT $1 /* assembler temp - uppercase because of ".set at" */ -#define v0 $2 /* return value */ -#define v1 $3 -#define a0 $4 /* argument registers */ -#define a1 $5 -#define a2 $6 -#define a3 $7 -#define t0 $8 /* caller saved */ -#define t1 $9 -#define t2 $10 -#define t3 $11 -#define t4 $12 -#define t5 $13 -#define t6 $14 -#define t7 $15 -#define s0 $16 /* callee saved */ -#define s1 $17 -#define s2 $18 -#define s3 $19 -#define s4 $20 -#define s5 $21 -#define s6 $22 -#define s7 $23 -#define t8 $24 /* caller saved */ -#define t9 $25 -#define jp $25 /* PIC jump register */ -#define k0 $26 /* kernel scratch */ -#define k1 $27 -#define gp $28 /* global pointer */ -#define sp $29 /* stack pointer */ -#define fp $30 /* frame pointer */ -#define s8 $30 /* same like fp! */ -#define ra $31 /* return address */ - - - -#endif /* _ASM_REGDEF_H */ diff --git a/ucore-thumips/kern/include/atomic.h b/ucore-thumips/kern/include/atomic.h deleted file mode 100644 index 5ee4316..0000000 --- a/ucore-thumips/kern/include/atomic.h +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef __LIBS_ATOMIC_H__ -#define __LIBS_ATOMIC_H__ - -#include -#include -#include -#include -/* Atomic operations that C can't guarantee us. Useful for resource counting etc.. */ - - - - -typedef struct { - volatile int counter; -} atomic_t; - -/* * - * atomic_read - read atomic variable - * @v: pointer of type atomic_t - * - * Atomically reads the value of @v. - * */ -static __always_inline int -atomic_read(const atomic_t *v) { - return v->counter; -} - -/* * - * atomic_set - set atomic variable - * @v: pointer of type atomic_t - * @i: required value - * - * Atomically sets the value of @v to @i. - * */ -static __always_inline void -atomic_set(atomic_t *v, int i) { - v->counter = i; -} - -/* * - * atomic_add - add integer to atomic variable - * @v: pointer of type atomic_t - * @i: integer value to add - * - * Atomically adds @i to @v. - * */ -static __always_inline void -atomic_add(atomic_t *v, int i) { - v->counter += i; -} - -/* * - * atomic_sub - subtract integer from atomic variable - * @v: pointer of type atomic_t - * @i: integer value to subtract - * - * Atomically subtracts @i from @v. - * */ -static __always_inline void -atomic_sub(atomic_t *v, int i) { - v->counter -= i; -} - -/* * - * atomic_sub_test_zero - subtract value from variable and test result - * @v: pointer of type atomic_t - * @i: integer value to subtract - * - * Atomically subtracts @i from @v and - * returns true if the result is zero, or false for all other cases. - * */ -static __always_inline bool -atomic_sub_test_zero(atomic_t *v, int i) { - unsigned char c = 0; - int intr_flag; - local_intr_save (intr_flag); - v->counter -= i; - if (v->counter == 0) - c = 1; - local_intr_restore (intr_flag); - return c != 0; - -} - -/* * - * atomic_inc - increment atomic variable - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1. - * */ -static __always_inline void -atomic_inc(atomic_t *v) { - atomic_add(v, 1); -} - -/* * - * atomic_dec - decrement atomic variable - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1. - * */ -static __always_inline void -atomic_dec(atomic_t *v) { - atomic_sub(v, 1); -} - -/* * - * atomic_inc_test_zero - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 and - * returns true if the result is zero, or false for all other cases. - * */ -static __always_inline bool -atomic_inc_test_zero(atomic_t *v) { - unsigned char c = 0; - int intr_flag; - local_intr_save (intr_flag); - atomic_inc(v); - if (v->counter == 0) - c = 1; - local_intr_restore (intr_flag); - return c != 0; - -} - -/* * - * atomic_dec_test_zero - decrement and test - * @v: pointer of type atomic_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other cases. - * */ -static __always_inline bool -atomic_dec_test_zero(atomic_t *v) { - unsigned char c = 0; - int intr_flag; - local_intr_save (intr_flag); - atomic_dec(v); - if (v->counter == 0) - c = 1; - local_intr_restore (intr_flag); - return c != 0; -} - -/* * - * atomic_add_return - add integer and return - * @i: integer value to add - * @v: pointer of type atomic_t - * - * Atomically adds @i to @v and returns @i + @v - * Requires Modern 486+ processor - * */ -static __always_inline int -atomic_add_return(atomic_t *v, int i) { - int intr_flag; - local_intr_save (intr_flag); - v->counter += i; - local_intr_restore (intr_flag); - return v->counter; - -} - -/* * - * atomic_sub_return - subtract integer and return - * @v: pointer of type atomic_t - * @i: integer value to subtract - * - * Atomically subtracts @i from @v and returns @v - @i - * */ -static __always_inline int -atomic_sub_return(atomic_t *v, int i) { - return atomic_add_return(v, -i); -} - -/* * - * set_bit - Atomically set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * Note that @nr may be almost arbitrarily large; this function is not - * restricted to acting on a single-word quantity. - * */ -static __always_inline void -set_bit(int nr, volatile uint32_t *addr) { - int intr_flag; - local_intr_save (intr_flag); - *addr |= (1 << nr); - local_intr_restore (intr_flag); - -} - -/* * - * clear_bit - Atomically clears a bit in memory - * @nr: the bit to clear - * @addr: the address to start counting from - * */ -static __always_inline void -clear_bit(int nr, volatile uint32_t *addr) { - int intr_flag; - local_intr_save (intr_flag); - *addr &= ~(1 << nr); - local_intr_restore (intr_flag); - -} - -/* * - * change_bit - Atomically toggle a bit in memory - * @nr: the bit to change - * @addr: the address to start counting from - * */ -static __always_inline void -change_bit(int nr, volatile uint32_t *addr) { - int intr_flag; - local_intr_save (intr_flag); - //asm volatile ("l.xor %0, %0, %1" :"=m" (*(volatile long *)addr) : "Ir" (1 << nr)); - //#error Fill HERE - //asm volatile ("ldr r0, [%0]"); - *(volatile long*)addr ^= (1<> (n) ) << (n)) - -/* Round up to the nearest multiple of n */ -#define ROUNDUP_2N(a, n) ({ \ - size_t __n = (size_t)(n); \ - (typeof(a))(ROUNDDOWN_2N((size_t)(a) + (1<<__n) - 1, __n)); \ - }) - - -/* Round up the result of dividing of n */ -#define ROUNDUP_DIV_2N(a, n) ({ \ -uint32_t __n = (1<<(uint32_t)(n)); \ -(typeof(a))(((a) + __n - 1) >> (n)); \ -}) - - -/* Return the offset of 'member' relative to the beginning of a struct type */ -#define offsetof(type, member) \ - ((size_t)(&((type *)0)->member)) - -/* * - * to_struct - get the struct from a ptr - * @ptr: a struct pointer of member - * @type: the type of the struct this is embedded in - * @member: the name of the member within the struct - * */ -#define to_struct(ptr, type, member) \ - ((type *)((char *)(ptr) - offsetof(type, member))) - -#endif /* !__LIBS_DEFS_H__ */ - diff --git a/ucore-thumips/kern/include/dirent.h b/ucore-thumips/kern/include/dirent.h deleted file mode 100644 index 429e4fe..0000000 --- a/ucore-thumips/kern/include/dirent.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __LIBS_DIRENT_H__ -#define __LIBS_DIRENT_H__ - -#include -#include - -struct dirent { - off_t offset; - char name[FS_MAX_FNAME_LEN + 1]; -}; - -#endif /* !__LIBS_DIRENT_H__ */ - diff --git a/ucore-thumips/kern/include/elf.h b/ucore-thumips/kern/include/elf.h deleted file mode 100644 index af26f86..0000000 --- a/ucore-thumips/kern/include/elf.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef __LIBS_ELF_H__ -#define __LIBS_ELF_H__ - -#include - -#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian - -/* file header */ -struct __elfhdr { - uint32_t e_magic; // must equal ELF_MAGIC - uint8_t e_elf[12]; - unsigned short e_type; // 1=relocatable, 2=executable, 3=shared object, 4=core image - unsigned short e_machine; // 3=x86, 4=68K, etc. - uint32_t e_version; // file version, always 1 - uint32_t e_entry; // entry point if executable - uint32_t e_phoff; // file position of program header or 0 - uint32_t e_shoff; // file position of section header or 0 - uint32_t e_flags; // architecture-specific flags, usually 0 - unsigned short e_ehsize; // size of this elf header - unsigned short e_phentsize; // size of an entry in program header - unsigned short e_phnum; // number of entries in program header or 0 - unsigned short e_shentsize; // size of an entry in section header - unsigned short e_shnum; // number of entries in section header or 0 - unsigned short e_shstrndx; // section number that contains section name strings -}; - -struct elfhdr32 { - uint32_t e_magic; // must equal ELF_MAGIC - uint8_t e_elf[12]; - uint32_t e_type; // 1=relocatable, 2=executable, 3=shared object, 4=core image - uint32_t e_machine; // 3=x86, 4=68K, etc. - uint32_t e_version; // file version, always 1 - uint32_t e_entry; // entry point if executable - uint32_t e_phoff; // file position of program header or 0 - uint32_t e_shoff; // file position of section header or 0 - uint32_t e_flags; // architecture-specific flags, usually 0 - uint32_t e_ehsize; // size of this elf header - uint32_t e_phentsize; // size of an entry in program header - uint32_t e_phnum; // number of entries in program header or 0 - uint32_t e_shentsize; // size of an entry in section header - uint32_t e_shnum; // number of entries in section header or 0 - uint32_t e_shstrndx; // section number that contains section name strings -}; - -static inline void _load_elfhdr(unsigned char* base, struct elfhdr32 *hdr) -{ - struct __elfhdr *eh = (struct __elfhdr*)base; - hdr->e_magic = eh->e_magic; - hdr->e_version = eh->e_version; - hdr->e_entry = eh->e_entry; - hdr->e_phoff = eh->e_phoff; - hdr->e_shoff = eh->e_shoff; - hdr->e_flags = eh->e_flags; - - uint32_t t = *(uint32_t*)(&eh->e_type); - hdr->e_type = t & 0xFFFF; - hdr->e_machine = t >> 16; - - t = *(uint32_t*)(&eh->e_ehsize); - hdr->e_ehsize = t & 0xFFFF; - hdr->e_phentsize = t >> 16; - - t = *(uint32_t*)(&eh->e_phnum); - hdr->e_phnum = t & 0xFFFF; - hdr->e_shentsize = t >> 16; - - t = *(uint32_t*)(&eh->e_shnum); - hdr->e_shnum = t & 0xFFFF; - hdr->e_shstrndx = t >> 16; -} - -/* program section header */ -struct proghdr { - uint32_t p_type; // loadable code or data, dynamic linking info,etc. - uint32_t p_offset; // file offset of segment - uint32_t p_va; // virtual address to map segment - uint32_t p_pa; // physical address, not used - uint32_t p_filesz; // size of segment in file - uint32_t p_memsz; // size of segment in memory (bigger if contains bss) - uint32_t p_flags; // read/write/execute bits - uint32_t p_align; // required alignment, invariably hardware page size -}; - -/* values for Proghdr::p_type */ -#define ELF_PT_LOAD 1 - -/* flag bits for Proghdr::p_flags */ -#define ELF_PF_X 1 -#define ELF_PF_W 2 -#define ELF_PF_R 4 - -#endif /* !__LIBS_ELF_H__ */ - diff --git a/ucore-thumips/kern/include/error.h b/ucore-thumips/kern/include/error.h deleted file mode 100644 index ddad593..0000000 --- a/ucore-thumips/kern/include/error.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __LIBS_ERROR_H__ -#define __LIBS_ERROR_H__ - -/* kernel error codes -- keep in sync with list in lib/printfmt.c */ -#define E_UNSPECIFIED 1 // Unspecified or unknown problem -#define E_BAD_PROC 2 // Process doesn't exist or otherwise -#define E_INVAL 3 // Invalid parameter -#define E_NO_MEM 4 // Request failed due to memory shortage -#define E_NO_FREE_PROC 5 // Attempt to create a new process beyond -#define E_FAULT 6 // Memory fault -#define E_SWAP_FAULT 7 // SWAP READ/WRITE fault -#define E_INVAL_ELF 8 // Invalid elf file -#define E_KILLED 9 // Process is killed -#define E_PANIC 10 // Panic Failure -#define E_TIMEOUT 11 // Timeout -#define E_TOO_BIG 12 // Argument is Too Big -#define E_NO_DEV 13 // No such Device -#define E_NA_DEV 14 // Device Not Available -#define E_BUSY 15 // Device/File is Busy -#define E_NOENT 16 // No Such File or Directory -#define E_ISDIR 17 // Is a Directory -#define E_NOTDIR 18 // Not a Directory -#define E_XDEV 19 // Cross Device-Link -#define E_UNIMP 20 // Unimplemented Feature -#define E_SEEK 21 // Illegal Seek -#define E_MAX_OPEN 22 // Too Many Files are Open -#define E_EXISTS 23 // File/Directory Already Exists -#define E_NOTEMPTY 24 // Directory is Not Empty -/* the maximum allowed */ -#define MAXERROR 24 - -#endif /* !__LIBS_ERROR_H__ */ - diff --git a/ucore-thumips/kern/include/glue_pgmap.h b/ucore-thumips/kern/include/glue_pgmap.h deleted file mode 100644 index d8d26bc..0000000 --- a/ucore-thumips/kern/include/glue_pgmap.h +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef __GLUE_PGMAP_H__ -#define __GLUE_PGMAP_H__ - -#include - -typedef pte_t pte_perm_t; - -static inline void -ptep_map (pte_t *ptep, uintptr_t pa) -{ - *ptep = (pa | PTE_P); -} - -static inline void -ptep_unmap (pte_t *ptep) -{ - *ptep = 0; -} - -static inline int -ptep_invalid (pte_t *ptep) -{ - return (*ptep == 0); -} - -static inline int -ptep_present (pte_t *ptep) -{ - return (*ptep & PTE_P); -} - -static inline int -ptep_s_read (pte_t *ptep) -{ - return (*ptep & PTE_P); -} - -static inline int -ptep_s_write (pte_t *ptep) -{ - return (*ptep & PTE_W); -} - -static inline int -ptep_u_read (pte_t *ptep) -{ - return (*ptep & PTE_U); -} - -static inline int -ptep_u_write (pte_t *ptep) -{ - return ((*ptep & PTE_U) && (*ptep & PTE_W)); -} - -static inline void -ptep_set_s_read (pte_t *ptep) -{ -} - -static inline void -ptep_set_s_write (pte_t *ptep) -{ - *ptep |= PTE_W; -} - -static inline void -ptep_set_u_read (pte_t *ptep) -{ - *ptep |= PTE_U; -} - -static inline void -ptep_set_u_write (pte_t *ptep) -{ - *ptep |= PTE_W | PTE_U; -} - -static inline void -ptep_unset_s_read (pte_t *ptep) -{ -} - -static inline void -ptep_unset_s_write (pte_t *ptep) -{ - *ptep &= (~PTE_W); -} - -static inline void -ptep_unset_u_read (pte_t *ptep) -{ - *ptep &= (~PTE_U); -} - -static inline void -ptep_unset_u_write (pte_t *ptep) -{ - *ptep &= (~PTE_W); -} - -static inline pte_perm_t -ptep_get_perm (pte_t *ptep, pte_perm_t perm) -{ - return (*ptep) & perm; -} - -static inline void -ptep_set_perm (pte_t *ptep, pte_perm_t perm) -{ - *ptep |= perm; -} - -static inline void -ptep_copy (pte_t *to, pte_t *from) -{ - *to = *from; -} - -static inline void -ptep_unset_perm (pte_t *ptep, pte_perm_t perm) -{ - *ptep &= (~perm); -} - -static inline int -ptep_accessed (pte_t *ptep) -{ - return *ptep & PTE_A; -} - -static inline int -ptep_dirty (pte_t *ptep) -{ - return *ptep & PTE_D; -} - -static inline void -ptep_set_accessed (pte_t *ptep) -{ - *ptep |= PTE_A; -} - -static inline void -ptep_set_dirty (pte_t *ptep) -{ - *ptep |= PTE_D; -} - -static inline void -ptep_unset_accessed (pte_t *ptep) -{ - *ptep &= (~PTE_A); -} - -static inline void -ptep_unset_dirty (pte_t *ptep) -{ - *ptep &= (~PTE_D); -} - -#endif /* !__GLUE_PGMAP_H__ */ diff --git a/ucore-thumips/kern/include/list.h b/ucore-thumips/kern/include/list.h deleted file mode 100644 index be3da37..0000000 --- a/ucore-thumips/kern/include/list.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef __LIBS_LIST_H__ -#define __LIBS_LIST_H__ - -#ifndef __ASSEMBLER__ - -#include - -/* * - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when manipulating - * whole lists rather than single entries, as sometimes we already know - * the next/prev entries and we can generate better code by using them - * directly rather than using the generic single-entry routines. - * */ - -struct list_entry { - struct list_entry *prev, *next; -}; - -typedef struct list_entry list_entry_t; - -static __always_inline void __list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next); -static __always_inline void __list_del(list_entry_t *prev, list_entry_t *next); - -/* * - * list_init - initialize a new entry - * @elm: new entry to be initialized - * */ -static __always_inline void -list_init(list_entry_t *elm) { - elm->prev = elm->next = elm; -} - -/* * - * list_add_before - add a new entry - * @listelm: list head to add before - * @elm: new entry to be added - * - * Insert the new element @elm *before* the element @listelm which - * is already in the list. - * */ -static __always_inline void -list_add_before(list_entry_t *listelm, list_entry_t *elm) { - __list_add(elm, listelm->prev, listelm); -} - -/* * - * list_add_after - add a new entry - * @listelm: list head to add after - * @elm: new entry to be added - * - * Insert the new element @elm *after* the element @listelm which - * is already in the list. - * */ -static __always_inline void -list_add_after(list_entry_t *listelm, list_entry_t *elm) { - __list_add(elm, listelm, listelm->next); -} - -/* * - * list_add - add a new entry - * @listelm: list head to add after - * @elm: new entry to be added - * - * Insert the new element @elm *after* the element @listelm which - * is already in the list. - * */ -static __always_inline void -list_add(list_entry_t *listelm, list_entry_t *elm) { - list_add_after(listelm, elm); -} - -/* * - * list_del - deletes entry from list - * @listelm: the element to delete from the list - * - * Note: list_empty() on @listelm does not return true after this, the entry is - * in an undefined state. - * */ -static __always_inline void -list_del(list_entry_t *listelm) { - __list_del(listelm->prev, listelm->next); -} - -/* * - * list_del_init - deletes entry from list and reinitialize it. - * @listelm: the element to delete from the list. - * - * Note: list_empty() on @listelm returns true after this. - * */ -static __always_inline void -list_del_init(list_entry_t *listelm) { - list_del(listelm); - list_init(listelm); -} - -/* * - * list_empty - tests whether a list is empty - * @list: the list to test. - * */ -static __always_inline bool -list_empty(list_entry_t *list) { - return list->next == list; -} - -/* * - * list_next - get the next entry - * @listelm: the list head - **/ -static __always_inline list_entry_t * -list_next(list_entry_t *listelm) { - return listelm->next; -} - -/* * - * list_prev - get the previous entry - * @listelm: the list head - **/ -static __always_inline list_entry_t * -list_prev(list_entry_t *listelm) { - return listelm->prev; -} - -/* * - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - * */ -static __always_inline void -__list_add(list_entry_t *elm, list_entry_t *prev, list_entry_t *next) { - prev->next = next->prev = elm; - elm->next = next; - elm->prev = prev; -} - -/* * - * Delete a list entry by making the prev/next entries point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - * */ -static __always_inline void -__list_del(list_entry_t *prev, list_entry_t *next) { - prev->next = next; - next->prev = prev; -} - -#endif /* !__ASSEMBLER__ */ - -#endif /* !__LIBS_LIST_H__ */ - diff --git a/ucore-thumips/kern/include/mips_vm.h b/ucore-thumips/kern/include/mips_vm.h deleted file mode 100644 index ab804ed..0000000 --- a/ucore-thumips/kern/include/mips_vm.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _MIPS_VM_H_ -#define _MIPS_VM_H_ - -/* - * Machine-dependent VM system definitions. - */ - -//#define PAGE_SIZE 4096 /* size of VM page */ -#define PAGE_FRAME 0xfffff000 /* mask for getting page number from addr */ - -/* - * MIPS hardwired memory layout: - * 0xc0000000 - 0xffffffff kseg2 (kernel, tlb-mapped) - * 0xa0000000 - 0xbfffffff kseg1 (kernel, unmapped, uncached) - * 0x80000000 - 0x9fffffff kseg0 (kernel, unmapped, cached) - * 0x00000000 - 0x7fffffff kuseg (user, tlb-mapped) - */ - -#define MIPS_KUSEG 0x00000000 -#define MIPS_KSEG0 0x80000000 -#define MIPS_KSEG1 0xa0000000 -#define MIPS_KSEG2 0xc0000000 - -/* - * The first 512 megs of physical space can be addressed in both kseg0 and - * kseg1. We use kseg0 for the kernel. This macro returns the kernel virtual - * address of a given physical address within that range. (We assume we're - * not using systems with more physical space than that anyway.) - * - * N.B. If you, say, call a function that returns a paddr or 0 on error, - * check the paddr for being 0 *before* you use this macro. While paddr 0 - * is not legal for memory allocation or memory management (it holds - * exception handler code) when converted to a vaddr it's *not* NULL, *is* - * a valid address, and will make a *huge* mess if you scribble on it. - */ -#define PADDR_TO_KVADDR(paddr) ((paddr)+MIPS_KSEG0) - -/* - * The top of user space. (Actually, the address immediately above the - * last valid user address.) - */ -//#define USERTOP MIPS_KSEG0 - -/* - * The starting value for the stack pointer at user level. Because - * the stack is subtract-then-store, this can start as the next - * address after the stack area. - * - * We put the stack at the very top of user virtual memory because it - * grows downwards. - */ -//#define USERSTACK USERTOP - -/* - * Interface to the low-level module that looks after the amount of - * physical memory we have. - * - * ram_getsize returns the lowest valid physical address, and one past - * the highest valid physical address. (Both are page-aligned.) This - * is the memory that is available for use during operation, and - * excludes the memory the kernel is loaded into and memory that is - * grabbed in the very early stages of bootup. - * - * ram_stealmem can be used before ram_getsize is called to allocate - * memory that cannot be freed later. This is intended for use early - * in bootup before VM initialization is complete. - */ - -void ram_getsize(uintptr_t *lo, uintptr_t *hi); - -/* - * The ELF executable type for this platform. - */ -#define EM_MACHINE EM_MIPS - -#endif /* _MIPS_VM_H_ */ diff --git a/ucore-thumips/kern/include/stat.h b/ucore-thumips/kern/include/stat.h deleted file mode 100644 index 41a392d..0000000 --- a/ucore-thumips/kern/include/stat.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __LIBS_STAT_H__ -#define __LIBS_STAT_H__ - -#include - -struct stat { - uint32_t st_mode; // protection mode and file type - size_t st_nlinks; // number of hard links - size_t st_blocks; // number of blocks file is using - size_t st_size; // file size (bytes) -}; - -#define S_IFMT 070000 // mask for type of file -#define S_IFREG 010000 // ordinary regular file -#define S_IFDIR 020000 // directory -#define S_IFLNK 030000 // symbolic link -#define S_IFCHR 040000 // character device -#define S_IFBLK 050000 // block device - -#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) // regular file -#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) // directory -#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) // symlink -#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) // char device -#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) // block device - -#endif /* !__LIBS_STAT_H__ */ - diff --git a/ucore-thumips/kern/include/stdarg.h b/ucore-thumips/kern/include/stdarg.h deleted file mode 100644 index f6e0758..0000000 --- a/ucore-thumips/kern/include/stdarg.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __LIBS_STDARG_H__ -#define __LIBS_STDARG_H__ - -/* compiler provides size of save area */ -typedef __builtin_va_list va_list; - -#define va_start(ap, last) (__builtin_va_start(ap, last)) -#define va_arg(ap, type) (__builtin_va_arg(ap, type)) -#define va_end(ap) /*nothing*/ - -#endif /* !__LIBS_STDARG_H__ */ - diff --git a/ucore-thumips/kern/include/thumips.h b/ucore-thumips/kern/include/thumips.h deleted file mode 100644 index 9643622..0000000 --- a/ucore-thumips/kern/include/thumips.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef __LIBS_THUMIPS_H__ -#define __LIBS_THUMIPS_H__ - -#include - -#define do_div(n, base) ({ \ - unsigned long __mod; \ - (__mod) = ((unsigned long)n) % (base); \ - (n) = ((unsigned long)n) / (base); \ - __mod; \ - }) - -#define barrier() __asm__ __volatile__ ("" ::: "memory") - -#define __read_reg(source) (\ - {int __res;\ - __asm__ __volatile__("move %0, " #source "\n\t"\ - : "=r"(__res));\ - __res;\ - }) - -static inline unsigned int __mulu10(unsigned int n) -{ - return (n<<3)+(n<<1); -} - -/* __divu* routines are from the book, Hacker's Delight */ - -static inline unsigned int __divu10(unsigned int n) { - unsigned int q, r; - q = (n >> 1) + (n >> 2); - q = q + (q >> 4); - q = q + (q >> 8); - q = q + (q >> 16); - q = q >> 3; - r = n - __mulu10(q); - return q + ((r + 6) >> 4); -} - -static inline unsigned __divu5(unsigned int n) { - unsigned int q, r; - q = (n >> 3) + (n >> 4); - q = q + (q >> 4); - q = q + (q >> 8); - q = q + (q >> 16); - r = n - q*5; - return q + (13*r >> 6); -} - -static inline uint8_t inb(uint32_t port) __attribute__((always_inline)); -static inline void outb(uint32_t port, uint8_t data) __attribute__((always_inline)); -static inline uint32_t inw(uint32_t port) __attribute__((always_inline)); -static inline void outw(uint32_t port, uint32_t data) __attribute__((always_inline)); - -static inline uint8_t -inb(uint32_t port) { - uint8_t data = *((volatile uint8_t*) port); - return data; -} - -static inline void -outb(uint32_t port, uint8_t data) { - *((volatile uint8_t*) port) = data; -} - -static inline uint32_t -inw(uint32_t port) { - uint32_t data = *((volatile uintptr_t *) port); - return data; -} - -static inline void -outw(uint32_t port, uint32_t data) { - *((volatile uintptr_t *) port) = data; -} - -/* board specification */ -#define ISA_BASE 0xbfd00000 -#define COM1 (ISA_BASE+0x3F8) -#define COM1_IRQ 4 -#define VGA_BASE 0xbfe00000 -#define VGA_TOP 0xbfe4b000 -#define LATTICE_BASE 0xbfe4b000 - -#define TIMER0_IRQ 7 - - -#endif /* !__LIBS_THUMIPS_H__ */ - diff --git a/ucore-thumips/kern/include/thumips_tlb.h b/ucore-thumips/kern/include/thumips_tlb.h deleted file mode 100644 index 85f724a..0000000 --- a/ucore-thumips/kern/include/thumips_tlb.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * ===================================================================================== - * - * Filename: thumips_tlb.h - * - * Description: - * - * Version: 1.0 - * Created: 07/06/2012 10:20:30 AM - * Revision: none - * Compiler: gcc - * - * Author: Chen Yuheng (Chen Yuheng), chyh1990@163.com - * Organization: Tsinghua Unv. - * - * ===================================================================================== - */ -#ifndef _THUMIPS_TLB_H -#define _THUMIPS_TLB_H - -#include -#include -#include - -#define THUMIPS_TLB_ENTRYL_V (1<<1) -#define THUMIPS_TLB_ENTRYL_D (1<<2) -#define THUMIPS_TLB_ENTRYL_G (1<<0) -#define THUMIPS_TLB_ENTRYH_VPN2_MASK (~0x1FFF) - -static inline void write_one_tlb(int index, unsigned int pagemask, unsigned int hi, unsigned int low0, unsigned int low1) -{ - write_c0_entrylo0(low0); - write_c0_pagemask(pagemask); - write_c0_entrylo1(low1); - write_c0_entryhi(hi); - write_c0_index(index); - tlb_write_indexed(); -} - -static inline void tlb_replace_random(unsigned int pagemask, unsigned int hi, unsigned int low0, unsigned int low1) -{ - write_c0_entrylo0(low0); - write_c0_pagemask(pagemask); - write_c0_entrylo1(low1); - write_c0_entryhi(hi); - tlb_write_random(); -} - -#define PTE2TLBLOW(x) (((((uint32_t)(*(x))-KERNBASE)>> 12)<<6)|THUMIPS_TLB_ENTRYL_V|THUMIPS_TLB_ENTRYL_D|(2<<3)) -static inline uint32_t pte2tlblow(pte_t pte) -{ - uint32_t t = (((uint32_t)pte - KERNBASE ) >> 12)<<6; - if(!ptep_present(&pte)) - return 0; - t |= THUMIPS_TLB_ENTRYL_V; - /* always ignore ASID */ - t |= THUMIPS_TLB_ENTRYL_G; - t |= (3<<3); - if(ptep_s_write(&pte)) - t |= THUMIPS_TLB_ENTRYL_D; - return t; -} - -static inline void tlb_refill(uint32_t badaddr, pte_t *pte) -{ - if(!pte) - return ; - if(badaddr & (1<<12)) - pte--; - tlb_replace_random(0, badaddr & THUMIPS_TLB_ENTRYH_VPN2_MASK, - pte2tlblow(*pte), pte2tlblow(*(pte+1))); -} - -void tlb_invalidate_all(); -#endif diff --git a/ucore-thumips/kern/include/unistd.h b/ucore-thumips/kern/include/unistd.h deleted file mode 100644 index b8ed4e7..0000000 --- a/ucore-thumips/kern/include/unistd.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef __LIBS_UNISTD_H__ -#define __LIBS_UNISTD_H__ - -#define SYSCALL_BASE 0x80 - -/* syscall number */ -#define SYS_exit 1 -#define SYS_fork 2 -#define SYS_wait 3 -#define SYS_exec 4 -#define SYS_clone 5 -#define SYS_yield 10 -#define SYS_sleep 11 -#define SYS_kill 12 -#define SYS_gettime 17 -#define SYS_getpid 18 -#define SYS_mmap 20 -#define SYS_munmap 21 -#define SYS_shmem 22 -#define SYS_putc 30 -#define SYS_pgdir 31 -#define SYS_open 100 -#define SYS_close 101 -#define SYS_read 102 -#define SYS_write 103 -#define SYS_seek 104 -#define SYS_fstat 110 -#define SYS_fsync 111 -#define SYS_getcwd 121 -#define SYS_getdirentry 128 -#define SYS_dup 130 -/* OLNY FOR LAB6 */ -#define SYS_lab6_set_priority 255 - -/* SYS_fork flags */ -#define CLONE_VM 0x00000100 // set if VM shared between processes -#define CLONE_THREAD 0x00000200 // thread group -#define CLONE_FS 0x00000800 // set if shared between processes - -/* VFS flags */ -// flags for open: choose one of these -#define O_RDONLY 0 // open for reading only -#define O_WRONLY 1 // open for writing only -#define O_RDWR 2 // open for reading and writing -// then or in any of these: -#define O_CREAT 0x00000004 // create file if it does not exist -#define O_EXCL 0x00000008 // error if O_CREAT and the file exists -#define O_TRUNC 0x00000010 // truncate file upon open -#define O_APPEND 0x00000020 // append on each write -// additonal related definition -#define O_ACCMODE 3 // mask for O_RDONLY / O_WRONLY / O_RDWR - -#define NO_FD -0x9527 // invalid fd - -/* lseek codes */ -#define LSEEK_SET 0 // seek relative to beginning of file -#define LSEEK_CUR 1 // seek relative to current position in file -#define LSEEK_END 2 // seek relative to end of file - -#define FS_MAX_DNAME_LEN 31 -#define FS_MAX_FNAME_LEN 255 -#define FS_MAX_FPATH_LEN 4095 - -#define EXEC_MAX_ARG_NUM 32 -#define EXEC_MAX_ARG_LEN 4095 - -#endif /* !__LIBS_UNISTD_H__ */ - diff --git a/ucore-thumips/kern/init/entry.S b/ucore-thumips/kern/init/entry.S deleted file mode 100644 index bbe1b0e..0000000 --- a/ucore-thumips/kern/init/entry.S +++ /dev/null @@ -1,89 +0,0 @@ - -#include - -.global kernel_entry -.extern kern_init - -.extern edata -.extern end - -.set noreorder - -.section .startup - -#define KSTACKSIZE (4096*2) - -kernel_entry: - b reset - nop - - .align 4 -reset: - /* from u-boot */ -#ifdef MACH_QEMU - /* Clear watch registers */ - mtc0 $zero, CP0_WATCHLO - mtc0 $zero, CP0_WATCHHI -#endif - - /* WP(Watch Pending), SW0/1 should be cleared */ - mtc0 $zero, CP0_CAUSE - /* clear SR(ERL), which is 1 after reset */ - mtc0 $zero, CP0_STATUS - - jal 1f - nop - .word _gp -1: - lw $gp, 0($ra) - la $sp, bootstacktop -#setup ram exception - la $t0, __exception_vector -#TODO - mtc0 $t0, $15, 1 - - mfc0 $t0, CP0_STATUS - li $t1, ~ST0_BEV - and $t0, $t0, $t1 - mtc0 $t0, CP0_STATUS - -#zero bss - la $t0, edata - la $t1, end - -2: - sw $zero, 0($t0) - addiu $t0, $t0, 4 - slt $t3, $t0, $t1 - bgtz $t3, 2b - nop - - addiu $sp, $sp, -16 - la $t9, kern_init - jal $t9 - nop -#never here - bgez $zero, . - nop - - -# bfc00280: R4000 xtlbmiss vector -romExcHandle_280: - b romExcHandle_280 - nop - -# bfc00300: R4000 cache vector -romExcHandle_300: - b romExcHandle_300 - nop - - -.section .data - .global bootstack -bootstack: - .space KSTACKSIZE - .global bootstacktop -bootstacktop: - .space 32 - - diff --git a/ucore-thumips/kern/init/init.c b/ucore-thumips/kern/init/init.c deleted file mode 100644 index 2d4d357..0000000 --- a/ucore-thumips/kern/init/init.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void setup_exception_vector() -{ - //for QEMU sim - extern unsigned char __exception_vector, __exception_vector_end; - memcpy((unsigned int*)0xBFC00000, &__exception_vector, - &__exception_vector_end - &__exception_vector); -} - -void __noreturn -kern_init(void) { - //setup_exception_vector(); - tlb_invalidate_all(); - - pic_init(); // init interrupt controller - cons_init(); // init the console - vga_init(); // init the vga - clock_init(); // init clock interrupt - - check_initrd(); - - const char *message = "(THU.CST) os is loading ...\n\n"; - kprintf(message); - - print_kerninfo(); - -#if 0 - kprintf("EX\n"); - __asm__ volatile("syscall"); - kprintf("EX RET\n"); -#endif - - pmm_init(); // init physical memory management - - vmm_init(); // init virtual memory management - sched_init(); - proc_init(); // init process table - - ide_init(); - fs_init(); - - intr_enable(); // enable irq interrupt - //*(int*)(0x00124) = 0x432; - //asm volatile("divu $1, $1, $1"); - cpu_idle(); -} - diff --git a/ucore-thumips/kern/libs/hash.c b/ucore-thumips/kern/libs/hash.c deleted file mode 100644 index 61bcd88..0000000 --- a/ucore-thumips/kern/libs/hash.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - -/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */ -#define GOLDEN_RATIO_PRIME_32 0x9e370001UL - -/* * - * hash32 - generate a hash value in the range [0, 2^@bits - 1] - * @val: the input value - * @bits: the number of bits in a return value - * - * High bits are more random, so we use them. - * */ -uint32_t -hash32(uint32_t val, unsigned int bits) { - uint32_t hash = val * GOLDEN_RATIO_PRIME_32; - return (hash >> (32 - bits)); -} - diff --git a/ucore-thumips/kern/libs/printfmt.c b/ucore-thumips/kern/libs/printfmt.c deleted file mode 100644 index 87a3042..0000000 --- a/ucore-thumips/kern/libs/printfmt.c +++ /dev/null @@ -1,360 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* * - * Space or zero padding and a field width are supported for the numeric - * formats only. - * - * The special format %e takes an integer error code - * and prints a string describing the error. - * The integer may be positive or negative, - * so that -E_NO_MEM and E_NO_MEM are equivalent. - * */ - -static const char * const error_string[MAXERROR + 1] = { - [0] NULL, - [E_UNSPECIFIED] "unspecified error", - [E_BAD_PROC] "bad process", - [E_INVAL] "invalid parameter", - [E_NO_MEM] "out of memory", - [E_NO_FREE_PROC] "out of processes", - [E_FAULT] "segmentation fault", - [E_INVAL_ELF] "invalid elf file", - [E_KILLED] "process is killed", - [E_PANIC] "panic failure", - [E_NO_DEV] "no such device", - [E_NA_DEV] "device not available", - [E_BUSY] "device/file is busy", - [E_NOENT] "no such file or directory", - [E_ISDIR] "is a directory", - [E_NOTDIR] "not a directory", - [E_XDEV] "cross device link", - [E_UNIMP] "unimplemented feature", - [E_SEEK] "illegal seek", - [E_MAX_OPEN] "too many files are open", - [E_EXISTS] "file or directory already exists", - [E_NOTEMPTY] "directory is not empty", -}; - - - -/* * - * getuint - get an unsigned int of various possible sizes from a varargs list - * @ap: a varargs list pointer - * @lflag: determines the size of the vararg that @ap points to - * */ -static unsigned long long -getuint(va_list *ap, int lflag) { - if (lflag >= 2) { - return va_arg(*ap, unsigned long long); - } - else if (lflag) { - return va_arg(*ap, unsigned long); - } - else { - return va_arg(*ap, unsigned int); - } -} - -/* * - * getint - same as getuint but signed, we can't use getuint because of sign extension - * @ap: a varargs list pointer - * @lflag: determines the size of the vararg that @ap points to - * */ -static long long -getint(va_list *ap, int lflag) { - if (lflag >= 2) { - return va_arg(*ap, long long); - } - else if (lflag) { - return va_arg(*ap, long); - } - else { - return va_arg(*ap, int); - } -} - -/* * - * printnum - print a number (base <= 16) in reverse order - * @putch: specified putch function, print a single character - * @putdat: used by @putch function - * @num: the number will be printed - * @base: base for print, must be in [1, 16] - * @width: maximum number of digits, if the actual width is less than @width, use @padc instead - * @padc: character that padded on the left if the actual width is less than @width - * */ -static void -printnum(void (*putch)(int, void*, int), int fd, void *putdat, - unsigned int num, unsigned int base, int width, int padc) { - unsigned int result = num; - unsigned int mod = 0; - if(base == 10){ - unsigned int t = __divu10(result); - mod = result - __mulu10(t); - result = t; - }else if(base == 8){ - mod = result & 0x7; - result = result >> 3; - }else{ - mod = result & 0xF; - result = result >> 4; - } - - // first recursively print all preceding (more significant) digits - if (num >= base) { - printnum(putch, fd, putdat, result, base, width - 1, padc); - } else { - // print any needed pad characters before first digit - while (-- width > 0) - putch(padc, putdat, fd); - } - // then print this (the least significant) digit - putch("0123456789abcdef"[mod], putdat, fd); -} - - - -/* * - * vprintfmt - format a string and print it by using putch, it's called with a va_list - * instead of a variable number of arguments - * @fd: file descriptor - * @putch: specified putch function, print a single character - * @putdat: used by @putch function - * @fmt: the format string to use - * @ap: arguments for the format string - * - * Call this function if you are already dealing with a va_list. - * Or you probably want printfmt() instead. - * */ -void -vprintfmt(void (*putch)(int, void*, int), int fd, void *putdat, const char *fmt, va_list ap) { - register const char *p; - register int ch, err; - unsigned long long num; - int base, width, precision, lflag, altflag; - - while (1) { - while ((ch = *(unsigned char *)fmt ++) != '%') { - if (ch == '\0') { - return; - } - putch(ch, putdat, fd); - } - - // Process a %-escape sequence - char padc = ' '; - width = precision = -1; - lflag = altflag = 0; - - reswitch: - switch (ch = *(unsigned char *)fmt ++) { - - // flag to pad on the right - case '-': - padc = '-'; - goto reswitch; - - // flag to pad with 0's instead of spaces - case '0': - padc = '0'; - goto reswitch; - - // width field - case '1' ... '9': - for (precision = 0; ; ++ fmt) { - precision = precision * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') { - break; - } - } - goto process_precision; - - case '*': - precision = va_arg(ap, int); - goto process_precision; - - case '.': - if (width < 0) - width = 0; - goto reswitch; - - case '#': - altflag = 1; - goto reswitch; - - process_precision: - if (width < 0) - width = precision, precision = -1; - goto reswitch; - - // long flag (doubled for long long) - case 'l': - lflag ++; - goto reswitch; - - // character - case 'c': - putch(va_arg(ap, int), putdat, fd); - break; - - // error message - case 'e': - err = va_arg(ap, int); - if (err < 0) { - err = -err; - } - if (err > MAXERROR || (p = error_string[err]) == NULL) { - printfmt(putch, fd, putdat, "error %d", err); - } - else { - printfmt(putch, fd, putdat, "%s", p); - } - break; - - // string - case 's': - if ((p = va_arg(ap, char *)) == NULL) { - p = "(null)"; - } - if (width > 0 && padc != '-') { - for (width -= strnlen(p, precision); width > 0; width --) { - putch(padc, putdat, fd); - } - } - for (; (ch = *p ++) != '\0' && (precision < 0 || -- precision >= 0); width --) { - if (altflag && (ch < ' ' || ch > '~')) { - putch('?', putdat, fd); - } - else { - putch(ch, putdat, fd); - } - } - for (; width > 0; width --) { - putch(' ', putdat, fd); - } - break; - - // (signed) decimal - case 'd': - num = getint(&ap, lflag); - if ((long long)num < 0) { - putch('-', putdat, fd); - num = -(long long)num; - } - base = 10; - goto number; - // pointer - case 'p': - putch('0', putdat, fd); - putch('x', putdat, fd); - num = (unsigned long long)(uintptr_t)va_arg(ap, void *); - base = 16; - goto number; - - // (unsigned) hexadecimal - case 'x': - num = getuint(&ap, lflag); - base = 16; - number: - printnum(putch, fd, putdat, num, base, width, padc); - break; - - // escaped '%' character - case '%': - putch(ch, putdat, fd); - break; - - // unrecognized escape sequence - just print it literally - default: - putch('%', putdat, fd); - for (fmt --; fmt[-1] != '%'; fmt --) - /* do nothing */; - break; - } - } -} - -/* * - * printfmt - format a string and print it by using putch - * @putch: specified putch function, print a single character - * @fd: file descriptor - * @putdat: used by @putch function - * @fmt: the format string to use - * */ -void -printfmt(void (*putch)(int, void*, int), int fd, void *putdat, const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vprintfmt(putch, fd, putdat, fmt, ap); - va_end(ap); -} - -/* sprintbuf is used to save enough information of a buffer */ -struct sprintbuf { - char *buf; // address pointer points to the first unused memory - char *ebuf; // points the end of the buffer - int cnt; // the number of characters that have been placed in this buffer -}; - -/* * - * sprintputch - 'print' a single character in a buffer - * @ch: the character will be printed - * @b: the buffer to place the character @ch - * */ -static void -sprintputch(int ch, struct sprintbuf *b) { - b->cnt ++; - if (b->buf < b->ebuf) { - *b->buf ++ = ch; - } -} - -/* * - * snprintf - format a string and place it in a buffer - * @str: the buffer to place the result into - * @size: the size of buffer, including the trailing null space - * @fmt: the format string to use - * */ -int -snprintf(char *str, size_t size, const char *fmt, ...) { - va_list ap; - int cnt; - va_start(ap, fmt); - cnt = vsnprintf(str, size, fmt, ap); - va_end(ap); - return cnt; -} - -/* * - * vsnprintf - format a string and place it in a buffer, it's called with a va_list - * instead of a variable number of arguments - * @str: the buffer to place the result into - * @size: the size of buffer, including the trailing null space - * @fmt: the format string to use - * @ap: arguments for the format string - * - * The return value is the number of characters which would be generated for the - * given input, excluding the trailing '\0'. - * - * Call this function if you are already dealing with a va_list. - * Or you probably want snprintf() instead. - * */ -int -vsnprintf(char *str, size_t size, const char *fmt, va_list ap) { - struct sprintbuf b = {str, str + size - 1, 0}; - if (str == NULL || b.buf > b.ebuf) { - return -E_INVAL; - } - // print the string to the buffer - vprintfmt((void*)sprintputch, NO_FD, &b, fmt, ap); - // null terminate the buffer - *b.buf = '\0'; - return b.cnt; -} - diff --git a/ucore-thumips/kern/libs/rand.c b/ucore-thumips/kern/libs/rand.c deleted file mode 100644 index 1010787..0000000 --- a/ucore-thumips/kern/libs/rand.c +++ /dev/null @@ -1,25 +0,0 @@ -#include - -static unsigned long next = 1; - -/* * - * rand - returns a pseudo-random integer - * - * The rand() function return a value in the range [0, RAND_MAX]. - * */ -int -rand(void) { - next = (next * 0xDEECE66D + 0xB) & ((1 << 17) - 1); - unsigned long long result = (next >> 12); - return result & RAND_MAX; -} - -/* * - * srand - seed the random number generator with the given number - * @seed: the required seed number - * */ -void -srand(unsigned int seed) { - next = seed; -} - diff --git a/ucore-thumips/kern/libs/rb_tree.c b/ucore-thumips/kern/libs/rb_tree.c deleted file mode 100644 index 7f401d3..0000000 --- a/ucore-thumips/kern/libs/rb_tree.c +++ /dev/null @@ -1,530 +0,0 @@ -#include -#include -#include -#include -#include - -/* rb_node_create - create a new rb_node */ -static inline rb_node * -rb_node_create(void) { - return kmalloc(sizeof(rb_node)); -} - -/* rb_tree_empty - tests if tree is empty */ -static inline bool -rb_tree_empty(rb_tree *tree) { - rb_node *nil = tree->nil, *root = tree->root; - return root->left == nil; -} - -/* * - * rb_tree_create - creates a new red-black tree, the 'compare' function - * is required and returns 'NULL' if failed. - * - * Note that, root->left should always point to the node that is the root - * of the tree. And nil points to a 'NULL' node which should always be - * black and may have arbitrary children and parent node. - * */ -rb_tree * -rb_tree_create(int (*compare)(rb_node *node1, rb_node *node2)) { - assert(compare != NULL); - - rb_tree *tree; - rb_node *nil, *root; - - if ((tree = kmalloc(sizeof(rb_tree))) == NULL) { - goto bad_tree; - } - - tree->compare = compare; - - if ((nil = rb_node_create()) == NULL) { - goto bad_node_cleanup_tree; - } - - nil->parent = nil->left = nil->right = nil; - nil->red = 0; - tree->nil = nil; - - if ((root = rb_node_create()) == NULL) { - goto bad_node_cleanup_nil; - } - - root->parent = root->left = root->right = nil; - root->red = 0; - tree->root = root; - return tree; - -bad_node_cleanup_nil: - kfree(nil); -bad_node_cleanup_tree: - kfree(tree); -bad_tree: - return NULL; -} - -/* * - * FUNC_ROTATE - rotates as described in "Introduction to Algorithm". - * - * For example, FUNC_ROTATE(rb_left_rotate, left, right) can be expaned to a - * left-rotate function, which requires an red-black 'tree' and a node 'x' - * to be rotated on. Basically, this function, named rb_left_rotate, makes the - * parent of 'x' be the left child of 'x', 'x' the parent of its parent before - * rotation and finally fixes other nodes accordingly. - * - * FUNC_ROTATE(xx, left, right) means left-rotate, - * and FUNC_ROTATE(xx, right, left) means right-rotate. - * */ -#define FUNC_ROTATE(func_name, _left, _right) \ -static void \ -func_name(rb_tree *tree, rb_node *x) { \ - rb_node *nil = tree->nil, *y = x->_right; \ - assert(x != tree->root && x != nil && y != nil); \ - x->_right = y->_left; \ - if (y->_left != nil) { \ - y->_left->parent = x; \ - } \ - y->parent = x->parent; \ - if (x == x->parent->_left) { \ - x->parent->_left = y; \ - } \ - else { \ - x->parent->_right = y; \ - } \ - y->_left = x; \ - x->parent = y; \ - assert(!(nil->red)); \ -} - -FUNC_ROTATE(rb_left_rotate, left, right); -FUNC_ROTATE(rb_right_rotate, right, left); - -#undef FUNC_ROTATE - -#define COMPARE(tree, node1, node2) \ - ((tree))->compare((node1), (node2)) - -/* * - * rb_insert_binary - insert @node to red-black @tree as if it were - * a regular binary tree. This function is only intended to be called - * by function rb_insert. - * */ -static inline void -rb_insert_binary(rb_tree *tree, rb_node *node) { - rb_node *x, *y, *z = node, *nil = tree->nil, *root = tree->root; - - z->left = z->right = nil; - y = root, x = y->left; - while (x != nil) { - y = x; - x = (COMPARE(tree, x, node) > 0) ? x->left : x->right; - } - z->parent = y; - if (y == root || COMPARE(tree, y, z) > 0) { - y->left = z; - } - else { - y->right = z; - } -} - -/* rb_insert - insert a node to red-black tree */ -void -rb_insert(rb_tree *tree, rb_node *node) { - rb_insert_binary(tree, node); - node->red = 1; - - rb_node *x = node, *y; - -#define RB_INSERT_SUB(_left, _right) \ - do { \ - y = x->parent->parent->_right; \ - if (y->red) { \ - x->parent->red = 0; \ - y->red = 0; \ - x->parent->parent->red = 1; \ - x = x->parent->parent; \ - } \ - else { \ - if (x == x->parent->_right) { \ - x = x->parent; \ - rb_##_left##_rotate(tree, x); \ - } \ - x->parent->red = 0; \ - x->parent->parent->red = 1; \ - rb_##_right##_rotate(tree, x->parent->parent); \ - } \ - } while (0) - - while (x->parent->red) { - if (x->parent == x->parent->parent->left) { - RB_INSERT_SUB(left, right); - } - else { - RB_INSERT_SUB(right, left); - } - } - tree->root->left->red = 0; - assert(!(tree->nil->red) && !(tree->root->red)); - -#undef RB_INSERT_SUB -} - -/* * - * rb_tree_successor - returns the successor of @node, or nil - * if no successor exists. Make sure that @node must belong to @tree, - * and this function should only be called by rb_node_prev. - * */ -static inline rb_node * -rb_tree_successor(rb_tree *tree, rb_node *node) { - rb_node *x = node, *y, *nil = tree->nil; - - if ((y = x->right) != nil) { - while (y->left != nil) { - y = y->left; - } - return y; - } - else { - y = x->parent; - while (x == y->right) { - x = y, y = y->parent; - } - if (y == tree->root) { - return nil; - } - return y; - } -} - -/* * - * rb_tree_predecessor - returns the predecessor of @node, or nil - * if no predecessor exists, likes rb_tree_successor. - * */ -static inline rb_node * -rb_tree_predecessor(rb_tree *tree, rb_node *node) { - rb_node *x = node, *y, *nil = tree->nil; - - if ((y = x->left) != nil) { - while (y->right != nil) { - y = y->right; - } - return y; - } - else { - y = x->parent; - while (x == y->left) { - if (y == tree->root) { - return nil; - } - x = y, y = y->parent; - } - return y; - } -} - -/* * - * rb_search - returns a node with value 'equal' to @key (according to - * function @compare). If there're multiple nodes with value 'equal' to @key, - * the functions returns the one highest in the tree. - * */ -rb_node * -rb_search(rb_tree *tree, int (*compare)(rb_node *node, void *key), void *key) { - rb_node *nil = tree->nil, *node = tree->root->left; - int r; - while (node != nil && (r = compare(node, key)) != 0) { - node = (r > 0) ? node->left : node->right; - } - return (node != nil) ? node : NULL; -} - -/* * - * rb_delete_fixup - performs rotations and changes colors to restore - * red-black properties after a node is deleted. - * */ -static void -rb_delete_fixup(rb_tree *tree, rb_node *node) { - rb_node *x = node, *w, *root = tree->root->left; - -#define RB_DELETE_FIXUP_SUB(_left, _right) \ - do { \ - w = x->parent->_right; \ - if (w->red) { \ - w->red = 0; \ - x->parent->red = 1; \ - rb_##_left##_rotate(tree, x->parent); \ - w = x->parent->_right; \ - } \ - if (!w->_left->red && !w->_right->red) { \ - w->red = 1; \ - x = x->parent; \ - } \ - else { \ - if (!w->_right->red) { \ - w->_left->red = 0; \ - w->red = 1; \ - rb_##_right##_rotate(tree, w); \ - w = x->parent->_right; \ - } \ - w->red = x->parent->red; \ - x->parent->red = 0; \ - w->_right->red = 0; \ - rb_##_left##_rotate(tree, x->parent); \ - x = root; \ - } \ - } while (0) - - while (x != root && !x->red) { - if (x == x->parent->left) { - RB_DELETE_FIXUP_SUB(left, right); - } - else { - RB_DELETE_FIXUP_SUB(right, left); - } - } - x->red = 0; - -#undef RB_DELETE_FIXUP_SUB -} - -/* * - * rb_delete - deletes @node from @tree, and calls rb_delete_fixup to - * restore red-black properties. - * */ -void -rb_delete(rb_tree *tree, rb_node *node) { - rb_node *x, *y, *z = node; - rb_node *nil = tree->nil, *root = tree->root; - - y = (z->left == nil || z->right == nil) ? z : rb_tree_successor(tree, z); - x = (y->left != nil) ? y->left : y->right; - - assert(y != root && y != nil); - - x->parent = y->parent; - if (y == y->parent->left) { - y->parent->left = x; - } - else { - y->parent->right = x; - } - - bool need_fixup = !(y->red); - - if (y != z) { - if (z == z->parent->left) { - z->parent->left = y; - } - else { - z->parent->right = y; - } - z->left->parent = z->right->parent = y; - *y = *z; - } - if (need_fixup) { - rb_delete_fixup(tree, x); - } -} - -/* rb_tree_destroy - destroy a tree and free memory */ -void -rb_tree_destroy(rb_tree *tree) { - kfree(tree->root); - kfree(tree->nil); - kfree(tree); -} - -/* * - * rb_node_prev - returns the predecessor node of @node in @tree, - * or 'NULL' if no predecessor exists. - * */ -rb_node * -rb_node_prev(rb_tree *tree, rb_node *node) { - rb_node *prev = rb_tree_predecessor(tree, node); - return (prev != tree->nil) ? prev : NULL; -} - -/* * - * rb_node_next - returns the successor node of @node in @tree, - * or 'NULL' if no successor exists. - * */ -rb_node * -rb_node_next(rb_tree *tree, rb_node *node) { - rb_node *next = rb_tree_successor(tree, node); - return (next != tree->nil) ? next : NULL; -} - -/* rb_node_root - returns the root node of a @tree, or 'NULL' if tree is empty */ -rb_node * -rb_node_root(rb_tree *tree) { - rb_node *node = tree->root->left; - return (node != tree->nil) ? node : NULL; -} - -/* rb_node_left - gets the left child of @node, or 'NULL' if no such node */ -rb_node * -rb_node_left(rb_tree *tree, rb_node *node) { - rb_node *left = node->left; - return (left != tree->nil) ? left : NULL; -} - -/* rb_node_right - gets the right child of @node, or 'NULL' if no such node */ -rb_node * -rb_node_right(rb_tree *tree, rb_node *node) { - rb_node *right = node->right; - return (right != tree->nil) ? right : NULL; -} - -int -check_tree(rb_tree *tree, rb_node *node) { - rb_node *nil = tree->nil; - if (node == nil) { - assert(!node->red); - return 1; - } - if (node->left != nil) { - assert(COMPARE(tree, node, node->left) >= 0); - assert(node->left->parent == node); - } - if (node->right != nil) { - assert(COMPARE(tree, node, node->right) <= 0); - assert(node->right->parent == node); - } - if (node->red) { - assert(!node->left->red && !node->right->red); - } - int hb_left = check_tree(tree, node->left); - int hb_right = check_tree(tree, node->right); - assert(hb_left == hb_right); - int hb = hb_left; - if (!node->red) { - hb ++; - } - return hb; -} - -static void * -check_safe_kmalloc(size_t size) { - void *ret = kmalloc(size); - assert(ret != NULL); - return ret; -} - -struct check_data { - long data; - rb_node rb_link; -}; - -#define rbn2data(node) \ - (to_struct(node, struct check_data, rb_link)) - -static inline int -check_compare1(rb_node *node1, rb_node *node2) { - return rbn2data(node1)->data - rbn2data(node2)->data; -} - -static inline int -check_compare2(rb_node *node, void *key) { - return rbn2data(node)->data - (long)key; -} - -void -check_rb_tree(void) { - rb_tree *tree = rb_tree_create(check_compare1); - assert(tree != NULL); - - rb_node *nil = tree->nil, *root = tree->root; - assert(!nil->red && root->left == nil); - - int total = 1000; - struct check_data **all = check_safe_kmalloc(sizeof(struct check_data *) * total); - - long i; - for (i = 0; i < total; i ++) { - all[i] = check_safe_kmalloc(sizeof(struct check_data)); - all[i]->data = i; - } - - int *mark = check_safe_kmalloc(sizeof(int) * total); - memset(mark, 0, sizeof(int) * total); - - for (i = 0; i < total; i ++) { - mark[all[i]->data] = 1; - } - for (i = 0; i < total; i ++) { - assert(mark[i] == 1); - } - - for (i = 0; i < total; i ++) { - //int j = (rand() % (total - i)) + i; - int j = i + (total - i*i); - if(j < i) j = i; - if(j >= total) j = total -1; - struct check_data *z = all[i]; - all[i] = all[j]; - all[j] = z; - } - - memset(mark, 0, sizeof(int) * total); - for (i = 0; i < total; i ++) { - mark[all[i]->data] = 1; - } - for (i = 0; i < total; i ++) { - assert(mark[i] == 1); - } - - for (i = 0; i < total; i ++) { - rb_insert(tree, &(all[i]->rb_link)); - check_tree(tree, root->left); - } - - rb_node *node; - for (i = 0; i < total; i ++) { - node = rb_search(tree, check_compare2, (void *)(all[i]->data)); - assert(node != NULL && node == &(all[i]->rb_link)); - } - - for (i = 0; i < total; i ++) { - node = rb_search(tree, check_compare2, (void *)i); - assert(node != NULL && rbn2data(node)->data == i); - rb_delete(tree, node); - check_tree(tree, root->left); - } - - assert(!nil->red && root->left == nil); - - long max = 32; - if (max > total) { - max = total; - } - - for (i = 0; i < max; i ++) { - all[i]->data = max; - rb_insert(tree, &(all[i]->rb_link)); - check_tree(tree, root->left); - } - - for (i = 0; i < max; i ++) { - node = rb_search(tree, check_compare2, (void *)max); - assert(node != NULL && rbn2data(node)->data == max); - rb_delete(tree, node); - check_tree(tree, root->left); - } - - assert(rb_tree_empty(tree)); - - for (i = 0; i < total; i ++) { - rb_insert(tree, &(all[i]->rb_link)); - check_tree(tree, root->left); - } - - rb_tree_destroy(tree); - - for (i = 0; i < total; i ++) { - kfree(all[i]); - } - - kfree(mark); - kfree(all); -} - diff --git a/ucore-thumips/kern/libs/rb_tree.h b/ucore-thumips/kern/libs/rb_tree.h deleted file mode 100644 index a2aa9aa..0000000 --- a/ucore-thumips/kern/libs/rb_tree.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __KERN_LIBS_RB_TREE_H__ -#define __KERN_LIBS_RB_TREE_H__ - -#include - -typedef struct rb_node { - bool red; // if red = 0, it's a black node - struct rb_node *parent; - struct rb_node *left, *right; -} rb_node; - -typedef struct rb_tree { - // compare function should return -1 if *node1 < *node2, 1 if *node1 > *node2, and 0 otherwise - int (*compare)(rb_node *node1, rb_node *node2); - struct rb_node *nil, *root; -} rb_tree; - -rb_tree *rb_tree_create(int (*compare)(rb_node *node1, rb_node *node2)); -void rb_tree_destroy(rb_tree *tree); -void rb_insert(rb_tree *tree, rb_node *node); -void rb_delete(rb_tree *tree, rb_node *node); -rb_node *rb_search(rb_tree *tree, int (*compare)(rb_node *node, void *key), void *key); -rb_node *rb_node_prev(rb_tree *tree, rb_node *node); -rb_node *rb_node_next(rb_tree *tree, rb_node *node); -rb_node *rb_node_root(rb_tree *tree); -rb_node *rb_node_left(rb_tree *tree, rb_node *node); -rb_node *rb_node_right(rb_tree *tree, rb_node *node); - -void check_rb_tree(void); - -#endif /* !__KERN_LIBS_RBTREE_H__ */ - diff --git a/ucore-thumips/kern/libs/readline.c b/ucore-thumips/kern/libs/readline.c deleted file mode 100644 index 49cc0eb..0000000 --- a/ucore-thumips/kern/libs/readline.c +++ /dev/null @@ -1,50 +0,0 @@ -#include - -#define BUFSIZE 1024 -static char buf[BUFSIZE]; - -/* * - * readline - get a line from stdin - * @prompt: the string to be written to stdout - * - * The readline() function will write the input string @prompt to - * stdout first. If the @prompt is NULL or the empty string, - * no prompt is issued. - * - * This function will keep on reading characters and saving them to buffer - * 'buf' until '\n' or '\r' is encountered. - * - * Note that, if the length of string that will be read is longer than - * buffer size, the end of string will be discarded. - * - * The readline() function returns the text of the line read. If some errors - * are happened, NULL is returned. The return value is a global variable, - * thus it should be copied before it is used. - * */ -char * -readline(const char *prompt) { - if (prompt != NULL) { - kprintf(prompt); - } - int i = 0, c; - while (1) { - c = getchar(); - if (c < 0) { - return NULL; - } - else if (c >= ' ' && i < BUFSIZE - 1) { - kputchar(c); - buf[i ++] = c; - } - else if (c == '\b' && i > 0) { - kputchar(c); - i --; - } - else if (c == '\n' || c == '\r') { - kputchar(c); - buf[i] = '\0'; - return buf; - } - } -} - diff --git a/ucore-thumips/kern/libs/stdio.c b/ucore-thumips/kern/libs/stdio.c deleted file mode 100644 index 6c3cc91..0000000 --- a/ucore-thumips/kern/libs/stdio.c +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include -#include -#include - -/* HIGH level console I/O */ - -/* * - * cputch - writes a single character @c to stdout, and it will - * increace the value of counter pointed by @cnt. - * */ -static void -cputch(int c, int *cnt) { - cons_putc(c); - (*cnt) ++; -} -#if 0 -/* * - * kprintf - formats a string and writes it to stdout - * - * The return value is the number of characters which would be - * written to stdout. - * */ -int -kprintf(const char *str) { - int cnt = 0; - while(*str){ - kputchar(*str); - cnt++; - str++; - } - //va_start(ap, fmt); - //cnt = vkprintf(fmt, ap); - //va_end(ap); - return cnt; -} -#endif - -/* * - * vkprintf - format a string and writes it to stdout - * - * The return value is the number of characters which would be - * written to stdout. - * - * Call this function if you are already dealing with a va_list. - * Or you probably want kprintf() instead. - * */ -int -vkprintf(const char *fmt, va_list ap) { - int cnt = 0; - vprintfmt((void*)cputch, NO_FD, &cnt, fmt, ap); - return cnt; -} - -/* * - * kprintf - formats a string and writes it to stdout - * - * The return value is the number of characters which would be - * written to stdout. - * */ -int -kprintf(const char *fmt, ...) { - va_list ap; - int cnt; - va_start(ap, fmt); - cnt = vkprintf(fmt, ap); - va_end(ap); - return cnt; -} - - -static const char* hexdigits = "0123456789ABCDEF"; -void printhex(unsigned int x){ - char tmp[9]; - int i=0; - tmp[8] = 0; - for(i=7;i>=0;i--){ - tmp[i] = hexdigits[x & 0xf]; - x = x >> 4; - } - kprintf(tmp); -} - - - -void printbase10(int x){ - unsigned int t; - int i = 0; - char buf[16]; - if(x<0) - kputchar('-'); - x = (x<0)?-x:x; - while(x >= 10){ - t = __divu10(x); - buf[i++] = ('0'+(x-__mulu10(t))); - x = t; - } - buf[i] = ('0'+x); - for(;i>=0;i--){ - kputchar(buf[i]); - } -} - -/* kputchar - writes a single character to stdout */ -void -kputchar(int c) { - cons_putc(c); -} - -/* * - * kputs- writes the string pointed by @str to stdout and - * appends a newline character. - * */ -int -kputs(const char *str) { - int cnt = 0; - char c; - while ((c = *str ++) != '\0') { - cputch(c, &cnt); - } - cputch('\n', &cnt); - return cnt; -} - -/* getchar - reads a single non-zero character from stdin */ -int -getchar(void) { - int c; - while ((c = cons_getc()) == 0) - /* do nothing */; - return c; -} - diff --git a/ucore-thumips/kern/libs/stdio.h b/ucore-thumips/kern/libs/stdio.h deleted file mode 100644 index bfbfc93..0000000 --- a/ucore-thumips/kern/libs/stdio.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __LIBS_STDIO_H__ -#define __LIBS_STDIO_H__ - -#include -#include - -/* kern/libs/stdio.c */ -int vkprintf(const char *fmt, va_list ap); -int kprintf(const char *fmt, ...); -void kputchar(int c); -int kputs(const char *str); -int getchar(void); - -void printhex(unsigned int x); -void printbase10(int x); - -/* kern/libs/readline.c */ -char *readline(const char *prompt); - -#define PRINT_HEX(str,x) {kprintf(str);printhex((unsigned int)x);kprintf("\n");} - -#endif /* !__LIBS_STDIO_H__ */ - - diff --git a/ucore-thumips/kern/libs/stdlib.h b/ucore-thumips/kern/libs/stdlib.h deleted file mode 100644 index 8c4f730..0000000 --- a/ucore-thumips/kern/libs/stdlib.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __LIBS_STDLIB_H__ -#define __LIBS_STDLIB_H__ - -#include - -/* the largest number rand will return */ -#define RAND_MAX 0xFFFF - -/* libs/rand.c */ -int rand(void); -void srand(unsigned int seed); - -/* libs/hash.c */ -uint32_t hash32(uint32_t val, unsigned int bits); - -#endif /* !__LIBS_RAND_H__ */ - diff --git a/ucore-thumips/kern/libs/string.c b/ucore-thumips/kern/libs/string.c deleted file mode 100644 index f2a17db..0000000 --- a/ucore-thumips/kern/libs/string.c +++ /dev/null @@ -1,392 +0,0 @@ -#include -#include - -/* * - * strlen - calculate the length of the string @s, not including - * the terminating '\0' character. - * @s: the input string - * - * The strlen() function returns the length of string @s. - * */ -size_t -strlen(const char *s) { - size_t cnt = 0; - while (*s ++ != '\0') { - cnt ++; - } - return cnt; -} - -/* * - * strnlen - calculate the length of the string @s, not including - * the terminating '\0' char acter, but at most @len. - * @s: the input string - * @len: the max-length that function will scan - * - * Note that, this function looks only at the first @len characters - * at @s, and never beyond @s + @len. - * - * The return value is strlen(s), if that is less than @len, or - * @len if there is no '\0' character among the first @len characters - * pointed by @s. - * */ -size_t -strnlen(const char *s, size_t len) { - size_t cnt = 0; - while (cnt < len && *s ++ != '\0') { - cnt ++; - } - return cnt; -} - -/* * - * strcpy - copies the string pointed by @src into the array pointed by @dst, - * including the terminating null character. - * @dst: pointer to the destination array where the content is to be copied - * @src: string to be copied - * - * The return value is @dst. - * - * To avoid overflows, the size of array pointed by @dst should be long enough to - * contain the same string as @src (including the terminating null character), and - * should not overlap in memory with @src. - * */ -char * -strcpy(char *dst, const char *src) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __strcpy(dst, src); -#else - char *p = dst; - while ((*p ++ = *src ++) != '\0') - /* nothing */; - return dst; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * strncpy - copies the first @len characters of @src to @dst. If the end of string @src - * if found before @len characters have been copied, @dst is padded with '\0' until a - * total of @len characters have been written to it. - * @dst: pointer to the destination array where the content is to be copied - * @src: string to be copied - * @len: maximum number of characters to be copied from @src - * - * The return value is @dst - * */ -char * -strncpy(char *dst, const char *src, size_t len) { - char *p = dst; - while (len > 0) { - if ((*p = *src) != '\0') { - src ++; - } - p ++, len --; - } - return dst; -} - -/* * - * strcmp - compares the string @s1 and @s2 - * @s1: string to be compared - * @s2: string to be compared - * - * This function starts comparing the first character of each string. If - * they are equal to each other, it continues with the following pairs until - * the characters differ or until a terminanting null-character is reached. - * - * Returns an integral value indicating the relationship between the strings: - * - A zero value indicates that both strings are equal; - * - A value greater than zero indicates that the first character that does - * not match has a greater value in @s1 than in @s2; - * - And a value less than zero indicates the opposite. - * */ -int -strcmp(const char *s1, const char *s2) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __strcmp(s1, s2); -#else - while (*s1 != '\0' && *s1 == *s2) { - s1 ++, s2 ++; - } - return (int)((unsigned char)*s1 - (unsigned char)*s2); -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * strncmp - compares up to @n characters of the string @s1 to those of the string @s2 - * @s1: string to be compared - * @s2: string to be compared - * @n: maximum number of characters to compare - * - * This function starts comparing the first character of each string. If - * they are equal to each other, it continues with the following pairs until - * the characters differ, until a terminating null-character is reached, or - * until @n characters match in both strings, whichever happens first. - * */ -int -strncmp(const char *s1, const char *s2, size_t n) { - while (n > 0 && *s1 != '\0' && *s1 == *s2) { - n --, s1 ++, s2 ++; - } - return (n == 0) ? 0 : (int)((unsigned char)*s1 - (unsigned char)*s2); -} - -/* * - * strchr - locates first occurrence of character in string - * @s: the input string - * @c: character to be located - * - * The strchr() function returns a pointer to the first occurrence of - * character in @s. If the value is not found, the function returns 'NULL'. - * */ -char * -strchr(const char *s, char c) { - while (*s != '\0') { - if (*s == c) { - return (char *)s; - } - s ++; - } - return NULL; -} - -/* * - * strfind - locates first occurrence of character in string - * @s: the input string - * @c: character to be located - * - * The strfind() function is like strchr() except that if @c is - * not found in @s, then it returns a pointer to the null byte at the - * end of @s, rather than 'NULL'. - * */ -char * -strfind(const char *s, char c) { - while (*s != '\0') { - if (*s == c) { - break; - } - s ++; - } - return (char *)s; -} - -/* * - * strtol - converts string to long integer - * @s: the input string that contains the representation of an integer number - * @endptr: reference to an object of type char *, whose value is set by the - * function to the next character in @s after the numerical value. This - * parameter can also be a null pointer, in which case it is not used. - * @base: x - * - * The function first discards as many whitespace characters as necessary until - * the first non-whitespace character is found. Then, starting from this character, - * takes as many characters as possible that are valid following a syntax that - * depends on the base parameter, and interprets them as a numerical value. Finally, - * a pointer to the first character following the integer representation in @s - * is stored in the object pointed by @endptr. - * - * If the value of base is zero, the syntax expected is similar to that of - * integer constants, which is formed by a succession of: - * - An optional plus or minus sign; - * - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively) - * - A sequence of decimal digits (if no base prefix was specified) or either octal - * or hexadecimal digits if a specific prefix is present - * - * If the base value is between 2 and 36, the format expected for the integral number - * is a succession of the valid digits and/or letters needed to represent integers of - * the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The - * sequence may optionally be preceded by a plus or minus sign and, if base is 16, - * an optional "0x" or "0X" prefix. - * - * The strtol() function returns the converted integral number as a long int value. - * */ -#if 0 -long -strtol(const char *s, char **endptr, int base) { - int neg = 0; - long val = 0; - - // gobble initial whitespace - while (*s == ' ' || *s == '\t') { - s ++; - } - - // plus/minus sign - if (*s == '+') { - s ++; - } - else if (*s == '-') { - s ++, neg = 1; - } - - // hex or octal base prefix - if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) { - s += 2, base = 16; - } - else if (base == 0 && s[0] == '0') { - s ++, base = 8; - } - else if (base == 0) { - base = 10; - } - - // digits - while (1) { - int dig; - - if (*s >= '0' && *s <= '9') { - dig = *s - '0'; - } - else if (*s >= 'a' && *s <= 'z') { - dig = *s - 'a' + 10; - } - else if (*s >= 'A' && *s <= 'Z') { - dig = *s - 'A' + 10; - } - else { - break; - } - if (dig >= base) { - break; - } - s ++, val = (val * base) + dig; - // we don't properly detect overflow! - } - - if (endptr) { - *endptr = (char *) s; - } - return (neg ? -val : val); -} -#endif - -/* * - * memset - sets the first @n bytes of the memory area pointed by @s - * to the specified value @c. - * @s: pointer the the memory area to fill - * @c: value to set - * @n: number of bytes to be set to the value - * - * The memset() function returns @s. - * */ -void * -memset(void *s, char c, size_t n) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __memset(s, c, n); -#else - char *p = s; - while (n -- > 0) { - *p ++ = c; - } - return s; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * memcpy - copies the value of @n bytes from the location pointed by @src to - * the memory area pointed by @dst. - * @dst pointer to the destination array where the content is to be copied - * @src pointer to the source of data to by copied - * @n: number of bytes to copy - * - * The memcpy() returns @dst. - * - * Note that, the function does not check any terminating null character in @src, - * it always copies exactly @n bytes. To avoid overflows, the size of arrays pointed - * by both @src and @dst, should be at least @n bytes, and should not overlap - * (for overlapping memory area, memmove is a safer approach). - * */ -void * -memcpy(void *dst, const void *src, size_t n) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __memcpy(dst, src, n); -#else - const char *s = src; - char *d = dst; - while (n -- > 0) { - *d ++ = *s ++; - } - return dst; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * memmove - copies the values of @n bytes from the location pointed by @src to - * the memory area pointed by @dst. @src and @dst are allowed to overlap. - * @dst pointer to the destination array where the content is to be copied - * @src pointer to the source of data to by copied - * @n: number of bytes to copy - * - * The memmove() function returns @dst. - * */ -void * -memmove(void *dst, const void *src, size_t n) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __memmove(dst, src, n); -#else - const char *s = src; - char *d = dst; - if (s < d && s + n > d) { - s += n, d += n; - while (n -- > 0) { - *-- d = *-- s; - } - } else { - while (n -- > 0) { - *d ++ = *s ++; - } - } - return dst; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * memcmp - compares two blocks of memory - * @v1: pointer to block of memory - * @v2: pointer to block of memory - * @n: number of bytes to compare - * - * The memcmp() functions returns an integral value indicating the - * relationship between the content of the memory blocks: - * - A zero value indicates that the contents of both memory blocks are equal; - * - A value greater than zero indicates that the first byte that does not - * match in both memory blocks has a greater value in @v1 than in @v2 - * as if evaluated as unsigned char values; - * - And a value less than zero indicates the opposite. - * */ -int -memcmp(const void *v1, const void *v2, size_t n) { - const char *s1 = (const char *)v1; - const char *s2 = (const char *)v2; - while (n -- > 0) { - if (*s1 != *s2) { - return (int)((unsigned char)*s1 - (unsigned char)*s2); - } - s1 ++, s2 ++; - } - return 0; -} - -char * -strdup(const char *src) { - char *dst; - size_t len = strlen(src); - if ((dst = kmalloc(len + 1)) != NULL) { - memcpy(dst, src, len); - dst[len] = '\0'; - } - return dst; -} - -char * -stradd(const char *src1, const char *src2) { - char *ret, *dst; - size_t len1 = strlen(src1), len2 = strlen(src2); - if ((ret = dst = kmalloc(len1 + len2 + 1)) != NULL) { - memcpy(dst, src1, len1), dst += len1; - memcpy(dst, src2, len2), dst += len2; - *dst = '\0'; - } - return ret; -} - diff --git a/ucore-thumips/kern/libs/string.h b/ucore-thumips/kern/libs/string.h deleted file mode 100644 index a046bdf..0000000 --- a/ucore-thumips/kern/libs/string.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __LIBS_STRING_H__ -#define __LIBS_STRING_H__ - -#include - -size_t strlen(const char *s); -size_t strnlen(const char *s, size_t len); - -char *strcpy(char *dst, const char *src); -char *strncpy(char *dst, const char *src, size_t len); - -int strcmp(const char *s1, const char *s2); -int strncmp(const char *s1, const char *s2, size_t n); - -char *strchr(const char *s, char c); -char *strfind(const char *s, char c); -//long strtol(const char *s, char **endptr, int base); - -void *memset(void *s, char c, size_t n); -void *memmove(void *dst, const void *src, size_t n); -void *memcpy(void *dst, const void *src, size_t n); -int memcmp(const void *v1, const void *v2, size_t n); - -char * strdup(const char *src); - -#endif /* !__LIBS_STRING_H__ */ - diff --git a/ucore-thumips/kern/mm/buddy_pmm.c b/ucore-thumips/kern/mm/buddy_pmm.c deleted file mode 100644 index a5b0546..0000000 --- a/ucore-thumips/kern/mm/buddy_pmm.c +++ /dev/null @@ -1,325 +0,0 @@ - -#include -#include -#include -#include -#include - -/* The buddy memory allocation technique is a memory allocation algorithm that divides memory into partitions - to try to satisfy a memory request as suitably as possible. This system makes use of splitting memory into halves - to try to give a best-fit. - - The "Buddy System" algorithm in ucore is drived from: - 1 Page 203~206, Section 8.4 of Yan Wei Ming's chinese book "Data Structure -- C programming language" - 2 Algorithm R & S of section 2.5 of Volume 1 of Knuth's "The Art of Computer Programming", with note taken - of exercises 25 and 29 of that section. - - In a buddy system, the entire memory space available for allocation is initially treated as a single block whose size - is a power of 2. When the first request is made, if its size is greater than half of the initial block then the entire - block is allocated. Otherwise, the block is split in two equal companion buddies. If the size of the request is greater - than half of one of the buddies, then allocate one to it. Otherwise, one of the buddies is split in half again. This - method continues until the smallest block greater than or equal to the size of the request is found and allocated to it. - - In this method, when a process terminates the buddy block that was allocated to it is freed. Whenever possible, an - unnallocated buddy is merged with a companion buddy in order to form a larger free block. Two blocks are said to be - companion buddies if they resulted from the split of the same direct parent block. -*/ - -// {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024} -// from 2^0 ~ 2^10 -#define MAX_ORDER 10 -static free_area_t free_area[MAX_ORDER + 1]; - -//x from 0 ~ MAX_ORDER -#define free_list(x) (free_area[x].free_list) -#define nr_free(x) (free_area[x].nr_free) - -#define MAX_ZONE_NUM 10 -struct Zone { - struct Page *mem_base; -} zones[MAX_ZONE_NUM] = {{NULL}}; - -//buddy_init - init the free_list(0 ~ MAX_ORDER) & reset nr_free(0 ~ MAX_ORDER) -static void -buddy_init(void) { - int i; - for (i = 0; i <= MAX_ORDER; i ++) { - list_init(&free_list(i)); - nr_free(i) = 0; - } -} - -//buddy_init_memmap - build free_list for Page base follow n continuous pages. -static void -buddy_init_memmap(struct Page *base, size_t n) { - static int zone_num = 0; - assert(n > 0 && zone_num < MAX_ZONE_NUM); - struct Page *p = base; - for (; p != base + n; p ++) { - assert(PageReserved(p)); - p->flags = p->property = 0; - p->zone_num = zone_num; - set_page_ref(p, 0); - } - p = zones[zone_num ++].mem_base = base; - size_t order = MAX_ORDER, order_size = (1 << order); - while (n != 0) { - while (n >= order_size) { - p->property = order; - SetPageProperty(p); - list_add(&free_list(order), &(p->page_link)); - n -= order_size, p += order_size; - nr_free(order) ++; - } - order --; - order_size >>= 1; - } -} - -//getorder - return order, the minmal 2^order >= n -static inline size_t -getorder(size_t n) { - size_t order, order_size; - for (order = 0, order_size = 1; order <= MAX_ORDER; order ++, order_size <<= 1) { - if (n <= order_size) { - return order; - } - } - panic("getorder failed. %d\n", n); -} - -//buddy_alloc_pages_sub - the actual allocation implimentation, return a page whose size >=n, -// - the remaining free parts insert to other free list -static inline struct Page * -buddy_alloc_pages_sub(size_t order) { - assert(order <= MAX_ORDER); - size_t cur_order; - for (cur_order = order; cur_order <= MAX_ORDER; cur_order ++) { - if (!list_empty(&free_list(cur_order))) { - list_entry_t *le = list_next(&free_list(cur_order)); - struct Page *page = le2page(le, page_link); - nr_free(cur_order) --; - list_del(le); - size_t size = 1 << cur_order; - while (cur_order > order) { - cur_order --; - size >>= 1; - struct Page *buddy = page + size; - buddy->property = cur_order; - SetPageProperty(buddy); - nr_free(cur_order) ++; - list_add(&free_list(cur_order), &(buddy->page_link)); - } - ClearPageProperty(page); - return page; - } - } - return NULL; -} - -//buddy_alloc_pages - call buddy_alloc_pages_sub to alloc 2^order>=n pages -static struct Page * -buddy_alloc_pages(size_t n) { - assert(n > 0); - size_t order = getorder(n), order_size = (1 << order); - struct Page *page = buddy_alloc_pages_sub(order); - if (page != NULL && n != order_size) { - free_pages(page + n, order_size - n); - } - return page; -} - -//page_is_buddy - Does this page belong to the No. zone_num Zone & this page -// - be in the continuous page block whose size is 2^order pages? -static inline bool -page_is_buddy(struct Page *page, size_t order, int zone_num) { - if (page2ppn(page) < npage) { - if (page->zone_num == zone_num) { - return !PageReserved(page) && PageProperty(page) && page->property == order; - } - } - return 0; -} - -//page2idx - get the related index number idx of continuous page block which this page belongs to -static ppn_t -page2idx(struct Page *page) { - return page - zones[page->zone_num].mem_base; -} - -//idx2page - get the related page according to the index number idx of continuous page block -static struct Page * -idx2page(int zone_num, ppn_t idx) { - return zones[zone_num].mem_base + idx; -} - -//buddy_free_pages_sub - the actual free implimentation, should consider how to -// - merge the adjacent buddy block -static void -buddy_free_pages_sub(struct Page *base, size_t order) { - ppn_t buddy_idx, page_idx = page2idx(base); - assert((page_idx & ((1 << order) - 1)) == 0); - struct Page *p = base; - for (; p != base + (1 << order); p ++) { - assert(!PageReserved(p) && !PageProperty(p)); - p->flags = 0; - set_page_ref(p, 0); - } - int zone_num = base->zone_num; - while (order < MAX_ORDER) { - buddy_idx = page_idx ^ (1 << order); - struct Page *buddy = idx2page(zone_num, buddy_idx); - if (!page_is_buddy(buddy, order, zone_num)) { - break; - } - nr_free(order) --; - list_del(&(buddy->page_link)); - ClearPageProperty(buddy); - page_idx &= buddy_idx; - order ++; - } - struct Page *page = idx2page(zone_num, page_idx); - page->property = order; - SetPageProperty(page); - nr_free(order) ++; - list_add(&free_list(order), &(page->page_link)); -} - -//buddy_free_pages - call buddy_free_pages_sub to free n continuous page block -static void -buddy_free_pages(struct Page *base, size_t n) { - assert(n > 0); - if (n == 1) { - buddy_free_pages_sub(base, 0); - } - else { - size_t order = 0, order_size = 1; - while (n >= order_size) { - assert(order <= MAX_ORDER); - if ((page2idx(base) & order_size) != 0) { - buddy_free_pages_sub(base, order); - base += order_size; - n -= order_size; - } - order ++; - order_size <<= 1; - } - while (n != 0) { - while (n < order_size) { - order --; - order_size >>= 1; - } - buddy_free_pages_sub(base, order); - base += order_size; - n -= order_size; - } - } -} - -//buddy_nr_free_pages - get the nr: the number of free pages -static size_t -buddy_nr_free_pages(void) { - size_t ret = 0, order = 0; - for (; order <= MAX_ORDER; order ++) { - ret += nr_free(order) * (1 << order); - } - return ret; -} - -//buddy_check - check the correctness of buddy system -static void -buddy_check(void) { - int i; - int count = 0, total = 0; - for (i = 0; i <= MAX_ORDER; i ++) { - list_entry_t *list = &free_list(i), *le = list; - while ((le = list_next(le)) != list) { - struct Page *p = le2page(le, page_link); - assert(PageProperty(p) && p->property == i); - count ++, total += (1 << i); - } - } - assert(total == nr_free_pages()); - - struct Page *p0 = alloc_pages(8), *buddy = alloc_pages(8), *p1; - - assert(p0 != NULL); - assert((page2idx(p0) & 7) == 0); - assert(!PageProperty(p0)); - - list_entry_t free_lists_store[MAX_ORDER + 1]; - unsigned int nr_free_store[MAX_ORDER + 1]; - - for (i = 0; i <= MAX_ORDER; i ++) { - free_lists_store[i] = free_list(i); - list_init(&free_list(i)); - assert(list_empty(&free_list(i))); - nr_free_store[i] = nr_free(i); - nr_free(i) = 0; - } - - assert(nr_free_pages() == 0); - assert(alloc_page() == NULL); - free_pages(p0, 8); - assert(nr_free_pages() == 8); - assert(PageProperty(p0) && p0->property == 3); - assert((p0 = alloc_pages(6)) != NULL && !PageProperty(p0) && nr_free_pages() == 2); - - assert((p1 = alloc_pages(2)) != NULL && p1 == p0 + 6); - assert(nr_free_pages() == 0); - - free_pages(p0, 3); - assert(PageProperty(p0) && p0->property == 1); - assert(PageProperty(p0 + 2) && p0[2].property == 0); - - free_pages(p0 + 3, 3); - free_pages(p1, 2); - - assert(PageProperty(p0) && p0->property == 3); - - assert((p0 = alloc_pages(6)) != NULL); - assert((p1 = alloc_pages(2)) != NULL); - free_pages(p0 + 4, 2); - free_pages(p1, 2); - - p1 = p0 + 4; - assert(PageProperty(p1) && p1->property == 2); - free_pages(p0, 4); - assert(PageProperty(p0) && p0->property == 3); - - assert((p0 = alloc_pages(8)) != NULL); - assert(alloc_page() == NULL && nr_free_pages() == 0); - - for (i = 0; i <= MAX_ORDER; i ++) { - free_list(i) = free_lists_store[i]; - nr_free(i) = nr_free_store[i]; - } - - free_pages(p0, 8); - free_pages(buddy, 8); - - assert(total == nr_free_pages()); - - for (i = 0; i <= MAX_ORDER; i ++) { - list_entry_t *list = &free_list(i), *le = list; - while ((le = list_next(le)) != list) { - struct Page *p = le2page(le, page_link); - assert(PageProperty(p) && p->property == i); - count --, total -= (1 << i); - } - } - assert(count == 0); - assert(total == 0); -} - -//the buddy system pmm -const struct pmm_manager buddy_pmm_manager = { - .name = "buddy_pmm_manager", - .init = buddy_init, - .init_memmap = buddy_init_memmap, - .alloc_pages = buddy_alloc_pages, - .free_pages = buddy_free_pages, - .nr_free_pages = buddy_nr_free_pages, - .check = buddy_check, -}; - diff --git a/ucore-thumips/kern/mm/buddy_pmm.h b/ucore-thumips/kern/mm/buddy_pmm.h deleted file mode 100644 index 25ce1ed..0000000 --- a/ucore-thumips/kern/mm/buddy_pmm.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __KERN_MM_BUDDY_PMM_H__ -#define __KERN_MM_BUDDY_PMM_H__ - -#include - -extern const struct pmm_manager buddy_pmm_manager; - -#endif /* !__KERN_MM_BUDDY_PMM_H__ */ - diff --git a/ucore-thumips/kern/mm/kmalloc.c b/ucore-thumips/kern/mm/kmalloc.c deleted file mode 100644 index 01c91b6..0000000 --- a/ucore-thumips/kern/mm/kmalloc.c +++ /dev/null @@ -1,659 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* IMPORTANT: Do NOT modify any constants in this file!!! (FOR thumips) */ - -/* The slab allocator used in ucore is based on an algorithm first introduced by - Jeff Bonwick for the SunOS operating system. The paper can be download from - http://citeseer.ist.psu.edu/bonwick94slab.html - An implementation of the Slab Allocator as described in outline in; - UNIX Internals: The New Frontiers by Uresh Vahalia - Pub: Prentice Hall ISBN 0-13-101908-2 - Within a kernel, a considerable amount of memory is allocated for a finite set - of objects such as file descriptors and other common structures. Jeff found that - the amount of time required to initialize a regular object in the kernel exceeded - the amount of time required to allocate and deallocate it. His conclusion was - that instead of freeing the memory back to a global pool, he would have the memory - remain initialized for its intended purpose. - In our simple slab implementation, the the high-level organization of the slab - structures is simplied. At the highest level is an array slab_cache[SLAB_CACHE_NUM], - and each array element is a slab_cache which has slab chains. Each slab_cache has - two list, one list chains the full allocated slab, and another list chains the notfull - allocated(maybe empty) slab. And each slab has fixed number(2^n) of pages. In each - slab, there are a lot of objects (such as ) with same fixed size(32B ~ 128KB). - - +----------------------------------+ - | slab_cache[0] for 0~32B obj | - +----------------------------------+ - | slab_cache[1] for 33B~64B obj |-->lists for slabs - +----------------------------------+ | - | slab_cache[2] for 65B~128B obj | | - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | - +----------------------------------+ | - | slab_cache[12]for 64KB~128KB obj | | - +----------------------------------+ | - | - slabs_full/slabs_not +---------------------+ - -<-----------<----------<-+ - | | | - slab1 slab2 slab3... - | - |-------|-------| - pages1 pages2 pages3... - | - | - | - slab_t+n*bufctl_t+obj1-obj2-obj3...objn (the size of obj is small) - | - OR - | - obj1-obj2-obj3...objn WITH slab_t+n*bufctl_t in another slab (the size of obj is BIG) - - The important functions are: - kmem_cache_grow(kmem_cache_t *cachep) - kmem_slab_destroy(kmem_cache_t *cachep, slab_t *slabp) - kmalloc(size_t size): used by outside functions need dynamicly get memory - kfree(void *objp): used by outside functions need dynamicly release memory -*/ - -#define BUFCTL_END 0xFFFFFFFFL // the signature of the last bufctl -#define SLAB_LIMIT 0xFFFFFFFEL // the max value of obj number - -typedef size_t kmem_bufctl_t; //the index of obj in slab - -typedef struct slab_s { - list_entry_t slab_link; // the list entry linked to kmem_cache list - void *s_mem; // the kernel virtual address of the first obj in slab - size_t inuse; // the number of allocated objs - size_t offset; // the first obj's offset value in slab - kmem_bufctl_t free; // the first free obj's index in slab -} slab_t; - -// get the slab address according to the link element (see list.h) -#define le2slab(le, member) \ - to_struct((le), slab_t, member) - -typedef struct kmem_cache_s kmem_cache_t; - - -struct kmem_cache_s { - list_entry_t slabs_full; // list for fully allocated slabs - list_entry_t slabs_notfull; // list for not-fully allocated slabs - - size_t objsize; // the fixed size of obj - size_t objsize_shift; - size_t num; // number of objs per slab - size_t offset; // this first obj's offset in slab - bool off_slab; // the control part of slab in slab or not. - - /* order of pages per slab (2^n) */ - size_t page_order; - - kmem_cache_t *slab_cachep; -}; - -#define MIN_SIZE_ORDER 5 // 32 -#define MAX_SIZE_ORDER 17 // 128k -#define SLAB_CACHE_NUM (MAX_SIZE_ORDER - MIN_SIZE_ORDER + 1) - -static kmem_cache_t slab_cache[SLAB_CACHE_NUM]; - -static void init_kmem_cache(kmem_cache_t *cachep, size_t objsize); -static void check_slab(void); - -#define ALIGN_SHIFT 4 - -//slab_init - call init_kmem_cache function to reset the slab_cache array -static void -slab_init(void) { - size_t i; - //the align bit for obj in slab. 2^n could be better for performance - //size_t align = 16; - for (i = 0; i < SLAB_CACHE_NUM; i ++) { - init_kmem_cache(slab_cache + i, 1 << (i + MIN_SIZE_ORDER)); - } - check_slab(); -} - -inline void -kmalloc_init(void) { - slab_init(); - kprintf("kmalloc_init() succeeded!\n"); -} - -//slab_allocated - summary the total size of allocated objs -static size_t -slab_allocated(void) { - size_t total = 0; - int i; - bool intr_flag; - local_intr_save(intr_flag); - { - for (i = 0; i < SLAB_CACHE_NUM; i ++) { - kmem_cache_t *cachep = slab_cache + i; - list_entry_t *list, *le; - list = le = &(cachep->slabs_full); - while ((le = list_next(le)) != list) { - total += cachep->num * cachep->objsize; - } - list = le = &(cachep->slabs_notfull); - while ((le = list_next(le)) != list) { - slab_t *slabp = le2slab(le, slab_link); - total += slabp->inuse * cachep->objsize; - } - } - } - local_intr_restore(intr_flag); - return total; -} - -inline size_t -kallocated(void) { - return slab_allocated(); -} - -// slab_mgmt_size - get the size of slab control area (slab_t+num*kmem_bufctl_t) -static size_t -slab_mgmt_size(size_t num) { - return ROUNDUP_2N(sizeof(slab_t) + num * sizeof(kmem_bufctl_t), ALIGN_SHIFT); -} - - -static int __slab_div_table[/* order */][/* objsize_shift-5 */ 8] = { - {113, 59, 30, 15}, -}; - -// cacahe_estimate - estimate the number of objs in a slab -static void -cache_estimate(size_t order, size_t objsize_shift, bool off_slab, size_t *remainder, size_t *num) { - size_t nr_objs, mgmt_size; - size_t slab_size = (PGSIZE << order); - size_t objsize = 1<> objsize_shift; - if (nr_objs > SLAB_LIMIT) { - nr_objs = SLAB_LIMIT; - } - } - else { - /* no div! precomputed */ - //panic("no div, precompute?"); - //nr_objs = (slab_size - sizeof(slab_t)) / (objsize + sizeof(kmem_bufctl_t)); - nr_objs = __slab_div_table[order][objsize_shift - 5]; - while (slab_mgmt_size(nr_objs) + nr_objs * objsize > slab_size) { - nr_objs --; - } - if (nr_objs > SLAB_LIMIT) { - nr_objs = SLAB_LIMIT; - } - mgmt_size = slab_mgmt_size(nr_objs); - } - *num = nr_objs; - *remainder = slab_size - nr_objs * objsize - mgmt_size; -} - -// calculate_slab_order - estimate the size(4K~4M) of slab -// paramemters: -// cachep: the slab_cache -// objsize: the size of obj -// align: align bit for objs -// off_slab: the control part of slab in slab or not -// left_over: the size of can not be used area in slab -static void -calculate_slab_order(kmem_cache_t *cachep, size_t objsize_shift, bool off_slab, size_t *left_over) { - size_t order; - size_t objsize = 1 << objsize_shift; - for (order = 0; order <= KMALLOC_MAX_ORDER; order ++) { - size_t num, remainder; - cache_estimate(order, objsize_shift, off_slab, &remainder, &num); - if (num != 0) { - if (off_slab) { - size_t off_slab_limit = objsize - sizeof(slab_t); - /* sizeof(kmem_cache_t) == 4 */ - off_slab_limit /= sizeof(kmem_bufctl_t); - if (num > off_slab_limit) { - panic("off_slab: objsize = %d, num = %d.", objsize, num); - } - } - if (remainder * 8 <= (PGSIZE << order)) { - cachep->num = num; - cachep->page_order = order; - if (left_over != NULL) { - *left_over = remainder; - } - return ; - } - } - } - panic("calculate_slab_over: failed."); -} - -// getorder - find order, should satisfy n <= minest 2^order -static inline size_t -getorder(size_t n) { - size_t order = MIN_SIZE_ORDER, order_size = (1 << order); - for (; order <= MAX_SIZE_ORDER; order ++, order_size <<= 1) { - if (n <= order_size) { - return order; - } - } - panic("getorder failed. %d\n", n); -} - - -// init_kmem_cache - initial a slab_cache cachep according to the obj with the size = objsize -static void -init_kmem_cache(kmem_cache_t *cachep, size_t objsize) { - list_init(&(cachep->slabs_full)); - list_init(&(cachep->slabs_notfull)); - - objsize = ROUNDUP_2N(objsize, ALIGN_SHIFT); - cachep->objsize = objsize; - cachep->off_slab = (objsize >= (PGSIZE >> 3)); -// cachep->off_slab = 1; - cachep->objsize_shift = getorder(objsize); - - size_t left_over; - calculate_slab_order(cachep, cachep->objsize_shift, cachep->off_slab, &left_over); - - assert(cachep->num > 0); - - size_t mgmt_size = slab_mgmt_size(cachep->num); - - if (cachep->off_slab && left_over >= mgmt_size) { - cachep->off_slab = 0; - } - - if (cachep->off_slab) { - cachep->offset = 0; - cachep->slab_cachep = slab_cache + (getorder(mgmt_size) - MIN_SIZE_ORDER); - } - else { - cachep->offset = mgmt_size; - } -} - -static void *kmem_cache_alloc(kmem_cache_t *cachep); - -#define slab_bufctl(slabp) \ - ((kmem_bufctl_t*)(((slab_t *)(slabp)) + 1)) - -// kmem_cache_slabmgmt - get the address of a slab according to page -// - and initialize the slab according to cachep -static slab_t * -kmem_cache_slabmgmt(kmem_cache_t *cachep, struct Page *page) { - void *objp = page2kva(page); - slab_t *slabp; - if (cachep->off_slab) { - if ((slabp = kmem_cache_alloc(cachep->slab_cachep)) == NULL) { - return NULL; - } - } - else { - slabp = page2kva(page); - } - slabp->inuse = 0; - slabp->offset = cachep->offset; - slabp->s_mem = objp + cachep->offset; - return slabp; -} - -#define SET_PAGE_CACHE(page, cachep) \ - do { \ - struct Page *__page = (struct Page *)(page); \ - kmem_cache_t **__cachepp = (kmem_cache_t **)&(__page->page_link.next); \ - *__cachepp = (kmem_cache_t *)(cachep); \ - } while (0) - -#define SET_PAGE_SLAB(page, slabp) \ - do { \ - struct Page *__page = (struct Page *)(page); \ - slab_t **__cachepp = (slab_t **)&(__page->page_link.prev); \ - *__cachepp = (slab_t *)(slabp); \ - } while (0) - -// kmem_cache_grow - allocate a new slab by calling alloc_pages -// - set control area in the new slab -static bool -kmem_cache_grow(kmem_cache_t *cachep) { - struct Page *page = alloc_pages(1 << cachep->page_order); - if (page == NULL) { - goto failed; - } - - slab_t *slabp; - if ((slabp = kmem_cache_slabmgmt(cachep, page)) == NULL) { - goto oops; - } - - size_t order_size = (1 << cachep->page_order); - do { - //setup this page in the free list (see memlayout.h: struct page)??? - SET_PAGE_CACHE(page, cachep); - SET_PAGE_SLAB(page, slabp); - //this page is used for slab - SetPageSlab(page); - page ++; - } while (-- order_size); - - int i; - for (i = 0; i < cachep->num; i ++) { - slab_bufctl(slabp)[i] = i + 1; - } - slab_bufctl(slabp)[cachep->num - 1] = BUFCTL_END; - slabp->free = 0; - - bool intr_flag; - local_intr_save(intr_flag); - { - list_add(&(cachep->slabs_notfull), &(slabp->slab_link)); - } - local_intr_restore(intr_flag); - return 1; - -oops: - free_pages(page, 1 << cachep->page_order); -failed: - return 0; -} - -// kmem_cache_alloc_one - allocate a obj in a slab -static void * -kmem_cache_alloc_one(kmem_cache_t *cachep, slab_t *slabp) { - slabp->inuse ++; - void *objp = slabp->s_mem + slabp->free * cachep->objsize; - slabp->free = slab_bufctl(slabp)[slabp->free]; - - if (slabp->free == BUFCTL_END) { - list_del(&(slabp->slab_link)); - list_add(&(cachep->slabs_full), &(slabp->slab_link)); - } - return objp; -} - -// kmem_cache_alloc - call kmem_cache_alloc_one function to allocate a obj -// - if no free obj, try to allocate a slab -static void * -kmem_cache_alloc(kmem_cache_t *cachep) { - void *objp; - bool intr_flag; - -try_again: - local_intr_save(intr_flag); - if (list_empty(&(cachep->slabs_notfull))) { - goto alloc_new_slab; - } - slab_t *slabp = le2slab(list_next(&(cachep->slabs_notfull)), slab_link); - objp = kmem_cache_alloc_one(cachep, slabp); - local_intr_restore(intr_flag); - return objp; - -alloc_new_slab: - local_intr_restore(intr_flag); - - if (kmem_cache_grow(cachep)) { - goto try_again; - } - return NULL; -} - -// kmalloc - simple interface used by outside functions -// - to allocate a free memory using kmem_cache_alloc function -void * -kmalloc(size_t size) { - assert(size > 0); - size_t order = getorder(size); - if (order > MAX_SIZE_ORDER) { - return NULL; - } - return kmem_cache_alloc(slab_cache + (order - MIN_SIZE_ORDER)); -} - -static void kmem_cache_free(kmem_cache_t *cachep, void *obj); - -// kmem_slab_destroy - call free_pages & kmem_cache_free to free a slab -static void -kmem_slab_destroy(kmem_cache_t *cachep, slab_t *slabp) { - struct Page *page = kva2page(slabp->s_mem - slabp->offset); - - struct Page *p = page; - size_t order_size = (1 << cachep->page_order); - do { - assert(PageSlab(p)); - ClearPageSlab(p); - p ++; - } while (-- order_size); - - free_pages(page, 1 << cachep->page_order); - - if (cachep->off_slab) { - kmem_cache_free(cachep->slab_cachep, slabp); - } -} - -// kmem_cache_free_one - free an obj in a slab -// - if slab->inuse==0, then free the slab -static void -kmem_cache_free_one(kmem_cache_t *cachep, slab_t *slabp, void *objp) { - //should not use divide operator ??? - size_t objnr = (objp - slabp->s_mem) >> cachep->objsize_shift; - slab_bufctl(slabp)[objnr] = slabp->free; - slabp->free = objnr; - - slabp->inuse --; - - if (slabp->inuse == 0) { - list_del(&(slabp->slab_link)); - kmem_slab_destroy(cachep, slabp); - } - else if (slabp->inuse == cachep->num -1 ) { - list_del(&(slabp->slab_link)); - list_add(&(cachep->slabs_notfull), &(slabp->slab_link)); - } -} - -#define GET_PAGE_CACHE(page) \ - (kmem_cache_t *)((page)->page_link.next) - -#define GET_PAGE_SLAB(page) \ - (slab_t *)((page)->page_link.prev) - -// kmem_cache_free - call kmem_cache_free_one function to free an obj -static void -kmem_cache_free(kmem_cache_t *cachep, void *objp) { - bool intr_flag; - struct Page *page = kva2page(objp); - - if (!PageSlab(page)) { - panic("not a slab page %08x\n", objp); - } - local_intr_save(intr_flag); - { - kmem_cache_free_one(cachep, GET_PAGE_SLAB(page), objp); - } - local_intr_restore(intr_flag); -} - -// kfree - simple interface used by ooutside functions to free an obj -void -kfree(void *objp) { - kmem_cache_free(GET_PAGE_CACHE(kva2page(objp)), objp); -} - -static inline void -check_slab_empty(void) { - int i; - for (i = 0; i < SLAB_CACHE_NUM; i ++) { - kmem_cache_t *cachep = slab_cache + i; - assert(list_empty(&(cachep->slabs_full))); - assert(list_empty(&(cachep->slabs_notfull))); - } -} - -void -check_slab(void) { - int i; - void *v0, *v1; - - size_t nr_free_pages_store = nr_free_pages(); - size_t slab_allocated_store = slab_allocated(); - - /* slab must be empty now */ - check_slab_empty(); - assert(slab_allocated() == 0); - - kmem_cache_t *cachep0, *cachep1; - - cachep0 = slab_cache; - assert(cachep0->objsize == 32 && cachep0->num > 1 && !cachep0->off_slab); - assert((v0 = kmalloc(16)) != NULL); - - slab_t *slabp0, *slabp1; - - assert(!list_empty(&(cachep0->slabs_notfull))); - slabp0 = le2slab(list_next(&(cachep0->slabs_notfull)), slab_link); - assert(slabp0->inuse == 1 && list_next(&(slabp0->slab_link)) == &(cachep0->slabs_notfull)); - - struct Page *p0, *p1; - size_t order_size; - - - p0 = kva2page(slabp0->s_mem - slabp0->offset), p1 = p0; - order_size = (1 << cachep0->page_order); - for (i = 0; i < cachep0->page_order; i ++, p1 ++) { - assert(PageSlab(p1)); - assert(GET_PAGE_CACHE(p1) == cachep0 && GET_PAGE_SLAB(p1) == slabp0); - } - - assert(v0 == slabp0->s_mem); - assert((v1 = kmalloc(16)) != NULL && v1 == v0 + 32); - - kfree(v0); - assert(slabp0->free == 0); - kfree(v1); - assert(list_empty(&(cachep0->slabs_notfull))); - - for (i = 0; i < cachep0->page_order; i ++, p0 ++) { - assert(!PageSlab(p0)); - } - - - v0 = kmalloc(16); - assert(!list_empty(&(cachep0->slabs_notfull))); - slabp0 = le2slab(list_next(&(cachep0->slabs_notfull)), slab_link); - - for (i = 0; i < cachep0->num - 1; i ++) { - kmalloc(16); - } - - assert(slabp0->inuse == cachep0->num); - assert(list_next(&(cachep0->slabs_full)) == &(slabp0->slab_link)); - assert(list_empty(&(cachep0->slabs_notfull))); - - v1 = kmalloc(16); - assert(!list_empty(&(cachep0->slabs_notfull))); - slabp1 = le2slab(list_next(&(cachep0->slabs_notfull)), slab_link); - - kfree(v0); - assert(list_empty(&(cachep0->slabs_full))); - assert(list_next(&(slabp0->slab_link)) == &(slabp1->slab_link) - || list_next(&(slabp1->slab_link)) == &(slabp0->slab_link)); - - kfree(v1); - assert(!list_empty(&(cachep0->slabs_notfull))); - assert(list_next(&(cachep0->slabs_notfull)) == &(slabp0->slab_link)); - assert(list_next(&(slabp0->slab_link)) == &(cachep0->slabs_notfull)); - - v1 = kmalloc(16); - assert(v1 == v0); - assert(list_next(&(cachep0->slabs_full)) == &(slabp0->slab_link)); - assert(list_empty(&(cachep0->slabs_notfull))); - - for (i = 0; i < cachep0->num; i ++) { - kfree(v1 + i * cachep0->objsize); - } - - assert(list_empty(&(cachep0->slabs_full))); - assert(list_empty(&(cachep0->slabs_notfull))); - - cachep0 = slab_cache; - - bool has_off_slab = 0; - for (i = 0; i < SLAB_CACHE_NUM; i ++, cachep0 ++) { - if (cachep0->off_slab) { - has_off_slab = 1; - cachep1 = cachep0->slab_cachep; - if (!cachep1->off_slab) { - break; - } - } - } - - if (!has_off_slab) { - goto check_pass; - } - - assert(cachep0->off_slab && !cachep1->off_slab); - assert(cachep1 < cachep0); - - assert(list_empty(&(cachep0->slabs_full))); - assert(list_empty(&(cachep0->slabs_notfull))); - - assert(list_empty(&(cachep1->slabs_full))); - assert(list_empty(&(cachep1->slabs_notfull))); - - v0 = kmalloc(cachep0->objsize); - p0 = kva2page(v0); - assert(page2kva(p0) == v0); - - if (cachep0->num == 1) { - assert(!list_empty(&(cachep0->slabs_full))); - slabp0 = le2slab(list_next(&(cachep0->slabs_full)), slab_link); - } - else { - assert(!list_empty(&(cachep0->slabs_notfull))); - slabp0 = le2slab(list_next(&(cachep0->slabs_notfull)), slab_link); - } - - assert(slabp0 != NULL); - - if (cachep1->num == 1) { - assert(!list_empty(&(cachep1->slabs_full))); - slabp1 = le2slab(list_next(&(cachep1->slabs_full)), slab_link); - } - else { - assert(!list_empty(&(cachep1->slabs_notfull))); - slabp1 = le2slab(list_next(&(cachep1->slabs_notfull)), slab_link); - } - - assert(slabp1 != NULL); - - order_size = (1 << cachep0->page_order); - for (i = 0; i < order_size; i ++, p0 ++) { - assert(PageSlab(p0)); - assert(GET_PAGE_CACHE(p0) == cachep0 && GET_PAGE_SLAB(p0) == slabp0); - } - - kfree(v0); - -check_pass: - - check_rb_tree(); - check_slab_empty(); - assert(slab_allocated() == 0); - assert(nr_free_pages_store == nr_free_pages()); - assert(slab_allocated_store == slab_allocated()); - - kprintf("check_slab() succeeded!\n"); -} - - diff --git a/ucore-thumips/kern/mm/kmalloc.h b/ucore-thumips/kern/mm/kmalloc.h deleted file mode 100644 index aeb543c..0000000 --- a/ucore-thumips/kern/mm/kmalloc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __KERN_MM_SLAB_H__ -#define __KERN_MM_SLAB_H__ - -#include - -#define KMALLOC_MAX_ORDER 10 - -void kmalloc_init(void); - -void *kmalloc(size_t n); -void kfree(void *objp); - -size_t kallocated(void); - -// size_t kmalloc_allocated(void); - -#endif /* !__KERN_MM_SLAB_H__ */ - diff --git a/ucore-thumips/kern/mm/memlayout.h b/ucore-thumips/kern/mm/memlayout.h deleted file mode 100644 index 5fc97d4..0000000 --- a/ucore-thumips/kern/mm/memlayout.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef __KERN_MM_MEMLAYOUT_H__ -#define __KERN_MM_MEMLAYOUT_H__ - -/* This file contains the definitions for memory management in our OS. */ - -#define KERNBASE 0x80000000 - -#ifdef MACH_FPGA -#define KMEMSIZE (1 << 22) -#else -#define KMEMSIZE (32 << 20) // 512M the maximum amount of physical memory -#endif - -#define KERNTOP (KERNBASE + KMEMSIZE) - -#define KSTACKPAGE 2 // # of pages in kernel stack -#define KSTACKSIZE (KSTACKPAGE * 4096) // sizeof kernel stack - -#define USERBASE 0x10000000 -#define USERTOP MIPS_KSEG0 - -#define USTACKTOP USERTOP -#define USTACKPAGE 16 // # of pages in user stack -#define USTACKSIZE (USTACKPAGE * PGSIZE) // sizeof user stack - -#define USER_ACCESS(start, end) \ -(USERBASE <= (start) && (start) < (end) && (end) <= USERTOP) - -#define KERN_ACCESS(start, end) \ -(KERNBASE <= (start) && (start) < (end) && (end) <= KERNTOP) - - -#ifndef __ASSEMBLER__ - -#include -#include -#include -#include - -typedef uintptr_t pte_t; -typedef uintptr_t pde_t; - - -/* * - * struct Page - Page descriptor structures. Each Page describes one - * physical page (1MB). In kern/mm/pmm.h, you can find lots of useful functions - * that convert Page to other data types, such as phyical address. - * */ -struct Page { - atomic_t ref; // page frame's reference counter - uint32_t flags; // array of flags that describe the status of the page frame - unsigned int property; // used in buddy system, stores the order (the X in 2^X) of the continuous memory block - int zone_num; // used in buddy system, the No. of zone which the page belongs to - list_entry_t page_link; // free list link -// swap_entry_t index; // stores a swapped-out page identifier - list_entry_t swap_link; // swap hash link -}; - -/* Flags describing the status of a page frame */ -#define PG_reserved 0 // the page descriptor is reserved for kernel or unusable -#define PG_property 1 // the member 'property' is valid -#define PG_slab 2 // page frame is included in a slab -#define PG_dirty 3 // the page has been modified -#define PG_swap 4 // the page is in the active or inactive page list (and swap hash table) -#define PG_active 5 // the page is in the active page list - -#define SetPageReserved(page) set_bit(PG_reserved, &((page)->flags)) -#define ClearPageReserved(page) clear_bit(PG_reserved, &((page)->flags)) -#define PageReserved(page) test_bit(PG_reserved, &((page)->flags)) -#define SetPageProperty(page) set_bit(PG_property, &((page)->flags)) -#define ClearPageProperty(page) clear_bit(PG_property, &((page)->flags)) -#define PageProperty(page) test_bit(PG_property, &((page)->flags)) -#define SetPageSlab(page) set_bit(PG_slab, &((page)->flags)) -#define ClearPageSlab(page) clear_bit(PG_slab, &((page)->flags)) -#define PageSlab(page) test_bit(PG_slab, &((page)->flags)) -#define SetPageDirty(page) set_bit(PG_dirty, &((page)->flags)) -#define ClearPageDirty(page) clear_bit(PG_dirty, &((page)->flags)) -#define PageDirty(page) test_bit(PG_dirty, &((page)->flags)) -#define SetPageSwap(page) set_bit(PG_swap, &((page)->flags)) -#define ClearPageSwap(page) clear_bit(PG_swap, &((page)->flags)) -#define PageSwap(page) test_bit(PG_swap, &((page)->flags)) -#define SetPageActive(page) set_bit(PG_active, &((page)->flags)) -#define ClearPageActive(page) clear_bit(PG_active, &((page)->flags)) -#define PageActive(page) test_bit(PG_active, &((page)->flags)) - -// convert list entry to page -#define le2page(le, member) \ - to_struct((le), struct Page, member) - -/* free_area_t - maintains a doubly linked list to record free (unused) pages */ -typedef struct { - list_entry_t free_list; // the list header - unsigned int nr_free; // # of free pages in this free list -} free_area_t; - -#endif /* !__ASSEMBLER__ */ - -#endif /* !__KERN_MM_MEMLAYOUT_H__ */ - diff --git a/ucore-thumips/kern/mm/mmu.h b/ucore-thumips/kern/mm/mmu.h deleted file mode 100644 index 37fa0f3..0000000 --- a/ucore-thumips/kern/mm/mmu.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef __KERN_MM_MMU_H__ -#define __KERN_MM_MMU_H__ - - -#include -#include - -// A linear address 'la' has a three-part structure as follows: -// -// +--------10------+-------10-------+---------12----------+ -// | Page Directory | Page Table | Offset within Page | -// | Index | Index | | -// +----------------+----------------+---------------------+ -// \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/ -// \----------- PPN(la) -----------/ -// -// The PDX, PTX, PGOFF, and PPN macros decompose linear addresses as shown. -// To construct a linear address la from PDX(la), PTX(la), and PGOFF(la), -// use PGADDR(PDX(la), PTX(la), PGOFF(la)). - -// page directory index -#define PDX(la) ((((uintptr_t)(la)) >> PDXSHIFT) & 0x3FF) - -// page table index -#define PTX(la) ((((uintptr_t)(la)) >> PTXSHIFT) & 0x3FF) - -// page number field of address -#define PPN(la) (((uintptr_t)(la - KERNBASE)) >> PTXSHIFT) - -// offset in page -#define PGOFF(la) (((uintptr_t)(la)) & 0xFFF) - -// construct linear address from indexes and offset -#define PGADDR(d, t, o) ((uintptr_t)((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) - -// address in page table or page directory entry -#define PTE_ADDR(pte) ((uintptr_t)(pte) & ~0xFFF) -#define PDE_ADDR(pde) PTE_ADDR(pde) - -/* page directory and page table constants */ -#define NPDEENTRY 1024 // page directory entries per page directory -#define NPTEENTRY 1024 // page table entries per page table - -#define PGSIZE 4096 // bytes mapped by a page -#define PGSHIFT 12 // log2(PGSIZE) -#define PTSIZE (PGSIZE * NPTEENTRY) // bytes mapped by a page directory entry -#define PTSHIFT 22 // log2(PTSIZE) - -#define PTXSHIFT 12 // offset of PTX in a linear address -#define PDXSHIFT 22 // offset of PDX in a linear address - -/* page table/directory entry flags */ -#define PTE_P 0x001 // Present -#define PTE_W 0x002 // Writeable -#define PTE_U 0x004 // User -#define PTE_PWT 0x008 // Write-Through -#define PTE_PCD 0x010 // Cache-Disable -#define PTE_A 0x020 // Accessed -#define PTE_D 0x040 // Dirty -#define PTE_PS 0x080 // Page Size -#define PTE_MBZ 0x180 // Bits must be zero -#define PTE_AVAIL 0xE00 // Available for software use - // The PTE_AVAIL bits aren't used by the kernel or interpreted by the - // hardware, so user processes are allowed to set them arbitrarily. - -#define PTE_USER (PTE_U | PTE_W | PTE_P) - -#endif /* !__KERN_MM_MMU_H__ */ - diff --git a/ucore-thumips/kern/mm/pmm.c b/ucore-thumips/kern/mm/pmm.c deleted file mode 100644 index d762015..0000000 --- a/ucore-thumips/kern/mm/pmm.c +++ /dev/null @@ -1,576 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - - -// virtual address of physicall page array -struct Page *pages; -// amount of physical memory (in pages) -size_t npage = 0; - -// virtual address of boot-time page directory -pde_t *boot_pgdir = NULL; - -/* this is our emulated "CR3" */ -pde_t *current_pgdir = NULL; - -// physical address of boot-time page directory -uintptr_t boot_cr3; - -// physical memory management -const struct pmm_manager *pmm_manager; - -static void check_alloc_page(void); -static void check_pgdir(void); -static void check_boot_pgdir(void); - -void lcr3(uintptr_t cr3) -{ - current_pgdir = (pde_t*)cr3; -} - -//init_pmm_manager - initialize a pmm_manager instance -static void -init_pmm_manager(void) { - pmm_manager = &buddy_pmm_manager; - kprintf("memory management: "); - kprintf(pmm_manager->name); - kprintf("\n"); - pmm_manager->init(); -} - -//init_memmap - call pmm->init_memmap to build Page struct for free memory -static void -init_memmap(struct Page *base, size_t n) { - pmm_manager->init_memmap(base, n); -} - -//alloc_pages - call pmm->alloc_pages to allocate a continuous n*PAGESIZE memory -struct Page * -alloc_pages(size_t n) { - struct Page *page; - bool intr_flag; - local_intr_save(intr_flag); - { - page = pmm_manager->alloc_pages(n); - } - local_intr_restore(intr_flag); - return page; -} - -//free_pages - call pmm->free_pages to free a continuous n*PAGESIZE memory -void -free_pages(struct Page *base, size_t n) { - bool intr_flag; - local_intr_save(intr_flag); - { - pmm_manager->free_pages(base, n); - } - local_intr_restore(intr_flag); -} - -//nr_free_pages - call pmm->nr_free_pages to get the size (nr*PAGESIZE) -//of current free memory -size_t -nr_free_pages(void) { - size_t ret; - bool intr_flag; - local_intr_save(intr_flag); - { - ret = pmm_manager->nr_free_pages(); - } - local_intr_restore(intr_flag); - return ret; -} - -/* pmm_init - initialize the physical memory management */ -static void -page_init(void) { - uint32_t maxpa; - int i; - - //panic("unimpl"); - kprintf("memory map:\n"); - kprintf(" ["); - printhex(KERNBASE); - kprintf(", "); - printhex(KERNTOP); - kprintf("]\n\n"); - - maxpa = KERNTOP; - npage = KMEMSIZE >> PGSHIFT; - - // end address of kernel - extern char end[]; - // put page structure table at the end of kernel - pages = (struct Page *)ROUNDUP_2N((void *)end, PGSHIFT); - - for(i=0; i < npage; i++){ - SetPageReserved(pages + i); - } - - uintptr_t freemem = PADDR((uintptr_t)pages + sizeof(struct Page) * npage); - PRINT_HEX("freemem start at: ", freemem); - - uint32_t mbegin = ROUNDUP_2N(freemem, PGSHIFT); - uint32_t mend = ROUNDDOWN_2N(KERNTOP, PGSHIFT); - assert( mbegin < mend ); - init_memmap(pa2page(mbegin), (mend - mbegin) >> PGSHIFT ); - PRINT_HEX("free pages: ", (mend-mbegin)>>PGSHIFT); - PRINT_HEX("## ", sizeof(struct Page)); -} - -static void -enable_paging(void) { - /* nothing */ -} - -//boot_map_segment - setup&enable the paging mechanism -// parameters -// la: linear address of this memory need to map (after x86 segment map) -// size: memory size -// pa: physical address of this memory -// perm: permission of this memory -static void -boot_map_segment(pde_t *pgdir, uintptr_t la, size_t size, uintptr_t pa, uint32_t perm) { - assert(PGOFF(la) == PGOFF(pa)); - size_t n = ROUNDUP_2N(size + PGOFF(la), PGSHIFT) >> PGSHIFT; - la = ROUNDDOWN_2N(la, PGSHIFT); - pa = ROUNDDOWN_2N(pa, PGSHIFT); - for (; n > 0; n --, la += PGSIZE, pa += PGSIZE) { - pte_t *ptep = get_pte(pgdir, la, 1); - assert(ptep != NULL); - *ptep = pa | PTE_P | perm; - } -} - -//boot_alloc_page - allocate one page using pmm->alloc_pages(1) -// return value: the kernel virtual address of this allocated page -//note: this function is used to get the memory for PDT(Page Directory Table)&PT(Page Table) -static void * -boot_alloc_page(void) { - struct Page *p = alloc_page(); - if (p == NULL) { - panic("boot_alloc_page failed.\n"); - } - return page2kva(p); -} - -//pmm_init - setup a pmm to manage physical memory, build PDT&PT to setup paging mechanism -// - check the correctness of pmm & paging mechanism, print PDT&PT -void -pmm_init(void) { - //We need to alloc/free the physical memory (granularity is 4KB or other size). - //So a framework of physical memory manager (struct pmm_manager)is defined in pmm.h - //First we should init a physical memory manager(pmm) based on the framework. - //Then pmm can alloc/free the physical memory. - //Now the first_fit/best_fit/worst_fit/buddy_system pmm are available. - init_pmm_manager(); - - // detect physical memory space, reserve already used memory, - // then use pmm->init_memmap to create free page list - page_init(); - - //use pmm->check to verify the correctness of the alloc/free function in a pmm - check_alloc_page(); - - // create boot_pgdir, an initial page directory(Page Directory Table, PDT) - boot_pgdir = boot_alloc_page(); - memset(boot_pgdir, 0, PGSIZE); - boot_cr3 = PADDR(boot_pgdir); - current_pgdir = boot_pgdir; - - check_pgdir(); - - enable_paging(); - - //now the basic virtual memory map(see memalyout.h) is established. - //check the correctness of the basic virtual memory map. - check_boot_pgdir(); - - memset(boot_pgdir, 0, PGSIZE); - print_pgdir(); - - kmalloc_init(); -} - -//get_pte - get pte and return the kernel virtual address of this pte for la -// - if the PT contians this pte didn't exist, alloc a page for PT -// parameter: -// pgdir: the kernel virtual base address of PDT -// la: the linear address need to map -// create: a logical value to decide if alloc a page for PT -// return vaule: the kernel virtual address of this pte -pte_t * -get_pte(pde_t *pgdir, uintptr_t la, bool create) { - /* LAB2 exercise2: 2009010989 - * - * if you need to visit a physical address, please use KADDR() - * please read pmm.h for useful macros - */ - // YOU want comment, HERE is comment - pde_t *pdep = NULL; // find page directory entry - pdep = pgdir + PDX(la); - - if ( ((*pdep)&PTE_P) == 0 ) { // check if entry is not present - // check if creating is needed, then alloc page for page table - if(!create) return NULL; - // CAUTION: this page is used for page table, not for common data page - // set page reference - struct Page* new_pte = alloc_page(); - if(!new_pte) return NULL; - page_ref_inc(new_pte); - uintptr_t pa = (uintptr_t)page2kva(new_pte); // get linear address of page - // clear page content using memset - memset((void*)pa, 0, PGSIZE); - //kprintf("@@@ %x\n", pa); - // set page directory entry's permission - *pdep = PADDR(pa); - (*pdep) |= (PTE_U|PTE_P|PTE_W); - } - pte_t *ret = (pte_t*)KADDR((uintptr_t)((pte_t*)(PDE_ADDR(*pdep))+PTX(la))); - - //kprintf("@@GET_PTE %x %x %x\n", *pdep, ret, *ret); - return ret;// return page table entry -} - -//get_page - get related Page struct for linear address la using PDT pgdir -struct Page * -get_page(pde_t *pgdir, uintptr_t la, pte_t **ptep_store) { - pte_t *ptep = get_pte(pgdir, la, 0); - if (ptep_store != NULL) { - *ptep_store = ptep; - } - if (ptep != NULL && *ptep & PTE_P) { - return pa2page(*ptep); - } - return NULL; -} - -//page_remove_pte - free an Page sturct which is related linear address la -// - and clean(invalidate) pte which is related linear address la -//note: PT is changed, so the TLB need to be invalidate -static inline void -page_remove_pte(pde_t *pgdir, uintptr_t la, pte_t *ptep) { - if (ptep && (*ptep & PTE_P)) { // check if page directory is present - struct Page *page = pte2page(*ptep); // find corresponding page to pte - // decrease page reference - page_ref_dec(page); - // and free it when reach 0 - if(page_ref(page) == 0){ - free_page(page); - } - // clear page directory entry - *ptep = 0; - } - // flush tlb - tlb_invalidate_all(); -} - -//page_remove - free an Page which is related linear address la and has an validated pte -void -page_remove(pde_t *pgdir, uintptr_t la) { - pte_t *ptep = get_pte(pgdir, la, 0); - if (ptep != NULL) { - page_remove_pte(pgdir, la, ptep); - } -} - -//page_insert - build the map of phy addr of an Page with the linear addr la -// paramemters: -// pgdir: the kernel virtual base address of PDT -// page: the Page which need to map -// la: the linear address need to map -// perm: the permission of this Page which is setted in related pte -// return value: always 0 -//note: PT is changed, so the TLB need to be invalidate -int -page_insert(pde_t *pgdir, struct Page *page, uintptr_t la, uint32_t perm) { - pte_t *ptep = get_pte(pgdir, la, 1); - if (ptep == NULL) { - return -E_NO_MEM; - } - page_ref_inc(page); - if (*ptep & PTE_P) { - struct Page *p = pte2page(*ptep); - if (p == page) { - page_ref_dec(page); - } - else { - page_remove_pte(pgdir, la, ptep); - } - } - *ptep = page2pa(page) | PTE_P | perm; - tlb_invalidate(pgdir, la); - return 0; -} - -extern int swap_init_ok; -// pgdir_alloc_page - call alloc_page & page_insert functions to -// - allocate a page size memory & setup an addr map -// - pa<->la with linear address la and the PDT pgdir -struct Page * -pgdir_alloc_page(pde_t *pgdir, uintptr_t la, uint32_t perm) { - struct Page *page = alloc_page(); - if (page != NULL) { - if (page_insert(pgdir, page, la, perm) != 0) { - free_page(page); - return NULL; - } - if (swap_init_ok){ - panic("No swap!! never reach!!"); - } - } - - return page; -} - -static void -check_alloc_page(void) { - pmm_manager->check(); - kprintf("check_alloc_page() succeeded!\n"); -} - -static void -check_pgdir(void) { - assert(npage <= KMEMSIZE / PGSIZE); - assert(boot_pgdir != NULL && (uint32_t)PGOFF(boot_pgdir) == 0); - assert(get_page(boot_pgdir, 0x0, NULL) == NULL); - - struct Page *p1, *p2; - p1 = alloc_page(); - assert(page_insert(boot_pgdir, p1, 0x0, 0) == 0); - - pte_t *ptep; - assert((ptep = get_pte(boot_pgdir, 0x0, 0)) != NULL); - assert(pa2page(*ptep) == p1); - assert(page_ref(p1) == 1); - - ptep = &((pte_t *)KADDR(PDE_ADDR(boot_pgdir[0])))[1]; - assert(get_pte(boot_pgdir, PGSIZE, 0) == ptep); - - p2 = alloc_page(); - assert(page_insert(boot_pgdir, p2, PGSIZE, PTE_U | PTE_W) == 0); - assert((ptep = get_pte(boot_pgdir, PGSIZE, 0)) != NULL); - assert(*ptep & PTE_U); - assert(*ptep & PTE_W); - assert(boot_pgdir[0] & PTE_U); - assert(page_ref(p2) == 1); - - assert(page_insert(boot_pgdir, p1, PGSIZE, 0) == 0); - assert(page_ref(p1) == 2); - assert(page_ref(p2) == 0); - assert((ptep = get_pte(boot_pgdir, PGSIZE, 0)) != NULL); - assert(pa2page(*ptep) == p1); - assert((*ptep & PTE_U) == 0); - - page_remove(boot_pgdir, 0x0); - assert(page_ref(p1) == 1); - assert(page_ref(p2) == 0); - - page_remove(boot_pgdir, PGSIZE); - assert(page_ref(p1) == 0); - assert(page_ref(p2) == 0); - - assert(page_ref(pa2page(boot_pgdir[0])) == 1); - free_page(pa2page(boot_pgdir[0])); - boot_pgdir[0] = 0; - - kprintf("check_pgdir() succeeded!\n"); -} - -static void -check_boot_pgdir(void) { - pte_t *ptep; - int i; - //assert(PDE_ADDR(boot_pgdir[PDX(VPT)]) == PADDR(boot_pgdir)); - - assert(boot_pgdir[0] == 0); - struct Page *p; - p = alloc_page(); - *(int*)(page2kva(p) + 0x100) = 0x1234; - //printhex(page2kva(p)); - //kprintf("\n"); - //printhex(*(int*)(page2kva(p)+0x100)); - - assert(page_insert(boot_pgdir, p, 0x100, PTE_W) == 0); - assert(page_ref(p) == 1); - assert(page_insert(boot_pgdir, p, 0x100 + PGSIZE, PTE_W) == 0); - assert(page_ref(p) == 2); - - //kprintf("\nHERE\n"); - - assert(*(int*)0x100 == 0x1234); - const char *str = "ucore: Hello world!!"; - strcpy((void *)0x100, str); - assert(strcmp((void *)0x100, (void *)(0x100 + PGSIZE)) == 0); - - *(char *)(page2kva(p) + 0x100) = '\0'; - assert(strlen((const char *)0x100) == 0); - - free_page(p); - free_page(pa2page(PDE_ADDR(boot_pgdir[0]))); - boot_pgdir[0] = 0; - tlb_invalidate_all(); - - kprintf("check_boot_pgdir() succeeded!\n"); -} - -//perm2str - use string 'u,r,w,-' to present the permission -static const char * -perm2str(int perm) { - static char str[4]; - str[0] = (perm & PTE_U) ? 'u' : '-'; - str[1] = 'r'; - str[2] = (perm & PTE_W) ? 'w' : '-'; - str[3] = '\0'; - return str; -} - -//get_pgtable_items - In [left, right] range of PDT or PT, find a continuous linear addr space -// - (left_store*X_SIZE~right_store*X_SIZE) for PDT or PT -// - X_SIZE=PTSIZE=4M, if PDT; X_SIZE=PGSIZE=4K, if PT -// paramemters: -// left: no use ??? -// right: the high side of table's range -// start: the low side of table's range -// table: the beginning addr of table -// left_store: the pointer of the high side of table's next range -// right_store: the pointer of the low side of table's next range -// return value: 0 - not a invalid item range, perm - a valid item range with perm permission -static int -get_pgtable_items(size_t left, size_t right, size_t start, uintptr_t *table, size_t *left_store, size_t *right_store) { - if (start >= right) { - return 0; - } - while (start < right && !(table[start] & PTE_P)) { - start ++; - } - if (start < right) { - if (left_store != NULL) { - *left_store = start; - } - int perm = (table[start ++] & PTE_USER); - while (start < right && (table[start] & PTE_USER) == perm) { - start ++; - } - if (right_store != NULL) { - *right_store = start; - } - return perm; - } - return 0; -} - -#define PRINT_PTE(s0, a0,a1,a2,a3,s1) kprintf(s0);printhex(a0);\ - kprintf(") ");printhex(a1);kprintf("-");printhex(a2);kprintf(" ");\ - printhex(a3);kprintf(" ");kprintf(s1);kprintf("\n"); -//print_pgdir - print the PDT&PT -void -print_pgdir(void) { - size_t left, right = 0, perm; - kprintf("-------------------- BEGIN --------------------\n"); - while ((perm = get_pgtable_items(0, NPDEENTRY, right, current_pgdir, &left, &right)) != 0) { - PRINT_PTE("PDE(", right - left, - left * PTSIZE, right * PTSIZE, (right - left) * PTSIZE, perm2str(perm)); - size_t l, r = 0; - - size_t perm_ref = get_pgtable_items(0, NPTEENTRY, r, (pte_t *) PDE_ADDR(current_pgdir[left]), &l, &r); - size_t count, count_ref = 0; - size_t count_ref_l = 0; - for (count=0; count -#include -#include -#include -#include - -/* fork flags used in do_fork*/ -#define CLONE_VM 0x00000100 // set if VM shared between processes -#define CLONE_THREAD 0x00000200 // thread group - -// pmm_manager is a physical memory management class. A special pmm manager - XXX_pmm_manager -// only needs to implement the methods in pmm_manager class, then XXX_pmm_manager can be used -// by ucore to manage the total physical memory space. -struct pmm_manager { - const char *name; // XXX_pmm_manager's name - void (*init)(void); // initialize internal description&management data structure - // (free block list, number of free block) of XXX_pmm_manager - void (*init_memmap)(struct Page *base, size_t n); // setup description&management data structcure according to - // the initial free physical memory space - struct Page *(*alloc_pages)(size_t n); // allocate >=n pages, depend on the allocation algorithm - void (*free_pages)(struct Page *base, size_t n); // free >=n pages with "base" addr of Page descriptor structures(memlayout.h) - size_t (*nr_free_pages)(void); // return the number of free pages - void (*check)(void); // check the correctness of XXX_pmm_manager -}; - -extern const struct pmm_manager *pmm_manager; -extern pde_t *boot_pgdir; -extern uintptr_t boot_cr3; - -void pmm_init(void); - -struct Page *alloc_pages(size_t n); -void free_pages(struct Page *base, size_t n); -size_t nr_free_pages(void); - - -void unmap_range(pde_t *pgdir, uintptr_t start, uintptr_t end); -void exit_range(pde_t *pgdir, uintptr_t start, uintptr_t end); -int copy_range(pde_t *to, pde_t *from, uintptr_t start, uintptr_t end, bool share); - -#define alloc_page() alloc_pages(1) -#define free_page(page) free_pages(page, 1) - -pte_t *get_pte(pde_t *pgdir, uintptr_t la, bool create); -struct Page *get_page(pde_t *pgdir, uintptr_t la, pte_t **ptep_store); -void page_remove(pde_t *pgdir, uintptr_t la); -int page_insert(pde_t *pgdir, struct Page *page, uintptr_t la, uint32_t perm); -struct Page * pgdir_alloc_page(pde_t *pgdir, uintptr_t la, uint32_t perm); - - -void print_pgdir(void); - -/* * - * PADDR - takes a kernel virtual address (an address that points above KERNBASE), - * where the machine's maximum 256MB of physical memory is mapped and returns the - * corresponding physical address. It panics if you pass it a non-kernel virtual address. - * */ -#define PADDR(kva) ({ \ - uintptr_t __m_kva = (uintptr_t)(kva); \ - if (__m_kva < KERNBASE) { \ - panic("PADDR called with invalid kva %08lx", __m_kva); \ - } \ - __m_kva ; \ - }) - -/* * - * KADDR - takes a physical address and returns the corresponding kernel virtual - * address. It panics if you pass an invalid physical address. - * */ -#define KADDR(pa) ({ \ - uintptr_t __m_pa = (pa); \ - size_t __m_ppn = PPN(__m_pa); \ - if (__m_ppn >= npage) { \ - panic("KADDR called with invalid pa %08lx", __m_pa); \ - } \ - (void *) (__m_pa); \ - }) - -extern struct Page *pages; -extern size_t npage; - -static inline ppn_t -page2ppn(struct Page *page) { - return page - pages; -} - -static inline uintptr_t -page2pa(struct Page *page) { - return KERNBASE + (page2ppn(page) << PGSHIFT); -} - -static inline struct Page * -pa2page(uintptr_t pa) { - if (PPN(pa) >= npage) { - panic("pa2page called with invalid pa"); - } - return &pages[PPN(pa)]; -} - -static inline void * -page2kva(struct Page *page) { - return KADDR(page2pa(page)); -} - -static inline struct Page * -kva2page(void *kva) { - return pa2page(PADDR(kva)); -} - -static inline struct Page * -pte2page(pte_t pte) { - if (!(pte & PTE_P)) { - panic("pte2page called with invalid pte"); - } - return pa2page(PTE_ADDR(pte)); -} - -static inline struct Page * -pde2page(pde_t pde) { - return pa2page(PDE_ADDR(pde)); -} - -static inline int -page_ref(struct Page *page) { - return atomic_read(&(page->ref)); -} - -static inline void -set_page_ref(struct Page *page, int val) { - atomic_set(&(page->ref), val); -} - -static inline int -page_ref_inc(struct Page *page) { - return atomic_add_return(&(page->ref), 1); -} - -static inline int -page_ref_dec(struct Page *page) { - return atomic_sub_return(&(page->ref), 1); -} - -extern char bootstack[], bootstacktop[]; - -#endif /* !__KERN_MM_PMM_H__ */ - diff --git a/ucore-thumips/kern/mm/thumips_tlb.c b/ucore-thumips/kern/mm/thumips_tlb.c deleted file mode 100644 index 8dc4004..0000000 --- a/ucore-thumips/kern/mm/thumips_tlb.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * ===================================================================================== - * - * Filename: thumips_tlb.c - * - * Description: - * - * Version: 1.0 - * Created: 07/06/2012 10:23:50 AM - * Revision: none - * Compiler: gcc - * - * Author: Chen Yuheng (Chen Yuheng), chyh1990@163.com - * Organization: Tsinghua Unv. - * - * ===================================================================================== - */ -#include -#include -#include -#include -#include -#include -#include -#include - -// invalidate both TLB -// (clean and flush, meaning we write the data back) -void -tlb_invalidate(pde_t *pgdir, uintptr_t la) { - tlb_invalidate_all(); -} - -void tlb_invalidate_all(){ - int i; - for(i=0;i<128;i++) - write_one_tlb(i, 0, 0x80000000+(i<<20), 0, 0); -} - diff --git a/ucore-thumips/kern/mm/vmm.c b/ucore-thumips/kern/mm/vmm.c deleted file mode 100644 index 3047b8a..0000000 --- a/ucore-thumips/kern/mm/vmm.c +++ /dev/null @@ -1,486 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - vmm design include two parts: mm_struct (mm) & vma_struct (vma) - mm is the memory manager for the set of continuous virtual memory - area which have the same PDT. vma is a continuous virtual memory area. - There a linear link list for vma & a redblack link list for vma in mm. - --------------- - mm related functions: - golbal functions - struct mm_struct * mm_create(void) - void mm_destroy(struct mm_struct *mm) - int do_pgfault(struct mm_struct *mm, uint32_t error_code, uintptr_t addr) - -------------- - vma related functions: - global functions - struct vma_struct * vma_create (uintptr_t vm_start, uintptr_t vm_end,...) - void insert_vma_struct(struct mm_struct *mm, struct vma_struct *vma) - struct vma_struct * find_vma(struct mm_struct *mm, uintptr_t addr) - local functions - inline void check_vma_overlap(struct vma_struct *prev, struct vma_struct *next) - --------------- - check correctness functions - void check_vmm(void); - void check_vma_struct(void); - void check_pgfault(void); - */ - -static void check_vmm(void); -static void check_vma_struct(void); -static void check_pgfault(void); - -int swap_init_ok = 0; -// mm_create - alloc a mm_struct & initialize it. -struct mm_struct * -mm_create(void) { - struct mm_struct *mm = kmalloc(sizeof(struct mm_struct)); - - if (mm != NULL) { - list_init(&(mm->mmap_list)); - mm->mmap_cache = NULL; - mm->pgdir = NULL; - mm->map_count = 0; - - mm->sm_priv = NULL; - - set_mm_count(mm, 0); - sem_init(&(mm->mm_sem), 1); - } - return mm; -} - -// vma_create - alloc a vma_struct & initialize it. (addr range: vm_start~vm_end) -struct vma_struct * -vma_create(uintptr_t vm_start, uintptr_t vm_end, uint32_t vm_flags) { - struct vma_struct *vma = kmalloc(sizeof(struct vma_struct)); - - if (vma != NULL) { - vma->vm_start = vm_start; - vma->vm_end = vm_end; - vma->vm_flags = vm_flags; - } - return vma; -} - - -// find_vma - find a vma (vma->vm_start <= addr <= vma_vm_end) -struct vma_struct * -find_vma(struct mm_struct *mm, uintptr_t addr) { - struct vma_struct *vma = NULL; - if (mm != NULL) { - vma = mm->mmap_cache; - if (!(vma != NULL && vma->vm_start <= addr && vma->vm_end > addr)) { - bool found = 0; - list_entry_t *list = &(mm->mmap_list), *le = list; - while ((le = list_next(le)) != list) { - vma = le2vma(le, list_link); - if (addr < vma->vm_end) { - found = 1; - break; - } - } - if (!found) { - vma = NULL; - } - } - if (vma != NULL) { - mm->mmap_cache = vma; - } - } - return vma; -} - - -// check_vma_overlap - check if vma1 overlaps vma2 ? -static inline void -check_vma_overlap(struct vma_struct *prev, struct vma_struct *next) { - assert(prev->vm_start < prev->vm_end); - assert(prev->vm_end <= next->vm_start); - assert(next->vm_start < next->vm_end); -} - - -// insert_vma_struct -insert vma in mm's list link -void -insert_vma_struct(struct mm_struct *mm, struct vma_struct *vma) { - assert(vma->vm_start < vma->vm_end); - list_entry_t *list = &(mm->mmap_list); - list_entry_t *le_prev = list, *le_next; - - list_entry_t *le = list; - while ((le = list_next(le)) != list) { - struct vma_struct *mmap_prev = le2vma(le, list_link); - if (mmap_prev->vm_start > vma->vm_start) { - break; - } - le_prev = le; - } - - le_next = list_next(le_prev); - - /* check overlap */ - if (le_prev != list) { - check_vma_overlap(le2vma(le_prev, list_link), vma); - } - if (le_next != list) { - check_vma_overlap(vma, le2vma(le_next, list_link)); - } - - vma->vm_mm = mm; - list_add_after(le_prev, &(vma->list_link)); - - mm->map_count ++; -} - -// mm_destroy - free mm and mm internal fields -void -mm_destroy(struct mm_struct *mm) { - assert(mm_count(mm) == 0); - - list_entry_t *list = &(mm->mmap_list), *le; - while ((le = list_next(list)) != list) { - list_del(le); - kfree(le2vma(le, list_link)); //kfree vma - } - kfree(mm); //kfree mm - mm=NULL; -} - - -int -mm_map(struct mm_struct *mm, uintptr_t addr, size_t len, uint32_t vm_flags, - struct vma_struct **vma_store) { - uintptr_t start = ROUNDDOWN_2N(addr, PGSHIFT), end = ROUNDUP_2N(addr + len, PGSHIFT); - if (!USER_ACCESS(start, end)) { - return -E_INVAL; - } - - assert(mm != NULL); - - int ret = -E_INVAL; - - struct vma_struct *vma; - if ((vma = find_vma(mm, start)) != NULL && end > vma->vm_start) { - goto out; - } - ret = -E_NO_MEM; - - if ((vma = vma_create(start, end, vm_flags)) == NULL) { - goto out; - } - insert_vma_struct(mm, vma); - if (vma_store != NULL) { - *vma_store = vma; - } - ret = 0; - -out: - return ret; -} - -int -dup_mmap(struct mm_struct *to, struct mm_struct *from) { - assert(to != NULL && from != NULL); - list_entry_t *list = &(from->mmap_list), *le = list; - while ((le = list_prev(le)) != list) { - struct vma_struct *vma, *nvma; - vma = le2vma(le, list_link); - nvma = vma_create(vma->vm_start, vma->vm_end, vma->vm_flags); - if (nvma == NULL) { - return -E_NO_MEM; - } - - insert_vma_struct(to, nvma); - - bool share = 0; - if (copy_range(to->pgdir, from->pgdir, vma->vm_start, vma->vm_end, share) != 0) { - return -E_NO_MEM; - } - } - return 0; -} - -void -exit_mmap(struct mm_struct *mm) { - assert(mm != NULL && mm_count(mm) == 0); - pde_t *pgdir = mm->pgdir; - list_entry_t *list = &(mm->mmap_list), *le = list; - while ((le = list_next(le)) != list) { - struct vma_struct *vma = le2vma(le, list_link); - unmap_range(pgdir, vma->vm_start, vma->vm_end); - } - while ((le = list_next(le)) != list) { - struct vma_struct *vma = le2vma(le, list_link); - exit_range(pgdir, vma->vm_start, vma->vm_end); - } -} - -bool -copy_from_user(struct mm_struct *mm, void *dst, const void *src, size_t len, bool writable) { - if (!user_mem_check(mm, (uintptr_t)src, len, writable)) { - return 0; - } - memcpy(dst, src, len); - return 1; -} - -bool -copy_to_user(struct mm_struct *mm, void *dst, const void *src, size_t len) { - if (!user_mem_check(mm, (uintptr_t)dst, len, 1)) { - return 0; - } - memcpy(dst, src, len); - return 1; -} - - -// vmm_init - initialize virtual memory management -// - now just call check_vmm to check correctness of vmm -void -vmm_init(void) { - check_vmm(); -} - -// check_vmm - check correctness of vmm -static void -check_vmm(void) { - size_t nr_free_pages_store = nr_free_pages(); - - check_vma_struct(); - check_pgfault(); - - assert(nr_free_pages_store == nr_free_pages()); - - kprintf("check_vmm() succeeded.\n"); -} - -static void -check_vma_struct(void) { - size_t nr_free_pages_store = nr_free_pages(); - - struct mm_struct *mm = mm_create(); - assert(mm != NULL); - - int step1 = 10, step2 = step1 * 10; - - int i; - for (i = step1; i >= 0; i --) { - struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); - assert(vma != NULL); - insert_vma_struct(mm, vma); - } - - for (i = step1 + 1; i <= step2; i ++) { - struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); - assert(vma != NULL); - insert_vma_struct(mm, vma); - } - - list_entry_t *le = list_next(&(mm->mmap_list)); - - for (i = 0; i <= step2; i ++) { - assert(le != &(mm->mmap_list)); - struct vma_struct *mmap = le2vma(le, list_link); - assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2); - le = list_next(le); - } - - for (i = 0; i < 5 * step2 + 2; i ++) { - struct vma_struct *vma = find_vma(mm, i); - assert(vma != NULL); - int j = __divu5(i); - if (i >= 5 * j + 2) { - j ++; - } - assert(vma->vm_start == j * 5 && vma->vm_end == j * 5 + 2); - } - - mm_destroy(mm); - - assert(nr_free_pages_store == nr_free_pages()); - - kprintf("check_vma_struct() succeeded!\n"); -} - -struct mm_struct *check_mm_struct; - -// check_pgfault - check correctness of pgfault handler -static void -check_pgfault(void) { - size_t nr_free_pages_store = nr_free_pages(); - - check_mm_struct = mm_create(); - assert(check_mm_struct != NULL); - - struct mm_struct *mm = check_mm_struct; - pde_t *pgdir = mm->pgdir = boot_pgdir; - assert(pgdir[0] == 0); - - struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE); - assert(vma != NULL); - - insert_vma_struct(mm, vma); - - uintptr_t addr = 0x100; - assert(find_vma(mm, addr) == vma); - - int i, sum = 0; - for (i = 0; i < 100; i ++) { - *(char *)(addr + i) = i; - sum += i; - } - for (i = 0; i < 100; i ++) { - sum -= *(char *)(addr + i); - } - assert(sum == 0); - - page_remove(pgdir, ROUNDDOWN_2N(addr, PGSHIFT)); - free_page(pa2page(pgdir[0])); - pgdir[0] = 0; - - mm->pgdir = NULL; - mm_destroy(mm); - check_mm_struct = NULL; - - assert(nr_free_pages_store == nr_free_pages()); - - kprintf("check_pgfault() succeeded!\n"); -} - - - -//page fault number -volatile unsigned int pgfault_num=0; -// do_pgfault - interrupt handler to process the page fault execption -int -do_pgfault(struct mm_struct *mm, uint32_t error_code, uintptr_t addr) { - int ret = -E_INVAL; - struct vma_struct *vma = find_vma(mm, addr); - //kprintf("## %08x %08x\n", error_code, addr); - - pgfault_num++; - if (vma == NULL || vma->vm_start > addr) { - kprintf("not valid addr %x, and can not find it in vma\n", addr); - goto failed; - } - - switch (error_code & 3) { - default: - /* default is 3: write, present */ - case 2: /* write, not present */ - if (!(vma->vm_flags & VM_WRITE)) { - kprintf("write, not present in do_pgfault failed\n"); - goto failed; - } - break; - case 1: /* read, present */ - kprintf("read, present in do_pgfault failed\n"); - goto failed; - case 0: /* read, not present */ - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) { - kprintf("read, not present in do_pgfault failed\n"); - goto failed; - } - } - - //kprintf("## check OK\n"); - - uint32_t perm = PTE_U; - if (vma->vm_flags & VM_WRITE) { - perm |= PTE_W; - } - addr = ROUNDDOWN_2N(addr, PGSHIFT); - - ret = -E_NO_MEM; - - - - // try to find a pte, if pte's PT(Page Table) isn't existed, then create a PT. - pte_t *ptep=NULL; - if ((ptep = get_pte(mm->pgdir, addr, 1)) == NULL) { - goto failed; - } - - if (*ptep == 0) { // if the phy addr isn't exist, then alloc a page & map the phy addr with logical addr - if (pgdir_alloc_page(mm->pgdir, addr, perm) == NULL) { - goto failed; - } - } - else { // if this pte is a swap entry, then load data from disk to a page with phy addr, - // map the phy addr with logical addr, trig swap manager to record the access situation of this page - if(swap_init_ok) { - panic("No swap!! never reach!!"); - } - else { - kprintf("no swap_init_ok but ptep is %x, failed\n",*ptep); - goto failed; - } - } - /* refill TLB for mips, no second exception */ - //tlb_refill(addr, ptep); - ret = 0; -failed: - return ret; -} - - -bool -user_mem_check(struct mm_struct *mm, uintptr_t addr, size_t len, bool write) { - if (mm != NULL) { - if (!USER_ACCESS(addr, addr + len)) { - return 0; - } - struct vma_struct *vma; - uintptr_t start = addr, end = addr + len; - while (start < end) { - if ((vma = find_vma(mm, start)) == NULL || start < vma->vm_start) { - return 0; - } - if (!(vma->vm_flags & ((write) ? VM_WRITE : VM_READ))) { - return 0; - } - if (write && (vma->vm_flags & VM_STACK)) { - if (start < vma->vm_start + PGSIZE) { //check stack start & size - return 0; - } - } - start = vma->vm_end; - } - return 1; - } - return KERN_ACCESS(addr, addr + len); -} - -bool -copy_string(struct mm_struct *mm, char *dst, const char *src, size_t maxn) -{ - size_t alen, part = ROUNDDOWN_2N((uintptr_t)src + PGSIZE, PGSHIFT) - (uintptr_t)src; - while (1) { - if (part > maxn) { - part = maxn; - } - if (!user_mem_check(mm, (uintptr_t)src, part, 0)) { - return 0; - } - if ((alen = strnlen(src, part)) < part) { - memcpy(dst, src, alen + 1); - return 1; - } - if (part == maxn) { - return 0; - } - memcpy(dst, src, part); - dst += part, src += part, maxn -= part; - part = PGSIZE; - } -} diff --git a/ucore-thumips/kern/mm/vmm.h b/ucore-thumips/kern/mm/vmm.h deleted file mode 100644 index 88fce03..0000000 --- a/ucore-thumips/kern/mm/vmm.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef __KERN_MM_VMM_H__ -#define __KERN_MM_VMM_H__ - -#include -#include -#include -#include -#include -#include -#include - -//pre define -struct mm_struct; - -// the virtual continuous memory area(vma) -struct vma_struct { - struct mm_struct *vm_mm; // the set of vma using the same PDT - uintptr_t vm_start; // start addr of vma - uintptr_t vm_end; // end addr of vma - uint32_t vm_flags; // flags of vma - list_entry_t list_link; // linear list link which sorted by start addr of vma -}; - -#define le2vma(le, member) \ - to_struct((le), struct vma_struct, member) - -#define VM_READ 0x00000001 -#define VM_WRITE 0x00000002 -#define VM_EXEC 0x00000004 -#define VM_STACK 0x00000008 - - -// the control struct for a set of vma using the same PDT -struct mm_struct { - list_entry_t mmap_list; // linear list link which sorted by start addr of vma - struct vma_struct *mmap_cache; // current accessed vma, used for speed purpose - pde_t *pgdir; // the PDT of these vma - int map_count; // the count of these vma - void *sm_priv; // the private data for swap manager - atomic_t mm_count; - semaphore_t mm_sem; - int locked_by; - -}; - -struct vma_struct *find_vma(struct mm_struct *mm, uintptr_t addr); -struct vma_struct *vma_create(uintptr_t vm_start, uintptr_t vm_end, uint32_t vm_flags); -void insert_vma_struct(struct mm_struct *mm, struct vma_struct *vma); - -struct mm_struct *mm_create(void); -void mm_destroy(struct mm_struct *mm); - -void vmm_init(void); - -int do_pgfault(struct mm_struct *mm, uint32_t error_code, uintptr_t addr); - -extern volatile unsigned int pgfault_num; -extern struct mm_struct *check_mm_struct; - -bool user_mem_check(struct mm_struct *mm, uintptr_t start, size_t len, bool write); -bool copy_from_user(struct mm_struct *mm, void *dst, const void *src, size_t len, bool writable); -bool copy_to_user(struct mm_struct *mm, void *dst, const void *src, size_t len); - -int mm_unmap(struct mm_struct *mm, uintptr_t addr, size_t len); -int dup_mmap(struct mm_struct *to, struct mm_struct *from); -void exit_mmap(struct mm_struct *mm); -uintptr_t get_unmapped_area(struct mm_struct *mm, size_t len); -int mm_brk(struct mm_struct *mm, uintptr_t addr, size_t len); - -static inline int -mm_count(struct mm_struct *mm) { - return atomic_read(&(mm->mm_count)); -} - -static inline void -set_mm_count(struct mm_struct *mm, int val) { - atomic_set(&(mm->mm_count), val); -} - -static inline int -mm_count_inc(struct mm_struct *mm) { - return atomic_add_return(&(mm->mm_count), 1); -} - -static inline int -mm_count_dec(struct mm_struct *mm) { - return atomic_sub_return(&(mm->mm_count), 1); -} - -static inline void -lock_mm(struct mm_struct *mm) { - if (mm != NULL) { - down(&(mm->mm_sem)); - if (current != NULL) { - mm->locked_by = current->pid; - } - } -} - -static inline void -unlock_mm(struct mm_struct *mm) { - if (mm != NULL) { - up(&(mm->mm_sem)); - mm->locked_by = 0; - } -} - -#endif /* !__KERN_MM_VMM_H__ */ - diff --git a/ucore-thumips/kern/process/entry.S b/ucore-thumips/kern/process/entry.S deleted file mode 100644 index 9e29b3a..0000000 --- a/ucore-thumips/kern/process/entry.S +++ /dev/null @@ -1,16 +0,0 @@ -.text -.globl kernel_thread_entry -/* $a0 = arg, $a1 = func - * see proc.c:kernel_thread - */ -kernel_thread_entry: # void kernel_thread(void) - addiu $sp, $sp, -16 - jal $a1 - nop - move $a0, $v0 - la $t0, do_exit - jal $t0 - nop - /* never here */ - - diff --git a/ucore-thumips/kern/process/proc.c b/ucore-thumips/kern/process/proc.c deleted file mode 100644 index 72e4060..0000000 --- a/ucore-thumips/kern/process/proc.c +++ /dev/null @@ -1,1049 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* ------------- process/thread mechanism design&implementation ------------- -(an simplified Linux process/thread mechanism ) -introduction: - ucore implements a simple process/thread mechanism. process contains the independent memory sapce, at least one threads -for execution, the kernel data(for management), processor state (for context switch), files(in lab6), etc. ucore needs to -manage all these details efficiently. In ucore, a thread is just a special kind of process(share process's memory). ------------------------------- -process state : meaning -- reason - PROC_UNINIT : uninitialized -- alloc_proc - PROC_SLEEPING : sleeping -- try_free_pages, do_wait, do_sleep - PROC_RUNNABLE : runnable(maybe running) -- proc_init, wakeup_proc, - PROC_ZOMBIE : almost dead -- do_exit - ------------------------------ -process state changing: - - alloc_proc RUNNING - + +--<----<--+ - + + proc_run + - V +-->---->--+ -PROC_UNINIT -- proc_init/wakeup_proc --> PROC_RUNNABLE -- try_free_pages/do_wait/do_sleep --> PROC_SLEEPING -- - A + + - | +--- do_exit --> PROC_ZOMBIE + - + + - -----------------------wakeup_proc---------------------------------- ------------------------------ -process relations -parent: proc->parent (proc is children) -children: proc->cptr (proc is parent) -older sibling: proc->optr (proc is younger sibling) -younger sibling: proc->yptr (proc is older sibling) ------------------------------ -related syscall for process: -SYS_exit : process exit, -->do_exit -SYS_fork : create child process, dup mm -->do_fork-->wakeup_proc -SYS_wait : wait process -->do_wait -SYS_exec : after fork, process execute a program -->load a program and refresh the mm -SYS_clone : create child thread -->do_fork-->wakeup_proc -SYS_yield : process flag itself need resecheduling, -- proc->need_sched=1, then scheduler will rescheule this process -SYS_sleep : process sleep -->do_sleep -SYS_kill : kill process -->do_kill-->proc->flags |= PF_EXITING - -->wakeup_proc-->do_wait-->do_exit -SYS_getpid : get the process's pid - -*/ - -// the process set's list -list_entry_t proc_list; - -#define HASH_SHIFT 10 -#define HASH_LIST_SIZE (1 << HASH_SHIFT) -#define pid_hashfn(x) (hash32(x, HASH_SHIFT)) - -// has list for process set based on pid -static list_entry_t hash_list[HASH_LIST_SIZE]; - -// idle proc -struct proc_struct *idleproc = NULL; -// init proc -struct proc_struct *initproc = NULL; -// current proc -struct proc_struct *current = NULL; - -static int nr_process = 0; - -void kernel_thread_entry(void); -void forkrets(struct trapframe *tf); -void switch_to(struct context *from, struct context *to); - -// alloc_proc - alloc a proc_struct and init all fields of proc_struct -static struct proc_struct * -alloc_proc(void) { - struct proc_struct *proc = kmalloc(sizeof(struct proc_struct)); - if (proc != NULL) { - //LAB4:EXERCISE1 2009010989 - proc->state = PROC_UNINIT; - proc->pid = -1; - proc->runs = 0; - proc->kstack = 0; - proc->need_resched = 0; - proc->parent = NULL; - proc->mm = NULL; - proc->tf = NULL; - proc->flags = 0; - proc->need_resched = 0; - proc->cr3 = boot_cr3; - memset(&(proc->context), 0, sizeof(struct context)); - memset(proc->name, 0, PROC_NAME_LEN); - proc->exit_code = 0; - proc->wait_state = 0; - list_init(&(proc->run_link)); - list_init(&(proc->list_link)); - proc->time_slice = 0; - proc->cptr = proc->yptr = proc->optr = NULL; - proc->fs_struct = NULL; - } - return proc; -} - -// set_proc_name - set the name of proc -char * -set_proc_name(struct proc_struct *proc, const char *name) { - memset(proc->name, 0, sizeof(proc->name)); - return memcpy(proc->name, name, PROC_NAME_LEN); -} - -// get_proc_name - get the name of proc -char * -get_proc_name(struct proc_struct *proc) { - static char name[PROC_NAME_LEN + 1]; - memset(name, 0, sizeof(name)); - return memcpy(name, proc->name, PROC_NAME_LEN); -} - -// set_links - set the relation links of process -static void -set_links(struct proc_struct *proc) { - list_add(&proc_list, &(proc->list_link)); - proc->yptr = NULL; - if ((proc->optr = proc->parent->cptr) != NULL) { - proc->optr->yptr = proc; - } - proc->parent->cptr = proc; - nr_process ++; -} - -// remove_links - clean the relation links of process -static void -remove_links(struct proc_struct *proc) { - list_del(&(proc->list_link)); - if (proc->optr != NULL) { - proc->optr->yptr = proc->yptr; - } - if (proc->yptr != NULL) { - proc->yptr->optr = proc->optr; - } - else { - proc->parent->cptr = proc->optr; - } - nr_process --; -} - -// get_pid - alloc a unique pid for process -static int -get_pid(void) { - static_assert(MAX_PID > MAX_PROCESS); - struct proc_struct *proc; - list_entry_t *list = &proc_list, *le; - static int next_safe = MAX_PID, last_pid = MAX_PID; - if (++ last_pid >= MAX_PID) { - last_pid = 1; - goto inside; - } - if (last_pid >= next_safe) { - inside: - next_safe = MAX_PID; - repeat: - le = list; - while ((le = list_next(le)) != list) { - proc = le2proc(le, list_link); - if (proc->pid == last_pid) { - if (++ last_pid >= next_safe) { - if (last_pid >= MAX_PID) { - last_pid = 1; - } - next_safe = MAX_PID; - goto repeat; - } - } - else if (proc->pid > last_pid && next_safe > proc->pid) { - next_safe = proc->pid; - } - } - } - return last_pid; -} - -// proc_run - make process "proc" running on cpu -// NOTE: before call switch_to, should load base addr of "proc"'s new PDT -void -proc_run(struct proc_struct *proc) { - if (proc != current) { - bool intr_flag; - struct proc_struct *prev = current, *next = proc; - local_intr_save(intr_flag); - { - //panic("unimpl"); - current = proc; - //load_sp(next->kstack + KSTACKSIZE); - lcr3(next->cr3); - tlb_invalidate_all(); - switch_to(&(prev->context), &(next->context)); - } - local_intr_restore(intr_flag); - } -} - -// forkret -- the first kernel entry point of a new thread/process -// NOTE: the addr of forkret is setted in copy_thread function -// after switch_to, the current proc will execute here. -static void -forkret(void) { - forkrets(current->tf); -} - -// hash_proc - add proc into proc hash_list -static void -hash_proc(struct proc_struct *proc) { - list_add(hash_list + pid_hashfn(proc->pid), &(proc->hash_link)); -} - -// unhash_proc - delete proc from proc hash_list -static void -unhash_proc(struct proc_struct *proc) { - list_del(&(proc->hash_link)); -} - -// find_proc - find proc frome proc hash_list according to pid -struct proc_struct * -find_proc(int pid) { - if (0 < pid && pid < MAX_PID) { - list_entry_t *list = hash_list + pid_hashfn(pid), *le = list; - while ((le = list_next(le)) != list) { - struct proc_struct *proc = le2proc(le, hash_link); - if (proc->pid == pid) { - return proc; - } - } - } - return NULL; -} - -// kernel_thread - create a kernel thread using "fn" function -// NOTE: the contents of temp trapframe tf will be copied to -// proc->tf in do_fork-->copy_thread function -int -kernel_thread(int (*fn)(void *), void *arg, uint32_t clone_flags) { - struct trapframe tf; - memset(&tf, 0, sizeof(struct trapframe)); - tf.tf_regs.reg_r[MIPS_REG_A0] = (uint32_t)arg; - tf.tf_regs.reg_r[MIPS_REG_A1] = (uint32_t)fn; - tf.tf_regs.reg_r[MIPS_REG_V0] = 0; - //TODO - tf.tf_status = read_c0_status(); - tf.tf_status &= ~ST0_KSU; - tf.tf_status |= ST0_IE; - tf.tf_status |= ST0_EXL; - tf.tf_regs.reg_r[MIPS_REG_GP] = __read_reg($28); - tf.tf_epc = (uint32_t)kernel_thread_entry; - return do_fork(clone_flags | CLONE_VM, 0, &tf); -} - -// setup_kstack - alloc pages with size KSTACKPAGE as process kernel stack -static int -setup_kstack(struct proc_struct *proc) { - struct Page *page = alloc_pages(KSTACKPAGE); - if (page != NULL) { - proc->kstack = (uintptr_t)page2kva(page); - return 0; - } - return -E_NO_MEM; -} - -// put_kstack - free the memory space of process kernel stack -static void -put_kstack(struct proc_struct *proc) { - free_pages(kva2page((void *)(proc->kstack)), KSTACKPAGE); -} - -// setup_pgdir - alloc one page as PDT -static int -setup_pgdir(struct mm_struct *mm) { - struct Page *page; - if ((page = alloc_page()) == NULL) { - return -E_NO_MEM; - } - pde_t *pgdir = page2kva(page); - memcpy(pgdir, boot_pgdir, PGSIZE); - //panic("unimpl"); - //pgdir[PDX(VPT)] = PADDR(pgdir) | PTE_P | PTE_W; - mm->pgdir = pgdir; - return 0; -} - -// put_pgdir - free the memory space of PDT -static void -put_pgdir(struct mm_struct *mm) { - free_page(kva2page(mm->pgdir)); -} - -// copy_mm - process "proc" duplicate OR share process "current"'s mm according clone_flags -// - if clone_flags & CLONE_VM, then "share" ; else "duplicate" -static int -copy_mm(uint32_t clone_flags, struct proc_struct *proc) { - struct mm_struct *mm, *oldmm = current->mm; - - /* current is a kernel thread */ - if (oldmm == NULL) { - return 0; - } - if (clone_flags & CLONE_VM) { - mm = oldmm; - goto good_mm; - } - - int ret = -E_NO_MEM; - if ((mm = mm_create()) == NULL) { - goto bad_mm; - } - if (setup_pgdir(mm) != 0) { - goto bad_pgdir_cleanup_mm; - } - - lock_mm(oldmm); - { - ret = dup_mmap(mm, oldmm); - } - unlock_mm(oldmm); - - if (ret != 0) { - goto bad_dup_cleanup_mmap; - } - -good_mm: - mm_count_inc(mm); - proc->mm = mm; - proc->cr3 = PADDR(mm->pgdir); - return 0; -bad_dup_cleanup_mmap: - exit_mmap(mm); - put_pgdir(mm); -bad_pgdir_cleanup_mm: - mm_destroy(mm); -bad_mm: - return ret; -} - -// copy_thread - setup the trapframe on the process's kernel stack top and -// - setup the kernel entry point and stack of process -static void -copy_thread(struct proc_struct *proc, uintptr_t esp, struct trapframe *tf) { - proc->tf = (struct trapframe *)(proc->kstack + KSTACKSIZE) - 1; - *(proc->tf) = *tf; - proc->tf->tf_regs.reg_r[MIPS_REG_V0] = 0; - if(esp == 0) //a kernel thread - esp = (uintptr_t)proc->tf - 32; - proc->tf->tf_regs.reg_r[MIPS_REG_SP] = esp; - proc->context.sf_ra = (uintptr_t)forkret; - proc->context.sf_sp = (uintptr_t)(proc->tf) - 32; -} - -//copy_fs&put_fs function used by do_fork in LAB8 -static int -copy_fs(uint32_t clone_flags, struct proc_struct *proc) { - struct fs_struct *fs_struct, *old_fs_struct = current->fs_struct; - assert(old_fs_struct != NULL); - - if (clone_flags & CLONE_FS) { - fs_struct = old_fs_struct; - goto good_fs_struct; - } - - int ret = -E_NO_MEM; - if ((fs_struct = fs_create()) == NULL) { - goto bad_fs_struct; - } - - if ((ret = dup_fs(fs_struct, old_fs_struct)) != 0) { - goto bad_dup_cleanup_fs; - } - -good_fs_struct: - fs_count_inc(fs_struct); - proc->fs_struct = fs_struct; - return 0; - -bad_dup_cleanup_fs: - fs_destroy(fs_struct); -bad_fs_struct: - return ret; -} - -static void -put_fs(struct proc_struct *proc) { - struct fs_struct *fs_struct = proc->fs_struct; - if (fs_struct != NULL) { - if (fs_count_dec(fs_struct) == 0) { - fs_destroy(fs_struct); - } - } -} - -// do_fork - parent process for a new child process -// 1. call alloc_proc to allocate a proc_struct -// 2. call setup_kstack to allocate a kernel stack for child process -// 3. call copy_mm to dup OR share mm according clone_flag -// 4. call copy_thread to setup tf & context in proc_struct -// 5. insert proc_struct into hash_list && proc_list -// 6. call wakup_proc to make the new child process RUNNABLE -// 7. set the -int -do_fork(uint32_t clone_flags, uintptr_t stack, struct trapframe *tf) { - int ret = -E_NO_FREE_PROC; - struct proc_struct *proc; - if (nr_process >= MAX_PROCESS) { - goto fork_out; - } - ret = -E_NO_MEM; - //LAB4:EXERCISE2 2009010989 - if ((proc = alloc_proc()) == NULL) { - goto fork_out; - } - - proc->parent = current; - - if(setup_kstack(proc)){ - goto bad_fork_cleanup_proc; - } - //LAB8:EXERCISE2 2009010989 HINT:how to copy the fs in parent's proc_struct? - if (copy_fs(clone_flags, proc) != 0) { - goto bad_fork_cleanup_kstack; - } - if (copy_mm(clone_flags, proc)){ - goto bad_fork_cleanup_fs; - } - - copy_thread(proc, (uint32_t)stack, tf); - - proc->pid = get_pid(); - hash_proc(proc); - - - //list_add(&proc_list, &(proc->list_link)); - set_links(proc); - - wakeup_proc(proc); - - ret = proc->pid; - -fork_out: - return ret; - -bad_fork_cleanup_fs: - put_fs(proc); -bad_fork_cleanup_kstack: - put_kstack(proc); -bad_fork_cleanup_proc: - kfree(proc); - goto fork_out; -} - -// do_exit - called by sys_exit -// 1. call exit_mmap & put_pgdir & mm_destroy to free the almost all memory space of process -// 2. set process' state as PROC_ZOMBIE, then call wakeup_proc(parent) to ask parent reclaim itself. -// 3. call scheduler to switch to other process -int -do_exit(int error_code) { - if (current == idleproc) { - panic("idleproc exit.\n"); - } - if (current == initproc) { - panic("initproc exit.\n"); - } - - struct mm_struct *mm = current->mm; - if (mm != NULL) { - lcr3(boot_cr3); - if (mm_count_dec(mm) == 0) { - exit_mmap(mm); - put_pgdir(mm); - mm_destroy(mm); - } - current->mm = NULL; - } - put_fs(current); //in LAB8 - current->state = PROC_ZOMBIE; - current->exit_code = error_code; - - - bool intr_flag; - struct proc_struct *proc; - local_intr_save(intr_flag); - { - proc = current->parent; - if (proc->wait_state == WT_CHILD) { - wakeup_proc(proc); - } - while (current->cptr != NULL) { - proc = current->cptr; - current->cptr = proc->optr; - - proc->yptr = NULL; - if ((proc->optr = initproc->cptr) != NULL) { - initproc->cptr->yptr = proc; - } - proc->parent = initproc; - initproc->cptr = proc; - if (proc->state == PROC_ZOMBIE) { - if (initproc->wait_state == WT_CHILD) { - wakeup_proc(initproc); - } - } - } - } - local_intr_restore(intr_flag); - - schedule(); - panic("do_exit will not return!! %d.\n", current->pid); -} - -//load_icode_read is used by load_icode in LAB8 -static int -load_icode_read(int fd, void *buf, size_t len, off_t offset) { - int ret; - if ((ret = sysfile_seek(fd, offset, LSEEK_SET)) != 0) { - return ret; - } - if ((ret = sysfile_read(fd, buf, len)) != len) { - return (ret < 0) ? ret : -1; - } - return 0; -} - -// load_icode - called by sys_exec-->do_execve -// 1. create a new mm for current process -// 2. create a new PDT, and mm->pgdir= kernel virtual addr of PDT -// 3. copy TEXT/DATA/BSS parts in binary to memory space of process -// 4. call mm_map to setup user stack, and put parameters into user stack -// 5. setup trapframe for user environment -static int -load_icode(int fd, int argc, char **kargv) { - if (current->mm != NULL) { - panic("load_icode: current->mm must be empty.\n"); - } - //panic("unimpl"); - int ret = -E_NO_MEM; - struct mm_struct *mm; - if ((mm = mm_create()) == NULL) { - goto bad_mm; - } - if (setup_pgdir(mm) != 0) { - goto bad_pgdir_cleanup_mm; - } - - //assert(((uint32_t)binary & 0x3) == 0); - - struct __elfhdr ___elfhdr__; - struct elfhdr32 __elf, *elf = &__elf; - if ((ret = load_icode_read(fd, &___elfhdr__, sizeof(struct __elfhdr), 0)) != 0) { - goto bad_elf_cleanup_pgdir; - } - - _load_elfhdr((unsigned char*)&___elfhdr__, &__elf); - - if (elf->e_magic != ELF_MAGIC) { - ret = -E_INVAL_ELF; - goto bad_elf_cleanup_pgdir; - } - - struct proghdr _ph, *ph = &_ph; - uint32_t vm_flags, phnum; - uint32_t perm = 0; - struct Page *page; - for (phnum = 0; phnum < elf->e_phnum; phnum ++) { - off_t phoff = elf->e_phoff + sizeof(struct proghdr) * phnum; - if ((ret = load_icode_read(fd, ph, sizeof(struct proghdr), phoff)) != 0) { - goto bad_cleanup_mmap; - } - if (ph->p_type != ELF_PT_LOAD) { - continue ; - } - if (ph->p_filesz > ph->p_memsz) { - ret = -E_INVAL_ELF; - goto bad_cleanup_mmap; - } - vm_flags = 0; - //ptep_set_u_read(&perm); - perm |= PTE_U; - if (ph->p_flags & ELF_PF_X) vm_flags |= VM_EXEC; - if (ph->p_flags & ELF_PF_W) vm_flags |= VM_WRITE; - if (ph->p_flags & ELF_PF_R) vm_flags |= VM_READ; - if (vm_flags & VM_WRITE) perm |= PTE_W; - - if ((ret = mm_map(mm, ph->p_va, ph->p_memsz, vm_flags, NULL)) != 0) { - goto bad_cleanup_mmap; - } - - off_t offset = ph->p_offset; - size_t off, size; - uintptr_t start = ph->p_va, end, la = ROUNDDOWN_2N(start, PGSHIFT); - - end = ph->p_va + ph->p_filesz; - while (start < end) { - if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) { - ret = -E_NO_MEM; - goto bad_cleanup_mmap; - } - off = start - la, size = PGSIZE - off, la += PGSIZE; - if (end < la) { - size -= la - end; - } - if ((ret = load_icode_read(fd, page2kva(page) + off, size, offset)) != 0) { - goto bad_cleanup_mmap; - } - start += size, offset += size; - } - - end = ph->p_va + ph->p_memsz; - - if (start < la) { - if (start >= end) { - continue ; - } - off = start + PGSIZE - la, size = PGSIZE - off; - if (end < la) { - size -= la - end; - } - memset(page2kva(page) + off, 0, size); - start += size; - assert((end < la && start == end) || (end >= la && start == la)); - } - - while (start < end) { - if ((page = pgdir_alloc_page(mm->pgdir, la, perm)) == NULL) { - ret = -E_NO_MEM; - goto bad_cleanup_mmap; - } - off = start - la, size = PGSIZE - off, la += PGSIZE; - if (end < la) { - size -= la - end; - } - memset(page2kva(page) + off, 0, size); - start += size; - } - } - sysfile_close(fd); - - //mm->brk_start = mm->brk = ROUNDUP(mm->brk_start, PGSIZE); - - vm_flags = VM_READ | VM_WRITE | VM_STACK; - if ((ret = mm_map(mm, USTACKTOP - USTACKSIZE, USTACKSIZE, vm_flags, NULL)) != 0) { - goto bad_cleanup_mmap; - } - - mm_count_inc(mm); - current->mm = mm; - current->cr3 = PADDR(mm->pgdir); - lcr3(PADDR(mm->pgdir)); - - //LAB5:EXERCISE1 2009010989 - // should set cs,ds,es,ss,esp,eip,eflags -#if 0 - tf->tf_cs = USER_CS; - tf->tf_ds = tf->tf_es = USER_DS; - tf->tf_ss = USER_DS; - tf->tf_esp = USTACKTOP; - tf->tf_eip = elf->e_entry; - tf->tf_eflags = FL_IF; -#endif - uintptr_t stacktop = USTACKTOP - argc * PGSIZE; - char **uargv = (char **)(stacktop - argc * sizeof(char *)); - int i; - for (i = 0; i < argc; i ++) { - uargv[i] = strcpy((char *)(stacktop + i * PGSIZE), kargv[i]); - } - //stacktop = (uintptr_t)uargv - sizeof(int); - //*(int *)stacktop = argc; - - struct trapframe *tf = current->tf; - memset(tf, 0, sizeof(struct trapframe)); - - tf->tf_epc = elf->e_entry; - tf->tf_regs.reg_r[MIPS_REG_SP] = USTACKTOP; - uint32_t status = read_c0_status(); - status &= ~ST0_KSU; - status |= KSU_USER; - status |= ST0_EXL; - tf->tf_status = status; - tf->tf_regs.reg_r[MIPS_REG_A0] = argc; - tf->tf_regs.reg_r[MIPS_REG_A1] = (uint32_t)uargv; - - //kprintf("## %08x\n", tf->tf_status); - ret = 0; -out: - return ret; -bad_cleanup_mmap: - exit_mmap(mm); -bad_elf_cleanup_pgdir: - put_pgdir(mm); -bad_pgdir_cleanup_mm: - mm_destroy(mm); -bad_mm: - goto out; -} - -// this function isn't very correct in LAB8 -static void -put_kargv(int argc, char **kargv) { - while (argc > 0) { - kfree(kargv[-- argc]); - } -} - -static int -copy_kargv(struct mm_struct *mm, int argc, char **kargv, const char **argv) { - int i, ret = -E_INVAL; - if (!user_mem_check(mm, (uintptr_t)argv, sizeof(const char *) * argc, 0)) { - return ret; - } - for (i = 0; i < argc; i ++) { - char *buffer; - if ((buffer = kmalloc(EXEC_MAX_ARG_LEN + 1)) == NULL) { - goto failed_nomem; - } - if (!copy_string(mm, buffer, argv[i], EXEC_MAX_ARG_LEN + 1)) { - kfree(buffer); - goto failed_cleanup; - } - kargv[i] = buffer; - } - return 0; - -failed_nomem: - ret = -E_NO_MEM; -failed_cleanup: - put_kargv(i, kargv); - return ret; -} - -// do_execve - call exit_mmap(mm)&pug_pgdir(mm) to reclaim memory space of current process -// - call load_icode to setup new memory space accroding binary prog. -int -do_execve(const char *name, int argc, const char **argv) { - static_assert(EXEC_MAX_ARG_LEN >= FS_MAX_FPATH_LEN); - struct mm_struct *mm = current->mm; - if (!(argc >= 1 && argc <= EXEC_MAX_ARG_NUM)) { - return -E_INVAL; - } - - char local_name[PROC_NAME_LEN + 1]; - memset(local_name, 0, sizeof(local_name)); - - char *kargv[EXEC_MAX_ARG_NUM]; - const char *path; - - int ret = -E_INVAL; - - lock_mm(mm); - if (name == NULL) { - snprintf(local_name, sizeof(local_name), " %d", current->pid); - } - else { - if (!copy_string(mm, local_name, name, sizeof(local_name))) { - unlock_mm(mm); - return ret; - } - } - if ((ret = copy_kargv(mm, argc, kargv, argv)) != 0) { - unlock_mm(mm); - return ret; - } - path = argv[0]; - unlock_mm(mm); - fs_closeall(current->fs_struct); - - /* sysfile_open will check the first argument path, thus we have to use a user-space pointer, and argv[0] may be incorrect */ - int fd; - if ((ret = fd = sysfile_open(path, O_RDONLY)) < 0) { - goto execve_exit; - } - if (mm != NULL) { - lcr3(boot_cr3); - if (mm_count_dec(mm) == 0) { - exit_mmap(mm); - put_pgdir(mm); - mm_destroy(mm); - } - current->mm = NULL; - } - ret= -E_NO_MEM;; - if ((ret = load_icode(fd, argc, kargv)) != 0) { - goto execve_exit; - } - put_kargv(argc, kargv); - set_proc_name(current, local_name); - return 0; - -execve_exit: - put_kargv(argc, kargv); - do_exit(ret); - panic("already exit: %e.\n", ret); -} - -// do_yield - ask the scheduler to reschedule -int -do_yield(void) { - current->need_resched = 1; - return 0; -} - -// do_wait - wait one OR any children with PROC_ZOMBIE state, and free memory space of kernel stack -// - proc struct of this child. -// NOTE: only after do_wait function, all resources of the child proces are free. -int -do_wait(int pid, int *code_store) { - assert(current); - struct mm_struct *mm = current->mm; - if (code_store != NULL) { - if (!user_mem_check(mm, (uintptr_t)code_store, sizeof(int), 1)) { - return -E_INVAL; - } - } - - struct proc_struct *proc; - bool intr_flag, haskid; -repeat: - haskid = 0; - if (pid != 0) { - proc = find_proc(pid); - if (proc != NULL && proc->parent == current) { - haskid = 1; - if (proc->state == PROC_ZOMBIE) { - goto found; - } - } - } - else { - proc = current->cptr; - for (; proc != NULL; proc = proc->optr) { - haskid = 1; - if (proc->state == PROC_ZOMBIE) { - goto found; - } - } - } - if (haskid) { - current->state = PROC_SLEEPING; - current->wait_state = WT_CHILD; - schedule(); - if (current->flags & PF_EXITING) { - do_exit(-E_KILLED); - } - goto repeat; - } - return -E_BAD_PROC; - -found: - if (proc == idleproc || proc == initproc) { - panic("wait idleproc or initproc.\n"); - } - if (code_store != NULL) { - *code_store = proc->exit_code; - } - local_intr_save(intr_flag); - { - unhash_proc(proc); - remove_links(proc); - } - local_intr_restore(intr_flag); - put_kstack(proc); - kfree(proc); - return 0; -} - -// do_kill - kill process with pid by set this process's flags with PF_EXITING -int -do_kill(int pid) { - struct proc_struct *proc; - if ((proc = find_proc(pid)) != NULL) { - if (!(proc->flags & PF_EXITING)) { - proc->flags |= PF_EXITING; - if (proc->wait_state & WT_INTERRUPTED) { - wakeup_proc(proc); - } - return 0; - } - return -E_KILLED; - } - return -E_INVAL; -} - -// kernel_execve - do SYS_exec syscall to exec a user program called by user_main kernel_thread -static int -kernel_execve(const char *name, const char **argv) { - int argc = 0, ret; - while (argv[argc] != NULL) { - argc ++; - } - //panic("unimpl"); - asm volatile( - "la $v0, %1;\n" /* syscall no. */ - "move $a0, %2;\n" - "move $a1, %3;\n" - "move $a2, %4;\n" - "move $a3, %5;\n" - "syscall;\n" - "nop;\n" - "move %0, $v0;\n" - : "=r"(ret) - : "i"(SYSCALL_BASE+SYS_exec), "r"(name), "r"(argc), "r"(argv), "r"(argc) - : "a0", "a1", "a2", "a3", "v0" - ); - return ret; -} - -#define __KERNEL_EXECVE(name, path, ...) ({ \ -const char *argv[] = {path, ##__VA_ARGS__, NULL}; \ - kprintf("kernel_execve: pid = %d, name = \"%s\".\n", \ - current->pid, name); \ - kernel_execve(name, argv); \ -}) - -#define KERNEL_EXECVE(x, ...) __KERNEL_EXECVE(#x, #x, ##__VA_ARGS__) - -#define KERNEL_EXECVE2(x, ...) KERNEL_EXECVE(x, ##__VA_ARGS__) - -#define __KERNEL_EXECVE3(x, s, ...) KERNEL_EXECVE(x, #s, ##__VA_ARGS__) - -#define KERNEL_EXECVE3(x, s, ...) __KERNEL_EXECVE3(x, s, ##__VA_ARGS__) - -// user_main - kernel thread used to exec a user program -static int -user_main(void *arg) { - KERNEL_EXECVE(sh); - panic("user_main execve failed.\n"); -} - -// init_main - the second kernel thread used to create user_main kernel threads -static int -init_main(void *arg) { - int ret; - if ((ret = vfs_set_bootfs("disk0:")) != 0) { - panic("set boot fs failed: %e.\n", ret); - } - - size_t nr_free_pages_store = nr_free_pages(); - size_t slab_allocated_store = kallocated(); - - int pid = kernel_thread(user_main, NULL, 0); - if (pid <= 0) { - panic("create user_main failed.\n"); - } - - while (do_wait(0, NULL) == 0) { - schedule(); - } - - fs_cleanup(); - kprintf("all user-mode processes have quit.\n"); - assert(initproc->cptr == NULL && initproc->yptr == NULL && initproc->optr == NULL); - assert(nr_process == 2); - assert(list_next(&proc_list) == &(initproc->list_link)); - assert(list_prev(&proc_list) == &(initproc->list_link)); - assert(nr_free_pages_store == nr_free_pages()); - assert(slab_allocated_store == kallocated()); - kprintf("init check memory pass.\n"); - return 0; -} - -// proc_init - set up the first kernel thread idleproc "idle" by itself and -// - create the second kernel thread init_main -void -proc_init(void) { - int i; - - list_init(&proc_list); - for (i = 0; i < HASH_LIST_SIZE; i ++) { - list_init(hash_list + i); - } - - if ((idleproc = alloc_proc()) == NULL) { - panic("cannot alloc idleproc.\n"); - } - - idleproc->pid = 0; - idleproc->state = PROC_RUNNABLE; - idleproc->kstack = (uintptr_t)bootstack; - idleproc->need_resched = 1; - - if ((idleproc->fs_struct = fs_create()) == NULL) { - panic("create fs_struct (idleproc) failed.\n"); - } - fs_count_inc(idleproc->fs_struct); - - set_proc_name(idleproc, "idle"); - nr_process ++; - - current = idleproc; - - int pid = kernel_thread(init_main, NULL, 0); - if (pid <= 0) { - panic("create init_main failed.\n"); - } - - initproc = find_proc(pid); - set_proc_name(initproc, "init"); - - assert(idleproc != NULL && idleproc->pid == 0); - assert(initproc != NULL && initproc->pid == 1); -} - -// cpu_idle - at the end of kern_init, the first kernel thread idleproc will do below works -void -cpu_idle(void) { - while (1) { - if (current->need_resched) { - schedule(); - } - } -} - -// do_sleep - set current process state to sleep and add timer with "time" -// - then call scheduler. if process run again, delete timer first. -int -do_sleep(unsigned int time) { - if (time == 0) { - return 0; - } - bool intr_flag; - local_intr_save(intr_flag); - timer_t __timer, *timer = timer_init(&__timer, current, time); - current->state = PROC_SLEEPING; - current->wait_state = WT_TIMER; - add_timer(timer); - local_intr_restore(intr_flag); - - schedule(); - - del_timer(timer); - return 0; -} diff --git a/ucore-thumips/kern/process/proc.h b/ucore-thumips/kern/process/proc.h deleted file mode 100644 index 5d3eef4..0000000 --- a/ucore-thumips/kern/process/proc.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __KERN_PROCESS_PROC_H__ -#define __KERN_PROCESS_PROC_H__ - -#include -#include -#include -#include - - -// process's state in his life cycle -enum proc_state { - PROC_UNINIT = 0, // uninitialized - PROC_SLEEPING, // sleeping - PROC_RUNNABLE, // runnable(maybe running) - PROC_ZOMBIE, // almost dead, and wait parent proc to reclaim his resource - PROC_FORCE_32 = 0xFFFFFFFF -}; - -// Saved registers for kernel context switches. -// Don't need to save all the %fs etc. segment registers, -// because they are constant across kernel contexts. -// Save all the regular registers so we don't need to care -// which are caller save, but not the return register %eax. -// (Not saving %eax just simplifies the switching code.) -// The layout of context must match code in switch.S. -struct context { - uint32_t sf_s0; - uint32_t sf_s1; - uint32_t sf_s2; - uint32_t sf_s3; - uint32_t sf_s4; - uint32_t sf_s5; - uint32_t sf_s6; - uint32_t sf_s7; - uint32_t sf_s8; - uint32_t sf_gp; - uint32_t sf_ra; - uint32_t sf_sp; -}; - -#define PROC_NAME_LEN 30 -#define MAX_PROCESS 4096 -#define MAX_PID (MAX_PROCESS * 2) - -extern list_entry_t proc_list; - -struct proc_struct { - enum proc_state state; // Process state - int pid; // Process ID - int runs; // the running times of Proces - uintptr_t kstack; // Process kernel stack - volatile bool need_resched; // bool value: need to be rescheduled to release CPU? - struct proc_struct *parent; // the parent process - struct mm_struct *mm; // Process's memory management field - struct context context; // Switch here to run process - struct trapframe *tf; // Trap frame for current interrupt - uintptr_t cr3; // CR3 register: the base addr of Page Directroy Table(PDT) - uint32_t flags; // Process flag - char name[PROC_NAME_LEN + 1]; // Process name - list_entry_t list_link; // Process link list - list_entry_t hash_link; // Process hash list - int exit_code; // exit code (be sent to parent proc) - uint32_t wait_state; // waiting state - struct proc_struct *cptr, *yptr, *optr; // relations between processes - struct run_queue *rq; // running queue contains Process - list_entry_t run_link; // the entry linked in run queue - int time_slice; // time slice for occupying the CPU - struct fs_struct *fs_struct; // the file related info(pwd, files_count, files_array, fs_semaphore) of process -}; - - -#define PF_EXITING 0x00000001 // getting shutdown - -#define WT_CHILD (0x00000001 | WT_INTERRUPTED) -#define WT_INTERRUPTED 0x80000000 // the wait state could be interrupted -#define WT_CHILD (0x00000001 | WT_INTERRUPTED) // wait child process -#define WT_KSEM 0x00000100 // wait kernel semaphore -#define WT_TIMER (0x00000002 | WT_INTERRUPTED) // wait timer -#define WT_KBD (0x00000004 | WT_INTERRUPTED) // wait the input of keyboard - -#define le2proc(le, member) \ - to_struct((le), struct proc_struct, member) - -extern struct proc_struct *idleproc, *initproc, *current; - -void proc_init(void); -void proc_run(struct proc_struct *proc); -int kernel_thread(int (*fn)(void *), void *arg, uint32_t clone_flags); - -char *set_proc_name(struct proc_struct *proc, const char *name); -char *get_proc_name(struct proc_struct *proc); -void cpu_idle(void) __attribute__((noreturn)); - -struct proc_struct *find_proc(int pid); -int do_fork(uint32_t clone_flags, uintptr_t stack, struct trapframe *tf); -int do_exit(int error_code); -int do_yield(void); -int do_execve(const char *name, int argc, const char **argv); -int do_wait(int pid, int *code_store); -int do_kill(int pid); -int do_sleep(unsigned int time); - -#endif /* !__KERN_PROCESS_PROC_H__ */ - diff --git a/ucore-thumips/kern/process/switch.S b/ucore-thumips/kern/process/switch.S deleted file mode 100644 index 855044f..0000000 --- a/ucore-thumips/kern/process/switch.S +++ /dev/null @@ -1,59 +0,0 @@ -#include - -.set noreorder - -.text -.globl switch_to -.type switch_to,@function -.ent switch_to -switch_to: -/* - * a0 contains a pointer to the old thread's struct pcb. - * a1 contains a pointer to the new thread's struct pcb. - * - * The only thing we touch in the pcb is the first word, which - * we save the stack pointer in. The other registers get saved - * on the stack, namely: - * - * s0-s8 - * gp, ra - * - * The order must match arch/mips/include/switchframe.h. - */ - - /* Save the registers */ - sw sp, 44(a0) - sw ra, 40(a0) - sw gp, 36(a0) - sw s8, 32(a0) - sw s7, 28(a0) - sw s6, 24(a0) - sw s5, 20(a0) - sw s4, 16(a0) - sw s3, 12(a0) - sw s2, 8(a0) - sw s1, 4(a0) - sw s0, 0(a0) - - nop - - /* Now, restore the registers */ - lw s0, 0(a1) - lw s1, 4(a1) - lw s2, 8(a1) - lw s3, 12(a1) - lw s4, 16(a1) - lw s5, 20(a1) - lw s6, 24(a1) - lw s7, 28(a1) - lw s8, 32(a1) - lw gp, 36(a1) - lw ra, 40(a1) - lw sp, 44(a1) - nop /* delay slot for load */ - - /* and return. */ - j ra - nop - .end switch_to - diff --git a/ucore-thumips/kern/schedule/default_sched.c b/ucore-thumips/kern/schedule/default_sched.c deleted file mode 100644 index 2316990..0000000 --- a/ucore-thumips/kern/schedule/default_sched.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include -#include - -static void -RR_init(struct run_queue *rq) { - list_init(&(rq->run_list)); - rq->proc_num = 0; -} - -static void -RR_enqueue(struct run_queue *rq, struct proc_struct *proc) { - assert(list_empty(&(proc->run_link))); - list_add_before(&(rq->run_list), &(proc->run_link)); - if (proc->time_slice == 0 || proc->time_slice > rq->max_time_slice) { - proc->time_slice = rq->max_time_slice; - } - proc->rq = rq; - rq->proc_num ++; -} - -static void -RR_dequeue(struct run_queue *rq, struct proc_struct *proc) { - assert(!list_empty(&(proc->run_link)) && proc->rq == rq); - list_del_init(&(proc->run_link)); - rq->proc_num --; -} - -static struct proc_struct * -RR_pick_next(struct run_queue *rq) { - list_entry_t *le = list_next(&(rq->run_list)); - if (le != &(rq->run_list)) { - return le2proc(le, run_link); - } - return NULL; -} - -static void -RR_proc_tick(struct run_queue *rq, struct proc_struct *proc) { - if (proc->time_slice > 0) { - proc->time_slice --; - } - if (proc->time_slice == 0) { - proc->need_resched = 1; - } -} - -struct sched_class default_sched_class = { - .name = "RR_scheduler", - .init = RR_init, - .enqueue = RR_enqueue, - .dequeue = RR_dequeue, - .pick_next = RR_pick_next, - .proc_tick = RR_proc_tick, -}; - diff --git a/ucore-thumips/kern/schedule/default_sched.h b/ucore-thumips/kern/schedule/default_sched.h deleted file mode 100644 index 2f21fbd..0000000 --- a/ucore-thumips/kern/schedule/default_sched.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __KERN_SCHEDULE_SCHED_RR_H__ -#define __KERN_SCHEDULE_SCHED_RR_H__ - -#include - -extern struct sched_class default_sched_class; - -#endif /* !__KERN_SCHEDULE_SCHED_RR_H__ */ - diff --git a/ucore-thumips/kern/schedule/sched.c b/ucore-thumips/kern/schedule/sched.c deleted file mode 100644 index f66c6e1..0000000 --- a/ucore-thumips/kern/schedule/sched.c +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static list_entry_t timer_list; - -static struct sched_class *sched_class; - -static struct run_queue *rq; - -static inline void -sched_class_enqueue(struct proc_struct *proc) { - if (proc != idleproc) { - sched_class->enqueue(rq, proc); - } -} - -static inline void -sched_class_dequeue(struct proc_struct *proc) { - sched_class->dequeue(rq, proc); -} - -static inline struct proc_struct * -sched_class_pick_next(void) { - return sched_class->pick_next(rq); -} - -static void -sched_class_proc_tick(struct proc_struct *proc) { - if (proc != idleproc) { - sched_class->proc_tick(rq, proc); - } - else { - proc->need_resched = 1; - } -} - -static struct run_queue __rq; - -void -sched_init(void) { - list_init(&timer_list); - - sched_class = &default_sched_class; - - rq = &__rq; - rq->max_time_slice = 20; - sched_class->init(rq); - - kprintf("sched class: %s\n", sched_class->name); -} - -void -wakeup_proc(struct proc_struct *proc) { - assert(proc->state != PROC_ZOMBIE); - bool intr_flag; - local_intr_save(intr_flag); - { - if (proc->state != PROC_RUNNABLE) { - proc->state = PROC_RUNNABLE; - proc->wait_state = 0; - if (proc != current) { - sched_class_enqueue(proc); - } - } - else { - warn("wakeup runnable process.\n"); - } - } - local_intr_restore(intr_flag); -} - -void -schedule(void) { - bool intr_flag; - struct proc_struct *next; - local_intr_save(intr_flag); - { - current->need_resched = 0; - if (current->state == PROC_RUNNABLE) { - sched_class_enqueue(current); - } - if ((next = sched_class_pick_next()) != NULL) { - sched_class_dequeue(next); - } - if (next == NULL) { - next = idleproc; - } - next->runs ++; - if (next != current) { - //kprintf("########################\n"); - //kprintf("c %d TO %d\n", current->pid, next->pid); - //print_trapframe(next->tf); - //kprintf("@@@@@@@@@@@@@@@@@@@@@@@@\n"); - proc_run(next); - } - } - local_intr_restore(intr_flag); -} - -void -add_timer(timer_t *timer) { - bool intr_flag; - local_intr_save(intr_flag); - { - assert(timer->expires > 0 && timer->proc != NULL); - assert(list_empty(&(timer->timer_link))); - list_entry_t *le = list_next(&timer_list); - while (le != &timer_list) { - timer_t *next = le2timer(le, timer_link); - if (timer->expires < next->expires) { - next->expires -= timer->expires; - break; - } - timer->expires -= next->expires; - le = list_next(le); - } - list_add_before(le, &(timer->timer_link)); - } - local_intr_restore(intr_flag); -} - -void -del_timer(timer_t *timer) { - bool intr_flag; - local_intr_save(intr_flag); - { - if (!list_empty(&(timer->timer_link))) { - if (timer->expires != 0) { - list_entry_t *le = list_next(&(timer->timer_link)); - if (le != &timer_list) { - timer_t *next = le2timer(le, timer_link); - next->expires += timer->expires; - } - } - list_del_init(&(timer->timer_link)); - } - } - local_intr_restore(intr_flag); -} - -void -run_timer_list(void) { - bool intr_flag; - local_intr_save(intr_flag); - { - list_entry_t *le = list_next(&timer_list); - if (le != &timer_list) { - timer_t *timer = le2timer(le, timer_link); - assert(timer->expires != 0); - timer->expires --; - while (timer->expires == 0) { - le = list_next(le); - struct proc_struct *proc = timer->proc; - if (proc->wait_state != 0) { - assert(proc->wait_state & WT_INTERRUPTED); - } - else { - warn("process %d's wait_state == 0.\n", proc->pid); - } - wakeup_proc(proc); - del_timer(timer); - if (le == &timer_list) { - break; - } - timer = le2timer(le, timer_link); - } - } - sched_class_proc_tick(current); - } - local_intr_restore(intr_flag); -} diff --git a/ucore-thumips/kern/schedule/sched.h b/ucore-thumips/kern/schedule/sched.h deleted file mode 100644 index 3adbe1b..0000000 --- a/ucore-thumips/kern/schedule/sched.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef __KERN_SCHEDULE_SCHED_H__ -#define __KERN_SCHEDULE_SCHED_H__ - -#include -#include -//#include - -struct proc_struct; - -typedef struct { - unsigned int expires; - struct proc_struct *proc; - list_entry_t timer_link; -} timer_t; - -#define le2timer(le, member) \ -to_struct((le), timer_t, member) - -static inline timer_t * -timer_init(timer_t *timer, struct proc_struct *proc, int expires) { - timer->expires = expires; - timer->proc = proc; - list_init(&(timer->timer_link)); - return timer; -} - -struct run_queue; - -// The introduction of scheduling classes is borrrowed from Linux, and makes the -// core scheduler quite extensible. These classes (the scheduler modules) encapsulate -// the scheduling policies. -struct sched_class { - // the name of sched_class - const char *name; - // Init the run queue - void (*init)(struct run_queue *rq); - // put the proc into runqueue, and this function must be called with rq_lock - void (*enqueue)(struct run_queue *rq, struct proc_struct *proc); - // get the proc out runqueue, and this function must be called with rq_lock - void (*dequeue)(struct run_queue *rq, struct proc_struct *proc); - // choose the next runnable task - struct proc_struct *(*pick_next)(struct run_queue *rq); - // dealer of the time-tick - void (*proc_tick)(struct run_queue *rq, struct proc_struct *proc); - /* for SMP support in the future - * load_balance - * void (*load_balance)(struct rq* rq); - * get some proc from this rq, used in load_balance, - * return value is the num of gotten proc - * int (*get_proc)(struct rq* rq, struct proc* procs_moved[]); - */ -}; - -struct run_queue { - list_entry_t run_list; - unsigned int proc_num; - int max_time_slice; -}; - -void sched_init(void); -void wakeup_proc(struct proc_struct *proc); -void schedule(void); -void add_timer(timer_t *timer); -void del_timer(timer_t *timer); -void run_timer_list(void); - -#endif /* !__KERN_SCHEDULE_SCHED_H__ */ diff --git a/ucore-thumips/kern/sync/sem.c b/ucore-thumips/kern/sync/sem.c deleted file mode 100644 index 62c81db..0000000 --- a/ucore-thumips/kern/sync/sem.c +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -void -sem_init(semaphore_t *sem, int value) { - sem->value = value; - wait_queue_init(&(sem->wait_queue)); -} - -static __noinline void __up(semaphore_t *sem, uint32_t wait_state) { - bool intr_flag; - local_intr_save(intr_flag); - { - wait_t *wait; - if ((wait = wait_queue_first(&(sem->wait_queue))) == NULL) { - sem->value ++; - } - else { - assert(wait->proc->wait_state == wait_state); - wakeup_wait(&(sem->wait_queue), wait, wait_state, 1); - } - } - local_intr_restore(intr_flag); -} - -static __noinline uint32_t __down(semaphore_t *sem, uint32_t wait_state) { - bool intr_flag; - local_intr_save(intr_flag); - if (sem->value > 0) { - sem->value --; - local_intr_restore(intr_flag); - return 0; - } - wait_t __wait, *wait = &__wait; - wait_current_set(&(sem->wait_queue), wait, wait_state); - local_intr_restore(intr_flag); - - schedule(); - - local_intr_save(intr_flag); - wait_current_del(&(sem->wait_queue), wait); - local_intr_restore(intr_flag); - - if (wait->wakeup_flags != wait_state) { - return wait->wakeup_flags; - } - return 0; -} - -void -up(semaphore_t *sem) { - __up(sem, WT_KSEM); -} - -void -down(semaphore_t *sem) { - uint32_t flags = __down(sem, WT_KSEM); - assert(flags == 0); -} - -bool -try_down(semaphore_t *sem) { - bool intr_flag, ret = 0; - local_intr_save(intr_flag); - if (sem->value > 0) { - sem->value --, ret = 1; - } - local_intr_restore(intr_flag); - return ret; -} - diff --git a/ucore-thumips/kern/sync/sem.h b/ucore-thumips/kern/sync/sem.h deleted file mode 100644 index 4450fe7..0000000 --- a/ucore-thumips/kern/sync/sem.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __KERN_SYNC_SEM_H__ -#define __KERN_SYNC_SEM_H__ - -#include -#include -#include - -typedef struct { - int value; - wait_queue_t wait_queue; -} semaphore_t; - -void sem_init(semaphore_t *sem, int value); -void up(semaphore_t *sem); -void down(semaphore_t *sem); -bool try_down(semaphore_t *sem); - -#endif /* !__KERN_SYNC_SEM_H__ */ - diff --git a/ucore-thumips/kern/sync/sync.h b/ucore-thumips/kern/sync/sync.h deleted file mode 100644 index 90b69fd..0000000 --- a/ucore-thumips/kern/sync/sync.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __KERN_SYNC_SYNC_H__ -#define __KERN_SYNC_SYNC_H__ - -#include -#include -#include -#include - -#include -#include - - -typedef volatile bool lock_t; - - -static inline void -lock_init(lock_t *lock) { - *lock = 0; -} - -static inline bool -try_lock(lock_t *lock) { - return !test_and_set_bit(0, lock); -} - -static inline void -lock(lock_t *lock) { - while (!try_lock(lock)) { - schedule(); - } -} - -static inline void -unlock(lock_t *lock) { - if (!test_and_clear_bit(0, lock)) { - panic("Unlock failed.\n"); - } -} - -#endif /* !__KERN_SYNC_SYNC_H__ */ - diff --git a/ucore-thumips/kern/sync/wait.c b/ucore-thumips/kern/sync/wait.c deleted file mode 100644 index 6aea172..0000000 --- a/ucore-thumips/kern/sync/wait.c +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include -#include -#include -#include - -void -wait_init(wait_t *wait, struct proc_struct *proc) { - wait->proc = proc; - wait->wakeup_flags = WT_INTERRUPTED; - list_init(&(wait->wait_link)); -} - -void -wait_queue_init(wait_queue_t *queue) { - list_init(&(queue->wait_head)); -} - -void -wait_queue_add(wait_queue_t *queue, wait_t *wait) { - assert(list_empty(&(wait->wait_link)) && wait->proc != NULL); - wait->wait_queue = queue; - list_add_before(&(queue->wait_head), &(wait->wait_link)); -} - -void -wait_queue_del(wait_queue_t *queue, wait_t *wait) { - assert(!list_empty(&(wait->wait_link)) && wait->wait_queue == queue); - list_del_init(&(wait->wait_link)); -} - -wait_t * -wait_queue_next(wait_queue_t *queue, wait_t *wait) { - assert(!list_empty(&(wait->wait_link)) && wait->wait_queue == queue); - list_entry_t *le = list_next(&(wait->wait_link)); - if (le != &(queue->wait_head)) { - return le2wait(le, wait_link); - } - return NULL; -} - -wait_t * -wait_queue_prev(wait_queue_t *queue, wait_t *wait) { - assert(!list_empty(&(wait->wait_link)) && wait->wait_queue == queue); - list_entry_t *le = list_prev(&(wait->wait_link)); - if (le != &(queue->wait_head)) { - return le2wait(le, wait_link); - } - return NULL; -} - -wait_t * -wait_queue_first(wait_queue_t *queue) { - list_entry_t *le = list_next(&(queue->wait_head)); - if (le != &(queue->wait_head)) { - return le2wait(le, wait_link); - } - return NULL; -} - -wait_t * -wait_queue_last(wait_queue_t *queue) { - list_entry_t *le = list_prev(&(queue->wait_head)); - if (le != &(queue->wait_head)) { - return le2wait(le, wait_link); - } - return NULL; -} - -bool -wait_queue_empty(wait_queue_t *queue) { - return list_empty(&(queue->wait_head)); -} - -bool -wait_in_queue(wait_t *wait) { - return !list_empty(&(wait->wait_link)); -} - -void -wakeup_wait(wait_queue_t *queue, wait_t *wait, uint32_t wakeup_flags, bool del) { - if (del) { - wait_queue_del(queue, wait); - } - wait->wakeup_flags = wakeup_flags; - wakeup_proc(wait->proc); -} - -void -wakeup_first(wait_queue_t *queue, uint32_t wakeup_flags, bool del) { - wait_t *wait; - if ((wait = wait_queue_first(queue)) != NULL) { - wakeup_wait(queue, wait, wakeup_flags, del); - } -} - -void -wakeup_queue(wait_queue_t *queue, uint32_t wakeup_flags, bool del) { - wait_t *wait; - if ((wait = wait_queue_first(queue)) != NULL) { - if (del) { - do { - wakeup_wait(queue, wait, wakeup_flags, 1); - } while ((wait = wait_queue_first(queue)) != NULL); - } - else { - do { - wakeup_wait(queue, wait, wakeup_flags, 0); - } while ((wait = wait_queue_next(queue, wait)) != NULL); - } - } -} - -void -wait_current_set(wait_queue_t *queue, wait_t *wait, uint32_t wait_state) { - assert(current != NULL); - wait_init(wait, current); - current->state = PROC_SLEEPING; - current->wait_state = wait_state; - wait_queue_add(queue, wait); -} - diff --git a/ucore-thumips/kern/sync/wait.h b/ucore-thumips/kern/sync/wait.h deleted file mode 100644 index 46758b7..0000000 --- a/ucore-thumips/kern/sync/wait.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __KERN_SYNC_WAIT_H__ -#define __KERN_SYNC_WAIT_H__ - -#include - -typedef struct { - list_entry_t wait_head; -} wait_queue_t; - -struct proc_struct; - -typedef struct { - struct proc_struct *proc; - uint32_t wakeup_flags; - wait_queue_t *wait_queue; - list_entry_t wait_link; -} wait_t; - -#define le2wait(le, member) \ - to_struct((le), wait_t, member) - -void wait_init(wait_t *wait, struct proc_struct *proc); -void wait_queue_init(wait_queue_t *queue); -void wait_queue_add(wait_queue_t *queue, wait_t *wait); -void wait_queue_del(wait_queue_t *queue, wait_t *wait); - -wait_t *wait_queue_next(wait_queue_t *queue, wait_t *wait); -wait_t *wait_queue_prev(wait_queue_t *queue, wait_t *wait); -wait_t *wait_queue_first(wait_queue_t *queue); -wait_t *wait_queue_last(wait_queue_t *queue); - -bool wait_queue_empty(wait_queue_t *queue); -bool wait_in_queue(wait_t *wait); -void wakeup_wait(wait_queue_t *queue, wait_t *wait, uint32_t wakeup_flags, bool del); -void wakeup_first(wait_queue_t *queue, uint32_t wakeup_flags, bool del); -void wakeup_queue(wait_queue_t *queue, uint32_t wakeup_flags, bool del); - -void wait_current_set(wait_queue_t *queue, wait_t *wait, uint32_t wait_state); - -#define wait_current_del(queue, wait) \ - do { \ - if (wait_in_queue(wait)) { \ - wait_queue_del(queue, wait); \ - } \ - } while (0) - -#endif /* !__KERN_SYNC_WAIT_H__ */ - diff --git a/ucore-thumips/kern/syscall/syscall.c b/ucore-thumips/kern/syscall/syscall.c deleted file mode 100644 index b00515c..0000000 --- a/ucore-thumips/kern/syscall/syscall.c +++ /dev/null @@ -1,209 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern volatile int ticks; - -static int -sys_exit(uint32_t arg[]) { - int error_code = (int)arg[0]; - return do_exit(error_code); -} - -static int -sys_fork(uint32_t arg[]) { - struct trapframe *tf = current->tf; - uintptr_t stack = tf->tf_regs.reg_r[MIPS_REG_SP]; - return do_fork(0, stack, tf); -} - -static int -sys_wait(uint32_t arg[]) { - int pid = (int)arg[0]; - int *store = (int *)arg[1]; - return do_wait(pid, store); -} - -static int -sys_exec(uint32_t arg[]) { - const char *name = (const char *)arg[0]; - int argc = (int)arg[1]; - const char **argv = (const char **)arg[2]; - return do_execve(name, argc, argv); -} - -static int -sys_yield(uint32_t arg[]) { - return do_yield(); -} - -static int -sys_kill(uint32_t arg[]) { - int pid = (int)arg[0]; - return do_kill(pid); -} - -static int -sys_getpid(uint32_t arg[]) { - return current->pid; -} - -static int -sys_putc(uint32_t arg[]) { - int c = (int)arg[0]; - kputchar(c); - return 0; -} - -static int -sys_pgdir(uint32_t arg[]) { - print_pgdir(); - return 0; -} - -static int -sys_gettime(uint32_t arg[]) { - return (int)ticks; -} - -static int -sys_sleep(uint32_t arg[]) { - unsigned int time = (unsigned int)arg[0]; - return do_sleep(time); -} - -static int -sys_open(uint32_t arg[]) { - const char *path = (const char *)arg[0]; - uint32_t open_flags = (uint32_t)arg[1]; - return sysfile_open(path, open_flags); -} - -static int -sys_close(uint32_t arg[]) { - int fd = (int)arg[0]; - return sysfile_close(fd); -} - -static int -sys_read(uint32_t arg[]) { - int fd = (int)arg[0]; - void *base = (void *)arg[1]; - size_t len = (size_t)arg[2]; - return sysfile_read(fd, base, len); -} - -static int -sys_write(uint32_t arg[]) { - int fd = (int)arg[0]; - void *base = (void *)arg[1]; - size_t len = (size_t)arg[2]; - return sysfile_write(fd, base, len); -} - -static int -sys_seek(uint32_t arg[]) { - int fd = (int)arg[0]; - off_t pos = (off_t)arg[1]; - int whence = (int)arg[2]; - return sysfile_seek(fd, pos, whence); -} - -static int -sys_fstat(uint32_t arg[]) { - int fd = (int)arg[0]; - struct stat *stat = (struct stat *)arg[1]; - return sysfile_fstat(fd, stat); -} - -static int -sys_fsync(uint32_t arg[]) { - int fd = (int)arg[0]; - return sysfile_fsync(fd); -} - -static int -sys_chdir(uint32_t arg[]) { - const char *path = (const char *)arg[0]; - return sysfile_chdir(path); -} - -static int -sys_getcwd(uint32_t arg[]) { - char *buf = (char *)arg[0]; - size_t len = (size_t)arg[1]; - return sysfile_getcwd(buf, len); -} - - -static int -sys_getdirentry(uint32_t arg[]) { - int fd = (int)arg[0]; - struct dirent *direntp = (struct dirent *)arg[1]; - return sysfile_getdirentry(fd, direntp); -} - -static int -sys_dup(uint32_t arg[]) { - int fd1 = (int)arg[0]; - int fd2 = (int)arg[1]; - return sysfile_dup(fd1, fd2); -} - - -static int (*syscalls[])(uint32_t arg[]) = { - [SYS_exit] sys_exit, - [SYS_fork] sys_fork, - [SYS_wait] sys_wait, - [SYS_exec] sys_exec, - [SYS_yield] sys_yield, - [SYS_kill] sys_kill, - [SYS_getpid] sys_getpid, - [SYS_putc] sys_putc, - [SYS_pgdir] sys_pgdir, - [SYS_gettime] sys_gettime, - [SYS_sleep] sys_sleep, - [SYS_open] sys_open, - [SYS_close] sys_close, - [SYS_read] sys_read, - [SYS_write] sys_write, - [SYS_seek] sys_seek, - [SYS_fstat] sys_fstat, - [SYS_fsync] sys_fsync, - [SYS_getcwd] sys_getcwd, - [SYS_getdirentry] sys_getdirentry, - [SYS_dup] sys_dup, -}; - -#define NUM_SYSCALLS ((sizeof(syscalls)) / (sizeof(syscalls[0]))) - -void -syscall(void) { - assert(current != NULL); - struct trapframe *tf = current->tf; - uint32_t arg[4]; - int num = tf->tf_regs.reg_r[MIPS_REG_V0]; - num -= SYSCALL_BASE; - //kprintf("$ %d %d\n",current->pid, num); - if (num >= 0 && num < NUM_SYSCALLS) { - if (syscalls[num] != NULL) { - arg[0] = tf->tf_regs.reg_r[MIPS_REG_A0]; - arg[1] = tf->tf_regs.reg_r[MIPS_REG_A1]; - arg[2] = tf->tf_regs.reg_r[MIPS_REG_A2]; - arg[3] = tf->tf_regs.reg_r[MIPS_REG_A3]; - tf->tf_regs.reg_r[MIPS_REG_V0] = syscalls[num](arg); - return ; - } - } - print_trapframe(tf); - panic("undefined syscall %d, pid = %d, name = %s.\n", - num, current->pid, current->name); -} - diff --git a/ucore-thumips/kern/syscall/syscall.h b/ucore-thumips/kern/syscall/syscall.h deleted file mode 100644 index a8fe843..0000000 --- a/ucore-thumips/kern/syscall/syscall.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __KERN_SYSCALL_SYSCALL_H__ -#define __KERN_SYSCALL_SYSCALL_H__ - -void syscall(void); - -#endif /* !__KERN_SYSCALL_SYSCALL_H__ */ - diff --git a/ucore-thumips/kern/trap/exception.S b/ucore-thumips/kern/trap/exception.S deleted file mode 100644 index ca65def..0000000 --- a/ucore-thumips/kern/trap/exception.S +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Entry points for exceptions - */ -#include -#include -#include - -.extern current # current pcb proc.h -.extern mips_trap - /* - * Do not allow the assembler to use $1 (at), because we need to be - * able to save it. - */ - .set noat - .set noreorder - .section .text -# +0x000: R4000 tlbmiss vector (user) -.global ramExcHandle_tlbmiss -ramExcHandle_tlbmiss: - #b ramExcHandle_tlbmiss - b ramExcHandle_general - nop - -.global ramReserved -ramReserved: - b ramReserved - nop - -# +0x180: R4000 general vector - .global ramExcHandle_general - .type ramExcHandle_general, @function - .ent ramExcHandle_general -ramExcHandle_general: - move k1, sp /* Save previous stack pointer in k1 */ - mfc0 k0, CP0_STATUS /* Get status register */ - andi k0, k0, KSU_USER/* Check the we-were-in-user-mode bit */ - beq k0, $0, 1f /* If clear, from kernel, already have stack */ - nop /* delay slot */ - - /* TODO */ - /* Coming from user mode - load kernel stack into sp */ - la k0, current /* get address of "curkstack" */ - lw k0, 0(k0) - lw k0, 12(k0) - addiu sp, k0, KSTACKSIZE - #lw sp, 72(k0) /* get its value */ - nop /* delay slot for the load */ - -1: - mfc0 k0, CP0_CAUSE /* Now, load the exception cause. */ - j common_exception /* Skip to common code */ - nop /* delay slot */ - -ramExcHandle_general_end: - .end ramExcHandle_general - -/****************************************************/ -/* */ -/* Common exception code */ -/* */ -/****************************************************/ - - .text - .type common_exception,@function - .ent common_exception -common_exception: - - /* - * At this point: - * Interrupts are off. (The processor did this for us.) - * k0 contains the exception cause value. - * k1 contains the old stack pointer. - * sp points into the kernel stack. - * All other registers are untouched. - */ - - /* - * Allocate stack space for 37 words to hold the trap frame, - * plus four more words for a minimal argument block. - */ - addiu sp, sp, -164 - - /* - * Save general registers. - * We exclude k0/k1, which the kernel is free to clobber (and which - * we already have clobbered), and $0, whose value is fixed. - * - * The order here must match mips/include/trapframe.h. - * - * gdb disassembles this code to try to figure out what registers - * are where, and it isn't very bright. So in order to make gdb be - * able to trace the stack back through here, we play some silly - * games. - * - * In particular: - * (1) We store the return address register into the epc slot, - * which makes gdb think it's the return address slot. Then - * we store the real epc value over that. - * (2) We store the current sp into the sp slot, which makes gdb - * think it's the stack pointer slot. Then we store the real - * value. - * (3) gdb also assumes that saved registers in a function are - * saved in order. This is why we put epc where it is, and - * handle the real value of ra afterwards. - * (4) Because gdb will think we're saving k0 and k1, we need to - * leave slots for them in the trap frame, even though the - * stuff we save there is useless. - */ - sw ra, 160(sp) /* dummy for gdb */ - sw s8, 156(sp) /* save s8 */ - sw sp, 152(sp) /* dummy for gdb */ - sw gp, 148(sp) /* save gp */ - sw k1, 144(sp) /* dummy for gdb */ - sw k0, 140(sp) /* dummy for gdb */ - - sw k1, 152(sp) /* real saved sp */ - nop /* delay slot for store */ - - mfc0 k1, CP0_EPC /* Copr.0 reg 13 == PC for exception */ - sw k1, 160(sp) /* real saved PC */ - - sw t9, 136(sp) - sw t8, 132(sp) - sw s7, 128(sp) - sw s6, 124(sp) - sw s5, 120(sp) - sw s4, 116(sp) - sw s3, 112(sp) - sw s2, 108(sp) - sw s1, 104(sp) - sw s0, 100(sp) - sw t7, 96(sp) - sw t6, 92(sp) - sw t5, 88(sp) - sw t4, 84(sp) - sw t3, 80(sp) - sw t2, 76(sp) - sw t1, 72(sp) - sw t0, 68(sp) - sw a3, 64(sp) - sw a2, 60(sp) - sw a1, 56(sp) - sw a0, 52(sp) - sw v1, 48(sp) - sw v0, 44(sp) - sw AT, 40(sp) - - sw ra, 36(sp) - - /* - * Save special registers. - */ - mfhi t0 - mflo t1 - sw t0, 32(sp) - sw t1, 28(sp) - - /* - * Save remaining exception context information. - */ - - sw k0, 24(sp) /* k0 was loaded with cause earlier */ - mfc0 t1, CP0_STATUS /* Copr.0 reg 11 == status */ - sw t1, 20(sp) - - - mfc0 t2, CP0_BADVADDR /* Copr.0 reg 8 == faulting vaddr */ - sw t2, 16(sp) - - /* - * Pretend to save $0 for gdb's benefit. - */ - sw $0, 12(sp) - - # support nested interrupt - la t0, ~(ST0_KSU|ST0_EXL|ST0_IE) - and t1, t1, t0 - mtc0 t1, CP0_STATUS /* Copr.0 reg 11 == status */ - - /* - * Prepare to call mips_trap(struct trapframe *) - */ - - addiu a0, sp, 16 /* set argument */ - la t9, mips_trap - jal t9 /* call it */ - nop /* delay slot */ - - /* Something must be here or gdb doesn't find the stack frame. */ - nop - - /* - * Now restore stuff and return from the exception. - * Interrupts should be off. - */ -exception_return: - - /* 16(sp) no need to restore tf_vaddr */ - lw t0, 20(sp) /* load status register value into t0 */ - ori t0, t0, ST0_EXL - nop /* load delay slot */ - mtc0 t0, CP0_STATUS /* store it back to coprocessor 0 */ - /* 24(sp) no need to restore tf_cause */ - - /* restore special registers */ - lw t1, 28(sp) - lw t0, 32(sp) - mtlo t1 - mthi t0 - - /* load the general registers */ - lw ra, 36(sp) - - lw AT, 40(sp) - lw v0, 44(sp) - lw v1, 48(sp) - lw a0, 52(sp) - lw a1, 56(sp) - lw a2, 60(sp) - lw a3, 64(sp) - lw t0, 68(sp) - lw t1, 72(sp) - lw t2, 76(sp) - lw t3, 80(sp) - lw t4, 84(sp) - lw t5, 88(sp) - lw t6, 92(sp) - lw t7, 96(sp) - lw s0, 100(sp) - lw s1, 104(sp) - lw s2, 108(sp) - lw s3, 112(sp) - lw s4, 116(sp) - lw s5, 120(sp) - lw s6, 124(sp) - lw s7, 128(sp) - lw t8, 132(sp) - lw t9, 136(sp) - - /* 140(sp) "saved" k0 was dummy garbage anyway */ - /* 144(sp) "saved" k1 was dummy garbage anyway */ - - lw gp, 148(sp) /* restore gp */ - /* 152(sp) stack pointer - below */ - lw s8, 156(sp) /* restore s8 */ - lw k0, 160(sp) /* fetch exception return PC into k0 */ - - lw sp, 152(sp) /* fetch saved sp (must be last) */ - /* done */ - - mtc0 k0, CP0_EPC /* Copr.0 reg 13 == PC for exception */ - nop - eret - nop - .end common_exception - - -.globl forkrets -.type forkrets, @function -.ent forkrets -forkrets: - addiu sp, a0, -16 - b exception_return - nop - -.end forkrets diff --git a/ucore-thumips/kern/trap/mips_trapframe.h b/ucore-thumips/kern/trap/mips_trapframe.h deleted file mode 100644 index ec218d4..0000000 --- a/ucore-thumips/kern/trap/mips_trapframe.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _MIPS_TRAPFRAME_H_ -#define _MIPS_TRAPFRAME_H_ - -/* $1 - $30 */ -struct pushregs { - uint32_t reg_r[30]; -}; - -#define MIPS_REG_START (0) -#define MIPS_REG_AT (MIPS_REG_START+0) -#define MIPS_REG_V0 (MIPS_REG_START+1) -#define MIPS_REG_V1 (MIPS_REG_START+2) -#define MIPS_REG_A0 (MIPS_REG_START+3) -#define MIPS_REG_A1 (MIPS_REG_START+4) -#define MIPS_REG_A2 (MIPS_REG_START+5) -#define MIPS_REG_A3 (MIPS_REG_START+6) -#define MIPS_REG_T0 (MIPS_REG_START+7) -#define MIPS_REG_T1 (MIPS_REG_START+8) -#define MIPS_REG_T2 (MIPS_REG_START+9) -#define MIPS_REG_T3 (MIPS_REG_START+10) -#define MIPS_REG_T4 (MIPS_REG_START+11) -#define MIPS_REG_T5 (MIPS_REG_START+12) -#define MIPS_REG_T6 (MIPS_REG_START+13) -#define MIPS_REG_T7 (MIPS_REG_START+14) - -#define MIPS_REG_S0 (MIPS_REG_START+15) -#define MIPS_REG_S1 (MIPS_REG_START+16) -#define MIPS_REG_S2 (MIPS_REG_START+17) -#define MIPS_REG_S3 (MIPS_REG_START+18) -#define MIPS_REG_S4 (MIPS_REG_START+19) -#define MIPS_REG_S5 (MIPS_REG_START+20) -#define MIPS_REG_S6 (MIPS_REG_START+21) -#define MIPS_REG_S7 (MIPS_REG_START+22) - -#define MIPS_REG_T8 (MIPS_REG_START+23) -#define MIPS_REG_T9 (MIPS_REG_START+24) - -#define MIPS_REG_GP (MIPS_REG_START+27) -#define MIPS_REG_SP (MIPS_REG_START+28) -#define MIPS_REG_FP (MIPS_REG_START+29) - -/* - * Structure describing what is saved on the stack during entry to - * the exception handler. - * - * This must agree with the code in exception.S. - */ - -struct trapframe { - uint32_t tf_vaddr; /* coprocessor 0 vaddr register */ - uint32_t tf_status; /* coprocessor 0 status register */ - uint32_t tf_cause; /* coprocessor 0 cause register */ - uint32_t tf_lo; - uint32_t tf_hi; - uint32_t tf_ra; /* Saved register 31 */ - struct pushregs tf_regs; - uint32_t tf_epc; /* coprocessor 0 epc register */ -}; - -/* - * MIPS exception codes. - */ -#define EX_IRQ 0 /* Interrupt */ -#define EX_MOD 1 /* TLB Modify (write to read-only page) */ -#define EX_TLBL 2 /* TLB miss on load */ -#define EX_TLBS 3 /* TLB miss on store */ -#define EX_ADEL 4 /* Address error on load */ -#define EX_ADES 5 /* Address error on store */ -#define EX_IBE 6 /* Bus error on instruction fetch */ -#define EX_DBE 7 /* Bus error on data load *or* store */ -#define EX_SYS 8 /* Syscall */ -#define EX_BP 9 /* Breakpoint */ -#define EX_RI 10 /* Reserved (illegal) instruction */ -#define EX_CPU 11 /* Coprocessor unusable */ -#define EX_OVF 12 /* Arithmetic overflow */ - -#endif /* _MIPS_TRAPFRAME_H_ */ diff --git a/ucore-thumips/kern/trap/trap.c b/ucore-thumips/kern/trap/trap.c deleted file mode 100644 index 528a690..0000000 --- a/ucore-thumips/kern/trap/trap.c +++ /dev/null @@ -1,306 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TICK_NUM 100 - -#define GET_CAUSE_EXCODE(x) ( ((x) & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE) - -static void print_ticks() { - PRINT_HEX("%d ticks\n",TICK_NUM); -} - - - -static const char * -trapname(int trapno) { - static const char * const excnames[] = { - "Interrupt", - "TLB Modify", - "TLB miss on load", - "TLB miss on store", - "Address error on load", - "Address error on store", - "Bus error on instruction fetch", - "Bus error on data load or store", - "Syscall", - "Breakpoint", - "Reserved (illegal) instruction", - "Coprocessor unusable", - "Arithmetic overflow", - }; - if(trapno <= 12) - return excnames[trapno]; - else - return "Unknown"; -} - -bool -trap_in_kernel(struct trapframe *tf) { - return !(tf->tf_status & KSU_USER); -} - - -void print_regs(struct pushregs *regs) -{ - int i; - for (i = 0; i < 30; i++) { - kprintf(" $"); - printbase10(i+1); - kprintf("\t: "); - printhex(regs->reg_r[i]); - kputchar('\n'); - } -} - -void -print_trapframe(struct trapframe *tf) { - PRINT_HEX("trapframe at ", tf); - print_regs(&tf->tf_regs); - PRINT_HEX(" $ra\t: ", tf->tf_ra); - PRINT_HEX(" BadVA\t: ", tf->tf_vaddr); - PRINT_HEX(" Status\t: ", tf->tf_status); - PRINT_HEX(" Cause\t: ", tf->tf_cause); - PRINT_HEX(" EPC\t: ", tf->tf_epc); - if (!trap_in_kernel(tf)) { - kprintf("Trap in usermode: "); - }else{ - kprintf("Trap in kernel: "); - } - kprintf(trapname(GET_CAUSE_EXCODE(tf->tf_cause))); - kputchar('\n'); -} - -static void interrupt_handler(struct trapframe *tf) -{ - extern clock_int_handler(void*); - extern serial_int_handler(void*); - int i; - for(i=0;i<8;i++){ - if(tf->tf_cause & (1<<(CAUSEB_IP+i))){ - switch(i){ - case TIMER0_IRQ: - clock_int_handler(NULL); - break; - case COM1_IRQ: - serial_int_handler(NULL); - break; - default: - print_trapframe(tf); - panic("Unknown interrupt!"); - } - } - } - -} - -extern pde_t *current_pgdir; - - - -static inline int get_error_code(int write, pte_t *pte) -{ - int r = 0; - if(pte!=NULL && ptep_present(pte)) - r |= 0x01; - if(write) - r |= 0x02; - return r; -} - -static int -pgfault_handler(struct trapframe *tf, uint32_t addr, uint32_t error_code) { -#if 0 - extern struct mm_struct *check_mm_struct; - if (check_mm_struct != NULL) { - return do_pgfault(check_mm_struct, error_code, addr); - } - panic("unhandled page fault.\n"); -#endif - extern struct mm_struct *check_mm_struct; - if(check_mm_struct !=NULL) { //used for test check_swap - //print_pgfault(tf); - } - struct mm_struct *mm; - if (check_mm_struct != NULL) { - assert(current == idleproc); - mm = check_mm_struct; - } - else { - if (current == NULL) { - print_trapframe(tf); - //print_pgfault(tf); - panic("unhandled page fault.\n"); - } - mm = current->mm; - } - return do_pgfault(mm, error_code, addr); -} - -/* use software emulated X86 pgfault */ -static void handle_tlbmiss(struct trapframe* tf, int write) -{ -#if 0 - if(!trap_in_kernel(tf)){ - print_trapframe(tf); - while(1); - } -#endif - - static int entercnt = 0; - entercnt ++; - //kprintf("## enter handle_tlbmiss %d times\n", entercnt); - int in_kernel = trap_in_kernel(tf); - assert(current_pgdir != NULL); - //print_trapframe(tf); - uint32_t badaddr = tf->tf_vaddr; - int ret = 0; - pte_t *pte = get_pte(current_pgdir, tf->tf_vaddr, 0); - if(pte==NULL || ptep_invalid(pte)){ //PTE miss, pgfault - //panic("unimpl"); - //TODO - //tlb will not be refill in do_pgfault, - //so a vmm pgfault will trigger 2 exception - //permission check in tlb miss - ret = pgfault_handler(tf, badaddr, get_error_code(write, pte)); - }else{ //tlb miss only, reload it - /* refill two slot */ - /* check permission */ - if(in_kernel){ - tlb_refill(badaddr, pte); - //kprintf("## refill K\n"); - return; - }else{ - if(!ptep_u_read(pte)){ - ret = -1; - goto exit; - } - if(write && !ptep_u_write(pte)){ - ret = -2; - goto exit; - } - //kprintf("## refill U %d %08x\n", write, badaddr); - tlb_refill(badaddr, pte); - return ; - } - } - -exit: - if(ret){ - print_trapframe(tf); - if(in_kernel){ - panic("unhandled pgfault"); - }else{ - do_exit(-E_KILLED); - } - } - return ; -} - -static void -trap_dispatch(struct trapframe *tf) { - int code = GET_CAUSE_EXCODE(tf->tf_cause); - switch(code){ - case EX_IRQ: - interrupt_handler(tf); - break; - case EX_TLBL: - handle_tlbmiss(tf, 0); - break; - case EX_TLBS: - handle_tlbmiss(tf, 1); - break; - case EX_RI: - print_trapframe(tf); - if(trap_in_kernel(tf)) { - panic("hey man! Do NOT use that insn!"); - } - do_exit(-E_KILLED); - break; - case EX_CPU: - print_trapframe(tf); - if(trap_in_kernel(tf)) { - panic("CpU exception should not occur in kernel mode!"); - } - do_exit(-E_KILLED); - break; - case EX_OVF: - print_trapframe(tf); - if(trap_in_kernel(tf)) { - panic("Ov exception occur in kernel mode!"); - } - do_exit(-E_KILLED); - break; - case EX_SYS: - //print_trapframe(tf); - tf->tf_epc += 4; - syscall(); - break; - /* alignment error or access kernel - * address space in user mode */ - case EX_ADEL: - case EX_ADES: - if(trap_in_kernel(tf)){ - print_trapframe(tf); - panic("Alignment Error"); - }else{ - print_trapframe(tf); - do_exit(-E_KILLED); - } - break; - default: - print_trapframe(tf); - panic("Unhandled Exception"); - } - -} - - -/* - * General trap (exception) handling function for mips. - * This is called by the assembly-language exception handler once - * the trapframe has been set up. - */ - void -mips_trap(struct trapframe *tf) -{ - // dispatch based on what type of trap occurred - // used for previous projects - if (current == NULL) { - trap_dispatch(tf); - } - else { - // keep a trapframe chain in stack - struct trapframe *otf = current->tf; - current->tf = tf; - - bool in_kernel = trap_in_kernel(tf); - - trap_dispatch(tf); - - current->tf = otf; - if (!in_kernel) { - if (current->flags & PF_EXITING) { - do_exit(-E_KILLED); - } - if (current->need_resched) { - schedule(); - } - } - } -} - diff --git a/ucore-thumips/kern/trap/trap.h b/ucore-thumips/kern/trap/trap.h deleted file mode 100644 index f01df09..0000000 --- a/ucore-thumips/kern/trap/trap.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __KERN_TRAP_TRAP_H__ -#define __KERN_TRAP_TRAP_H__ - -#include -#include - -void print_trapframe(struct trapframe *tf); -void print_regs(struct pushregs *regs); -bool trap_in_kernel(struct trapframe *tf); - -#endif /* !__KERN_TRAP_TRAP_H__ */ - diff --git a/ucore-thumips/kern/trap/vectors.S b/ucore-thumips/kern/trap/vectors.S deleted file mode 100644 index 4746c2c..0000000 --- a/ucore-thumips/kern/trap/vectors.S +++ /dev/null @@ -1,159 +0,0 @@ -/* we allocate exception vectors in ram statically - so we can trap exceptions as soon as possible - */ -#include -#include - - #define RVECENT(f,n) \ - b f; nop -#define XVECENT(f, n) \ - b f; nop - - -/* must be 4K alignment */ -.section .ramexv - -.extern ramReserved -.extern ramExcHandle_tlbmiss -.extern ramExcHandle_general - -.set noreorder -.global __exception_vector -__exception_vector: - RVECENT(ramExcHandle_tlbmiss,0) - RVECENT(ramReserved,1) - RVECENT(ramReserved,2) - RVECENT(ramReserved,3) - RVECENT(ramReserved,4) - RVECENT(ramReserved,5) - RVECENT(ramReserved,6) - RVECENT(ramReserved,7) - RVECENT(ramReserved,8) - RVECENT(ramReserved,9) - RVECENT(ramReserved,10) - RVECENT(ramReserved,11) - RVECENT(ramReserved,12) - RVECENT(ramReserved,13) - RVECENT(ramReserved,14) - RVECENT(ramReserved,15) - RVECENT(ramReserved,16) - RVECENT(ramReserved,17) - RVECENT(ramReserved,18) - RVECENT(ramReserved,19) - RVECENT(ramReserved,20) - RVECENT(ramReserved,21) - RVECENT(ramReserved,22) - RVECENT(ramReserved,23) - RVECENT(ramReserved,24) - RVECENT(ramReserved,25) - RVECENT(ramReserved,26) - RVECENT(ramReserved,27) - RVECENT(ramReserved,28) - RVECENT(ramReserved,29) - RVECENT(ramReserved,30) - RVECENT(ramReserved,31) - RVECENT(ramReserved,32) - RVECENT(ramReserved,33) - RVECENT(ramReserved,34) - RVECENT(ramReserved,35) - RVECENT(ramReserved,36) - RVECENT(ramReserved,37) - RVECENT(ramReserved,38) - RVECENT(ramReserved,39) - RVECENT(ramReserved,40) - RVECENT(ramReserved,41) - RVECENT(ramReserved,42) - RVECENT(ramReserved,43) - RVECENT(ramReserved,44) - RVECENT(ramReserved,45) - RVECENT(ramReserved,46) - RVECENT(ramReserved,47) - XVECENT(ramExcHandle_general, 0x180) - RVECENT(ramReserved,49) - RVECENT(ramReserved,50) - RVECENT(ramReserved,51) - RVECENT(ramReserved,52) - RVECENT(ramReserved,53) - RVECENT(ramReserved,54) - RVECENT(ramReserved,55) - RVECENT(ramReserved,56) - RVECENT(ramReserved,57) - RVECENT(ramReserved,58) - RVECENT(ramReserved,59) - RVECENT(ramReserved,60) - RVECENT(ramReserved,61) - RVECENT(ramReserved,62) - RVECENT(ramReserved,63) - RVECENT(ramReserved,64) - RVECENT(ramReserved,65) - RVECENT(ramReserved,66) - RVECENT(ramReserved,67) - RVECENT(ramReserved,68) - RVECENT(ramReserved,69) - RVECENT(ramReserved,70) - RVECENT(ramReserved,71) - RVECENT(ramReserved,72) - RVECENT(ramReserved,73) - RVECENT(ramReserved,74) - RVECENT(ramReserved,75) - RVECENT(ramReserved,76) - RVECENT(ramReserved,77) - RVECENT(ramReserved,78) - RVECENT(ramReserved,79) - RVECENT(ramReserved,80) - RVECENT(ramReserved,81) - RVECENT(ramReserved,82) - RVECENT(ramReserved,83) - RVECENT(ramReserved,84) - RVECENT(ramReserved,85) - RVECENT(ramReserved,86) - RVECENT(ramReserved,87) - RVECENT(ramReserved,88) - RVECENT(ramReserved,89) - RVECENT(ramReserved,90) - RVECENT(ramReserved,91) - RVECENT(ramReserved,92) - RVECENT(ramReserved,93) - RVECENT(ramReserved,94) - RVECENT(ramReserved,95) - RVECENT(ramReserved,96) - RVECENT(ramReserved,97) - RVECENT(ramReserved,98) - RVECENT(ramReserved,99) - RVECENT(ramReserved,100) - RVECENT(ramReserved,101) - RVECENT(ramReserved,102) - RVECENT(ramReserved,103) - RVECENT(ramReserved,104) - RVECENT(ramReserved,105) - RVECENT(ramReserved,106) - RVECENT(ramReserved,107) - RVECENT(ramReserved,108) - RVECENT(ramReserved,109) - RVECENT(ramReserved,110) - RVECENT(ramReserved,111) - RVECENT(ramReserved,112) - RVECENT(ramReserved,113) - RVECENT(ramReserved,114) - RVECENT(ramReserved,115) - RVECENT(ramReserved,116) - RVECENT(ramReserved,116) - RVECENT(ramReserved,118) - RVECENT(ramReserved,119) - RVECENT(ramReserved,120) - RVECENT(ramReserved,121) - RVECENT(ramReserved,122) - RVECENT(ramReserved,123) - RVECENT(ramReserved,124) - RVECENT(ramReserved,125) - RVECENT(ramReserved,126) - RVECENT(ramReserved,127) -.global __exception_vector_end -__exception_vector_end: -/* table end */ - /* - * We hope there are no more reserved vectors! - * 128 * 8 == 1024 == 0x400 - * so this is address R_VEC+0x400 == 0xbfc00400 - */ - diff --git a/ucore-thumips/run b/ucore-thumips/run deleted file mode 100644 index a724ad3..0000000 --- a/ucore-thumips/run +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -../qemu-thumips/bin/qemu-system-mipsel -M mipssim -m 32M -serial stdio -bios boot/loader.bin - diff --git a/ucore-thumips/thumips-cc b/ucore-thumips/thumips-cc deleted file mode 100644 index 6860b25..0000000 --- a/ucore-thumips/thumips-cc +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -CLANG="clang" -LLVM_BIN="/home/guest/cpu/llvm-thumips/llvm-3.1.src/Release+Asserts/bin" -#LLVM_BIN="/usr/bin/llc" -LLC=$LLVM_BIN"/llc -march=mipsel -mcpu=mips32 -mattr=-condmov,-bitcount,+o32,-swap" -GCC_PREFIX="mips-sde-elf-" -AS=$GCC_PREFIX"as -EL -g -mips1 -msoft-float" - - -if [ $# != 3 ]; then - echo "usage: thumips-cc [flag] [in] [out]" - exit -fi - -BCFILE=`tempfile -s .bc` -echo $BCFILE -$CLANG -O0 -emit-llvm -c -g $1 -o $BCFILE $2 && -#ASMFILE=`tempfile -s .s` -#$LLC -o $ASMFILE $BCFILE && -#$AS -KPIC -o $3 $ASMFILE && -$LLC -o - $BCFILE | $AS -KPIC -o $3 -rm $BCFILE -#rm $ASMFILE diff --git a/ucore-thumips/thumips_insn.txt b/ucore-thumips/thumips_insn.txt deleted file mode 100644 index 35cfae7..0000000 --- a/ucore-thumips/thumips_insn.txt +++ /dev/null @@ -1,44 +0,0 @@ -ADD 000000ssssstttttddddd00000100000 -ADDIU 001001ssssstttttiiiiiiiiiiiiiiii -ADDU 000000ssssstttttddddd00000100001 -ADDI 001000ssssstttttiiiiiiiiiiiiiiii -SLT 000000ssssstttttddddd00000101010 -SLTI 001010ssssstttttiiiiiiiiiiiiiiii -SLTIU 001011ssssstttttiiiiiiiiiiiiiiii -SLTU 000000ssssstttttddddd00000101011 -SUBU 000000ssssstttttddddd00000100011 -SUB 000000ssssstttttddddd00000100010 -BEQ 000100ssssstttttoooooooooooooooo -BGEZ 000001sssss00001oooooooooooooooo -BGTZ 000111sssss00000oooooooooooooooo -BLEZ 000110sssss00000oooooooooooooooo -BNE 000101ssssstttttoooooooooooooooo -J 000010iiiiiiiiiiiiiiiiiiiiiiiiii -JAL 000011iiiiiiiiiiiiiiiiiiiiiiiiii -JALR 000000sssss00000dddddhhhhh001001 -JR 000000sssss0000000000hhhhh001000 -LW 100011bbbbbtttttoooooooooooooooo -SW 101011bbbbbtttttoooooooooooooooo -AND 000000ssssstttttddddd00000100100 -ANDI 001100ssssstttttiiiiiiiiiiiiiiii -LUI 00111100000tttttiiiiiiiiiiiiiiii -NOR 000000ssssstttttddddd00000100111 -OR 000000ssssstttttddddd00000100101 -ORI 001101ssssstttttiiiiiiiiiiiiiiii -XOR 000000ssssstttttddddd00000100110 -XORI 001110ssssstttttiiiiiiiiiiiiiiii -SLL 00000000000tttttdddddaaaaa000000 -SLLV 000000ssssstttttddddd00000000100 -SRA 00000000000tttttdddddaaaaa000011 -SRAV 000000ssssstttttddddd00000000111 -SRL 00000000000tttttdddddaaaaa000010 -SRLV 000000ssssstttttddddd00000000110 -SYSCALL 000000cccccccccccccccccccc001100 -CACHE 101111bbbbbpppppoooooooooooooooo -ERET 01000010000000000000000000011000 -MFC0 01000000000tttttddddd00000000lll -MTC0 01000000100tttttddddd00000000lll -TLBP 01000010000000000000000000001000 -TLBWI 01000010000000000000000000000010 -TLBWR 01000010000000000000000000000110 -SLT 000000ssssstttttddddd00000101010 diff --git a/ucore-thumips/tools/initrd_piggy.S.in b/ucore-thumips/tools/initrd_piggy.S.in deleted file mode 100644 index b7e862d..0000000 --- a/ucore-thumips/tools/initrd_piggy.S.in +++ /dev/null @@ -1,12 +0,0 @@ -.section .data -.align 4 # which either means 4 or 2**4 depending on arch! - -.global _initrd_begin -.type _initrd_begin, @object -_initrd_begin: -.incbin "_FILE_" - -.align 4 -.global _initrd_end -_initrd_end: - diff --git a/ucore-thumips/tools/kernel.ld b/ucore-thumips/tools/kernel.ld deleted file mode 100644 index 55625fa..0000000 --- a/ucore-thumips/tools/kernel.ld +++ /dev/null @@ -1,68 +0,0 @@ -OUTPUT_FORMAT(elf32-tradlittlemips) -OUTPUT_ARCH(mips:isa32) -ENTRY(kernel_entry) - -SECTIONS -{ - . = 0x80000040; - .text : - { - . = ALIGN(4); - wrs_kernel_text_start = .; _wrs_kernel_text_start = .; - *(.startup) - *(.text) - *(.text.*) - *(.gnu.linkonce.t*) - *(.mips16.fn.*) - *(.mips16.call.*) /* for MIPS */ - *(.rodata) *(.rodata.*) *(.gnu.linkonce.r*) *(.rodata1) - . = ALIGN(4096); - *(.ramexv) - } -. = ALIGN(16); -wrs_kernel_text_end = .; _wrs_kernel_text_end = .; -etext = .; _etext = .; -.data ALIGN(4) : AT(etext) -{ - wrs_kernel_data_start = .; _wrs_kernel_data_start = .; - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - *(.data1) - *(.eh_frame) - *(.gcc_except_table) - . = ALIGN(8); - _gp = . + 0x7ff0; /* set gp for MIPS startup code */ - /* got*, dynamic, sdata*, lit[48], and sbss should follow _gp */ - *(.got.plt) - *(.got) - *(.dynamic) - *(.got2) - *(.sdata) *(.sdata.*) *(.lit8) *(.lit4) - . = ALIGN(16); -} -. = ALIGN(16); -edata = .; _edata = .; -wrs_kernel_data_end = .; _wrs_kernel_data_end = .; -.bss ALIGN(4) : -{ - wrs_kernel_bss_start = .; _wrs_kernel_bss_start = .; - *(.sbss) *(.scommon) *(.dynbss) *(.bss) *(COMMON) - . = ALIGN(16); -} -. = ALIGN(16); -end = .; _end = .; -wrs_kernel_bss_end = .; _wrs_kernel_bss_end = .; - -/DISCARD/ : -{ - /* - *(.stub) - *(.debug*) */ - *(.note) /* seen on Pentium ELF */ - *(.comment) /* seen on PPC & SH ELF */ - *(.reginfo) - *(.pdr) /* seen on MIPS ELF */ -} - -} diff --git a/ucore-thumips/tools/mksfs.c b/ucore-thumips/tools/mksfs.c deleted file mode 100644 index 41d2a0e..0000000 --- a/ucore-thumips/tools/mksfs.c +++ /dev/null @@ -1,582 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef int bool; - -#define __error(msg, quit, ...) \ - do { \ - fprintf(stderr, #msg ": function %s - line %d: ", __FUNCTION__, __LINE__); \ - if (errno != 0) { \ - fprintf(stderr, "[error] %s: ", strerror(errno)); \ - } \ - fprintf(stderr, "\n\t"), fprintf(stderr, __VA_ARGS__); \ - errno = 0; \ - if (quit) { \ - exit(-1); \ - } \ - } while (0) - -#define warn(...) __error(warn, 0, __VA_ARGS__) -#define bug(...) __error(bug, 1, __VA_ARGS__) - -#define static_assert(x) \ - switch (x) {case 0: case (x): ; } - -/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */ -#define GOLDEN_RATIO_PRIME_32 0x9e370001UL - -#define HASH_SHIFT 10 -#define HASH_LIST_SIZE (1 << HASH_SHIFT) - -static inline uint32_t -__hash32(uint32_t val, unsigned int bits) { - uint32_t hash = val * GOLDEN_RATIO_PRIME_32; - return (hash >> (32 - bits)); -} - -static uint32_t -hash32(uint32_t val) { - return __hash32(val, HASH_SHIFT); -} - -static uint32_t -hash64(uint64_t val) { - return __hash32((uint32_t)val, HASH_SHIFT); -} - -void * -safe_malloc(size_t size) { - void *ret; - if ((ret = malloc(size)) == NULL) { - bug("malloc %lu bytes failed.\n", (long unsigned)size); - } - return ret; -} - -char * -safe_strdup(const char *str) { - char *ret; - if ((ret = strdup(str)) == NULL) { - bug("strdup failed: %s\n", str); - } - return ret; -} - -struct stat * -safe_stat(const char *filename) { - static struct stat __stat; - if (stat(filename, &__stat) != 0) { - bug("stat %s failed.\n", filename); - } - return &__stat; -} - -struct stat * -safe_fstat(int fd) { - static struct stat __stat; - if (fstat(fd, &__stat) != 0) { - bug("fstat %d failed.\n", fd); - } - return &__stat; -} - -struct stat * -safe_lstat(const char *name) { - static struct stat __stat; - if (lstat(name, &__stat) != 0) { - bug("lstat '%s' failed.\n", name); - } - return &__stat; -} - -void -safe_fchdir(int fd) { - if (fchdir(fd) != 0) { - bug("fchdir failed %d.\n", fd); - } -} - -#define SFS_MAGIC 0x2f8dbe2a -#define SFS_NDIRECT 12 -#define SFS_BLKSIZE 4096 // 4K -#define SFS_MAX_NBLKS (1024UL * 512) // 4K * 512K -#define SFS_MAX_INFO_LEN 31 -#define SFS_MAX_FNAME_LEN 255 -#define SFS_MAX_FILE_SIZE (1024UL * 1024 * 128) // 128M - -#define SFS_BLKBITS (SFS_BLKSIZE * CHAR_BIT) -#define SFS_TYPE_FILE 1 -#define SFS_TYPE_DIR 2 -#define SFS_TYPE_LINK 3 - -#define SFS_BLKN_SUPER 0 -#define SFS_BLKN_ROOT 1 -#define SFS_BLKN_FREEMAP 2 - -struct cache_block { - uint32_t ino; - struct cache_block *hash_next; - void *cache; -}; - -struct cache_inode { - struct inode { - uint32_t size; - uint16_t type; - uint16_t nlinks; - uint32_t blocks; - uint32_t direct[SFS_NDIRECT]; - uint32_t indirect; - uint32_t db_indirect; - } inode; - ino_t real; - uint32_t ino; - uint32_t nblks; - struct cache_block *l1, *l2; - struct cache_inode *hash_next; -}; - -struct sfs_fs { - struct { - uint32_t magic; - uint32_t blocks; - uint32_t unused_blocks; - char info[SFS_MAX_INFO_LEN + 1]; - } super; - struct subpath { - struct subpath *next, *prev; - char *subname; - } __sp_nil, *sp_root, *sp_end; - int imgfd; - uint32_t ninos, next_ino; - struct cache_inode *root; - struct cache_inode *inodes[HASH_LIST_SIZE]; - struct cache_block *blocks[HASH_LIST_SIZE]; -}; - -struct sfs_entry { - uint32_t ino; - char name[SFS_MAX_FNAME_LEN + 1]; -}; - -static uint32_t -sfs_alloc_ino(struct sfs_fs *sfs) { - if (sfs->next_ino < sfs->ninos) { - sfs->super.unused_blocks --; - return sfs->next_ino ++; - } - bug("out of disk space.\n"); -} - -static struct cache_block * -alloc_cache_block(struct sfs_fs *sfs, uint32_t ino) { - struct cache_block *cb = safe_malloc(sizeof(struct cache_block)); - cb->ino = (ino != 0) ? ino : sfs_alloc_ino(sfs); - cb->cache = memset(safe_malloc(SFS_BLKSIZE), 0, SFS_BLKSIZE); - struct cache_block **head = sfs->blocks + hash32(ino); - cb->hash_next = *head, *head = cb; - return cb; -} - -struct cache_block * -search_cache_block(struct sfs_fs *sfs, uint32_t ino) { - struct cache_block *cb = sfs->blocks[hash32(ino)]; - while (cb != NULL && cb->ino != ino) { - cb = cb->hash_next; - } - return cb; -} - -static struct cache_inode * -alloc_cache_inode(struct sfs_fs *sfs, ino_t real, uint32_t ino, uint16_t type) { - struct cache_inode *ci = safe_malloc(sizeof(struct cache_inode)); - ci->ino = (ino != 0) ? ino : sfs_alloc_ino(sfs); - ci->real = real, ci->nblks = 0, ci->l1 = ci->l2 = NULL; - struct inode *inode = &(ci->inode); - memset(inode, 0, sizeof(struct inode)); - inode->type = type; - struct cache_inode **head = sfs->inodes + hash64(real); - ci->hash_next = *head, *head = ci; - return ci; -} - -struct cache_inode * -search_cache_inode(struct sfs_fs *sfs, ino_t real) { - struct cache_inode *ci = sfs->inodes[hash64(real)]; - while (ci != NULL && ci->real != real) { - ci = ci->hash_next; - } - return ci; -} - -struct sfs_fs * -create_sfs(int imgfd) { - uint32_t ninos, next_ino; - struct stat *stat = safe_fstat(imgfd); - if ((ninos = stat->st_size / SFS_BLKSIZE) > SFS_MAX_NBLKS) { - ninos = SFS_MAX_NBLKS; - warn("img file is too big (%llu bytes, only use %u blocks).\n", - (unsigned long long)stat->st_size, ninos); - } - if ((next_ino = SFS_BLKN_FREEMAP + (ninos + SFS_BLKBITS - 1) / SFS_BLKBITS) >= ninos) { - bug("img file is too small (%llu bytes, %u blocks, bitmap use at least %u blocks).\n", - (unsigned long long)stat->st_size, ninos, next_ino - 2); - } - - struct sfs_fs *sfs = safe_malloc(sizeof(struct sfs_fs)); - sfs->super.magic = SFS_MAGIC; - sfs->super.blocks = ninos, sfs->super.unused_blocks = ninos - next_ino; - snprintf(sfs->super.info, SFS_MAX_INFO_LEN, "simple file system"); - - sfs->ninos = ninos, sfs->next_ino = next_ino, sfs->imgfd = imgfd; - sfs->sp_root = sfs->sp_end = &(sfs->__sp_nil); - sfs->sp_end->prev = sfs->sp_end->next = NULL; - - int i; - for (i = 0; i < HASH_LIST_SIZE; i ++) { - sfs->inodes[i] = NULL; - sfs->blocks[i] = NULL; - } - - sfs->root = alloc_cache_inode(sfs, 0, SFS_BLKN_ROOT, SFS_TYPE_DIR); - return sfs; -} - -static void -subpath_push(struct sfs_fs *sfs, const char *subname) { - struct subpath *subpath = safe_malloc(sizeof(struct subpath)); - subpath->subname = safe_strdup(subname); - sfs->sp_end->next = subpath; - subpath->prev = sfs->sp_end; - subpath->next = NULL; - sfs->sp_end = subpath; -} - -static void -subpath_pop(struct sfs_fs *sfs) { - assert(sfs->sp_root != sfs->sp_end); - struct subpath *subpath = sfs->sp_end; - sfs->sp_end = sfs->sp_end->prev, sfs->sp_end->next = NULL; - free(subpath->subname), free(subpath); -} - -static void -subpath_show(FILE *fout, struct sfs_fs *sfs, const char *name) { - struct subpath *subpath = sfs->sp_root; - fprintf(fout, "current is: /"); - while ((subpath = subpath->next) != NULL) { - fprintf(fout, "%s/", subpath->subname); - } - if (name != NULL) { - fprintf(fout, "%s", name); - } - fprintf(fout, "\n"); -} - -static void -write_block(struct sfs_fs *sfs, void *data, size_t len, uint32_t ino) { - assert(len <= SFS_BLKSIZE && ino < sfs->ninos); - static char buffer[SFS_BLKSIZE]; - if (len != SFS_BLKSIZE) { - memset(buffer, 0, sizeof(buffer)); - data = memcpy(buffer, data, len); - } - off_t offset = (off_t)ino * SFS_BLKSIZE; - ssize_t ret; - if ((ret = pwrite(sfs->imgfd, data, SFS_BLKSIZE, offset)) != SFS_BLKSIZE) { - bug("write %u block failed: (%d/%d).\n", ino, (int)ret, SFS_BLKSIZE); - } -} - -static void -flush_cache_block(struct sfs_fs *sfs, struct cache_block *cb) { - write_block(sfs, cb->cache, SFS_BLKSIZE, cb->ino); -} - -static void -flush_cache_inode(struct sfs_fs *sfs, struct cache_inode *ci) { - write_block(sfs, &(ci->inode), sizeof(ci->inode), ci->ino); -} - -void -close_sfs(struct sfs_fs *sfs) { - static char buffer[SFS_BLKSIZE]; - uint32_t i, j, ino = SFS_BLKN_FREEMAP; - uint32_t ninos = sfs->ninos, next_ino = sfs->next_ino; - for (i = 0; i < ninos; ino ++, i += SFS_BLKBITS) { - memset(buffer, 0, sizeof(buffer)); - if (i + SFS_BLKBITS > next_ino) { - uint32_t start = 0, end = SFS_BLKBITS; - if (i < next_ino) { - start = next_ino - i; - } - if (i + SFS_BLKBITS > ninos) { - end = ninos - i; - } - uint32_t *data = (uint32_t *)buffer; - const uint32_t bits = sizeof(bits) * CHAR_BIT; - for (j = start; j < end; j ++) { - data[j / bits] |= (1 << (j % bits)); - } - } - write_block(sfs, buffer, sizeof(buffer), ino); - } - write_block(sfs, &(sfs->super), sizeof(sfs->super), SFS_BLKN_SUPER); - - for (i = 0; i < HASH_LIST_SIZE; i ++) { - struct cache_block *cb = sfs->blocks[i]; - while (cb != NULL) { - flush_cache_block(sfs, cb); - cb = cb->hash_next; - } - struct cache_inode *ci = sfs->inodes[i]; - while (ci != NULL) { - flush_cache_inode(sfs, ci); - ci = ci->hash_next; - } - } -} - -struct sfs_fs * -open_img(const char *imgname) { - const char *expect = ".img", *ext = imgname + strlen(imgname) - strlen(expect); - if (ext <= imgname || strcmp(ext, expect) != 0) { - bug("invalid .img file name '%s'.\n", imgname); - } - int imgfd; - if ((imgfd = open(imgname, O_WRONLY)) < 0) { - bug("open '%s' failed.\n", imgname); - } - return create_sfs(imgfd); -} - -#define open_bug(sfs, name, ...) \ - do { \ - subpath_show(stderr, sfs, name); \ - bug(__VA_ARGS__); \ - } while (0) - -#define show_fullpath(sfs, name) subpath_show(stderr, sfs, name) - -void open_dir(struct sfs_fs *sfs, struct cache_inode *current, struct cache_inode *parent); -void open_file(struct sfs_fs *sfs, struct cache_inode *file, const char *filename, int fd); -void open_link(struct sfs_fs *sfs, struct cache_inode *file, const char *filename); - -#define SFS_BLK_NENTRY (SFS_BLKSIZE / sizeof(uint32_t)) -#define SFS_L0_NBLKS SFS_NDIRECT -#define SFS_L1_NBLKS (SFS_BLK_NENTRY + SFS_L0_NBLKS) -#define SFS_L2_NBLKS (SFS_BLK_NENTRY * SFS_BLK_NENTRY + SFS_L1_NBLKS) -#define SFS_LN_NBLKS (SFS_MAX_FILE_SIZE / SFS_BLKSIZE) - -static void -update_cache(struct sfs_fs *sfs, struct cache_block **cbp, uint32_t *inop) { - uint32_t ino = *inop; - struct cache_block *cb = *cbp; - if (ino == 0) { - cb = alloc_cache_block(sfs, 0); - ino = cb->ino; - } - else if (cb == NULL || cb->ino != ino) { - cb = search_cache_block(sfs, ino); - assert(cb != NULL && cb->ino == ino); - } - *cbp = cb, *inop = ino; -} - -static void -append_block(struct sfs_fs *sfs, struct cache_inode *file, size_t size, uint32_t ino, const char *filename) { - static_assert(SFS_LN_NBLKS <= SFS_L2_NBLKS); - assert(size <= SFS_BLKSIZE); - uint32_t nblks = file->nblks; - struct inode *inode = &(file->inode); - if (nblks >= SFS_LN_NBLKS) { - open_bug(sfs, filename, "file is too big.\n"); - } - if (nblks < SFS_L0_NBLKS) { - inode->direct[nblks] = ino; - } - else if (nblks < SFS_L1_NBLKS) { - nblks -= SFS_L0_NBLKS; - update_cache(sfs, &(file->l1), &(inode->indirect)); - uint32_t *data = file->l1->cache; - data[nblks] = ino; - } - else if (nblks < SFS_L2_NBLKS) { - nblks -= SFS_L1_NBLKS; - update_cache(sfs, &(file->l2), &(inode->db_indirect)); - uint32_t *data2 = file->l2->cache; - update_cache(sfs, &(file->l1), &data2[nblks / SFS_BLK_NENTRY]); - uint32_t *data1 = file->l1->cache; - data1[nblks % SFS_BLK_NENTRY] = ino; - } - file->nblks ++; - inode->size += size; - inode->blocks ++; -} - -static void -add_entry(struct sfs_fs *sfs, struct cache_inode *current, struct cache_inode *file, const char *name) { - static struct sfs_entry __entry, *entry = &__entry; - assert(current->inode.type == SFS_TYPE_DIR && strlen(name) <= SFS_MAX_FNAME_LEN); - entry->ino = file->ino, strcpy(entry->name, name); - uint32_t entry_ino = sfs_alloc_ino(sfs); - write_block(sfs, entry, sizeof(entry->name), entry_ino); - append_block(sfs, current, sizeof(entry->name), entry_ino, name); - file->inode.nlinks ++; -} - -static void -add_dir(struct sfs_fs *sfs, struct cache_inode *parent, const char *dirname, int curfd, int fd, ino_t real) { - assert(search_cache_inode(sfs, real) == NULL); - struct cache_inode *current = alloc_cache_inode(sfs, real, 0, SFS_TYPE_DIR); - safe_fchdir(fd), subpath_push(sfs, dirname); - open_dir(sfs, current, parent); - safe_fchdir(curfd), subpath_pop(sfs); - add_entry(sfs, parent, current, dirname); -} - -static void -add_file(struct sfs_fs *sfs, struct cache_inode *current, const char *filename, int fd, ino_t real) { - struct cache_inode *file; - if ((file = search_cache_inode(sfs, real)) == NULL) { - file = alloc_cache_inode(sfs, real, 0, SFS_TYPE_FILE); - open_file(sfs, file, filename, fd); - } - add_entry(sfs, current, file, filename); -} - -static void -add_link(struct sfs_fs *sfs, struct cache_inode *current, const char *filename, ino_t real) { - struct cache_inode *file = alloc_cache_inode(sfs, real, 0, SFS_TYPE_LINK); - open_link(sfs, file, filename); - add_entry(sfs, current, file, filename); -} - -void -open_dir(struct sfs_fs *sfs, struct cache_inode *current, struct cache_inode *parent) { - DIR *dir; - if ((dir = opendir(".")) == NULL) { - open_bug(sfs, NULL, "opendir failed.\n"); - } - add_entry(sfs, current, current, "."); - add_entry(sfs, current, parent, ".."); - struct dirent *direntp; - while ((direntp = readdir(dir)) != NULL) { - const char *name = direntp->d_name; - if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { - continue ; - } - if (name[0] == '.') { - continue ; - } - if (strlen(name) > SFS_MAX_FNAME_LEN) { - open_bug(sfs, NULL, "file name is too long: %s\n", name); - } - struct stat *stat = safe_lstat(name); - if (S_ISLNK(stat->st_mode)) { - add_link(sfs, current, name, stat->st_ino); - } - else { - int fd; - if ((fd = open(name, O_RDONLY)) < 0) { - open_bug(sfs, NULL, "open failed: %s\n", name); - } - if (S_ISDIR(stat->st_mode)) { - add_dir(sfs, current, name, dirfd(dir), fd, stat->st_ino); - } - else if (S_ISREG(stat->st_mode)) { - add_file(sfs, current, name, fd, stat->st_ino); - } - else { - char mode = '?'; - if (S_ISFIFO(stat->st_mode)) mode = 'f'; - if (S_ISSOCK(stat->st_mode)) mode = 's'; - if (S_ISCHR(stat->st_mode)) mode = 'c'; - if (S_ISBLK(stat->st_mode)) mode = 'b'; - show_fullpath(sfs, NULL); - warn("unsupported mode %07x (%c): file %s\n", stat->st_mode, mode, name); - } - close(fd); - } - } - closedir(dir); -} - -void -open_file(struct sfs_fs *sfs, struct cache_inode *file, const char *filename, int fd) { - static char buffer[SFS_BLKSIZE]; - ssize_t ret, last = SFS_BLKSIZE; - while ((ret = read(fd, buffer, sizeof(buffer))) != 0) { - assert(last == SFS_BLKSIZE); - uint32_t ino = sfs_alloc_ino(sfs); - write_block(sfs, buffer, ret, ino); - append_block(sfs, file, ret, ino, filename); - last = ret; - } - if (ret < 0) { - open_bug(sfs, filename, "read file failed.\n"); - } -} - -void -open_link(struct sfs_fs *sfs, struct cache_inode *file, const char *filename) { - static char buffer[SFS_BLKSIZE]; - uint32_t ino = sfs_alloc_ino(sfs); - ssize_t ret = readlink(filename, buffer, sizeof(buffer)); - if (ret < 0 || ret == SFS_BLKSIZE) { - open_bug(sfs, filename, "read link failed, %d", (int)ret); - } - write_block(sfs, buffer, ret, ino); - append_block(sfs, file, ret, ino, filename); -} - -int -create_img(struct sfs_fs *sfs, const char *home) { - int curfd, homefd; - if ((curfd = open(".", O_RDONLY)) < 0) { - bug("get current fd failed.\n"); - } - if ((homefd = open(home, O_RDONLY | O_NOFOLLOW)) < 0) { - bug("open home directory '%s' failed.\n", home); - } - safe_fchdir(homefd); - open_dir(sfs, sfs->root, sfs->root); - safe_fchdir(curfd); - close(curfd), close(homefd); - close_sfs(sfs); - return 0; -} - -static void -static_check(void) { - static_assert(sizeof(off_t) == 8); - static_assert(sizeof(ino_t) == 8); - static_assert(SFS_MAX_NBLKS <= 0x80000000UL); - static_assert(SFS_MAX_FILE_SIZE <= 0x80000000UL); -} - -int -main(int argc, char **argv) { - static_check(); - if (argc != 3) { - bug("usage: \n"); - } - const char *imgname = argv[1], *home = argv[2]; - if (create_img(open_img(imgname), home) != 0) { - bug("create img failed.\n"); - } - printf("create %s (%s) successfully.\n", imgname, home); - return 0; -} - diff --git a/ucore-thumips/tools/piggy.S.in b/ucore-thumips/tools/piggy.S.in deleted file mode 100644 index 684635d..0000000 --- a/ucore-thumips/tools/piggy.S.in +++ /dev/null @@ -1,12 +0,0 @@ -.section .data -.align 4 # which either means 4 or 2**4 depending on arch! - -.global _binary_obj_user_$FILE_start -.type _binary_obj_user_$FILE_start, @object -_binary_obj_user_$FILE_start: -.incbin "obj/user/$FILE" - -.align 4 -.global _binary_obj_user_$FILE_end -_binary_obj_user_$FILE_end: - diff --git a/ucore-thumips/user/_archive/test.txt b/ucore-thumips/user/_archive/test.txt deleted file mode 100644 index a1d1c3f..0000000 --- a/ucore-thumips/user/_archive/test.txt +++ /dev/null @@ -1 +0,0 @@ -hello World! Haha... diff --git a/ucore-thumips/user/badarg.c b/ucore-thumips/user/badarg.c deleted file mode 100644 index 7b4ffad..0000000 --- a/ucore-thumips/user/badarg.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include - -int -main(void) { - int pid, exit_code; - if ((pid = fork()) == 0) { - cprintf("fork ok.\n"); - int i; - for (i = 0; i < 10; i ++) { - yield(); - } - exit(0xbeaf); - } - assert(pid > 0); - assert(waitpid(-1, NULL) != 0); - assert(waitpid(pid, (void *)0xC0000000) != 0); - assert(waitpid(pid, &exit_code) == 0 && exit_code == 0xbeaf); - cprintf("badarg pass.\n"); - return 0; -} - diff --git a/ucore-thumips/user/badsegment.c b/ucore-thumips/user/badsegment.c deleted file mode 100644 index cdd9e99..0000000 --- a/ucore-thumips/user/badsegment.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -/* try to load the kernel's TSS selector into the DS register */ - -int -main(void) { - asm volatile("movw $0x28,%ax; movw %ax,%ds"); - panic("FAIL: T.T\n"); -} - diff --git a/ucore-thumips/user/cat.c b/ucore-thumips/user/cat.c deleted file mode 100644 index f5e8f0e..0000000 --- a/ucore-thumips/user/cat.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include - -#define BUFSIZE 4096 - -int -cat(int fd) { - static char buffer[BUFSIZE]; - int ret1, ret2; - while ((ret1 = read(fd, buffer, sizeof(buffer))) > 0) { - if ((ret2 = write(1, buffer, ret1)) != ret1) { - return ret2; - } - } - return ret1; -} - -int -main(int argc, char **argv) { - if (argc == 1) { - return cat(0); - } - else { - int i, ret; - for (i = 1; i < argc; i ++) { - if ((ret = open(argv[i], O_RDONLY)) < 0) { - return ret; - } - if ((ret = cat(ret)) != 0) { - return ret; - } - } - } - return 0; -} - diff --git a/ucore-thumips/user/divzero.c b/ucore-thumips/user/divzero.c deleted file mode 100644 index 16c23d5..0000000 --- a/ucore-thumips/user/divzero.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -int zero; - -int -main(void) { - cprintf("value is %d.\n", 1 / zero); - panic("FAIL: T.T\n"); -} - diff --git a/ucore-thumips/user/echo.c b/ucore-thumips/user/echo.c deleted file mode 100644 index a95f61f..0000000 --- a/ucore-thumips/user/echo.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -int -main(int argc, char **argv) { - int i, nflag = 0; - if (argc > 1 && strcmp(argv[1], "-n") == 0) { - nflag = 1, argc --, argv ++; - } - for (i = 1; i < argc; i ++) { - if (i > 1) { - write(1, " ", 1); - } - write(1, argv[i], strlen(argv[i])); - } - if (!nflag) { - write(1, "\n", 1); - } - return 0; -} - diff --git a/ucore-thumips/user/exit.c b/ucore-thumips/user/exit.c deleted file mode 100644 index 674a5bb..0000000 --- a/ucore-thumips/user/exit.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -int magic = -0x10384; - -int -main(void) { - int pid, code; - cprintf("I am the parent. Forking the child...\n"); - if ((pid = fork()) == 0) { - cprintf("I am the child.\n"); - yield(); - yield(); - yield(); - yield(); - yield(); - yield(); - yield(); - exit(magic); - } - else { - cprintf("I am parent, fork a child pid %d\n",pid); - } - assert(pid > 0); - cprintf("I am the parent, waiting now..\n"); - - assert(waitpid(pid, &code) == 0 && code == magic); - assert(waitpid(pid, &code) != 0 && wait() != 0); - cprintf("waitpid %d ok.\n", pid); - - cprintf("exit pass.\n"); - return 0; -} - diff --git a/ucore-thumips/user/faultread.c b/ucore-thumips/user/faultread.c deleted file mode 100644 index 6d292e1..0000000 --- a/ucore-thumips/user/faultread.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int -main(void) { - cprintf("I read %8x from 0.\n", *(unsigned int *)0); - panic("FAIL: T.T\n"); -} - diff --git a/ucore-thumips/user/faultreadkernel.c b/ucore-thumips/user/faultreadkernel.c deleted file mode 100644 index 53457f6..0000000 --- a/ucore-thumips/user/faultreadkernel.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int -main(void) { - cprintf("I read %08x from 0xfac00000!\n", *(unsigned *)0xfac00000); - panic("FAIL: T.T\n"); -} - diff --git a/ucore-thumips/user/forktest.c b/ucore-thumips/user/forktest.c deleted file mode 100644 index 3eda228..0000000 --- a/ucore-thumips/user/forktest.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - -const int max_child = 32; - -int -main(void) { - int n, pid; - for (n = 0; n < max_child; n ++) { - if ((pid = fork()) == 0) { - cprintf("I am child %d\n", n); - exit(0); - } - assert(pid > 0); - } - - if (n > max_child) { - panic("fork claimed to work %d times!\n", n); - } - - for (; n > 0; n --) { - if (wait() != 0) { - panic("wait stopped early\n"); - } - } - - if (wait() == 0) { - panic("wait got too many\n"); - } - - cprintf("forktest pass.\n"); - return 0; -} - diff --git a/ucore-thumips/user/forktree.c b/ucore-thumips/user/forktree.c deleted file mode 100644 index ad45bc1..0000000 --- a/ucore-thumips/user/forktree.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include - -#define DEPTH 2 - -void forktree(const char *cur); - -void -forkchild(const char *cur, char branch) { - char nxt[DEPTH + 1]; - - if (strlen(cur) >= DEPTH) - return; - - snprintf(nxt, DEPTH + 1, "%s%c", cur, branch); - if (fork() == 0) { - forktree(nxt); - yield(); - exit(0); - } -} - -void -forktree(const char *cur) { - cprintf("%04x: I am '%s'\n", getpid(), cur); - - forkchild(cur, '0'); - forkchild(cur, '1'); -} - -int -main(void) { - forktree(""); - return 0; -} - diff --git a/ucore-thumips/user/hello.c b/ucore-thumips/user/hello.c deleted file mode 100644 index 0f05251..0000000 --- a/ucore-thumips/user/hello.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -int -main(void) { - cprintf("Hello world!!.\n"); - cprintf("I am process %d.\n", getpid()); - cprintf("hello pass.\n"); - return 0; -} - diff --git a/ucore-thumips/user/libs/dir.c b/ucore-thumips/user/libs/dir.c deleted file mode 100644 index 62d926e..0000000 --- a/ucore-thumips/user/libs/dir.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DIR dir, *dirp=&dir; -DIR * -opendir(const char *path) { - - if ((dirp->fd = open(path, O_RDONLY)) < 0) { - goto failed; - } - struct stat __stat, *stat = &__stat; - if (fstat(dirp->fd, stat) != 0 || !S_ISDIR(stat->st_mode)) { - goto failed; - } - dirp->dirent.offset = 0; - return dirp; - -failed: - return NULL; -} - -struct dirent * -readdir(DIR *dirp) { - if (sys_getdirentry(dirp->fd, &(dirp->dirent)) == 0) { - return &(dirp->dirent); - } - return NULL; -} - -void -closedir(DIR *dirp) { - close(dirp->fd); -} - -int -getcwd(char *buffer, size_t len) { - return sys_getcwd(buffer, len); -} - diff --git a/ucore-thumips/user/libs/dir.h b/ucore-thumips/user/libs/dir.h deleted file mode 100644 index 4862492..0000000 --- a/ucore-thumips/user/libs/dir.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __USER_LIBS_DIR_H__ -#define __USER_LIBS_DIR_H__ - -#include -#include - -typedef struct { - int fd; - struct dirent dirent; -} DIR; - -DIR *opendir(const char *path); -struct dirent *readdir(DIR *dirp); -void closedir(DIR *dirp); -int chdir(const char *path); -int getcwd(char *buffer, size_t len); - -#endif /* !__USER_LIBS_DIR_H__ */ - diff --git a/ucore-thumips/user/libs/file.c b/ucore-thumips/user/libs/file.c deleted file mode 100644 index 113e078..0000000 --- a/ucore-thumips/user/libs/file.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -int -open(const char *path, uint32_t open_flags) { - return sys_open(path, open_flags); -} - -int -close(int fd) { - return sys_close(fd); -} - -int -read(int fd, void *base, size_t len) { - return sys_read(fd, base, len); -} - -int -write(int fd, void *base, size_t len) { - return sys_write(fd, base, len); -} - -int -seek(int fd, off_t pos, int whence) { - return sys_seek(fd, pos, whence); -} - -int -fstat(int fd, struct stat *stat) { - return sys_fstat(fd, stat); -} - -int -fsync(int fd) { - return sys_fsync(fd); -} - -int -dup2(int fd1, int fd2) { - return sys_dup(fd1, fd2); -} - -static char -transmode(struct stat *stat) { - uint32_t mode = stat->st_mode; - if (S_ISREG(mode)) return 'r'; - if (S_ISDIR(mode)) return 'd'; - if (S_ISLNK(mode)) return 'l'; - if (S_ISCHR(mode)) return 'c'; - if (S_ISBLK(mode)) return 'b'; - return '-'; -} - -void -print_stat(const char *name, int fd, struct stat *stat) { - cprintf("[%03d] %s\n", fd, name); - cprintf(" mode : %c\n", transmode(stat)); - cprintf(" links : %lu\n", stat->st_nlinks); - cprintf(" blocks : %lu\n", stat->st_blocks); - cprintf(" size : %lu\n", stat->st_size); -} - diff --git a/ucore-thumips/user/libs/file.h b/ucore-thumips/user/libs/file.h deleted file mode 100644 index fc46fb5..0000000 --- a/ucore-thumips/user/libs/file.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __USER_LIBS_FILE_H__ -#define __USER_LIBS_FILE_H__ - -#include - -struct stat; - -int open(const char *path, uint32_t open_flags); -int close(int fd); -int read(int fd, void *base, size_t len); -int write(int fd, void *base, size_t len); -int seek(int fd, off_t pos, int whence); -int fstat(int fd, struct stat *stat); -int fsync(int fd); -int dup(int fd); -int dup2(int fd1, int fd2); -int pipe(int *fd_store); -int mkfifo(const char *name, uint32_t open_flags); - -void print_stat(const char *name, int fd, struct stat *stat); - -#endif /* !__USER_LIBS_FILE_H__ */ - diff --git a/ucore-thumips/user/libs/initcode.S b/ucore-thumips/user/libs/initcode.S deleted file mode 100644 index 0fb01ff..0000000 --- a/ucore-thumips/user/libs/initcode.S +++ /dev/null @@ -1,10 +0,0 @@ -.text -.globl _start -.extern _gp -_start: - nop - la $gp, _gp - addiu $sp, $sp, -16 - jal umain - nop - diff --git a/ucore-thumips/user/libs/lock.h b/ucore-thumips/user/libs/lock.h deleted file mode 100644 index ea9f41c..0000000 --- a/ucore-thumips/user/libs/lock.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __USER_LIBS_LOCK_H__ -#define __USER_LIBS_LOCK_H__ - -#include -#include - -#define INIT_LOCK {0} - -typedef volatile bool lock_t; - -static __always_inline bool -test_and_set_bit(int nr, volatile uint32_t *addr) { - //TODO - unsigned char c = 0; - if (*addr & (1 << nr)) - c = 1; - *addr |= (1 << nr); - return c != 0; -} - -static __always_inline bool -test_and_clear_bit(int nr, volatile uint32_t *addr) { - //TODO - unsigned char c = 0; - if (*addr & (1 << nr)) - c = 1; - *addr &= ~(1 << nr); - return c != 0; -} - - -static inline void -lock_init(lock_t *l) { - *l = 0; -} - -static inline bool -try_lock(lock_t *l) { - return test_and_set_bit(0, l); -} - -static inline void -lock(lock_t *l) { - if (try_lock(l)) { - int step = 0; - do { - yield(); - if (++ step == 100) { - step = 0; - sleep(10); - } - } while (try_lock(l)); - } -} - -static inline void -unlock(lock_t *l) { - test_and_clear_bit(0, l); -} - -#endif /* !__USER_LIBS_LOCK_H__ */ - diff --git a/ucore-thumips/user/libs/panic.c b/ucore-thumips/user/libs/panic.c deleted file mode 100644 index 783be16..0000000 --- a/ucore-thumips/user/libs/panic.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include -#include -#include - -void -__panic(const char *file, int line, const char *fmt, ...) { - // print the 'message' - va_list ap; - va_start(ap, fmt); - cprintf("user panic at %s:%d:\n ", file, line); - vcprintf(fmt, ap); - cprintf("\n"); - va_end(ap); - exit(-E_PANIC); -} - -void -__warn(const char *file, int line, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - cprintf("user warning at %s:%d:\n ", file, line); - vcprintf(fmt, ap); - cprintf("\n"); - va_end(ap); -} - diff --git a/ucore-thumips/user/libs/printfmt.c b/ucore-thumips/user/libs/printfmt.c deleted file mode 100644 index 54cdcdb..0000000 --- a/ucore-thumips/user/libs/printfmt.c +++ /dev/null @@ -1,358 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* * - * Space or zero padding and a field width are supported for the numeric - * formats only. - * - * The special format %e takes an integer error code - * and prints a string describing the error. - * The integer may be positive or negative, - * so that -E_NO_MEM and E_NO_MEM are equivalent. - * */ - -static const char * const error_string[MAXERROR + 1] = { - [0] NULL, - [E_UNSPECIFIED] "unspecified error", - [E_BAD_PROC] "bad process", - [E_INVAL] "invalid parameter", - [E_NO_MEM] "out of memory", - [E_NO_FREE_PROC] "out of processes", - [E_FAULT] "segmentation fault", - [E_INVAL_ELF] "invalid elf file", - [E_KILLED] "process is killed", - [E_PANIC] "panic failure", - [E_NO_DEV] "no such device", - [E_NA_DEV] "device not available", - [E_BUSY] "device/file is busy", - [E_NOENT] "no such file or directory", - [E_ISDIR] "is a directory", - [E_NOTDIR] "not a directory", - [E_XDEV] "cross device link", - [E_UNIMP] "unimplemented feature", - [E_SEEK] "illegal seek", - [E_MAX_OPEN] "too many files are open", - [E_EXISTS] "file or directory already exists", - [E_NOTEMPTY] "directory is not empty", -}; - - -/* * - * getuint - get an unsigned int of various possible sizes from a varargs list - * @ap: a varargs list pointer - * @lflag: determines the size of the vararg that @ap points to - * */ -static unsigned long long -getuint(va_list *ap, int lflag) { - if (lflag >= 2) { - return va_arg(*ap, unsigned long long); - } - else if (lflag) { - return va_arg(*ap, unsigned long); - } - else { - return va_arg(*ap, unsigned int); - } -} - -/* * - * getint - same as getuint but signed, we can't use getuint because of sign extension - * @ap: a varargs list pointer - * @lflag: determines the size of the vararg that @ap points to - * */ -static long long -getint(va_list *ap, int lflag) { - if (lflag >= 2) { - return va_arg(*ap, long long); - } - else if (lflag) { - return va_arg(*ap, long); - } - else { - return va_arg(*ap, int); - } -} - -/* * - * printnum - print a number (base <= 16) in reverse order - * @putch: specified putch function, print a single character - * @putdat: used by @putch function - * @num: the number will be printed - * @base: base for print, must be in [1, 16] - * @width: maximum number of digits, if the actual width is less than @width, use @padc instead - * @padc: character that padded on the left if the actual width is less than @width - * */ -static void -printnum(void (*putch)(int, void*, int), int fd, void *putdat, - unsigned int num, unsigned int base, int width, int padc) { - unsigned int result = num; - unsigned int mod = 0; - if(base == 10){ - unsigned int t = __divu10(result); - mod = result - __mulu10(t); - result = t; - }else if(base == 8){ - mod = result & 0x7; - result = result >> 3; - }else{ - mod = result & 0xF; - result = result >> 4; - } - - // first recursively print all preceding (more significant) digits - if (num >= base) { - printnum(putch, fd, putdat, result, base, width - 1, padc); - } else { - // print any needed pad characters before first digit - while (-- width > 0) - putch(padc, putdat, fd); - } - // then print this (the least significant) digit - putch("0123456789abcdef"[mod], putdat, fd); -} - - -/* * - * vprintfmt - format a string and print it by using putch, it's called with a va_list - * instead of a variable number of arguments - * @fd: file descriptor - * @putch: specified putch function, print a single character - * @putdat: used by @putch function - * @fmt: the format string to use - * @ap: arguments for the format string - * - * Call this function if you are already dealing with a va_list. - * Or you probably want printfmt() instead. - * */ -void -vprintfmt(void (*putch)(int, void*, int), int fd, void *putdat, const char *fmt, va_list ap) { - const char *p; - int ch, err; - int num; - int base, width, precision, lflag, altflag; - - while (1) { - while ((ch = *(unsigned char *)fmt ++) != '%') { - if (ch == '\0') { - return; - } - putch(ch, putdat, fd); - } - - // Process a %-escape sequence - char padc = ' '; - width = precision = -1; - lflag = altflag = 0; - - reswitch: - switch (ch = *(unsigned char *)fmt ++) { - - // flag to pad on the right - case '-': - padc = '-'; - goto reswitch; - - // flag to pad with 0's instead of spaces - case '0': - padc = '0'; - goto reswitch; - - // width field - case '1' ... '9': - for (precision = 0; ; ++ fmt) { - precision = precision * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') { - break; - } - } - goto process_precision; - - case '*': - precision = va_arg(ap, int); - goto process_precision; - - case '.': - if (width < 0) - width = 0; - goto reswitch; - - case '#': - altflag = 1; - goto reswitch; - - process_precision: - if (width < 0) - width = precision, precision = -1; - goto reswitch; - - // long flag (doubled for long long) - case 'l': - lflag ++; - goto reswitch; - - // character - case 'c': - putch(va_arg(ap, int), putdat, fd); - break; - - // error message - case 'e': - err = va_arg(ap, int); - if (err < 0) { - err = -err; - } - if (err > MAXERROR || (p = error_string[err]) == NULL) { - printfmt(putch, fd, putdat, "error %d", err); - } - else { - printfmt(putch, fd, putdat, "%s", p); - } - break; - - // string - case 's': - if ((p = va_arg(ap, char *)) == NULL) { - p = "(null)"; - } - if (width > 0 && padc != '-') { - for (width -= strnlen(p, precision); width > 0; width --) { - putch(padc, putdat, fd); - } - } - for (; (ch = *p ++) != '\0' && (precision < 0 || -- precision >= 0); width --) { - if (altflag && (ch < ' ' || ch > '~')) { - putch('?', putdat, fd); - } - else { - putch(ch, putdat, fd); - } - } - for (; width > 0; width --) { - putch(' ', putdat, fd); - } - break; - - // (signed) decimal - case 'd': - num = getint(&ap, lflag); - if (num < 0) { - putch('-', putdat, fd); - num = -num; - } - base = 10; - goto number; - // pointer - case 'p': - putch('0', putdat, fd); - putch('x', putdat, fd); - num = (unsigned int)(uintptr_t)va_arg(ap, void *); - base = 16; - goto number; - - // (unsigned) hexadecimal - case 'x': - num = getuint(&ap, lflag); - base = 16; - number: - printnum(putch, fd, putdat, num, base, width, padc); - break; - - // escaped '%' character - case '%': - putch(ch, putdat, fd); - break; - - // unrecognized escape sequence - just print it literally - default: - putch('%', putdat, fd); - for (fmt --; fmt[-1] != '%'; fmt --) - /* do nothing */; - break; - } - } -} - -/* * - * printfmt - format a string and print it by using putch - * @putch: specified putch function, print a single character - * @fd: file descriptor - * @putdat: used by @putch function - * @fmt: the format string to use - * */ -void -printfmt(void (*putch)(int, int*, int), int fd, void *putdat, const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vprintfmt(putch, fd, putdat, fmt, ap); - va_end(ap); -} - -/* sprintbuf is used to save enough information of a buffer */ -struct sprintbuf { - char *buf; // address pointer points to the first unused memory - char *ebuf; // points the end of the buffer - int cnt; // the number of characters that have been placed in this buffer -}; - -/* * - * sprintputch - 'print' a single character in a buffer - * @ch: the character will be printed - * @b: the buffer to place the character @ch - * */ -static void -sprintputch(int ch, struct sprintbuf *b) { - b->cnt ++; - if (b->buf < b->ebuf) { - *b->buf ++ = ch; - } -} - -/* * - * snprintf - format a string and place it in a buffer - * @str: the buffer to place the result into - * @size: the size of buffer, including the trailing null space - * @fmt: the format string to use - * */ -int -snprintf(char *str, size_t size, const char *fmt, ...) { - va_list ap; - int cnt; - va_start(ap, fmt); - cnt = vsnprintf(str, size, fmt, ap); - va_end(ap); - return cnt; -} - -/* * - * vsnprintf - format a string and place it in a buffer, it's called with a va_list - * instead of a variable number of arguments - * @str: the buffer to place the result into - * @size: the size of buffer, including the trailing null space - * @fmt: the format string to use - * @ap: arguments for the format string - * - * The return value is the number of characters which would be generated for the - * given input, excluding the trailing '\0'. - * - * Call this function if you are already dealing with a va_list. - * Or you probably want snprintf() instead. - * */ -int -vsnprintf(char *str, size_t size, const char *fmt, va_list ap) { - struct sprintbuf b = {str, str + size - 1, 0}; - if (str == NULL || b.buf > b.ebuf) { - return -E_INVAL; - } - // print the string to the buffer - vprintfmt((void*)sprintputch, NO_FD, &b, fmt, ap); - // null terminate the buffer - *b.buf = '\0'; - return b.cnt; -} - diff --git a/ucore-thumips/user/libs/stdio.c b/ucore-thumips/user/libs/stdio.c deleted file mode 100644 index b2b8a06..0000000 --- a/ucore-thumips/user/libs/stdio.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* HIGH level console I/O */ - -/* * - * cputch - writes a single character @c to stdout, and it will - * increace the value of counter pointed by @cnt. - * */ -static void -cputch(int c, int *cnt) { - sys_putc(c); - (*cnt) ++; -} - - -/* * - * vcprintf - format a string and writes it to stdout - * - * The return value is the number of characters which would be - * written to stdout. - * - * Call this function if you are already dealing with a va_list. - * Or you probably want cprintf() instead. - * */ -int -vcprintf(const char *fmt, va_list ap) { - int cnt = 0; - vprintfmt(cputch, NO_FD, &cnt, fmt, ap); - return cnt; -} - -/* * - * cprintf - formats a string and writes it to stdout - * - * The return value is the number of characters which would be - * written to stdout. - * */ -int -cprintf(const char *fmt, ...) { - va_list ap; - int cnt; - va_start(ap, fmt); - cnt = vcprintf(fmt, ap); - va_end(ap); - return cnt; -} - - -static const char* hexdigits = "0123456789ABCDEF"; -void printhex(unsigned int x){ - char tmp[9]; - int i=0; - tmp[8] = 0; - for(i=7;i>=0;i--){ - tmp[i] = hexdigits[x & 0xf]; - x = x >> 4; - } - cprintf(tmp); -} - - -/* cputchar - writes a single character to stdout */ -void -cputchar(int c) { - sys_putc(c); -} - -void printbase10(int x){ - unsigned int t; - int i = 0; - char buf[16]; - if(x<0) - cputchar('-'); - x = (x<0)?-x:x; - while(x >= 10){ - t = __divu10(x); - buf[i++] = ('0'+(x-__mulu10(t))); - x = t; - } - buf[i] = ('0'+x); - for(;i>=0;i--){ - cputchar(buf[i]); - } -} - - -/* * - * kputs- writes the string pointed by @str to stdout and - * appends a newline character. - * */ -int -cputs(const char *str) { - int cnt = 0; - char c; - while ((c = *str ++) != '\0') { - cputch(c, &cnt); - } - cputch('\n', &cnt); - return cnt; -} - - -static void -fputch(char c, int *cnt, int fd) { - write(fd, &c, sizeof(char)); - (*cnt) ++; -} - -int -vfprintf(int fd, const char *fmt, va_list ap) { - int cnt = 0; - vprintfmt((void*)fputch, fd, &cnt, fmt, ap); - return cnt; -} - -int -fprintf(int fd, const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - int cnt = vfprintf(fd, fmt, ap); - va_end(ap); - - return cnt; -} - diff --git a/ucore-thumips/user/libs/stdio.h b/ucore-thumips/user/libs/stdio.h deleted file mode 100644 index e9d9705..0000000 --- a/ucore-thumips/user/libs/stdio.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __LIBS_STDIO_H__ -#define __LIBS_STDIO_H__ - -#include -#include - -/* kern/libs/stdio.c */ -int vcprintf(const char *fmt, va_list ap); -int cprintf(const char *fmt, ...); -void cputchar(int c); -int getchar(void); - -void printhex(unsigned int x); -void printbase10(int x); - -/* kern/libs/readline.c */ -char *readline(const char *prompt); - - -#endif /* !__LIBS_STDIO_H__ */ - - diff --git a/ucore-thumips/user/libs/string.c b/ucore-thumips/user/libs/string.c deleted file mode 100644 index b5a07ae..0000000 --- a/ucore-thumips/user/libs/string.c +++ /dev/null @@ -1,369 +0,0 @@ -#include -#include - -/* * - * strlen - calculate the length of the string @s, not including - * the terminating '\0' character. - * @s: the input string - * - * The strlen() function returns the length of string @s. - * */ -size_t -strlen(const char *s) { - size_t cnt = 0; - while (*s ++ != '\0') { - cnt ++; - } - return cnt; -} - -/* * - * strnlen - calculate the length of the string @s, not including - * the terminating '\0' char acter, but at most @len. - * @s: the input string - * @len: the max-length that function will scan - * - * Note that, this function looks only at the first @len characters - * at @s, and never beyond @s + @len. - * - * The return value is strlen(s), if that is less than @len, or - * @len if there is no '\0' character among the first @len characters - * pointed by @s. - * */ -size_t -strnlen(const char *s, size_t len) { - size_t cnt = 0; - while (cnt < len && *s ++ != '\0') { - cnt ++; - } - return cnt; -} - -/* * - * strcpy - copies the string pointed by @src into the array pointed by @dst, - * including the terminating null character. - * @dst: pointer to the destination array where the content is to be copied - * @src: string to be copied - * - * The return value is @dst. - * - * To avoid overflows, the size of array pointed by @dst should be long enough to - * contain the same string as @src (including the terminating null character), and - * should not overlap in memory with @src. - * */ -char * -strcpy(char *dst, const char *src) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __strcpy(dst, src); -#else - char *p = dst; - while ((*p ++ = *src ++) != '\0') - /* nothing */; - return dst; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * strncpy - copies the first @len characters of @src to @dst. If the end of string @src - * if found before @len characters have been copied, @dst is padded with '\0' until a - * total of @len characters have been written to it. - * @dst: pointer to the destination array where the content is to be copied - * @src: string to be copied - * @len: maximum number of characters to be copied from @src - * - * The return value is @dst - * */ -char * -strncpy(char *dst, const char *src, size_t len) { - char *p = dst; - while (len > 0) { - if ((*p = *src) != '\0') { - src ++; - } - p ++, len --; - } - return dst; -} - -/* * - * strcmp - compares the string @s1 and @s2 - * @s1: string to be compared - * @s2: string to be compared - * - * This function starts comparing the first character of each string. If - * they are equal to each other, it continues with the following pairs until - * the characters differ or until a terminanting null-character is reached. - * - * Returns an integral value indicating the relationship between the strings: - * - A zero value indicates that both strings are equal; - * - A value greater than zero indicates that the first character that does - * not match has a greater value in @s1 than in @s2; - * - And a value less than zero indicates the opposite. - * */ -int -strcmp(const char *s1, const char *s2) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __strcmp(s1, s2); -#else - while (*s1 != '\0' && *s1 == *s2) { - s1 ++, s2 ++; - } - return (int)((unsigned char)*s1 - (unsigned char)*s2); -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * strncmp - compares up to @n characters of the string @s1 to those of the string @s2 - * @s1: string to be compared - * @s2: string to be compared - * @n: maximum number of characters to compare - * - * This function starts comparing the first character of each string. If - * they are equal to each other, it continues with the following pairs until - * the characters differ, until a terminating null-character is reached, or - * until @n characters match in both strings, whichever happens first. - * */ -int -strncmp(const char *s1, const char *s2, size_t n) { - while (n > 0 && *s1 != '\0' && *s1 == *s2) { - n --, s1 ++, s2 ++; - } - return (n == 0) ? 0 : (int)((unsigned char)*s1 - (unsigned char)*s2); -} - -/* * - * strchr - locates first occurrence of character in string - * @s: the input string - * @c: character to be located - * - * The strchr() function returns a pointer to the first occurrence of - * character in @s. If the value is not found, the function returns 'NULL'. - * */ -char * -strchr(const char *s, char c) { - while (*s != '\0') { - if (*s == c) { - return (char *)s; - } - s ++; - } - return NULL; -} - -/* * - * strfind - locates first occurrence of character in string - * @s: the input string - * @c: character to be located - * - * The strfind() function is like strchr() except that if @c is - * not found in @s, then it returns a pointer to the null byte at the - * end of @s, rather than 'NULL'. - * */ -char * -strfind(const char *s, char c) { - while (*s != '\0') { - if (*s == c) { - break; - } - s ++; - } - return (char *)s; -} - -/* * - * strtol - converts string to long integer - * @s: the input string that contains the representation of an integer number - * @endptr: reference to an object of type char *, whose value is set by the - * function to the next character in @s after the numerical value. This - * parameter can also be a null pointer, in which case it is not used. - * @base: x - * - * The function first discards as many whitespace characters as necessary until - * the first non-whitespace character is found. Then, starting from this character, - * takes as many characters as possible that are valid following a syntax that - * depends on the base parameter, and interprets them as a numerical value. Finally, - * a pointer to the first character following the integer representation in @s - * is stored in the object pointed by @endptr. - * - * If the value of base is zero, the syntax expected is similar to that of - * integer constants, which is formed by a succession of: - * - An optional plus or minus sign; - * - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively) - * - A sequence of decimal digits (if no base prefix was specified) or either octal - * or hexadecimal digits if a specific prefix is present - * - * If the base value is between 2 and 36, the format expected for the integral number - * is a succession of the valid digits and/or letters needed to represent integers of - * the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The - * sequence may optionally be preceded by a plus or minus sign and, if base is 16, - * an optional "0x" or "0X" prefix. - * - * The strtol() function returns the converted integral number as a long int value. - * */ -#if 0 -long -strtol(const char *s, char **endptr, int base) { - int neg = 0; - long val = 0; - - // gobble initial whitespace - while (*s == ' ' || *s == '\t') { - s ++; - } - - // plus/minus sign - if (*s == '+') { - s ++; - } - else if (*s == '-') { - s ++, neg = 1; - } - - // hex or octal base prefix - if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) { - s += 2, base = 16; - } - else if (base == 0 && s[0] == '0') { - s ++, base = 8; - } - else if (base == 0) { - base = 10; - } - - // digits - while (1) { - int dig; - - if (*s >= '0' && *s <= '9') { - dig = *s - '0'; - } - else if (*s >= 'a' && *s <= 'z') { - dig = *s - 'a' + 10; - } - else if (*s >= 'A' && *s <= 'Z') { - dig = *s - 'A' + 10; - } - else { - break; - } - if (dig >= base) { - break; - } - s ++, val = (val * base) + dig; - // we don't properly detect overflow! - } - - if (endptr) { - *endptr = (char *) s; - } - return (neg ? -val : val); -} -#endif - -/* * - * memset - sets the first @n bytes of the memory area pointed by @s - * to the specified value @c. - * @s: pointer the the memory area to fill - * @c: value to set - * @n: number of bytes to be set to the value - * - * The memset() function returns @s. - * */ -void * -memset(void *s, char c, size_t n) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __memset(s, c, n); -#else - char *p = s; - while (n -- > 0) { - *p ++ = c; - } - return s; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * memcpy - copies the value of @n bytes from the location pointed by @src to - * the memory area pointed by @dst. - * @dst pointer to the destination array where the content is to be copied - * @src pointer to the source of data to by copied - * @n: number of bytes to copy - * - * The memcpy() returns @dst. - * - * Note that, the function does not check any terminating null character in @src, - * it always copies exactly @n bytes. To avoid overflows, the size of arrays pointed - * by both @src and @dst, should be at least @n bytes, and should not overlap - * (for overlapping memory area, memmove is a safer approach). - * */ -void * -memcpy(void *dst, const void *src, size_t n) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __memcpy(dst, src, n); -#else - const char *s = src; - char *d = dst; - while (n -- > 0) { - *d ++ = *s ++; - } - return dst; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * memmove - copies the values of @n bytes from the location pointed by @src to - * the memory area pointed by @dst. @src and @dst are allowed to overlap. - * @dst pointer to the destination array where the content is to be copied - * @src pointer to the source of data to by copied - * @n: number of bytes to copy - * - * The memmove() function returns @dst. - * */ -void * -memmove(void *dst, const void *src, size_t n) { -#ifdef __HAVE_ARCH_MEM_OPTS - return __memmove(dst, src, n); -#else - const char *s = src; - char *d = dst; - if (s < d && s + n > d) { - s += n, d += n; - while (n -- > 0) { - *-- d = *-- s; - } - } else { - while (n -- > 0) { - *d ++ = *s ++; - } - } - return dst; -#endif /* __HAVE_ARCH_MEM_OPTS */ -} - -/* * - * memcmp - compares two blocks of memory - * @v1: pointer to block of memory - * @v2: pointer to block of memory - * @n: number of bytes to compare - * - * The memcmp() functions returns an integral value indicating the - * relationship between the content of the memory blocks: - * - A zero value indicates that the contents of both memory blocks are equal; - * - A value greater than zero indicates that the first byte that does not - * match in both memory blocks has a greater value in @v1 than in @v2 - * as if evaluated as unsigned char values; - * - And a value less than zero indicates the opposite. - * */ -int -memcmp(const void *v1, const void *v2, size_t n) { - const char *s1 = (const char *)v1; - const char *s2 = (const char *)v2; - while (n -- > 0) { - if (*s1 != *s2) { - return (int)((unsigned char)*s1 - (unsigned char)*s2); - } - s1 ++, s2 ++; - } - return 0; -} - diff --git a/ucore-thumips/user/libs/string.h b/ucore-thumips/user/libs/string.h deleted file mode 100644 index 573ef6b..0000000 --- a/ucore-thumips/user/libs/string.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __LIBS_STRING_H__ -#define __LIBS_STRING_H__ - -#include - -size_t strlen(const char *s); -size_t strnlen(const char *s, size_t len); - -char *strcpy(char *dst, const char *src); -char *strncpy(char *dst, const char *src, size_t len); - -int strcmp(const char *s1, const char *s2); -int strncmp(const char *s1, const char *s2, size_t n); - -char *strchr(const char *s, char c); -char *strfind(const char *s, char c); -//long strtol(const char *s, char **endptr, int base); - -void *memset(void *s, char c, size_t n); -void *memmove(void *dst, const void *src, size_t n); -void *memcpy(void *dst, const void *src, size_t n); -int memcmp(const void *v1, const void *v2, size_t n); - -#endif /* !__LIBS_STRING_H__ */ - diff --git a/ucore-thumips/user/libs/syscall.c b/ucore-thumips/user/libs/syscall.c deleted file mode 100644 index 4c342d1..0000000 --- a/ucore-thumips/user/libs/syscall.c +++ /dev/null @@ -1,143 +0,0 @@ -#include -#include -#include -#include - -#define MAX_ARGS 4 -#define SYSCALL_BASE 0x80 - -static inline int -syscall(int num, ...) { - va_list ap; - va_start(ap, num); - uint32_t arg[MAX_ARGS]; - int i, ret; - for (i = 0; i < MAX_ARGS; i ++) { - arg[i] = va_arg(ap, uint32_t); - } - va_end(ap); - - num += SYSCALL_BASE; - - asm volatile( - ".set noreorder;\n" - "move $v0, %1;\n" /* syscall no. */ - "move $a0, %2;\n" - "move $a1, %3;\n" - "move $a2, %4;\n" - "move $a3, %5;\n" - "syscall;\n" - "nop;\n" - "move %0, $v0;\n" - : "=r"(ret) - : "r"(num), "r"(arg[0]), "r"(arg[1]), "r"(arg[2]), "r"(arg[3]) - : "a0", "a1", "a2", "a3", "v0" - ); - return ret; -} - -int -sys_exit(int error_code) { - return syscall(SYS_exit, error_code); -} - -int -sys_fork(void) { - return syscall(SYS_fork); -} - -int -sys_wait(int pid, int *store) { - return syscall(SYS_wait, pid, store); -} - -int -sys_yield(void) { - return syscall(SYS_yield); -} - -int -sys_kill(int pid) { - return syscall(SYS_kill, pid); -} - -int -sys_getpid(void) { - return syscall(SYS_getpid); -} - -int -sys_putc(int c) { - return syscall(SYS_putc, c); -} - -int -sys_pgdir(void) { - return syscall(SYS_pgdir); -} - - -int -sys_sleep(unsigned int time) { - return syscall(SYS_sleep, time); -} - -size_t -sys_gettime(void) { - return syscall(SYS_gettime); -} - -int -sys_exec(const char *name, int argc, const char **argv) { - return syscall(SYS_exec, name, argc, argv); -} - -int -sys_open(const char *path, uint32_t open_flags) { - return syscall(SYS_open, path, open_flags); -} - -int -sys_close(int fd) { - return syscall(SYS_close, fd); -} - -int -sys_read(int fd, void *base, size_t len) { - return syscall(SYS_read, fd, base, len); -} - -int -sys_write(int fd, void *base, size_t len) { - return syscall(SYS_write, fd, base, len); -} - -int -sys_seek(int fd, off_t pos, int whence) { - return syscall(SYS_seek, fd, pos, whence); -} - -int -sys_fstat(int fd, struct stat *stat) { - return syscall(SYS_fstat, fd, stat); -} - -int -sys_fsync(int fd) { - return syscall(SYS_fsync, fd); -} - -int -sys_getcwd(char *buffer, size_t len) { - return syscall(SYS_getcwd, buffer, len); -} - -int -sys_getdirentry(int fd, struct dirent *dirent) { - return syscall(SYS_getdirentry, fd, dirent); -} - -int -sys_dup(int fd1, int fd2) { - return syscall(SYS_dup, fd1, fd2); -} diff --git a/ucore-thumips/user/libs/syscall.h b/ucore-thumips/user/libs/syscall.h deleted file mode 100644 index 93f700a..0000000 --- a/ucore-thumips/user/libs/syscall.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __USER_LIBS_SYSCALL_H__ -#define __USER_LIBS_SYSCALL_H__ - -int sys_exit(int error_code); -int sys_fork(void); -int sys_wait(int pid, int *store); -int sys_exec(const char *name, int argc, const char **argv); -int sys_yield(void); -int sys_kill(int pid); -int sys_getpid(void); -int sys_putc(int c); -int sys_pgdir(void); -int sys_sleep(unsigned int time); -size_t sys_gettime(void); - -struct stat; -struct dirent; - -int sys_open(const char *path, uint32_t open_flags); -int sys_close(int fd); -int sys_read(int fd, void *base, size_t len); -int sys_write(int fd, void *base, size_t len); -int sys_seek(int fd, off_t pos, int whence); -int sys_fstat(int fd, struct stat *stat); -int sys_fsync(int fd); -int sys_getcwd(char *buffer, size_t len); -int sys_getdirentry(int fd, struct dirent *dirent); -int sys_dup(int fd1, int fd2); -void sys_lab6_set_priority(uint32_t priority); //only for lab6 - - -#endif /* !__USER_LIBS_SYSCALL_H__ */ - diff --git a/ucore-thumips/user/libs/ulib.c b/ucore-thumips/user/libs/ulib.c deleted file mode 100644 index ce5f386..0000000 --- a/ucore-thumips/user/libs/ulib.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static lock_t fork_lock = INIT_LOCK; - -void -lock_fork(void) { - lock(&fork_lock); -} - -void -unlock_fork(void) { - unlock(&fork_lock); -} - -void -exit(int error_code) { - sys_exit(error_code); - cprintf("BUG: exit failed.\n"); - while (1); -} - -int -fork(void) { - return sys_fork(); -} - -int -wait(void) { - return sys_wait(0, NULL); -} - -int -waitpid(int pid, int *store) { - return sys_wait(pid, store); -} - -void -yield(void) { - sys_yield(); -} - -int -kill(int pid) { - return sys_kill(pid); -} - -int -getpid(void) { - return sys_getpid(); -} - -//print_pgdir - print the PDT&PT -void -print_pgdir(void) { - sys_pgdir(); -} - -int -sleep(unsigned int time) { - return sys_sleep(time); -} - -unsigned int -gettime_msec(void) { - return (unsigned int)sys_gettime(); -} - -int -__exec(const char *name, const char **argv) { - int argc = 0; - while (argv[argc] != NULL) { - argc ++; - } - return sys_exec(name, argc, argv); -} - diff --git a/ucore-thumips/user/libs/ulib.h b/ucore-thumips/user/libs/ulib.h deleted file mode 100644 index baca03b..0000000 --- a/ucore-thumips/user/libs/ulib.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __USER_LIBS_ULIB_H__ -#define __USER_LIBS_ULIB_H__ - -#include - -void __warn(const char *file, int line, const char *fmt, ...); -void __noreturn __panic(const char *file, int line, const char *fmt, ...); - -#define warn(...) \ - __warn(__FILE__, __LINE__, __VA_ARGS__) - -#define panic(...) \ - __panic(__FILE__, __LINE__, __VA_ARGS__) - -#define assert(x) \ - do { \ - if (!(x)) { \ - panic("assertion failed: %s", #x); \ - } \ - } while (0) - -// static_assert(x) will generate a compile-time error if 'x' is false. -#define static_assert(x) \ - switch (x) { case 0: case (x): ; } - -int fprintf(int fd, const char *fmt, ...); - -void __noreturn exit(int error_code); -int fork(void); -int wait(void); -int waitpid(int pid, int *store); -void yield(void); -int kill(int pid); -int getpid(void); -void print_pgdir(void); -int sleep(unsigned int time); -unsigned int gettime_msec(void); -int __exec(const char *name, const char **argv); - -#define __exec0(name, path, ...) \ -({ const char *argv[] = {path, ##__VA_ARGS__, NULL}; __exec(name, argv); }) - -#define exec(path, ...) __exec0(NULL, path, ##__VA_ARGS__) -#define nexec(name, path, ...) __exec0(name, path, ##__VA_ARGS__) - -void lab6_set_priority(uint32_t priority); //only for lab6 - -#endif /* !__USER_LIBS_ULIB_H__ */ - diff --git a/ucore-thumips/user/libs/umain.c b/ucore-thumips/user/libs/umain.c deleted file mode 100644 index 9bee9ab..0000000 --- a/ucore-thumips/user/libs/umain.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include -#include - -int main(int argc, char *argv[]); - -static int -initfd(int fd2, const char *path, uint32_t open_flags) { - int fd1, ret; - if ((fd1 = open(path, open_flags)) < 0) { - return fd1; - } - if (fd1 != fd2) { - close(fd2); - ret = dup2(fd1, fd2); - close(fd1); - } - return ret; -} - -void -umain(int argc, char *argv[]) { - int fd; - if ((fd = initfd(0, "stdin:", O_RDONLY)) < 0) { - warn("open failed: %e.\n", fd); - } - if ((fd = initfd(1, "stdout:", O_WRONLY)) < 0) { - warn("open failed: %e.\n", fd); - } - int ret = main(argc, argv); - exit(ret); -} - diff --git a/ucore-thumips/user/libs/user.ld b/ucore-thumips/user/libs/user.ld deleted file mode 100644 index 507b86c..0000000 --- a/ucore-thumips/user/libs/user.ld +++ /dev/null @@ -1,57 +0,0 @@ -OUTPUT_FORMAT(elf32-tradlittlemips) -OUTPUT_ARCH(mips:isa32) -ENTRY(_start) - -SECTIONS -{ - . = 0x10000000; - .text : - { - . = ALIGN(4); - *(.text) - *(.text.*) - *(.gnu.linkonce.t*) - *(.mips16.fn.*) - *(.mips16.call.*) /* for MIPS */ - *(.rodata) *(.rodata.*) *(.gnu.linkonce.r*) *(.rodata1) - } -. = ALIGN(4096); -.data : -{ - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - *(.data1) - *(.eh_frame) - *(.gcc_except_table) - . = ALIGN(8); - _gp = . + 0x7ff0; /* set gp for MIPS startup code */ - /* got*, dynamic, sdata*, lit[48], and sbss should follow _gp */ - *(.got.plt) - *(.got) - *(.dynamic) - *(.got2) - *(.sdata) *(.sdata.*) *(.lit8) *(.lit4) - . = ALIGN(16); -} - -. = ALIGN(4096); -.bss : -{ - *(.sbss) *(.scommon) *(.dynbss) *(.bss) *(COMMON) - . = ALIGN(16); -} -. = ALIGN(16); - -/DISCARD/ : -{ - /* - *(.stub) - *(.debug*) */ - *(.note) /* seen on Pentium ELF */ - *(.comment) /* seen on PPC & SH ELF */ - *(.reginfo) - *(.pdr) /* seen on MIPS ELF */ -} - -} diff --git a/ucore-thumips/user/ls.c b/ucore-thumips/user/ls.c deleted file mode 100644 index 428a287..0000000 --- a/ucore-thumips/user/ls.c +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define printf(...) fprintf(1, __VA_ARGS__) -#define BUFSIZE 4096 - -static char -getmode(uint32_t st_mode) { - char mode = '?'; - if (S_ISREG(st_mode)) mode = '-'; - if (S_ISDIR(st_mode)) mode = 'd'; - if (S_ISLNK(st_mode)) mode = 'l'; - if (S_ISCHR(st_mode)) mode = 'c'; - if (S_ISBLK(st_mode)) mode = 'b'; - return mode; -} - -static int -getstat(const char *name, struct stat *stat) { - int fd, ret; - if ((fd = open(name, O_RDONLY)) < 0) { - return fd; - } - ret = fstat(fd, stat); - close(fd); - return ret; -} - -void -lsstat(struct stat *stat, const char *filename) { - printf(" [%c]", getmode(stat->st_mode)); - printf(" %3d(h)", stat->st_nlinks); - printf(" %8d(b)", stat->st_blocks); - printf(" %8d(s)", stat->st_size); - printf(" %s\n", filename); -} - -int -lsdir(const char *path) { - struct stat __stat, *stat = &__stat; - int ret; - DIR *dirp = opendir("."); - - if (dirp == NULL) { - return -1; - } - struct dirent *direntp; - while ((direntp = readdir(dirp)) != NULL) { - if ((ret = getstat(direntp->name, stat)) != 0) { - goto failed; - } - lsstat(stat, direntp->name); - } - printf("lsdir: step 4\n"); - closedir(dirp); - return 0; -failed: - closedir(dirp); - return ret; -} - -int -ls(const char *path) { - struct stat __stat, *stat = &__stat; - int ret, type; - if ((ret = getstat(path, stat)) != 0) { - return ret; - } - - static const char *filetype[] = { - " [ file ]", - " [directory]", - " [ symlink ]", - " [character]", - " [ block ]", - " [ ????? ]", - }; - switch (getmode(stat->st_mode)) { - case '0': type = 0; break; - case 'd': type = 1; break; - case 'l': type = 2; break; - case 'c': type = 3; break; - case 'b': type = 4; break; - default: type = 5; break; - } - - printf(" @ is %s", filetype[type]); - printf(" %d(hlinks)", stat->st_nlinks); - printf(" %d(blocks)", stat->st_blocks); - printf(" %d(bytes) : @'%s'\n", stat->st_size, path); - if (S_ISDIR(stat->st_mode)) { - return lsdir(path); - } - return 0; -} - -int -main(int argc, char **argv) { - if (argc == 1) { - return ls("."); - } - else { - int i, ret; - for (i = 1; i < argc; i ++) { - if ((ret = ls(argv[i])) != 0) { - return ret; - } - } - } - return 0; -} - diff --git a/ucore-thumips/user/pgdir.c b/ucore-thumips/user/pgdir.c deleted file mode 100644 index 09fd7e3..0000000 --- a/ucore-thumips/user/pgdir.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -int -main(void) { - cprintf("I am %d, print pgdir.\n", getpid()); - print_pgdir(); - cprintf("pgdir pass.\n"); - return 0; -} - diff --git a/ucore-thumips/user/pwd.c b/ucore-thumips/user/pwd.c deleted file mode 100644 index 9f16a38..0000000 --- a/ucore-thumips/user/pwd.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -#define printf(...) fprintf(1, __VA_ARGS__) -#define BUFSIZE 4096 - -int -main(int argc, char **argv) { - int ret; - static char cwdbuf[BUFSIZE]; - if ((ret = getcwd(cwdbuf, sizeof(cwdbuf))) != 0) { - return ret; - } - printf("%s\n", cwdbuf); - return 0; -} - diff --git a/ucore-thumips/user/sh.c b/ucore-thumips/user/sh.c deleted file mode 100644 index 2cd1550..0000000 --- a/ucore-thumips/user/sh.c +++ /dev/null @@ -1,255 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define printf(...) fprintf(1, __VA_ARGS__) -#define putc(c) printf("%c", c) - -#define BUFSIZE 4096 -#define WHITESPACE " \t\r\n" -#define SYMBOLS "<|>&;" - -char shcwd[BUFSIZE]; - -int -gettoken(char **p1, char **p2) { - char *s; - if ((s = *p1) == NULL) { - return 0; - } - while (strchr(WHITESPACE, *s) != NULL) { - *s ++ = '\0'; - } - if (*s == '\0') { - return 0; - } - - *p2 = s; - int token = 'w'; - if (strchr(SYMBOLS, *s) != NULL) { - token = *s, *s ++ = '\0'; - } - else { - bool flag = 0; - while (*s != '\0' && (flag || strchr(WHITESPACE SYMBOLS, *s) == NULL)) { - if (*s == '"') { - *s = ' ', flag = !flag; - } - s ++; - } - } - *p1 = (*s != '\0' ? s : NULL); - return token; -} - -char * -readline(const char *prompt) { - static char buffer[BUFSIZE]; - if (prompt != NULL) { - printf("%s", prompt); - } - int ret, i = 0; - while (1) { - char c; - if ((ret = read(0, &c, sizeof(char))) < 0) { - return NULL; - } - else if (ret == 0) { - if (i > 0) { - buffer[i] = '\0'; - break; - } - return NULL; - } - - if (c == 3) { - return NULL; - } - else if (c >= ' ' && i < BUFSIZE - 1) { - putc(c); - buffer[i ++] = c; - } - else if (c == '\b' && i > 0) { - putc(c); - i --; - } - else if (c == '\n' || c == '\r') { - putc(c); - buffer[i] = '\0'; - break; - } - } - return buffer; -} - -void -usage(void) { - printf("usage: sh [command-file]\n"); -} - -int -reopen(int fd2, const char *filename, uint32_t open_flags) { - int ret, fd1; - close(fd2); - if ((ret = open(filename, open_flags)) >= 0 && ret != fd2) { - close(fd2); - fd1 = ret, ret = dup2(fd1, fd2); - close(fd1); - } - return ret < 0 ? ret : 0; -} - -int -testfile(const char *name) { - int ret; - if ((ret = open(name, O_RDONLY)) < 0) { - return ret; - } - close(ret); - return 0; -} - -int -runcmd(char *cmd) { - static char argv0[BUFSIZE]; - const char *argv[EXEC_MAX_ARG_NUM + 1]; - char *t; - int argc, token, ret, p[2]; -again: - argc = 0; - while (1) { - switch (token = gettoken(&cmd, &t)) { - case 'w': - if (argc == EXEC_MAX_ARG_NUM) { - printf("sh error: too many arguments\n"); - return -1; - } - argv[argc ++] = t; - break; - case '<': - if (gettoken(&cmd, &t) != 'w') { - printf("sh error: syntax error: < not followed by word\n"); - return -1; - } - if ((ret = reopen(0, t, O_RDONLY)) != 0) { - return ret; - } - break; - case '>': - if (gettoken(&cmd, &t) != 'w') { - printf("sh error: syntax error: > not followed by word\n"); - return -1; - } - if ((ret = reopen(1, t, O_RDWR | O_TRUNC | O_CREAT)) != 0) { - return ret; - } - break; - case '|': - // if ((ret = pipe(p)) != 0) { - // return ret; - // } - if ((ret = fork()) == 0) { - close(0); - if ((ret = dup2(p[0], 0)) < 0) { - return ret; - } - close(p[0]), close(p[1]); - goto again; - } - else { - if (ret < 0) { - return ret; - } - close(1); - if ((ret = dup2(p[1], 1)) < 0) { - return ret; - } - close(p[0]), close(p[1]); - goto runit; - } - break; - case 0: - goto runit; - case ';': - if ((ret = fork()) == 0) { - goto runit; - } - else { - if (ret < 0) { - return ret; - } - waitpid(ret, NULL); - goto again; - } - break; - default: - printf("sh error: bad return %d from gettoken\n", token); - return -1; - } - } - -runit: - if (argc == 0) { - return 0; - } - else if (strcmp(argv[0], "cd") == 0) { - if (argc != 2) { - return -1; - } - strcpy(shcwd, argv[1]); - return 0; - } - if ((ret = testfile(argv[0])) != 0) { - if (ret != -E_NOENT) { - return ret; - } - snprintf(argv0, sizeof(argv0), "/%s", argv[0]); - argv[0] = argv0; - } - argv[argc] = NULL; - return __exec(NULL, argv); -} - -int -main(int argc, char **argv) { - printf("user sh is running!!!\n"); - int ret, interactive = 1; - if (argc == 2) { - if ((ret = reopen(0, argv[1], O_RDONLY)) != 0) { - return ret; - } - interactive = 0; - } - else if (argc > 2) { - usage(); - return -1; - } - //shcwd = malloc(BUFSIZE); - assert(shcwd != NULL); - - char *buffer; - while ((buffer = readline((interactive) ? "$ " : NULL)) != NULL) { - printf("\r\n"); - shcwd[0] = '\0'; - int pid; - if ((pid = fork()) == 0) { - ret = runcmd(buffer); - exit(ret); - } - assert(pid >= 0); - if (waitpid(pid, &ret) == 0) { - if (ret == 0 && shcwd[0] != '\0') { - ret = 0; - } - if (ret != 0) { - printf("error: %d - %e\n", ret, ret); - } - } - } - return 0; -} - diff --git a/ucore-thumips/user/sleep.c b/ucore-thumips/user/sleep.c deleted file mode 100644 index e66dcf7..0000000 --- a/ucore-thumips/user/sleep.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -void -sleepy(int pid) { - int i, time = 100; - for (i = 0; i < 10; i ++) { - sleep(time); - cprintf("sleep %d x %d slices.\n", i + 1, time); - } - exit(0); -} - -int -main(void) { - unsigned int time = gettime_msec(); - int pid1, exit_code; - - if ((pid1 = fork()) == 0) { - sleepy(pid1); - } - - assert(waitpid(pid1, &exit_code) == 0 && exit_code == 0); - cprintf("use %04d msecs.\n", gettime_msec() - time); - cprintf("sleep pass.\n"); - return 0; -} - diff --git a/ucore-thumips/user/softint.c b/ucore-thumips/user/softint.c deleted file mode 100644 index 2f14d15..0000000 --- a/ucore-thumips/user/softint.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int -main(void) { - asm volatile("int $14"); - panic("FAIL: T.T\n"); -} - diff --git a/ucore-thumips/user/spin.c b/ucore-thumips/user/spin.c deleted file mode 100644 index 91581e5..0000000 --- a/ucore-thumips/user/spin.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -int -main(void) { - int pid, ret; - cprintf("I am the parent. Forking the child...\n"); - if ((pid = fork()) == 0) { - cprintf("I am the child. spinning ...\n"); - while (1); - } - cprintf("I am the parent. Running the child...\n"); - - yield(); - yield(); - yield(); - - cprintf("I am the parent. Killing the child...\n"); - - assert((ret = kill(pid)) == 0); - cprintf("kill returns %d\n", ret); - - assert((ret = waitpid(pid, NULL)) == 0); - cprintf("wait returns %d\n", ret); - - cprintf("spin may pass.\n"); - return 0; -} - diff --git a/ucore-thumips/user/testbss.c b/ucore-thumips/user/testbss.c deleted file mode 100644 index 14dc6e1..0000000 --- a/ucore-thumips/user/testbss.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -#define ARRAYSIZE (1024*1024) - -uint32_t bigarray[ARRAYSIZE]; - -int -main(void) { - cprintf("Making sure bss works right...\n"); - int i; - for (i = 0; i < ARRAYSIZE; i ++) { - if (bigarray[i] != 0) { - panic("bigarray[%d] isn't cleared!\n", i); - } - } - for (i = 0; i < ARRAYSIZE; i ++) { - bigarray[i] = i; - } - for (i = 0; i < ARRAYSIZE; i ++) { - if (bigarray[i] != i) { - panic("bigarray[%d] didn't hold its value!\n", i); - } - } - - cprintf("Yes, good. Now doing a wild write off the end...\n"); - cprintf("testbss may pass.\n"); - - bigarray[ARRAYSIZE + 1024] = 0; - asm volatile ("int $0x14"); - panic("FAIL: T.T\n"); -} - diff --git a/ucore-thumips/user/waitkill.c b/ucore-thumips/user/waitkill.c deleted file mode 100644 index 9bb3f80..0000000 --- a/ucore-thumips/user/waitkill.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -void -do_yield(void) { - yield(); - yield(); - yield(); - yield(); - yield(); - yield(); -} - -int parent, pid1, pid2; - -void -loop(void) { - cprintf("child 1.\n"); - while (1); -} - -void -work(void) { - cprintf("child 2.\n"); - do_yield(); - if (kill(parent) == 0) { - cprintf("kill parent ok.\n"); - do_yield(); - if (kill(pid1) == 0) { - cprintf("kill child1 ok.\n"); - exit(0); - } - } - exit(-1); -} - -int -main(void) { - parent = getpid(); - if ((pid1 = fork()) == 0) { - loop(); - } - - assert(pid1 > 0); - - if ((pid2 = fork()) == 0) { - work(); - } - if (pid2 > 0) { - cprintf("wait child 1.\n"); - waitpid(pid1, NULL); - panic("waitpid %d returns\n", pid1); - } - else { - kill(pid1); - } - panic("FAIL: T.T\n"); -} - diff --git a/ucore-thumips/user/yield.c b/ucore-thumips/user/yield.c deleted file mode 100644 index a19890d..0000000 --- a/ucore-thumips/user/yield.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include - -int -main(void) { - int i; - cprintf("Hello, I am process %d.\n", getpid()); - for (i = 0; i < 5; i ++) { - yield(); - cprintf("Back in process %d, iteration %d.\n", getpid(), i); - } - cprintf("All done in process %d.\n", getpid()); - cprintf("yield pass.\n"); - return 0; -} -