pagetable lab initialized
This commit is contained in:
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
The xv6 software is:
|
The xv6 software is:
|
||||||
|
|
||||||
Copyright (c) 2006-2019 Frans Kaashoek, Robert Morris, Russ Cox,
|
Copyright (c) 2006-2024 Frans Kaashoek, Robert Morris, Russ Cox,
|
||||||
Massachusetts Institute of Technology
|
Massachusetts Institute of Technology
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
|||||||
67
Makefile
67
Makefile
@ -44,7 +44,7 @@ OBJS_KCSAN += \
|
|||||||
$K/kcsan.o
|
$K/kcsan.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(LAB),$(filter $(LAB), lock))
|
ifeq ($(LAB),lock)
|
||||||
OBJS += \
|
OBJS += \
|
||||||
$K/stats.o\
|
$K/stats.o\
|
||||||
$K/sprintf.o
|
$K/sprintf.o
|
||||||
@ -55,7 +55,6 @@ ifeq ($(LAB),net)
|
|||||||
OBJS += \
|
OBJS += \
|
||||||
$K/e1000.o \
|
$K/e1000.o \
|
||||||
$K/net.o \
|
$K/net.o \
|
||||||
$K/sysnet.o \
|
|
||||||
$K/pci.o
|
$K/pci.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -86,7 +85,7 @@ LD = $(TOOLPREFIX)ld
|
|||||||
OBJCOPY = $(TOOLPREFIX)objcopy
|
OBJCOPY = $(TOOLPREFIX)objcopy
|
||||||
OBJDUMP = $(TOOLPREFIX)objdump
|
OBJDUMP = $(TOOLPREFIX)objdump
|
||||||
|
|
||||||
CFLAGS = -Wall -Werror -Ofast -fno-omit-frame-pointer -ggdb -gdwarf-2
|
CFLAGS = -Wall -Werror -O -fno-omit-frame-pointer -ggdb -gdwarf-2
|
||||||
|
|
||||||
ifdef LAB
|
ifdef LAB
|
||||||
LABUPPER = $(shell echo $(LAB) | tr a-z A-Z)
|
LABUPPER = $(shell echo $(LAB) | tr a-z A-Z)
|
||||||
@ -96,7 +95,14 @@ endif
|
|||||||
CFLAGS += $(XCFLAGS)
|
CFLAGS += $(XCFLAGS)
|
||||||
CFLAGS += -MD
|
CFLAGS += -MD
|
||||||
CFLAGS += -mcmodel=medany
|
CFLAGS += -mcmodel=medany
|
||||||
CFLAGS += -ffreestanding -fno-common -nostdlib -mno-relax
|
# CFLAGS += -ffreestanding -fno-common -nostdlib -mno-relax
|
||||||
|
CFLAGS += -fno-common -nostdlib
|
||||||
|
CFLAGS += -fno-builtin-strncpy -fno-builtin-strncmp -fno-builtin-strlen -fno-builtin-memset
|
||||||
|
CFLAGS += -fno-builtin-memmove -fno-builtin-memcmp -fno-builtin-log -fno-builtin-bzero
|
||||||
|
CFLAGS += -fno-builtin-strchr -fno-builtin-exit -fno-builtin-malloc -fno-builtin-putc
|
||||||
|
CFLAGS += -fno-builtin-free
|
||||||
|
CFLAGS += -fno-builtin-memcpy -Wno-main
|
||||||
|
CFLAGS += -fno-builtin-printf -fno-builtin-fprintf -fno-builtin-vprintf
|
||||||
CFLAGS += -I.
|
CFLAGS += -I.
|
||||||
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
|
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
|
||||||
|
|
||||||
@ -141,7 +147,7 @@ tags: $(OBJS) _init
|
|||||||
|
|
||||||
ULIB = $U/ulib.o $U/usys.o $U/printf.o $U/umalloc.o
|
ULIB = $U/ulib.o $U/usys.o $U/printf.o $U/umalloc.o
|
||||||
|
|
||||||
ifeq ($(LAB),$(filter $(LAB), lock))
|
ifeq ($(LAB),lock)
|
||||||
ULIB += $U/statistics.o
|
ULIB += $U/statistics.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -188,19 +194,18 @@ UPROGS=\
|
|||||||
$U/_grind\
|
$U/_grind\
|
||||||
$U/_wc\
|
$U/_wc\
|
||||||
$U/_zombie\
|
$U/_zombie\
|
||||||
$U/_sleep\
|
|
||||||
$U/_uptime\
|
|
||||||
$U/_pingpong\
|
|
||||||
$U/_primes\
|
|
||||||
$U/_find\
|
|
||||||
$U/_xargs\
|
|
||||||
$U/_trace\
|
|
||||||
$U/_sysinfo\
|
|
||||||
$U/_sysinfotest\
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(LAB),$(filter $(LAB), lock))
|
|
||||||
|
ifeq ($(LAB),syscall)
|
||||||
|
UPROGS += \
|
||||||
|
$U/_attack\
|
||||||
|
$U/_attacktest\
|
||||||
|
$U/_secret
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LAB),lock)
|
||||||
UPROGS += \
|
UPROGS += \
|
||||||
$U/_stats
|
$U/_stats
|
||||||
endif
|
endif
|
||||||
@ -233,10 +238,10 @@ $U/_uthread: $U/uthread.o $U/uthread_switch.o $(ULIB)
|
|||||||
$(OBJDUMP) -S $U/_uthread > $U/uthread.asm
|
$(OBJDUMP) -S $U/_uthread > $U/uthread.asm
|
||||||
|
|
||||||
ph: notxv6/ph.c
|
ph: notxv6/ph.c
|
||||||
gcc -o ph -g -Ofast $(XCFLAGS) notxv6/ph.c -pthread
|
gcc -o ph -g -O2 $(XCFLAGS) notxv6/ph.c -pthread
|
||||||
|
|
||||||
barrier: notxv6/barrier.c
|
barrier: notxv6/barrier.c
|
||||||
gcc -o barrier -g -Ofast $(XCFLAGS) notxv6/barrier.c -pthread
|
gcc -o barrier -g -O2 $(XCFLAGS) notxv6/barrier.c -pthread
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(LAB),pgtbl)
|
ifeq ($(LAB),pgtbl)
|
||||||
@ -259,7 +264,7 @@ endif
|
|||||||
|
|
||||||
ifeq ($(LAB),net)
|
ifeq ($(LAB),net)
|
||||||
UPROGS += \
|
UPROGS += \
|
||||||
$U/_nettests
|
$U/_nettest
|
||||||
endif
|
endif
|
||||||
|
|
||||||
UEXTRA=
|
UEXTRA=
|
||||||
@ -273,14 +278,12 @@ fs.img: mkfs/mkfs README $(UEXTRA) $(UPROGS)
|
|||||||
|
|
||||||
-include kernel/*.d user/*.d
|
-include kernel/*.d user/*.d
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
|
rm -rf *.tex *.dvi *.idx *.aux *.log *.ind *.ilg *.dSYM *.zip *.pcap \
|
||||||
*/*.o */*.d */*.asm */*.sym \
|
*/*.o */*.d */*.asm */*.sym \
|
||||||
$U/initcode $U/initcode.out $K/kernel fs.img \
|
$U/initcode $U/initcode.out $U/usys.S $U/_* \
|
||||||
mkfs/mkfs .gdbinit \
|
$K/kernel \
|
||||||
$U/usys.S \
|
mkfs/mkfs fs.img .gdbinit __pycache__ xv6.out* \
|
||||||
$(UPROGS) \
|
|
||||||
*.zip \
|
|
||||||
ph barrier
|
ph barrier
|
||||||
|
|
||||||
# try to generate a unique GDB port
|
# try to generate a unique GDB port
|
||||||
@ -296,7 +299,8 @@ ifeq ($(LAB),fs)
|
|||||||
CPUS := 1
|
CPUS := 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
FWDPORT = $(shell expr `id -u` % 5000 + 25999)
|
FWDPORT1 = $(shell expr `id -u` % 5000 + 25999)
|
||||||
|
FWDPORT2 = $(shell expr `id -u` % 5000 + 30999)
|
||||||
|
|
||||||
QEMUOPTS = -machine virt -bios none -kernel $K/kernel -m 128M -smp $(CPUS) -nographic
|
QEMUOPTS = -machine virt -bios none -kernel $K/kernel -m 128M -smp $(CPUS) -nographic
|
||||||
QEMUOPTS += -global virtio-mmio.force-legacy=false
|
QEMUOPTS += -global virtio-mmio.force-legacy=false
|
||||||
@ -304,7 +308,7 @@ QEMUOPTS += -drive file=fs.img,if=none,format=raw,id=x0
|
|||||||
QEMUOPTS += -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
QEMUOPTS += -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
||||||
|
|
||||||
ifeq ($(LAB),net)
|
ifeq ($(LAB),net)
|
||||||
QEMUOPTS += -netdev user,id=net0,hostfwd=udp::$(FWDPORT)-:2000 -object filter-dump,id=net0,netdev=net0,file=packets.pcap
|
QEMUOPTS += -netdev user,id=net0,hostfwd=udp::$(FWDPORT1)-:2000,hostfwd=udp::$(FWDPORT2)-:2001 -object filter-dump,id=net0,netdev=net0,file=packets.pcap
|
||||||
QEMUOPTS += -device e1000,netdev=net0,bus=pcie.0
|
QEMUOPTS += -device e1000,netdev=net0,bus=pcie.0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -322,11 +326,6 @@ ifeq ($(LAB),net)
|
|||||||
# try to generate a unique port for the echo server
|
# try to generate a unique port for the echo server
|
||||||
SERVERPORT = $(shell expr `id -u` % 5000 + 25099)
|
SERVERPORT = $(shell expr `id -u` % 5000 + 25099)
|
||||||
|
|
||||||
server:
|
|
||||||
python3 server.py $(SERVERPORT)
|
|
||||||
|
|
||||||
ping:
|
|
||||||
python3 ping.py $(FWDPORT)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
##
|
##
|
||||||
@ -344,9 +343,7 @@ grade:
|
|||||||
@echo $(MAKE) clean
|
@echo $(MAKE) clean
|
||||||
@$(MAKE) clean || \
|
@$(MAKE) clean || \
|
||||||
(echo "'make clean' failed. HINT: Do you have another running instance of xv6?" && exit 1)
|
(echo "'make clean' failed. HINT: Do you have another running instance of xv6?" && exit 1)
|
||||||
# ./grade-lab-$(LAB) $(GRADEFLAGS)
|
./grade-lab-$(LAB) $(GRADEFLAGS)
|
||||||
python grade-lab-$(LAB)
|
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## FOR submissions
|
## FOR submissions
|
||||||
|
|||||||
35
README
35
README
@ -14,25 +14,22 @@ locking), Cliff Frey (MP), Xiao Yu (MP), Nickolai Zeldovich, and Austin
|
|||||||
Clements.
|
Clements.
|
||||||
|
|
||||||
We are also grateful for the bug reports and patches contributed by
|
We are also grateful for the bug reports and patches contributed by
|
||||||
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, carlclone, Ian
|
Takahiro Aoyagi, Marcelo Arroyo, Silas Boyd-Wickizer, Anton Burtsev,
|
||||||
Chen, Dan Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi,
|
carlclone, Ian Chen, Dan Cross, Cody Cutler, Mike CAT, Tej Chajed,
|
||||||
eyalz800, Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel
|
Asami Doi,Wenyang Duan, eyalz800, Nelson Elhage, Saar Ettinger, Alice
|
||||||
Filardo, flespark, Peter Froehlich, Yakir Goaron, Shivam Handa, Matt
|
Ferrazzi, Nathaniel Filardo, flespark, Peter Froehlich, Yakir Goaron,
|
||||||
Harvey, Bryan Henry, jaichenhengjie, Jim Huang, Matúš Jókay, John
|
Shivam Handa, Matt Harvey, Bryan Henry, jaichenhengjie, Jim Huang,
|
||||||
Jolly, Alexander Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller,
|
Matúš Jókay, John Jolly, Alexander Kapshuk, Anders Kaseorg, kehao95,
|
||||||
Jungwoo Kim, Jonathan Kimmitt, Eddie Kohler, Vadim Kolontsov, Austin
|
Wolfgang Keller, Jungwoo Kim, Jonathan Kimmitt, Eddie Kohler, Vadim
|
||||||
Liew, l0stman, Pavan Maddamsetti, Imbar Marinescu, Yandong Mao, Matan
|
Kolontsov, Austin Liew, l0stman, Pavan Maddamsetti, Imbar Marinescu,
|
||||||
Shabtay, Hitoshi Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel
|
Yandong Mao, Matan Shabtay, Hitoshi Mitake, Carmi Merimovich, Mark
|
||||||
Nider, Hayato Ohhashi, OptimisticSide, Harry Porter, Greg Price, Jude
|
Morrissey, mtasm, Joel Nider, Hayato Ohhashi, OptimisticSide,
|
||||||
Rich, segfault, Ayan Shafqat, Eldar Sehayek, Yongming Shen, Fumiya
|
phosphagos, Harry Porter, Greg Price, RayAndrew, Jude Rich, segfault,
|
||||||
Shigemitsu, Cam Tenny, tyfkda, Warren Toomey, Stephen Tu, Rafael Ubal,
|
Ayan Shafqat, Eldar Sehayek, Yongming Shen, Fumiya Shigemitsu, snoire,
|
||||||
Amane Uehara, Pablo Ventura, Xi Wang, WaheedHafez, Keiichi Watanabe,
|
Taojie, Cam Tenny, tyfkda, Warren Toomey, Stephen Tu, Alissa Tung,
|
||||||
Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng,
|
Rafael Ubal, Amane Uehara, Pablo Ventura, Xi Wang, WaheedHafez,
|
||||||
ZhUyU1997, and Zou Chang Wei.
|
Keiichi Watanabe, Lucas Wolf, Nicolas Wolovick, wxdao, Grant Wu, x653,
|
||||||
|
Jindong Zhang, Icenowy Zheng, ZhUyU1997, and Zou Chang Wei.
|
||||||
|
|
||||||
The code in the files that constitute xv6 is
|
|
||||||
Copyright 2006-2022 Frans Kaashoek, Robert Morris, and Russ Cox.
|
|
||||||
|
|
||||||
ERROR REPORTS
|
ERROR REPORTS
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
在xv6中,当执行到地址 0x3ffffff11c 处的 sret 指令时,特权级和执行流程的变化如下:
|
|
||||||
|
|
||||||
1. 特权级变化
|
|
||||||
- 执行前:核心态(S模式,特权级 1)
|
|
||||||
- 执行后:用户态(U模式,特权级 0)
|
|
||||||
sret 指令会从 sstatus 寄存器中恢复之前的特权级(由 SPP 位决定)。在进入陷阱处理时,处理器已自动将用户态的特权级(0)保存到 sstatus.SPP,因此 sret 会将特权级切换回用户态。
|
|
||||||
|
|
||||||
2. 恢复点地址
|
|
||||||
恢复点地址由 sepc 寄存器指定。在进入陷阱处理时,sepc 被设置为触发 ecall 的下一条指令地址(即 0x14)。因此,sret 执行后,程序会跳转到 0x14 处继续执行用户代码。
|
|
||||||
|
|
||||||
3. 执行的函数
|
|
||||||
sret 返回后,用户程序会从 0x14 处继续执行。根据 initcode.S 的代码,0x14 是 ecall 指令的下一条地址。若 exec 系统调用成功,用户地址空间会被替换为新程序(如 init),此时 sret 返回后直接进入新程序的入口点。若 exec 失败(理论上不会发生),则会继续执行 initcode.S 中 ecall 后的代码(但实际代码中 ecall 后无其他指令)。
|
|
||||||
|
|
||||||
综上所述
|
|
||||||
- 特权级:核心态(1)→ 用户态(0)
|
|
||||||
- 恢复点地址:0x14(用户代码中 ecall 的下一条指令)
|
|
||||||
- 执行函数:若 exec 成功,执行新程序(如 init);否则继续 initcode.S 的后续代码(实际无后续指令)。
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@
|
|||||||
LAB=syscall
|
LAB=pgtbl
|
||||||
|
|||||||
62
grade-lab-pgtbl
Executable file
62
grade-lab-pgtbl
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import re
|
||||||
|
from gradelib import *
|
||||||
|
|
||||||
|
r = Runner(save("xv6.out"))
|
||||||
|
|
||||||
|
@test(0, "pgtbltest")
|
||||||
|
def test_pgtbltest():
|
||||||
|
r.run_qemu(shell_script([
|
||||||
|
'pgtbltest'
|
||||||
|
]), timeout=300)
|
||||||
|
|
||||||
|
@test(10, "pgtbltest: ugetpid", parent=test_pgtbltest)
|
||||||
|
def test_ugetpid_():
|
||||||
|
r.match('^ugetpid_test: OK$')
|
||||||
|
|
||||||
|
@test(10, "pgtbltest: print_kpgtbl", parent=test_pgtbltest)
|
||||||
|
def test_print_kpgtbl_():
|
||||||
|
r.match(
|
||||||
|
'^page table 0x',
|
||||||
|
'^ \.\.0x0000000000000000',
|
||||||
|
'^ \.\. \.\.0x0000000000000000',
|
||||||
|
'^ \.\. \.\. \.\.0x0000000000000000',
|
||||||
|
'^ \.\. \.\. \.\.0x0000000000001000',
|
||||||
|
'^ \.\. \.\. \.\.0x0000000000002000',
|
||||||
|
'^ \.\. \.\. \.\.0x0000000000003000',
|
||||||
|
'^ \.\.(0xffffffffc0000000|0x0000003fc0000000)',
|
||||||
|
'^ \.\. \.\.(0xffffffffffe00000|0x0000003fffe00000)',
|
||||||
|
'^ \.\. \.\. \.\.(0xffffffffffffd000|0x0000003fffffd000)',
|
||||||
|
'^ \.\. \.\. \.\.(0xffffffffffffe000|0x0000003fffffe000)',
|
||||||
|
'^ \.\. \.\. \.\.(0xfffffffffffff000|0x0000003ffffff000)',
|
||||||
|
)
|
||||||
|
|
||||||
|
@test(10, "pgtbltest: pgaccess", parent=test_pgtbltest)
|
||||||
|
def test_nettest_():
|
||||||
|
r.match('^pgaccess_test: OK$')
|
||||||
|
|
||||||
|
@test(15, "pgtbltest: superpg", parent=test_pgtbltest)
|
||||||
|
def test_superpg_():
|
||||||
|
r.match('^superpg_test: OK$')
|
||||||
|
|
||||||
|
@test(5, "answers-pgtbl.txt")
|
||||||
|
def test_answers():
|
||||||
|
# just a simple sanity check, will be graded manually
|
||||||
|
check_answers("answers-pgtbl.txt")
|
||||||
|
|
||||||
|
@test(0, "usertests")
|
||||||
|
def test_usertests():
|
||||||
|
r.run_qemu(shell_script([
|
||||||
|
'usertests -q'
|
||||||
|
]), timeout=300)
|
||||||
|
|
||||||
|
@test(10, "usertests: all tests", parent=test_usertests)
|
||||||
|
def test_usertests():
|
||||||
|
r.match('^ALL TESTS PASSED$')
|
||||||
|
|
||||||
|
@test(1, "time")
|
||||||
|
def test_time():
|
||||||
|
check_time()
|
||||||
|
|
||||||
|
run_tests()
|
||||||
@ -1,136 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import re
|
|
||||||
from gradelib import *
|
|
||||||
|
|
||||||
r = Runner(save("xv6.out"))
|
|
||||||
|
|
||||||
@test(5, "answers-syscall.txt")
|
|
||||||
def test_answers():
|
|
||||||
# just a simple sanity check, will be graded manually
|
|
||||||
check_answers("answers-syscall.txt")
|
|
||||||
|
|
||||||
@test(5, "trace 32 grep")
|
|
||||||
def test_trace_32_grep():
|
|
||||||
r.run_qemu(shell_script([
|
|
||||||
'trace 32 grep hello README'
|
|
||||||
]))
|
|
||||||
|
|
||||||
sys_cnt = {
|
|
||||||
'read' : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 1023'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 961'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 321'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 0'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
@test(5, "trace all grep")
|
|
||||||
def test_trace_all_grep():
|
|
||||||
r.run_qemu(shell_script([
|
|
||||||
'trace 2147483647 grep hello README'
|
|
||||||
]))
|
|
||||||
|
|
||||||
sys_cnt = {
|
|
||||||
'read' : 0,
|
|
||||||
'trace' : 0,
|
|
||||||
'exec' : 0,
|
|
||||||
'open' : 0,
|
|
||||||
'close' : 0,
|
|
||||||
'fork' : 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
sys_cnt['trace'] += 1
|
|
||||||
s = r'^\d+: syscall trace\(trace counts: ' + str(sys_cnt['trace']) + r'\) -> 0'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['exec'] += 1
|
|
||||||
s = r'^\d+: syscall exec\(trace counts: ' + str(sys_cnt['exec']) + r'\) -> 3'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['open'] += 1
|
|
||||||
s = r'^\d+: syscall open\(trace counts: ' + str(sys_cnt['open']) + r'\) -> 3'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 1023'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 961'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 321'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['read'] += 1
|
|
||||||
s = r'^\d+: syscall read\(trace counts: ' + str(sys_cnt['read']) + r'\) -> 0'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
sys_cnt['close'] += 1
|
|
||||||
s = r'^\d+: syscall close\(trace counts: ' + str(sys_cnt['close']) + r'\) -> 0'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
@test(5, "trace nothing")
|
|
||||||
def test_trace_nothing():
|
|
||||||
r.run_qemu(shell_script([
|
|
||||||
'grep hello README'
|
|
||||||
]))
|
|
||||||
r.match(no=[".* syscall .*"])
|
|
||||||
|
|
||||||
@test(5, "trace children")
|
|
||||||
def test_trace_children():
|
|
||||||
r.run_qemu(shell_script([
|
|
||||||
'trace 2 usertests forkforkfork'
|
|
||||||
]))
|
|
||||||
|
|
||||||
sys_cnt = {
|
|
||||||
'read' : 0,
|
|
||||||
'trace' : 0,
|
|
||||||
'exec' : 0,
|
|
||||||
'open' : 0,
|
|
||||||
'close' : 0,
|
|
||||||
'fork' : 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
sys_cnt['fork'] += 1
|
|
||||||
s = r'3: syscall fork\(trace counts: ' + str(sys_cnt['fork']) + r'\) -> 4'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
s = r'^5: syscall fork\(trace counts: \d+\) -> \d+'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
s = r'^6: syscall fork\(trace counts: \d+\) -> \d+'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
s = r'^\d+: syscall fork\(trace counts: \d+\) -> -1'
|
|
||||||
r.match(s)
|
|
||||||
|
|
||||||
r.match('^ALL TESTS PASSED')
|
|
||||||
|
|
||||||
@test(14, "sysinfotest")
|
|
||||||
def test_sysinfotest():
|
|
||||||
r.run_qemu(shell_script([
|
|
||||||
'sysinfotest'
|
|
||||||
]))
|
|
||||||
r.match('^sysinfotest: OK', no=[".* FAIL .*"])
|
|
||||||
|
|
||||||
@test(1, "time")
|
|
||||||
def test_time():
|
|
||||||
check_time()
|
|
||||||
|
|
||||||
run_tests()
|
|
||||||
|
|
||||||
321
kernel/defs.h
321
kernel/defs.h
@ -1,3 +1,7 @@
|
|||||||
|
#ifdef LAB_MMAP
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
typedef long int off_t;
|
||||||
|
#endif
|
||||||
struct buf;
|
struct buf;
|
||||||
struct context;
|
struct context;
|
||||||
struct file;
|
struct file;
|
||||||
@ -10,183 +14,226 @@ struct stat;
|
|||||||
struct superblock;
|
struct superblock;
|
||||||
|
|
||||||
// bio.c
|
// bio.c
|
||||||
void binit(void);
|
void binit(void);
|
||||||
struct buf *bread(uint, uint);
|
struct buf* bread(uint, uint);
|
||||||
void brelse(struct buf *);
|
void brelse(struct buf*);
|
||||||
void bwrite(struct buf *);
|
void bwrite(struct buf*);
|
||||||
void bpin(struct buf *);
|
void bpin(struct buf*);
|
||||||
void bunpin(struct buf *);
|
void bunpin(struct buf*);
|
||||||
|
|
||||||
// console.c
|
// console.c
|
||||||
void consoleinit(void);
|
void consoleinit(void);
|
||||||
void consoleintr(int);
|
void consoleintr(int);
|
||||||
void consputc(int);
|
void consputc(int);
|
||||||
|
|
||||||
// exec.c
|
// exec.c
|
||||||
int exec(char *, char **);
|
int exec(char*, char**);
|
||||||
|
|
||||||
// file.c
|
// file.c
|
||||||
struct file *filealloc(void);
|
struct file* filealloc(void);
|
||||||
void fileclose(struct file *);
|
void fileclose(struct file*);
|
||||||
struct file *filedup(struct file *);
|
struct file* filedup(struct file*);
|
||||||
void fileinit(void);
|
void fileinit(void);
|
||||||
int fileread(struct file *, uint64, int n);
|
int fileread(struct file*, uint64, int n);
|
||||||
int filestat(struct file *, uint64 addr);
|
int filestat(struct file*, uint64 addr);
|
||||||
int filewrite(struct file *, uint64, int n);
|
int filewrite(struct file*, uint64, int n);
|
||||||
|
|
||||||
// fs.c
|
// fs.c
|
||||||
void fsinit(int);
|
void fsinit(int);
|
||||||
int dirlink(struct inode *, char *, uint);
|
int dirlink(struct inode*, char*, uint);
|
||||||
struct inode *dirlookup(struct inode *, char *, uint *);
|
struct inode* dirlookup(struct inode*, char*, uint*);
|
||||||
struct inode *ialloc(uint, short);
|
struct inode* ialloc(uint, short);
|
||||||
struct inode *idup(struct inode *);
|
struct inode* idup(struct inode*);
|
||||||
void iinit();
|
void iinit();
|
||||||
void ilock(struct inode *);
|
void ilock(struct inode*);
|
||||||
void iput(struct inode *);
|
void iput(struct inode*);
|
||||||
void iunlock(struct inode *);
|
void iunlock(struct inode*);
|
||||||
void iunlockput(struct inode *);
|
void iunlockput(struct inode*);
|
||||||
void iupdate(struct inode *);
|
void iupdate(struct inode*);
|
||||||
int namecmp(const char *, const char *);
|
int namecmp(const char*, const char*);
|
||||||
struct inode *namei(char *);
|
struct inode* namei(char*);
|
||||||
struct inode *nameiparent(char *, char *);
|
struct inode* nameiparent(char*, char*);
|
||||||
int readi(struct inode *, int, uint64, uint, uint);
|
int readi(struct inode*, int, uint64, uint, uint);
|
||||||
void stati(struct inode *, struct stat *);
|
void stati(struct inode*, struct stat*);
|
||||||
int writei(struct inode *, int, uint64, uint, uint);
|
int writei(struct inode*, int, uint64, uint, uint);
|
||||||
void itrunc(struct inode *);
|
void itrunc(struct inode*);
|
||||||
|
|
||||||
// ramdisk.c
|
// ramdisk.c
|
||||||
void ramdiskinit(void);
|
void ramdiskinit(void);
|
||||||
void ramdiskintr(void);
|
void ramdiskintr(void);
|
||||||
void ramdiskrw(struct buf *);
|
void ramdiskrw(struct buf*);
|
||||||
|
|
||||||
// kalloc.c
|
// kalloc.c
|
||||||
void *kalloc(void);
|
void* kalloc(void);
|
||||||
void kfree(void *);
|
void kfree(void *);
|
||||||
void kinit(void);
|
void kinit(void);
|
||||||
int freemem(void);
|
|
||||||
|
|
||||||
// log.c
|
// log.c
|
||||||
void initlog(int, struct superblock *);
|
void initlog(int, struct superblock*);
|
||||||
void log_write(struct buf *);
|
void log_write(struct buf*);
|
||||||
void begin_op(void);
|
void begin_op(void);
|
||||||
void end_op(void);
|
void end_op(void);
|
||||||
|
|
||||||
// pipe.c
|
// pipe.c
|
||||||
int pipealloc(struct file **, struct file **);
|
int pipealloc(struct file**, struct file**);
|
||||||
void pipeclose(struct pipe *, int);
|
void pipeclose(struct pipe*, int);
|
||||||
int piperead(struct pipe *, uint64, int);
|
int piperead(struct pipe*, uint64, int);
|
||||||
int pipewrite(struct pipe *, uint64, int);
|
int pipewrite(struct pipe*, uint64, int);
|
||||||
|
|
||||||
// printf.c
|
// printf.c
|
||||||
void printf(char *, ...);
|
int printf(char*, ...) __attribute__ ((format (printf, 1, 2)));
|
||||||
void panic(char *) __attribute__((noreturn));
|
void panic(char*) __attribute__((noreturn));
|
||||||
void printfinit(void);
|
void printfinit(void);
|
||||||
|
|
||||||
// proc.c
|
// proc.c
|
||||||
int cpuid(void);
|
int cpuid(void);
|
||||||
void exit(int);
|
void exit(int);
|
||||||
int fork(void);
|
int fork(void);
|
||||||
int growproc(int);
|
int growproc(int);
|
||||||
void proc_mapstacks(pagetable_t);
|
void proc_mapstacks(pagetable_t);
|
||||||
pagetable_t proc_pagetable(struct proc *);
|
pagetable_t proc_pagetable(struct proc *);
|
||||||
void proc_freepagetable(pagetable_t, uint64);
|
void proc_freepagetable(pagetable_t, uint64);
|
||||||
int kill(int);
|
int kill(int);
|
||||||
int killed(struct proc *);
|
int killed(struct proc*);
|
||||||
void setkilled(struct proc *);
|
void setkilled(struct proc*);
|
||||||
struct cpu *mycpu(void);
|
struct cpu* mycpu(void);
|
||||||
struct cpu *getmycpu(void);
|
struct cpu* getmycpu(void);
|
||||||
struct proc *myproc();
|
struct proc* myproc();
|
||||||
void procinit(void);
|
void procinit(void);
|
||||||
void scheduler(void) __attribute__((noreturn));
|
void scheduler(void) __attribute__((noreturn));
|
||||||
void sched(void);
|
void sched(void);
|
||||||
void sleep(void *, struct spinlock *);
|
void sleep(void*, struct spinlock*);
|
||||||
void userinit(void);
|
void userinit(void);
|
||||||
int wait(uint64);
|
int wait(uint64);
|
||||||
void wakeup(void *);
|
void wakeup(void*);
|
||||||
void yield(void);
|
void yield(void);
|
||||||
int either_copyout(int user_dst, uint64 dst, void *src, uint64 len);
|
int either_copyout(int user_dst, uint64 dst, void *src, uint64 len);
|
||||||
int either_copyin(void *dst, int user_src, uint64 src, uint64 len);
|
int either_copyin(void *dst, int user_src, uint64 src, uint64 len);
|
||||||
void procdump(void);
|
void procdump(void);
|
||||||
int proc_size(void);
|
|
||||||
int update_load(void);
|
|
||||||
|
|
||||||
// swtch.S
|
// swtch.S
|
||||||
void swtch(struct context *, struct context *);
|
void swtch(struct context*, struct context*);
|
||||||
|
|
||||||
// spinlock.c
|
// spinlock.c
|
||||||
void acquire(struct spinlock *);
|
void acquire(struct spinlock*);
|
||||||
int holding(struct spinlock *);
|
int holding(struct spinlock*);
|
||||||
void initlock(struct spinlock *, char *);
|
void initlock(struct spinlock*, char*);
|
||||||
void release(struct spinlock *);
|
void release(struct spinlock*);
|
||||||
void push_off(void);
|
void push_off(void);
|
||||||
void pop_off(void);
|
void pop_off(void);
|
||||||
|
int atomic_read4(int *addr);
|
||||||
|
#ifdef LAB_LOCK
|
||||||
|
void freelock(struct spinlock*);
|
||||||
|
#endif
|
||||||
|
|
||||||
// sleeplock.c
|
// sleeplock.c
|
||||||
void acquiresleep(struct sleeplock *);
|
void acquiresleep(struct sleeplock*);
|
||||||
void releasesleep(struct sleeplock *);
|
void releasesleep(struct sleeplock*);
|
||||||
int holdingsleep(struct sleeplock *);
|
int holdingsleep(struct sleeplock*);
|
||||||
void initsleeplock(struct sleeplock *, char *);
|
void initsleeplock(struct sleeplock*, char*);
|
||||||
|
|
||||||
// string.c
|
// string.c
|
||||||
int memcmp(const void *, const void *, uint);
|
int memcmp(const void*, const void*, uint);
|
||||||
void *memmove(void *, const void *, uint);
|
void* memmove(void*, const void*, uint);
|
||||||
void *memset(void *, int, uint);
|
void* memset(void*, int, uint);
|
||||||
char *safestrcpy(char *, const char *, int);
|
char* safestrcpy(char*, const char*, int);
|
||||||
int strlen(const char *);
|
int strlen(const char*);
|
||||||
int strncmp(const char *, const char *, uint);
|
int strncmp(const char*, const char*, uint);
|
||||||
char *strncpy(char *, const char *, int);
|
char* strncpy(char*, const char*, int);
|
||||||
|
|
||||||
// syscall.c
|
// syscall.c
|
||||||
void argint(int, int *);
|
void argint(int, int*);
|
||||||
int argstr(int, char *, int);
|
int argstr(int, char*, int);
|
||||||
void argaddr(int, uint64 *);
|
void argaddr(int, uint64 *);
|
||||||
int fetchstr(uint64, char *, int);
|
int fetchstr(uint64, char*, int);
|
||||||
int fetchaddr(uint64, uint64 *);
|
int fetchaddr(uint64, uint64*);
|
||||||
void syscall();
|
void syscall();
|
||||||
|
|
||||||
// trap.c
|
// trap.c
|
||||||
extern uint ticks;
|
extern uint ticks;
|
||||||
void trapinit(void);
|
void trapinit(void);
|
||||||
void trapinithart(void);
|
void trapinithart(void);
|
||||||
extern struct spinlock tickslock;
|
extern struct spinlock tickslock;
|
||||||
void usertrapret(void);
|
void usertrapret(void);
|
||||||
|
|
||||||
// uart.c
|
// uart.c
|
||||||
void uartinit(void);
|
void uartinit(void);
|
||||||
void uartintr(void);
|
void uartintr(void);
|
||||||
void uartputc(int);
|
void uartputc(int);
|
||||||
void uartputc_sync(int);
|
void uartputc_sync(int);
|
||||||
int uartgetc(void);
|
int uartgetc(void);
|
||||||
|
|
||||||
// vm.c
|
// vm.c
|
||||||
void kvminit(void);
|
void kvminit(void);
|
||||||
void kvminithart(void);
|
void kvminithart(void);
|
||||||
void kvmmap(pagetable_t, uint64, uint64, uint64, int);
|
void kvmmap(pagetable_t, uint64, uint64, uint64, int);
|
||||||
int mappages(pagetable_t, uint64, uint64, uint64, int);
|
int mappages(pagetable_t, uint64, uint64, uint64, int);
|
||||||
pagetable_t uvmcreate(void);
|
pagetable_t uvmcreate(void);
|
||||||
void uvmfirst(pagetable_t, uchar *, uint);
|
void uvmfirst(pagetable_t, uchar *, uint);
|
||||||
uint64 uvmalloc(pagetable_t, uint64, uint64, int);
|
uint64 uvmalloc(pagetable_t, uint64, uint64, int);
|
||||||
uint64 uvmdealloc(pagetable_t, uint64, uint64);
|
uint64 uvmdealloc(pagetable_t, uint64, uint64);
|
||||||
int uvmcopy(pagetable_t, pagetable_t, uint64);
|
int uvmcopy(pagetable_t, pagetable_t, uint64);
|
||||||
void uvmfree(pagetable_t, uint64);
|
void uvmfree(pagetable_t, uint64);
|
||||||
void uvmunmap(pagetable_t, uint64, uint64, int);
|
void uvmunmap(pagetable_t, uint64, uint64, int);
|
||||||
void uvmclear(pagetable_t, uint64);
|
void uvmclear(pagetable_t, uint64);
|
||||||
pte_t *walk(pagetable_t, uint64, int);
|
pte_t * walk(pagetable_t, uint64, int);
|
||||||
uint64 walkaddr(pagetable_t, uint64);
|
uint64 walkaddr(pagetable_t, uint64);
|
||||||
int copyout(pagetable_t, uint64, char *, uint64);
|
int copyout(pagetable_t, uint64, char *, uint64);
|
||||||
int copyin(pagetable_t, char *, uint64, uint64);
|
int copyin(pagetable_t, char *, uint64, uint64);
|
||||||
int copyinstr(pagetable_t, char *, uint64, uint64);
|
int copyinstr(pagetable_t, char *, uint64, uint64);
|
||||||
|
#if defined(LAB_PGTBL) || defined(SOL_MMAP)
|
||||||
|
void vmprint(pagetable_t);
|
||||||
|
#endif
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
pte_t* pgpte(pagetable_t, uint64);
|
||||||
|
#endif
|
||||||
|
|
||||||
// plic.c
|
// plic.c
|
||||||
void plicinit(void);
|
void plicinit(void);
|
||||||
void plicinithart(void);
|
void plicinithart(void);
|
||||||
int plic_claim(void);
|
int plic_claim(void);
|
||||||
void plic_complete(int);
|
void plic_complete(int);
|
||||||
|
|
||||||
// virtio_disk.c
|
// virtio_disk.c
|
||||||
void virtio_disk_init(void);
|
void virtio_disk_init(void);
|
||||||
void virtio_disk_rw(struct buf *, int);
|
void virtio_disk_rw(struct buf *, int);
|
||||||
void virtio_disk_intr(void);
|
void virtio_disk_intr(void);
|
||||||
|
|
||||||
// number of elements in fixed-size array
|
// number of elements in fixed-size array
|
||||||
#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
|
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
// vmcopyin.c
|
||||||
|
int copyin_new(pagetable_t, char *, uint64, uint64);
|
||||||
|
int copyinstr_new(pagetable_t, char *, uint64, uint64);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LAB_LOCK
|
||||||
|
// stats.c
|
||||||
|
void statsinit(void);
|
||||||
|
void statsinc(void);
|
||||||
|
|
||||||
|
// sprintf.c
|
||||||
|
int snprintf(char*, unsigned long, const char*, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef KCSAN
|
||||||
|
void kcsaninit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LAB_NET
|
||||||
|
// pci.c
|
||||||
|
void pci_init();
|
||||||
|
|
||||||
|
// e1000.c
|
||||||
|
void e1000_init(uint32 *);
|
||||||
|
void e1000_intr(void);
|
||||||
|
int e1000_transmit(char *, int);
|
||||||
|
|
||||||
|
// net.c
|
||||||
|
void netinit(void);
|
||||||
|
void net_rx(char *buf, int len);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@ -75,17 +75,17 @@ exec(char *path, char **argv)
|
|||||||
p = myproc();
|
p = myproc();
|
||||||
uint64 oldsz = p->sz;
|
uint64 oldsz = p->sz;
|
||||||
|
|
||||||
// Allocate two pages at the next page boundary.
|
// Allocate some pages at the next page boundary.
|
||||||
// Make the first inaccessible as a stack guard.
|
// Make the first inaccessible as a stack guard.
|
||||||
// Use the second as the user stack.
|
// Use the rest as the user stack.
|
||||||
sz = PGROUNDUP(sz);
|
sz = PGROUNDUP(sz);
|
||||||
uint64 sz1;
|
uint64 sz1;
|
||||||
if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE, PTE_W)) == 0)
|
if((sz1 = uvmalloc(pagetable, sz, sz + (USERSTACK+1)*PGSIZE, PTE_W)) == 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
sz = sz1;
|
sz = sz1;
|
||||||
uvmclear(pagetable, sz-2*PGSIZE);
|
uvmclear(pagetable, sz-(USERSTACK+1)*PGSIZE);
|
||||||
sp = sz;
|
sp = sz;
|
||||||
stackbase = sp - PGSIZE;
|
stackbase = sp - USERSTACK*PGSIZE;
|
||||||
|
|
||||||
// Push argument strings, prepare rest of stack in ustack.
|
// Push argument strings, prepare rest of stack in ustack.
|
||||||
for(argc = 0; argv[argc]; argc++) {
|
for(argc = 0; argv[argc]; argc++) {
|
||||||
|
|||||||
43
kernel/fs.h
43
kernel/fs.h
@ -1,9 +1,9 @@
|
|||||||
// On-disk file system format.
|
// On-disk file system format.
|
||||||
// Both the kernel and user programs use this header file.
|
// Both the kernel and user programs use this header file.
|
||||||
#include "kernel/types.h"
|
|
||||||
|
|
||||||
#define ROOTINO 1 // root i-number
|
|
||||||
#define BSIZE 1024 // block size
|
#define ROOTINO 1 // root i-number
|
||||||
|
#define BSIZE 1024 // block size
|
||||||
|
|
||||||
// Disk layout:
|
// Disk layout:
|
||||||
// [ boot block | super block | log | inode blocks |
|
// [ boot block | super block | log | inode blocks |
|
||||||
@ -12,14 +12,14 @@
|
|||||||
// mkfs computes the super block and builds an initial file system. The
|
// mkfs computes the super block and builds an initial file system. The
|
||||||
// super block describes the disk layout:
|
// super block describes the disk layout:
|
||||||
struct superblock {
|
struct superblock {
|
||||||
uint magic; // Must be FSMAGIC
|
uint magic; // Must be FSMAGIC
|
||||||
uint size; // Size of file system image (blocks)
|
uint size; // Size of file system image (blocks)
|
||||||
uint nblocks; // Number of data blocks
|
uint nblocks; // Number of data blocks
|
||||||
uint ninodes; // Number of inodes.
|
uint ninodes; // Number of inodes.
|
||||||
uint nlog; // Number of log blocks
|
uint nlog; // Number of log blocks
|
||||||
uint logstart; // Block number of first log block
|
uint logstart; // Block number of first log block
|
||||||
uint inodestart; // Block number of first inode block
|
uint inodestart; // Block number of first inode block
|
||||||
uint bmapstart; // Block number of first free map block
|
uint bmapstart; // Block number of first free map block
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FSMAGIC 0x10203040
|
#define FSMAGIC 0x10203040
|
||||||
@ -30,25 +30,25 @@ struct superblock {
|
|||||||
|
|
||||||
// On-disk inode structure
|
// On-disk inode structure
|
||||||
struct dinode {
|
struct dinode {
|
||||||
short type; // File type
|
short type; // File type
|
||||||
short major; // Major device number (T_DEVICE only)
|
short major; // Major device number (T_DEVICE only)
|
||||||
short minor; // Minor device number (T_DEVICE only)
|
short minor; // Minor device number (T_DEVICE only)
|
||||||
short nlink; // Number of links to inode in file system
|
short nlink; // Number of links to inode in file system
|
||||||
uint size; // Size of file (bytes)
|
uint size; // Size of file (bytes)
|
||||||
uint addrs[NDIRECT + 1]; // Data block addresses
|
uint addrs[NDIRECT+1]; // Data block addresses
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inodes per block.
|
// Inodes per block.
|
||||||
#define IPB (BSIZE / sizeof(struct dinode))
|
#define IPB (BSIZE / sizeof(struct dinode))
|
||||||
|
|
||||||
// Block containing inode i
|
// Block containing inode i
|
||||||
#define IBLOCK(i, sb) ((i) / IPB + sb.inodestart)
|
#define IBLOCK(i, sb) ((i) / IPB + sb.inodestart)
|
||||||
|
|
||||||
// Bitmap bits per block
|
// Bitmap bits per block
|
||||||
#define BPB (BSIZE * 8)
|
#define BPB (BSIZE*8)
|
||||||
|
|
||||||
// Block of free map containing bit for block b
|
// Block of free map containing bit for block b
|
||||||
#define BBLOCK(b, sb) ((b) / BPB + sb.bmapstart)
|
#define BBLOCK(b, sb) ((b)/BPB + sb.bmapstart)
|
||||||
|
|
||||||
// Directory is a file containing a sequence of dirent structures.
|
// Directory is a file containing a sequence of dirent structures.
|
||||||
#define DIRSIZ 14
|
#define DIRSIZ 14
|
||||||
@ -57,3 +57,4 @@ struct dirent {
|
|||||||
ushort inum;
|
ushort inum;
|
||||||
char name[DIRSIZ];
|
char name[DIRSIZ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "proc.h"
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
void freerange(void *pa_start, void *pa_end);
|
void freerange(void *pa_start, void *pa_end);
|
||||||
@ -81,17 +80,3 @@ kalloc(void)
|
|||||||
memset((char*)r, 5, PGSIZE); // fill with junk
|
memset((char*)r, 5, PGSIZE); // fill with junk
|
||||||
return (void*)r;
|
return (void*)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
freemem(void)
|
|
||||||
{
|
|
||||||
struct run* p = kmem.freelist;
|
|
||||||
uint64 num = 0;
|
|
||||||
while (p) {
|
|
||||||
num += 1;
|
|
||||||
p = p->next;
|
|
||||||
}
|
|
||||||
return num * PGSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
# mode come here.
|
# mode come here.
|
||||||
#
|
#
|
||||||
# the current stack is a kernel stack.
|
# the current stack is a kernel stack.
|
||||||
# push all registers, call kerneltrap().
|
# push registers, call kerneltrap().
|
||||||
# when kerneltrap() returns, restore registers, return.
|
# when kerneltrap() returns, restore registers, return.
|
||||||
#
|
#
|
||||||
.globl kerneltrap
|
.globl kerneltrap
|
||||||
@ -13,7 +13,7 @@ kernelvec:
|
|||||||
# make room to save registers.
|
# make room to save registers.
|
||||||
addi sp, sp, -256
|
addi sp, sp, -256
|
||||||
|
|
||||||
# save the registers.
|
# save caller-saved registers.
|
||||||
sd ra, 0(sp)
|
sd ra, 0(sp)
|
||||||
sd sp, 8(sp)
|
sd sp, 8(sp)
|
||||||
sd gp, 16(sp)
|
sd gp, 16(sp)
|
||||||
@ -21,8 +21,6 @@ kernelvec:
|
|||||||
sd t0, 32(sp)
|
sd t0, 32(sp)
|
||||||
sd t1, 40(sp)
|
sd t1, 40(sp)
|
||||||
sd t2, 48(sp)
|
sd t2, 48(sp)
|
||||||
sd s0, 56(sp)
|
|
||||||
sd s1, 64(sp)
|
|
||||||
sd a0, 72(sp)
|
sd a0, 72(sp)
|
||||||
sd a1, 80(sp)
|
sd a1, 80(sp)
|
||||||
sd a2, 88(sp)
|
sd a2, 88(sp)
|
||||||
@ -31,16 +29,6 @@ kernelvec:
|
|||||||
sd a5, 112(sp)
|
sd a5, 112(sp)
|
||||||
sd a6, 120(sp)
|
sd a6, 120(sp)
|
||||||
sd a7, 128(sp)
|
sd a7, 128(sp)
|
||||||
sd s2, 136(sp)
|
|
||||||
sd s3, 144(sp)
|
|
||||||
sd s4, 152(sp)
|
|
||||||
sd s5, 160(sp)
|
|
||||||
sd s6, 168(sp)
|
|
||||||
sd s7, 176(sp)
|
|
||||||
sd s8, 184(sp)
|
|
||||||
sd s9, 192(sp)
|
|
||||||
sd s10, 200(sp)
|
|
||||||
sd s11, 208(sp)
|
|
||||||
sd t3, 216(sp)
|
sd t3, 216(sp)
|
||||||
sd t4, 224(sp)
|
sd t4, 224(sp)
|
||||||
sd t5, 232(sp)
|
sd t5, 232(sp)
|
||||||
@ -57,8 +45,6 @@ kernelvec:
|
|||||||
ld t0, 32(sp)
|
ld t0, 32(sp)
|
||||||
ld t1, 40(sp)
|
ld t1, 40(sp)
|
||||||
ld t2, 48(sp)
|
ld t2, 48(sp)
|
||||||
ld s0, 56(sp)
|
|
||||||
ld s1, 64(sp)
|
|
||||||
ld a0, 72(sp)
|
ld a0, 72(sp)
|
||||||
ld a1, 80(sp)
|
ld a1, 80(sp)
|
||||||
ld a2, 88(sp)
|
ld a2, 88(sp)
|
||||||
@ -67,16 +53,6 @@ kernelvec:
|
|||||||
ld a5, 112(sp)
|
ld a5, 112(sp)
|
||||||
ld a6, 120(sp)
|
ld a6, 120(sp)
|
||||||
ld a7, 128(sp)
|
ld a7, 128(sp)
|
||||||
ld s2, 136(sp)
|
|
||||||
ld s3, 144(sp)
|
|
||||||
ld s4, 152(sp)
|
|
||||||
ld s5, 160(sp)
|
|
||||||
ld s6, 168(sp)
|
|
||||||
ld s7, 176(sp)
|
|
||||||
ld s8, 184(sp)
|
|
||||||
ld s9, 192(sp)
|
|
||||||
ld s10, 200(sp)
|
|
||||||
ld s11, 208(sp)
|
|
||||||
ld t3, 216(sp)
|
ld t3, 216(sp)
|
||||||
ld t4, 224(sp)
|
ld t4, 224(sp)
|
||||||
ld t5, 232(sp)
|
ld t5, 232(sp)
|
||||||
@ -86,39 +62,3 @@ kernelvec:
|
|||||||
|
|
||||||
# return to whatever we were doing in the kernel.
|
# return to whatever we were doing in the kernel.
|
||||||
sret
|
sret
|
||||||
|
|
||||||
#
|
|
||||||
# machine-mode timer interrupt.
|
|
||||||
#
|
|
||||||
.globl timervec
|
|
||||||
.align 4
|
|
||||||
timervec:
|
|
||||||
# start.c has set up the memory that mscratch points to:
|
|
||||||
# scratch[0,8,16] : register save area.
|
|
||||||
# scratch[24] : address of CLINT's MTIMECMP register.
|
|
||||||
# scratch[32] : desired interval between interrupts.
|
|
||||||
|
|
||||||
csrrw a0, mscratch, a0
|
|
||||||
sd a1, 0(a0)
|
|
||||||
sd a2, 8(a0)
|
|
||||||
sd a3, 16(a0)
|
|
||||||
|
|
||||||
# schedule the next timer interrupt
|
|
||||||
# by adding interval to mtimecmp.
|
|
||||||
ld a1, 24(a0) # CLINT_MTIMECMP(hart)
|
|
||||||
ld a2, 32(a0) # interval
|
|
||||||
ld a3, 0(a1)
|
|
||||||
add a3, a3, a2
|
|
||||||
sd a3, 0(a1)
|
|
||||||
|
|
||||||
# arrange for a supervisor software interrupt
|
|
||||||
# after this handler returns.
|
|
||||||
li a1, 2
|
|
||||||
csrw sip, a1
|
|
||||||
|
|
||||||
ld a3, 16(a0)
|
|
||||||
ld a2, 8(a0)
|
|
||||||
ld a1, 0(a0)
|
|
||||||
csrrw a0, mscratch, a0
|
|
||||||
|
|
||||||
mret
|
|
||||||
|
|||||||
@ -25,10 +25,9 @@
|
|||||||
#define VIRTIO0 0x10001000
|
#define VIRTIO0 0x10001000
|
||||||
#define VIRTIO0_IRQ 1
|
#define VIRTIO0_IRQ 1
|
||||||
|
|
||||||
// core local interruptor (CLINT), which contains the timer.
|
#ifdef LAB_NET
|
||||||
#define CLINT 0x2000000L
|
#define E1000_IRQ 33
|
||||||
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8*(hartid))
|
#endif
|
||||||
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.
|
|
||||||
|
|
||||||
// qemu puts platform-level interrupt controller (PLIC) here.
|
// qemu puts platform-level interrupt controller (PLIC) here.
|
||||||
#define PLIC 0x0c000000L
|
#define PLIC 0x0c000000L
|
||||||
@ -50,7 +49,7 @@
|
|||||||
|
|
||||||
// map kernel stacks beneath the trampoline,
|
// map kernel stacks beneath the trampoline,
|
||||||
// each surrounded by invalid guard pages.
|
// each surrounded by invalid guard pages.
|
||||||
#define KSTACK(p) (TRAMPOLINE - ((p)+1)* 2*PGSIZE)
|
#define KSTACK(p) (TRAMPOLINE - (p)*2*PGSIZE - 3*PGSIZE)
|
||||||
|
|
||||||
// User memory layout.
|
// User memory layout.
|
||||||
// Address zero first:
|
// Address zero first:
|
||||||
@ -59,6 +58,14 @@
|
|||||||
// fixed-size stack
|
// fixed-size stack
|
||||||
// expandable heap
|
// expandable heap
|
||||||
// ...
|
// ...
|
||||||
|
// USYSCALL (shared with kernel)
|
||||||
// TRAPFRAME (p->trapframe, used by the trampoline)
|
// TRAPFRAME (p->trapframe, used by the trampoline)
|
||||||
// TRAMPOLINE (the same page as in the kernel)
|
// TRAMPOLINE (the same page as in the kernel)
|
||||||
#define TRAPFRAME (TRAMPOLINE - PGSIZE)
|
#define TRAPFRAME (TRAMPOLINE - PGSIZE)
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
#define USYSCALL (TRAPFRAME - PGSIZE)
|
||||||
|
|
||||||
|
struct usyscall {
|
||||||
|
int pid; // Process ID
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|||||||
@ -11,3 +11,5 @@
|
|||||||
#define NBUF (MAXOPBLOCKS*3) // size of disk block cache
|
#define NBUF (MAXOPBLOCKS*3) // size of disk block cache
|
||||||
#define FSSIZE 2000 // size of file system in blocks
|
#define FSSIZE 2000 // size of file system in blocks
|
||||||
#define MAXPATH 128 // maximum file path name
|
#define MAXPATH 128 // maximum file path name
|
||||||
|
#define USERSTACK 1 // user stack pages
|
||||||
|
|
||||||
|
|||||||
@ -26,13 +26,13 @@ static struct {
|
|||||||
static char digits[] = "0123456789abcdef";
|
static char digits[] = "0123456789abcdef";
|
||||||
|
|
||||||
static void
|
static void
|
||||||
printint(int xx, int base, int sign)
|
printint(long long xx, int base, int sign)
|
||||||
{
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
int i;
|
int i;
|
||||||
uint x;
|
unsigned long long x;
|
||||||
|
|
||||||
if(sign && (sign = xx < 0))
|
if(sign && (sign = (xx < 0)))
|
||||||
x = -xx;
|
x = -xx;
|
||||||
else
|
else
|
||||||
x = xx;
|
x = xx;
|
||||||
@ -59,30 +59,71 @@ printptr(uint64 x)
|
|||||||
consputc(digits[x >> (sizeof(uint64) * 8 - 4)]);
|
consputc(digits[x >> (sizeof(uint64) * 8 - 4)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print to the console. only understands %d, %x, %p, %s.
|
// Print to the console.
|
||||||
void
|
int
|
||||||
printf(char *fmt, ...)
|
printf(char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int i, c, locking;
|
int i, cx, c0, c1, c2, locking;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
locking = pr.locking;
|
locking = pr.locking;
|
||||||
if(locking)
|
if(locking)
|
||||||
acquire(&pr.lock);
|
acquire(&pr.lock);
|
||||||
|
|
||||||
if (fmt == 0)
|
|
||||||
panic("null fmt");
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
|
for(i = 0; (cx = fmt[i] & 0xff) != 0; i++){
|
||||||
if(c != '%'){
|
if(cx != '%'){
|
||||||
consputc(c);
|
consputc(cx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
c = fmt[++i] & 0xff;
|
i++;
|
||||||
if(c == 0)
|
c0 = fmt[i+0] & 0xff;
|
||||||
|
c1 = c2 = 0;
|
||||||
|
if(c0) c1 = fmt[i+1] & 0xff;
|
||||||
|
if(c1) c2 = fmt[i+2] & 0xff;
|
||||||
|
if(c0 == 'd'){
|
||||||
|
printint(va_arg(ap, int), 10, 1);
|
||||||
|
} else if(c0 == 'l' && c1 == 'd'){
|
||||||
|
printint(va_arg(ap, uint64), 10, 1);
|
||||||
|
i += 1;
|
||||||
|
} else if(c0 == 'l' && c1 == 'l' && c2 == 'd'){
|
||||||
|
printint(va_arg(ap, uint64), 10, 1);
|
||||||
|
i += 2;
|
||||||
|
} else if(c0 == 'u'){
|
||||||
|
printint(va_arg(ap, int), 10, 0);
|
||||||
|
} else if(c0 == 'l' && c1 == 'u'){
|
||||||
|
printint(va_arg(ap, uint64), 10, 0);
|
||||||
|
i += 1;
|
||||||
|
} else if(c0 == 'l' && c1 == 'l' && c2 == 'u'){
|
||||||
|
printint(va_arg(ap, uint64), 10, 0);
|
||||||
|
i += 2;
|
||||||
|
} else if(c0 == 'x'){
|
||||||
|
printint(va_arg(ap, int), 16, 0);
|
||||||
|
} else if(c0 == 'l' && c1 == 'x'){
|
||||||
|
printint(va_arg(ap, uint64), 16, 0);
|
||||||
|
i += 1;
|
||||||
|
} else if(c0 == 'l' && c1 == 'l' && c2 == 'x'){
|
||||||
|
printint(va_arg(ap, uint64), 16, 0);
|
||||||
|
i += 2;
|
||||||
|
} else if(c0 == 'p'){
|
||||||
|
printptr(va_arg(ap, uint64));
|
||||||
|
} else if(c0 == 's'){
|
||||||
|
if((s = va_arg(ap, char*)) == 0)
|
||||||
|
s = "(null)";
|
||||||
|
for(; *s; s++)
|
||||||
|
consputc(*s);
|
||||||
|
} else if(c0 == '%'){
|
||||||
|
consputc('%');
|
||||||
|
} else if(c0 == 0){
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
// Print unknown % sequence to draw attention.
|
||||||
|
consputc('%');
|
||||||
|
consputc(c0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
switch(c){
|
switch(c){
|
||||||
case 'd':
|
case 'd':
|
||||||
printint(va_arg(ap, int), 10, 1);
|
printint(va_arg(ap, int), 10, 1);
|
||||||
@ -108,11 +149,14 @@ printf(char *fmt, ...)
|
|||||||
consputc(c);
|
consputc(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if(locking)
|
if(locking)
|
||||||
release(&pr.lock);
|
release(&pr.lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -120,8 +164,7 @@ panic(char *s)
|
|||||||
{
|
{
|
||||||
pr.locking = 0;
|
pr.locking = 0;
|
||||||
printf("panic: ");
|
printf("panic: ");
|
||||||
printf(s);
|
printf("%s\n", s);
|
||||||
printf("\n");
|
|
||||||
panicked = 1; // freeze uart output from other CPUs
|
panicked = 1; // freeze uart output from other CPUs
|
||||||
for(;;)
|
for(;;)
|
||||||
;
|
;
|
||||||
|
|||||||
@ -5,9 +5,6 @@
|
|||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "sysinfo.h"
|
|
||||||
|
|
||||||
uint64 current_load = 0;
|
|
||||||
|
|
||||||
struct cpu cpus[NCPU];
|
struct cpu cpus[NCPU];
|
||||||
|
|
||||||
@ -149,9 +146,6 @@ found:
|
|||||||
p->context.ra = (uint64)forkret;
|
p->context.ra = (uint64)forkret;
|
||||||
p->context.sp = p->kstack + PGSIZE;
|
p->context.sp = p->kstack + PGSIZE;
|
||||||
|
|
||||||
// 初始化计数器
|
|
||||||
memset(p->syscall_counts, 0, sizeof(p->syscall_counts));
|
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,8 +310,6 @@ fork(void)
|
|||||||
|
|
||||||
safestrcpy(np->name, p->name, sizeof(p->name));
|
safestrcpy(np->name, p->name, sizeof(p->name));
|
||||||
|
|
||||||
// 复制掩码
|
|
||||||
np->tracemask = p->tracemask;
|
|
||||||
pid = np->pid;
|
pid = np->pid;
|
||||||
|
|
||||||
release(&np->lock);
|
release(&np->lock);
|
||||||
@ -454,7 +446,6 @@ scheduler(void)
|
|||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
struct cpu *c = mycpu();
|
struct cpu *c = mycpu();
|
||||||
/*update_load_avg();*/
|
|
||||||
|
|
||||||
c->proc = 0;
|
c->proc = 0;
|
||||||
for(;;){
|
for(;;){
|
||||||
@ -463,6 +454,7 @@ scheduler(void)
|
|||||||
// processes are waiting.
|
// processes are waiting.
|
||||||
intr_on();
|
intr_on();
|
||||||
|
|
||||||
|
int found = 0;
|
||||||
for(p = proc; p < &proc[NPROC]; p++) {
|
for(p = proc; p < &proc[NPROC]; p++) {
|
||||||
acquire(&p->lock);
|
acquire(&p->lock);
|
||||||
if(p->state == RUNNABLE) {
|
if(p->state == RUNNABLE) {
|
||||||
@ -471,15 +463,20 @@ scheduler(void)
|
|||||||
// before jumping back to us.
|
// before jumping back to us.
|
||||||
p->state = RUNNING;
|
p->state = RUNNING;
|
||||||
c->proc = p;
|
c->proc = p;
|
||||||
current_load += 1;
|
|
||||||
swtch(&c->context, &p->context);
|
swtch(&c->context, &p->context);
|
||||||
|
|
||||||
// Process is done running for now.
|
// Process is done running for now.
|
||||||
// It should have changed its p->state before coming back.
|
// It should have changed its p->state before coming back.
|
||||||
c->proc = 0;
|
c->proc = 0;
|
||||||
|
found = 1;
|
||||||
}
|
}
|
||||||
release(&p->lock);
|
release(&p->lock);
|
||||||
}
|
}
|
||||||
|
if(found == 0) {
|
||||||
|
// nothing to run; stop running on this core until an interrupt.
|
||||||
|
intr_on();
|
||||||
|
asm volatile("wfi");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,18 +693,3 @@ procdump(void)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
proc_size()
|
|
||||||
{
|
|
||||||
int i =0, n = 0;
|
|
||||||
for (; i < NPROC; ++i) {
|
|
||||||
if (proc[i].state != UNUSED) n += 1;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
update_load() {
|
|
||||||
return current_load;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
#include "defs.h"
|
|
||||||
|
|
||||||
// Saved registers for kernel context switches.
|
// Saved registers for kernel context switches.
|
||||||
struct context {
|
struct context {
|
||||||
uint64 ra;
|
uint64 ra;
|
||||||
@ -93,7 +91,6 @@ struct proc {
|
|||||||
int killed; // If non-zero, have been killed
|
int killed; // If non-zero, have been killed
|
||||||
int xstate; // Exit status to be returned to parent's wait
|
int xstate; // Exit status to be returned to parent's wait
|
||||||
int pid; // Process ID
|
int pid; // Process ID
|
||||||
int tracemask; // Trace Mask
|
|
||||||
|
|
||||||
// wait_lock must be held when using this:
|
// wait_lock must be held when using this:
|
||||||
struct proc *parent; // Parent process
|
struct proc *parent; // Parent process
|
||||||
@ -107,5 +104,4 @@ struct proc {
|
|||||||
struct file *ofile[NOFILE]; // Open files
|
struct file *ofile[NOFILE]; // Open files
|
||||||
struct inode *cwd; // Current directory
|
struct inode *cwd; // Current directory
|
||||||
char name[16]; // Process name (debugging)
|
char name[16]; // Process name (debugging)
|
||||||
int syscall_counts[24]; // 每个系统调用的调用次数
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -96,9 +96,7 @@ w_sie(uint64 x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Machine-mode Interrupt Enable
|
// Machine-mode Interrupt Enable
|
||||||
#define MIE_MEIE (1L << 11) // external
|
#define MIE_STIE (1L << 5) // supervisor timer
|
||||||
#define MIE_MTIE (1L << 7) // timer
|
|
||||||
#define MIE_MSIE (1L << 3) // software
|
|
||||||
static inline uint64
|
static inline uint64
|
||||||
r_mie()
|
r_mie()
|
||||||
{
|
{
|
||||||
@ -176,11 +174,38 @@ r_stvec()
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Machine-mode interrupt vector
|
// Supervisor Timer Comparison Register
|
||||||
static inline void
|
static inline uint64
|
||||||
w_mtvec(uint64 x)
|
r_stimecmp()
|
||||||
{
|
{
|
||||||
asm volatile("csrw mtvec, %0" : : "r" (x));
|
uint64 x;
|
||||||
|
// asm volatile("csrr %0, stimecmp" : "=r" (x) );
|
||||||
|
asm volatile("csrr %0, 0x14d" : "=r" (x) );
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
w_stimecmp(uint64 x)
|
||||||
|
{
|
||||||
|
// asm volatile("csrw stimecmp, %0" : : "r" (x));
|
||||||
|
asm volatile("csrw 0x14d, %0" : : "r" (x));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Machine Environment Configuration Register
|
||||||
|
static inline uint64
|
||||||
|
r_menvcfg()
|
||||||
|
{
|
||||||
|
uint64 x;
|
||||||
|
// asm volatile("csrr %0, menvcfg" : "=r" (x) );
|
||||||
|
asm volatile("csrr %0, 0x30a" : "=r" (x) );
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
w_menvcfg(uint64 x)
|
||||||
|
{
|
||||||
|
//asm volatile("csrw menvcfg, %0" : : "r" (x));
|
||||||
|
asm volatile("csrw 0x30a, %0" : : "r" (x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Physical Memory Protection
|
// Physical Memory Protection
|
||||||
@ -217,12 +242,6 @@ r_satp()
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
w_mscratch(uint64 x)
|
|
||||||
{
|
|
||||||
asm volatile("csrw mscratch, %0" : : "r" (x));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supervisor Trap Cause
|
// Supervisor Trap Cause
|
||||||
static inline uint64
|
static inline uint64
|
||||||
r_scause()
|
r_scause()
|
||||||
@ -295,6 +314,14 @@ r_sp()
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint64
|
||||||
|
r_fp()
|
||||||
|
{
|
||||||
|
uint64 x;
|
||||||
|
asm volatile("mv %0, s0" : "=r" (x) );
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
// read and write tp, the thread pointer, which xv6 uses to hold
|
// read and write tp, the thread pointer, which xv6 uses to hold
|
||||||
// this core's hartid (core number), the index into cpus[].
|
// this core's hartid (core number), the index into cpus[].
|
||||||
static inline uint64
|
static inline uint64
|
||||||
@ -335,6 +362,11 @@ typedef uint64 *pagetable_t; // 512 PTEs
|
|||||||
#define PGSIZE 4096 // bytes per page
|
#define PGSIZE 4096 // bytes per page
|
||||||
#define PGSHIFT 12 // bits of offset within a page
|
#define PGSHIFT 12 // bits of offset within a page
|
||||||
|
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
#define SUPERPGSIZE (2 * (1 << 20)) // bytes per page
|
||||||
|
#define SUPERPGROUNDUP(sz) (((sz)+SUPERPGSIZE-1) & ~(SUPERPGSIZE-1))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
|
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
|
||||||
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))
|
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))
|
||||||
|
|
||||||
@ -344,6 +376,12 @@ typedef uint64 *pagetable_t; // 512 PTEs
|
|||||||
#define PTE_X (1L << 3)
|
#define PTE_X (1L << 3)
|
||||||
#define PTE_U (1L << 4) // user can access
|
#define PTE_U (1L << 4) // user can access
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(LAB_MMAP) || defined(LAB_PGTBL)
|
||||||
|
#define PTE_LEAF(pte) (((pte) & PTE_R) | ((pte) & PTE_W) | ((pte) & PTE_X))
|
||||||
|
#endif
|
||||||
|
|
||||||
// shift a physical address to the right place for a PTE.
|
// shift a physical address to the right place for a PTE.
|
||||||
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
|
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
|
||||||
|
|
||||||
|
|||||||
@ -10,12 +10,6 @@ void timerinit();
|
|||||||
// entry.S needs one stack per CPU.
|
// entry.S needs one stack per CPU.
|
||||||
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
|
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
|
||||||
|
|
||||||
// a scratch area per CPU for machine-mode timer interrupts.
|
|
||||||
uint64 timer_scratch[NCPU][5];
|
|
||||||
|
|
||||||
// assembly code in kernelvec.S for machine-mode timer interrupt.
|
|
||||||
extern void timervec();
|
|
||||||
|
|
||||||
// entry.S jumps here in machine mode on stack0.
|
// entry.S jumps here in machine mode on stack0.
|
||||||
void
|
void
|
||||||
start()
|
start()
|
||||||
@ -54,36 +48,19 @@ start()
|
|||||||
asm volatile("mret");
|
asm volatile("mret");
|
||||||
}
|
}
|
||||||
|
|
||||||
// arrange to receive timer interrupts.
|
// ask each hart to generate timer interrupts.
|
||||||
// they will arrive in machine mode at
|
|
||||||
// at timervec in kernelvec.S,
|
|
||||||
// which turns them into software interrupts for
|
|
||||||
// devintr() in trap.c.
|
|
||||||
void
|
void
|
||||||
timerinit()
|
timerinit()
|
||||||
{
|
{
|
||||||
// each CPU has a separate source of timer interrupts.
|
// enable supervisor-mode timer interrupts.
|
||||||
int id = r_mhartid();
|
w_mie(r_mie() | MIE_STIE);
|
||||||
|
|
||||||
// ask the CLINT for a timer interrupt.
|
// enable the sstc extension (i.e. stimecmp).
|
||||||
int interval = 1000000; // cycles; about 1/10th second in qemu.
|
w_menvcfg(r_menvcfg() | (1L << 63));
|
||||||
*(uint64*)CLINT_MTIMECMP(id) = *(uint64*)CLINT_MTIME + interval;
|
|
||||||
|
// allow supervisor to use stimecmp and time.
|
||||||
// prepare information in scratch[] for timervec.
|
w_mcounteren(r_mcounteren() | 2);
|
||||||
// scratch[0..2] : space for timervec to save registers.
|
|
||||||
// scratch[3] : address of CLINT MTIMECMP register.
|
// ask for the very first timer interrupt.
|
||||||
// scratch[4] : desired interval (in cycles) between timer interrupts.
|
w_stimecmp(r_time() + 1000000);
|
||||||
uint64 *scratch = &timer_scratch[id][0];
|
|
||||||
scratch[3] = CLINT_MTIMECMP(id);
|
|
||||||
scratch[4] = interval;
|
|
||||||
w_mscratch((uint64)scratch);
|
|
||||||
|
|
||||||
// set the machine-mode trap handler.
|
|
||||||
w_mtvec((uint64)timervec);
|
|
||||||
|
|
||||||
// enable machine-mode interrupts.
|
|
||||||
w_mstatus(r_mstatus() | MSTATUS_MIE);
|
|
||||||
|
|
||||||
// enable machine-mode timer interrupts.
|
|
||||||
w_mie(r_mie() | MIE_MTIE);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#define T_DIR 1 // Directory
|
#define T_DIR 1 // Directory
|
||||||
#define T_FILE 2 // File
|
#define T_FILE 2 // File
|
||||||
#define T_DEVICE 3 // Device
|
#define T_DEVICE 3 // Device
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
struct stat {
|
struct stat {
|
||||||
int dev; // File system's disk device
|
int dev; // File system's disk device
|
||||||
|
|||||||
@ -7,11 +7,6 @@
|
|||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
// 保留系统调用别名
|
|
||||||
char* syscalls_name[25] = {"", "fork", "exit", "wait", "pipe", "read", "kill", "exec",
|
|
||||||
"fstat", "chdir", "dup", "getpid", "sbrk", "sleep", "uptime",
|
|
||||||
"open", "write", "mknod", "unlink", "link", "mkdir", "close", "trace", "sysinfo"};
|
|
||||||
|
|
||||||
// Fetch the uint64 at addr from the current process.
|
// Fetch the uint64 at addr from the current process.
|
||||||
int
|
int
|
||||||
fetchaddr(uint64 addr, uint64 *ip)
|
fetchaddr(uint64 addr, uint64 *ip)
|
||||||
@ -106,8 +101,17 @@ extern uint64 sys_unlink(void);
|
|||||||
extern uint64 sys_link(void);
|
extern uint64 sys_link(void);
|
||||||
extern uint64 sys_mkdir(void);
|
extern uint64 sys_mkdir(void);
|
||||||
extern uint64 sys_close(void);
|
extern uint64 sys_close(void);
|
||||||
extern uint64 sys_trace(void);
|
|
||||||
extern uint64 sys_sysinfo(void);
|
#ifdef LAB_NET
|
||||||
|
extern uint64 sys_bind(void);
|
||||||
|
extern uint64 sys_unbind(void);
|
||||||
|
extern uint64 sys_send(void);
|
||||||
|
extern uint64 sys_recv(void);
|
||||||
|
#endif
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
extern uint64 sys_pgpte(void);
|
||||||
|
extern uint64 sys_kpgtbl(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
// An array mapping syscall numbers from syscall.h
|
// An array mapping syscall numbers from syscall.h
|
||||||
// to the function that handles the system call.
|
// to the function that handles the system call.
|
||||||
@ -133,10 +137,20 @@ static uint64 (*syscalls[])(void) = {
|
|||||||
[SYS_link] sys_link,
|
[SYS_link] sys_link,
|
||||||
[SYS_mkdir] sys_mkdir,
|
[SYS_mkdir] sys_mkdir,
|
||||||
[SYS_close] sys_close,
|
[SYS_close] sys_close,
|
||||||
[SYS_trace] sys_trace,
|
#ifdef LAB_NET
|
||||||
[SYS_sysinfo] sys_sysinfo,
|
[SYS_bind] sys_bind,
|
||||||
|
[SYS_unbind] sys_unbind,
|
||||||
|
[SYS_send] sys_send,
|
||||||
|
[SYS_recv] sys_recv,
|
||||||
|
#endif
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
[SYS_pgpte] sys_pgpte,
|
||||||
|
[SYS_kpgtbl] sys_kpgtbl,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
syscall(void)
|
syscall(void)
|
||||||
{
|
{
|
||||||
@ -148,12 +162,6 @@ syscall(void)
|
|||||||
// Use num to lookup the system call function for num, call it,
|
// Use num to lookup the system call function for num, call it,
|
||||||
// and store its return value in p->trapframe->a0
|
// and store its return value in p->trapframe->a0
|
||||||
p->trapframe->a0 = syscalls[num]();
|
p->trapframe->a0 = syscalls[num]();
|
||||||
if (p->tracemask & (1 << num)) {
|
|
||||||
p->syscall_counts[num]++;
|
|
||||||
printf("%d: syscall %s(trace counts: %d) -> %d\n",
|
|
||||||
p->pid, syscalls_name[num], p->syscall_counts[num], p->trapframe->a0);
|
|
||||||
printf("a1:%d a2:%d a3:%d a4:%d a5:%d a6:%d a7:%d\n",p->trapframe->a1,p->trapframe->a2,p->trapframe->a3,p->trapframe->a4,p->trapframe->a5,p->trapframe->a6,p->trapframe->a7);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
printf("%d %s: unknown sys call %d\n",
|
printf("%d %s: unknown sys call %d\n",
|
||||||
p->pid, p->name, num);
|
p->pid, p->name, num);
|
||||||
|
|||||||
@ -20,5 +20,19 @@
|
|||||||
#define SYS_link 19
|
#define SYS_link 19
|
||||||
#define SYS_mkdir 20
|
#define SYS_mkdir 20
|
||||||
#define SYS_close 21
|
#define SYS_close 21
|
||||||
#define SYS_trace 22
|
|
||||||
#define SYS_sysinfo 23
|
// System calls for labs
|
||||||
|
#define SYS_trace 22
|
||||||
|
#define SYS_sysinfo 23
|
||||||
|
#define SYS_sigalarm 24
|
||||||
|
#define SYS_sigreturn 25
|
||||||
|
#define SYS_symlink 26
|
||||||
|
#define SYS_mmap 27
|
||||||
|
#define SYS_munmap 28
|
||||||
|
#define SYS_bind 29
|
||||||
|
#define SYS_unbind 30
|
||||||
|
#define SYS_send 31
|
||||||
|
#define SYS_recv 32
|
||||||
|
#define SYS_pgpte 33
|
||||||
|
#define SYS_kpgtbl 34
|
||||||
|
#define SYS_pgaccess 35
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "defs.h"
|
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
|
#include "defs.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "sysinfo.h"
|
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
sys_exit(void)
|
sys_exit(void)
|
||||||
@ -55,6 +54,7 @@ sys_sleep(void)
|
|||||||
int n;
|
int n;
|
||||||
uint ticks0;
|
uint ticks0;
|
||||||
|
|
||||||
|
|
||||||
argint(0, &n);
|
argint(0, &n);
|
||||||
if(n < 0)
|
if(n < 0)
|
||||||
n = 0;
|
n = 0;
|
||||||
@ -71,6 +71,37 @@ sys_sleep(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
int
|
||||||
|
sys_pgpte(void)
|
||||||
|
{
|
||||||
|
uint64 va;
|
||||||
|
struct proc *p;
|
||||||
|
|
||||||
|
p = myproc();
|
||||||
|
argaddr(0, &va);
|
||||||
|
pte_t *pte = pgpte(p->pagetable, va);
|
||||||
|
if(pte != 0) {
|
||||||
|
return (uint64) *pte;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
int
|
||||||
|
sys_kpgtbl(void)
|
||||||
|
{
|
||||||
|
struct proc *p;
|
||||||
|
|
||||||
|
p = myproc();
|
||||||
|
vmprint(p->pagetable);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
sys_kill(void)
|
sys_kill(void)
|
||||||
{
|
{
|
||||||
@ -92,30 +123,3 @@ sys_uptime(void)
|
|||||||
release(&tickslock);
|
release(&tickslock);
|
||||||
return xticks;
|
return xticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64
|
|
||||||
sys_trace(void)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
argint(0, &n);
|
|
||||||
if(n<0) return -1;
|
|
||||||
myproc()->tracemask = n;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64
|
|
||||||
sys_sysinfo(void)
|
|
||||||
{
|
|
||||||
struct sysinfo info;
|
|
||||||
uint64 addr;
|
|
||||||
argaddr(0, &addr);
|
|
||||||
if (addr < 0) return -1;
|
|
||||||
struct proc* p = myproc();
|
|
||||||
info.nproc = proc_size();
|
|
||||||
info.freemem = freemem();
|
|
||||||
info.unused_proc_num = NPROC - info.nproc;
|
|
||||||
info.load_avg = update_load() * 100 / sys_uptime();
|
|
||||||
if (copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -68,8 +68,8 @@ usertrap(void)
|
|||||||
} else if((which_dev = devintr()) != 0){
|
} else if((which_dev = devintr()) != 0){
|
||||||
// ok
|
// ok
|
||||||
} else {
|
} else {
|
||||||
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
|
printf("usertrap(): unexpected scause 0x%lx pid=%d\n", r_scause(), p->pid);
|
||||||
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
|
printf(" sepc=0x%lx stval=0x%lx\n", r_sepc(), r_stval());
|
||||||
setkilled(p);
|
setkilled(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +145,13 @@ kerneltrap()
|
|||||||
panic("kerneltrap: interrupts enabled");
|
panic("kerneltrap: interrupts enabled");
|
||||||
|
|
||||||
if((which_dev = devintr()) == 0){
|
if((which_dev = devintr()) == 0){
|
||||||
printf("scause %p\n", scause);
|
// interrupt or trap from an unknown source
|
||||||
printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
|
printf("scause=0x%lx sepc=0x%lx stval=0x%lx\n", scause, r_sepc(), r_stval());
|
||||||
panic("kerneltrap");
|
panic("kerneltrap");
|
||||||
}
|
}
|
||||||
|
|
||||||
// give up the CPU if this is a timer interrupt.
|
// give up the CPU if this is a timer interrupt.
|
||||||
if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING)
|
if(which_dev == 2 && myproc() != 0)
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
// the yield() may have caused some traps to occur,
|
// the yield() may have caused some traps to occur,
|
||||||
@ -163,10 +163,17 @@ kerneltrap()
|
|||||||
void
|
void
|
||||||
clockintr()
|
clockintr()
|
||||||
{
|
{
|
||||||
acquire(&tickslock);
|
if(cpuid() == 0){
|
||||||
ticks++;
|
acquire(&tickslock);
|
||||||
wakeup(&ticks);
|
ticks++;
|
||||||
release(&tickslock);
|
wakeup(&ticks);
|
||||||
|
release(&tickslock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ask for the next timer interrupt. this also clears
|
||||||
|
// the interrupt request. 1000000 is about a tenth
|
||||||
|
// of a second.
|
||||||
|
w_stimecmp(r_time() + 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if it's an external interrupt or software interrupt,
|
// check if it's an external interrupt or software interrupt,
|
||||||
@ -179,8 +186,7 @@ devintr()
|
|||||||
{
|
{
|
||||||
uint64 scause = r_scause();
|
uint64 scause = r_scause();
|
||||||
|
|
||||||
if((scause & 0x8000000000000000L) &&
|
if(scause == 0x8000000000000009L){
|
||||||
(scause & 0xff) == 9){
|
|
||||||
// this is a supervisor external interrupt, via PLIC.
|
// this is a supervisor external interrupt, via PLIC.
|
||||||
|
|
||||||
// irq indicates which device interrupted.
|
// irq indicates which device interrupted.
|
||||||
@ -201,18 +207,9 @@ devintr()
|
|||||||
plic_complete(irq);
|
plic_complete(irq);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} else if(scause == 0x8000000000000001L){
|
} else if(scause == 0x8000000000000005L){
|
||||||
// software interrupt from a machine-mode timer interrupt,
|
// timer interrupt.
|
||||||
// forwarded by timervec in kernelvec.S.
|
clockintr();
|
||||||
|
|
||||||
if(cpuid() == 0){
|
|
||||||
clockintr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// acknowledge the software interrupt by clearing
|
|
||||||
// the SSIP bit in sip.
|
|
||||||
w_sip(r_sip() & ~2);
|
|
||||||
|
|
||||||
return 2;
|
return 2;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
typedef unsigned short ushort;
|
typedef unsigned short ushort;
|
||||||
typedef unsigned char uchar;
|
typedef unsigned char uchar;
|
||||||
|
|
||||||
typedef unsigned char uint8;
|
typedef unsigned char uint8;
|
||||||
typedef unsigned short uint16;
|
typedef unsigned short uint16;
|
||||||
typedef unsigned int uint32;
|
typedef unsigned int uint32;
|
||||||
typedef unsigned long uint64;
|
typedef unsigned long uint64;
|
||||||
|
|
||||||
typedef uint64 pde_t;
|
typedef uint64 pde_t;
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
// the UART control registers are memory-mapped
|
// the UART control registers are memory-mapped
|
||||||
// at address UART0. this macro returns the
|
// at address UART0. this macro returns the
|
||||||
// address of one of the registers.
|
// address of one of the registers.
|
||||||
#define Reg(reg) ((volatile unsigned char *)(UART0 + reg))
|
#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg)))
|
||||||
|
|
||||||
// the UART control registers.
|
// the UART control registers.
|
||||||
// some have different meanings for
|
// some have different meanings for
|
||||||
@ -136,6 +136,7 @@ uartstart()
|
|||||||
while(1){
|
while(1){
|
||||||
if(uart_tx_w == uart_tx_r){
|
if(uart_tx_w == uart_tx_r){
|
||||||
// transmit buffer is empty.
|
// transmit buffer is empty.
|
||||||
|
ReadReg(ISR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
79
kernel/vm.c
79
kernel/vm.c
@ -4,6 +4,8 @@
|
|||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
#include "proc.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -30,8 +32,16 @@ kvmmake(void)
|
|||||||
// virtio mmio disk interface
|
// virtio mmio disk interface
|
||||||
kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
|
kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
|
||||||
|
|
||||||
|
#ifdef LAB_NET
|
||||||
|
// PCI-E ECAM (configuration space), for pci.c
|
||||||
|
kvmmap(kpgtbl, 0x30000000L, 0x30000000L, 0x10000000, PTE_R | PTE_W);
|
||||||
|
|
||||||
|
// pci.c maps the e1000's registers here.
|
||||||
|
kvmmap(kpgtbl, 0x40000000L, 0x40000000L, 0x20000, PTE_R | PTE_W);
|
||||||
|
#endif
|
||||||
|
|
||||||
// PLIC
|
// PLIC
|
||||||
kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
|
kvmmap(kpgtbl, PLIC, PLIC, 0x4000000, PTE_R | PTE_W);
|
||||||
|
|
||||||
// map kernel text executable and read-only.
|
// map kernel text executable and read-only.
|
||||||
kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);
|
kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);
|
||||||
@ -92,6 +102,11 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
|
|||||||
pte_t *pte = &pagetable[PX(level, va)];
|
pte_t *pte = &pagetable[PX(level, va)];
|
||||||
if(*pte & PTE_V) {
|
if(*pte & PTE_V) {
|
||||||
pagetable = (pagetable_t)PTE2PA(*pte);
|
pagetable = (pagetable_t)PTE2PA(*pte);
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
if(PTE_LEAF(*pte)) {
|
||||||
|
return pte;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
|
if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -125,6 +140,7 @@ walkaddr(pagetable_t pagetable, uint64 va)
|
|||||||
return pa;
|
return pa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// add a mapping to the kernel page table.
|
// add a mapping to the kernel page table.
|
||||||
// only used when booting.
|
// only used when booting.
|
||||||
// does not flush TLB or enable paging.
|
// does not flush TLB or enable paging.
|
||||||
@ -179,15 +195,19 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
|
|||||||
{
|
{
|
||||||
uint64 a;
|
uint64 a;
|
||||||
pte_t *pte;
|
pte_t *pte;
|
||||||
|
int sz;
|
||||||
|
|
||||||
if((va % PGSIZE) != 0)
|
if((va % PGSIZE) != 0)
|
||||||
panic("uvmunmap: not aligned");
|
panic("uvmunmap: not aligned");
|
||||||
|
|
||||||
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
|
for(a = va; a < va + npages*PGSIZE; a += sz){
|
||||||
|
sz = PGSIZE;
|
||||||
if((pte = walk(pagetable, a, 0)) == 0)
|
if((pte = walk(pagetable, a, 0)) == 0)
|
||||||
panic("uvmunmap: walk");
|
panic("uvmunmap: walk");
|
||||||
if((*pte & PTE_V) == 0)
|
if((*pte & PTE_V) == 0) {
|
||||||
|
printf("va=%ld pte=%ld\n", a, *pte);
|
||||||
panic("uvmunmap: not mapped");
|
panic("uvmunmap: not mapped");
|
||||||
|
}
|
||||||
if(PTE_FLAGS(*pte) == PTE_V)
|
if(PTE_FLAGS(*pte) == PTE_V)
|
||||||
panic("uvmunmap: not a leaf");
|
panic("uvmunmap: not a leaf");
|
||||||
if(do_free){
|
if(do_free){
|
||||||
@ -227,6 +247,7 @@ uvmfirst(pagetable_t pagetable, uchar *src, uint sz)
|
|||||||
memmove(mem, src, sz);
|
memmove(mem, src, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Allocate PTEs and physical memory to grow process from oldsz to
|
// Allocate PTEs and physical memory to grow process from oldsz to
|
||||||
// newsz, which need not be page aligned. Returns new size or 0 on error.
|
// newsz, which need not be page aligned. Returns new size or 0 on error.
|
||||||
uint64
|
uint64
|
||||||
@ -234,19 +255,23 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
|
|||||||
{
|
{
|
||||||
char *mem;
|
char *mem;
|
||||||
uint64 a;
|
uint64 a;
|
||||||
|
int sz;
|
||||||
|
|
||||||
if(newsz < oldsz)
|
if(newsz < oldsz)
|
||||||
return oldsz;
|
return oldsz;
|
||||||
|
|
||||||
oldsz = PGROUNDUP(oldsz);
|
oldsz = PGROUNDUP(oldsz);
|
||||||
for(a = oldsz; a < newsz; a += PGSIZE){
|
for(a = oldsz; a < newsz; a += sz){
|
||||||
|
sz = PGSIZE;
|
||||||
mem = kalloc();
|
mem = kalloc();
|
||||||
if(mem == 0){
|
if(mem == 0){
|
||||||
uvmdealloc(pagetable, a, oldsz);
|
uvmdealloc(pagetable, a, oldsz);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(mem, 0, PGSIZE);
|
#ifndef LAB_SYSCALL
|
||||||
if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_R|PTE_U|xperm) != 0){
|
memset(mem, 0, sz);
|
||||||
|
#endif
|
||||||
|
if(mappages(pagetable, a, sz, (uint64)mem, PTE_R|PTE_U|xperm) != 0){
|
||||||
kfree(mem);
|
kfree(mem);
|
||||||
uvmdealloc(pagetable, a, oldsz);
|
uvmdealloc(pagetable, a, oldsz);
|
||||||
return 0;
|
return 0;
|
||||||
@ -316,8 +341,11 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
|
|||||||
uint64 pa, i;
|
uint64 pa, i;
|
||||||
uint flags;
|
uint flags;
|
||||||
char *mem;
|
char *mem;
|
||||||
|
int szinc;
|
||||||
|
|
||||||
for(i = 0; i < sz; i += PGSIZE){
|
for(i = 0; i < sz; i += szinc){
|
||||||
|
szinc = PGSIZE;
|
||||||
|
szinc = PGSIZE;
|
||||||
if((pte = walk(old, i, 0)) == 0)
|
if((pte = walk(old, i, 0)) == 0)
|
||||||
panic("uvmcopy: pte should exist");
|
panic("uvmcopy: pte should exist");
|
||||||
if((*pte & PTE_V) == 0)
|
if((*pte & PTE_V) == 0)
|
||||||
@ -363,13 +391,21 @@ copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
|
|||||||
|
|
||||||
while(len > 0){
|
while(len > 0){
|
||||||
va0 = PGROUNDDOWN(dstva);
|
va0 = PGROUNDDOWN(dstva);
|
||||||
if(va0 >= MAXVA)
|
if (va0 >= MAXVA)
|
||||||
return -1;
|
return -1;
|
||||||
pte = walk(pagetable, va0, 0);
|
if((pte = walk(pagetable, va0, 0)) == 0) {
|
||||||
if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 ||
|
// printf("copyout: pte should exist 0x%x %d\n", dstva, len);
|
||||||
(*pte & PTE_W) == 0)
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// forbid copyout over read-only user text pages.
|
||||||
|
if((*pte & PTE_W) == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pa0 = walkaddr(pagetable, va0);
|
||||||
|
if(pa0 == 0)
|
||||||
return -1;
|
return -1;
|
||||||
pa0 = PTE2PA(*pte);
|
|
||||||
n = PGSIZE - (dstva - va0);
|
n = PGSIZE - (dstva - va0);
|
||||||
if(n > len)
|
if(n > len)
|
||||||
n = len;
|
n = len;
|
||||||
@ -389,7 +425,7 @@ int
|
|||||||
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
|
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
|
||||||
{
|
{
|
||||||
uint64 n, va0, pa0;
|
uint64 n, va0, pa0;
|
||||||
|
|
||||||
while(len > 0){
|
while(len > 0){
|
||||||
va0 = PGROUNDDOWN(srcva);
|
va0 = PGROUNDDOWN(srcva);
|
||||||
pa0 = walkaddr(pagetable, va0);
|
pa0 = walkaddr(pagetable, va0);
|
||||||
@ -449,3 +485,20 @@ copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
void
|
||||||
|
vmprint(pagetable_t pagetable) {
|
||||||
|
// your code here
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
pte_t*
|
||||||
|
pgpte(pagetable_t pagetable, uint64 va) {
|
||||||
|
return walk(pagetable, va, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
// Disk layout:
|
// Disk layout:
|
||||||
// [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
|
// [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
|
||||||
|
|
||||||
int nbitmap = FSSIZE/(BSIZE*8) + 1;
|
int nbitmap = FSSIZE/BPB + 1;
|
||||||
int ninodeblocks = NINODES / IPB + 1;
|
int ninodeblocks = NINODES / IPB + 1;
|
||||||
int nlog = LOGSIZE;
|
int nlog = LOGSIZE;
|
||||||
int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap)
|
int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap)
|
||||||
@ -147,6 +147,8 @@ main(int argc, char *argv[])
|
|||||||
if(shortname[0] == '_')
|
if(shortname[0] == '_')
|
||||||
shortname += 1;
|
shortname += 1;
|
||||||
|
|
||||||
|
assert(strlen(shortname) <= DIRSIZ);
|
||||||
|
|
||||||
inum = ialloc(T_FILE);
|
inum = ialloc(T_FILE);
|
||||||
|
|
||||||
bzero(&de, sizeof(de));
|
bzero(&de, sizeof(de));
|
||||||
@ -238,7 +240,7 @@ balloc(int used)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("balloc: first %d blocks have been allocated\n", used);
|
printf("balloc: first %d blocks have been allocated\n", used);
|
||||||
assert(used < BSIZE*8);
|
assert(used < BPB);
|
||||||
bzero(buf, BSIZE);
|
bzero(buf, BSIZE);
|
||||||
for(i = 0; i < used; i++){
|
for(i = 0; i < used; i++){
|
||||||
buf[i/8] = buf[i/8] | (0x1 << (i%8));
|
buf[i/8] = buf[i/8] | (0x1 << (i%8));
|
||||||
|
|||||||
21
user/cat.c
21
user/cat.c
@ -1,35 +1,38 @@
|
|||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "kernel/stat.h"
|
|
||||||
#include "kernel/types.h"
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/fcntl.h"
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
|
||||||
void cat(int fd) {
|
void
|
||||||
|
cat(int fd)
|
||||||
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while ((n = read(fd, buf, sizeof(buf))) > 0) {
|
while((n = read(fd, buf, sizeof(buf))) > 0) {
|
||||||
if (write(1, buf, n) != n) {
|
if (write(1, buf, n) != n) {
|
||||||
fprintf(2, "cat: write error\n");
|
fprintf(2, "cat: write error\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n < 0) {
|
if(n < 0){
|
||||||
fprintf(2, "cat: read error\n");
|
fprintf(2, "cat: read error\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
int fd, i;
|
int fd, i;
|
||||||
|
|
||||||
if (argc <= 1) {
|
if(argc <= 1){
|
||||||
cat(0);
|
cat(0);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for(i = 1; i < argc; i++){
|
||||||
if ((fd = open(argv[i], O_RDONLY)) < 0) {
|
if((fd = open(argv[i], O_RDONLY)) < 0){
|
||||||
fprintf(2, "cat: cannot open %s\n", argv[i]);
|
fprintf(2, "cat: cannot open %s\n", argv[i]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,5 +24,5 @@ init:
|
|||||||
# char *argv[] = { init, 0 };
|
# char *argv[] = { init, 0 };
|
||||||
.p2align 2
|
.p2align 2
|
||||||
argv:
|
argv:
|
||||||
.long init
|
.quad init
|
||||||
.long 0
|
.quad 0
|
||||||
|
|||||||
50
user/ls.c
50
user/ls.c
@ -1,81 +1,87 @@
|
|||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "kernel/fs.h"
|
|
||||||
#include "kernel/stat.h"
|
|
||||||
#include "kernel/types.h"
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/stat.h"
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
#include "kernel/fs.h"
|
||||||
|
#include "kernel/fcntl.h"
|
||||||
|
|
||||||
char *fmtname(char *path) {
|
char*
|
||||||
static char buf[DIRSIZ + 1];
|
fmtname(char *path)
|
||||||
|
{
|
||||||
|
static char buf[DIRSIZ+1];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
// Find first character after last slash.
|
// Find first character after last slash.
|
||||||
for (p = path + strlen(path); p >= path && *p != '/'; p--)
|
for(p=path+strlen(path); p >= path && *p != '/'; p--)
|
||||||
;
|
;
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
// Return blank-padded name.
|
// Return blank-padded name.
|
||||||
if (strlen(p) >= DIRSIZ)
|
if(strlen(p) >= DIRSIZ)
|
||||||
return p;
|
return p;
|
||||||
memmove(buf, p, strlen(p));
|
memmove(buf, p, strlen(p));
|
||||||
memset(buf + strlen(p), ' ', DIRSIZ - strlen(p));
|
memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ls(char *path) {
|
void
|
||||||
|
ls(char *path)
|
||||||
|
{
|
||||||
char buf[512], *p;
|
char buf[512], *p;
|
||||||
int fd;
|
int fd;
|
||||||
struct dirent de;
|
struct dirent de;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if ((fd = open(path, O_RDONLY)) < 0) {
|
if((fd = open(path, O_RDONLY)) < 0){
|
||||||
fprintf(2, "ls: cannot open %s\n", path);
|
fprintf(2, "ls: cannot open %s\n", path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat(fd, &st) < 0) {
|
if(fstat(fd, &st) < 0){
|
||||||
fprintf(2, "ls: cannot stat %s\n", path);
|
fprintf(2, "ls: cannot stat %s\n", path);
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (st.type) {
|
switch(st.type){
|
||||||
case T_DEVICE:
|
case T_DEVICE:
|
||||||
case T_FILE:
|
case T_FILE:
|
||||||
printf("%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size);
|
printf("%s %d %d %d\n", fmtname(path), st.type, st.ino, (int) st.size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_DIR:
|
case T_DIR:
|
||||||
if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) {
|
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
|
||||||
printf("ls: path too long\n");
|
printf("ls: path too long\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
strcpy(buf, path);
|
strcpy(buf, path);
|
||||||
p = buf + strlen(buf);
|
p = buf+strlen(buf);
|
||||||
*p++ = '/';
|
*p++ = '/';
|
||||||
while (read(fd, &de, sizeof(de)) == sizeof(de)) {
|
while(read(fd, &de, sizeof(de)) == sizeof(de)){
|
||||||
if (de.inum == 0)
|
if(de.inum == 0)
|
||||||
continue;
|
continue;
|
||||||
memmove(p, de.name, DIRSIZ);
|
memmove(p, de.name, DIRSIZ);
|
||||||
p[DIRSIZ] = 0;
|
p[DIRSIZ] = 0;
|
||||||
if (stat(buf, &st) < 0) {
|
if(stat(buf, &st) < 0){
|
||||||
printf("ls: cannot stat %s\n", buf);
|
printf("ls: cannot stat %s\n", buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
|
printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, (int) st.size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (argc < 2) {
|
if(argc < 2){
|
||||||
ls(".");
|
ls(".");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
for (i = 1; i < argc; i++)
|
for(i=1; i<argc; i++)
|
||||||
ls(argv[i]);
|
ls(argv[i]);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
164
user/pgtbltest.c
Normal file
164
user/pgtbltest.c
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#include "kernel/param.h"
|
||||||
|
#include "kernel/fcntl.h"
|
||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/riscv.h"
|
||||||
|
#include "user/user.h"
|
||||||
|
|
||||||
|
#define N (8 * (1 << 20))
|
||||||
|
|
||||||
|
void print_pgtbl();
|
||||||
|
void print_kpgtbl();
|
||||||
|
void ugetpid_test();
|
||||||
|
void pgaccess_test();
|
||||||
|
void superpg_test();
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
print_pgtbl();
|
||||||
|
ugetpid_test();
|
||||||
|
print_kpgtbl();
|
||||||
|
pgaccess_test();
|
||||||
|
superpg_test();
|
||||||
|
printf("pgtbltest: all tests succeeded\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *testname = "???";
|
||||||
|
|
||||||
|
void
|
||||||
|
err(char *why)
|
||||||
|
{
|
||||||
|
printf("pgtbltest: %s failed: %s, pid=%d\n", testname, why, getpid());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_pte(uint64 va)
|
||||||
|
{
|
||||||
|
pte_t pte = (pte_t) pgpte((void *) va);
|
||||||
|
printf("va 0x%lx pte 0x%lx pa 0x%lx perm 0x%lx\n", va, pte, PTE2PA(pte), PTE_FLAGS(pte));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_pgtbl()
|
||||||
|
{
|
||||||
|
printf("print_pgtbl starting\n");
|
||||||
|
for (uint64 i = 0; i < 10; i++) {
|
||||||
|
print_pte(i * PGSIZE);
|
||||||
|
}
|
||||||
|
uint64 top = MAXVA/PGSIZE;
|
||||||
|
for (uint64 i = top-10; i < top; i++) {
|
||||||
|
print_pte(i * PGSIZE);
|
||||||
|
}
|
||||||
|
printf("print_pgtbl: OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ugetpid_test()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("ugetpid_test starting\n");
|
||||||
|
testname = "ugetpid_test";
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
int ret = fork();
|
||||||
|
if (ret != 0) {
|
||||||
|
wait(&ret);
|
||||||
|
if (ret != 0)
|
||||||
|
exit(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (getpid() != ugetpid())
|
||||||
|
err("missmatched PID");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
printf("ugetpid_test: OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_kpgtbl()
|
||||||
|
{
|
||||||
|
printf("print_kpgtbl starting\n");
|
||||||
|
kpgtbl();
|
||||||
|
printf("print_kpgtbl: OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pgaccess_test()
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
unsigned int abits;
|
||||||
|
printf("pgaccess_test starting\n");
|
||||||
|
testname = "pgaccess_test";
|
||||||
|
buf = malloc(32 * PGSIZE);
|
||||||
|
if (pgaccess(buf, 32, &abits) < 0)
|
||||||
|
err("pgaccess failed");
|
||||||
|
buf[PGSIZE * 1] += 1;
|
||||||
|
buf[PGSIZE * 2] += 1;
|
||||||
|
buf[PGSIZE * 30] += 1;
|
||||||
|
if (pgaccess(buf, 32, &abits) < 0)
|
||||||
|
err("pgaccess failed");
|
||||||
|
if (abits != ((1 << 1) | (1 << 2) | (1 << 30)))
|
||||||
|
err("incorrect access bits set");
|
||||||
|
free(buf);
|
||||||
|
printf("pgaccess_test: OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
supercheck(uint64 s)
|
||||||
|
{
|
||||||
|
pte_t last_pte = 0;
|
||||||
|
|
||||||
|
for (uint64 p = s; p < s + 512 * PGSIZE; p += PGSIZE) {
|
||||||
|
pte_t pte = (pte_t) pgpte((void *) p);
|
||||||
|
if(pte == 0)
|
||||||
|
err("no pte");
|
||||||
|
if ((uint64) last_pte != 0 && pte != last_pte) {
|
||||||
|
err("pte different");
|
||||||
|
}
|
||||||
|
if((pte & PTE_V) == 0 || (pte & PTE_R) == 0 || (pte & PTE_W) == 0){
|
||||||
|
err("pte wrong");
|
||||||
|
}
|
||||||
|
last_pte = pte;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 512; i += PGSIZE){
|
||||||
|
*(int*)(s+i) = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 512; i += PGSIZE){
|
||||||
|
if(*(int*)(s+i) != i)
|
||||||
|
err("wrong value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
superpg_test()
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
printf("superpg_test starting\n");
|
||||||
|
testname = "superpg_test";
|
||||||
|
|
||||||
|
char *end = sbrk(N);
|
||||||
|
if (end == 0 || end == (char*)0xffffffffffffffff)
|
||||||
|
err("sbrk failed");
|
||||||
|
|
||||||
|
uint64 s = SUPERPGROUNDUP((uint64) end);
|
||||||
|
supercheck(s);
|
||||||
|
if((pid = fork()) < 0) {
|
||||||
|
err("fork");
|
||||||
|
} else if(pid == 0) {
|
||||||
|
supercheck(s);
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
int status;
|
||||||
|
wait(&status);
|
||||||
|
if (status != 0) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("superpg_test: OK\n");
|
||||||
|
}
|
||||||
115
user/printf.c
115
user/printf.c
@ -1,20 +1,26 @@
|
|||||||
#include "kernel/stat.h"
|
|
||||||
#include "kernel/types.h"
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/stat.h"
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
static char digits[] = "0123456789ABCDEF";
|
static char digits[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
static void putc(int fd, char c) { write(fd, &c, 1); }
|
static void
|
||||||
|
putc(int fd, char c)
|
||||||
|
{
|
||||||
|
write(fd, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void printint(int fd, int xx, int base, int sgn) {
|
static void
|
||||||
|
printint(int fd, int xx, int base, int sgn)
|
||||||
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
int i, neg;
|
int i, neg;
|
||||||
uint x;
|
uint x;
|
||||||
|
|
||||||
neg = 0;
|
neg = 0;
|
||||||
if (sgn && xx < 0) {
|
if(sgn && xx < 0){
|
||||||
neg = 1;
|
neg = 1;
|
||||||
x = -xx;
|
x = -xx;
|
||||||
} else {
|
} else {
|
||||||
@ -22,17 +28,18 @@ static void printint(int fd, int xx, int base, int sgn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do{
|
||||||
buf[i++] = digits[x % base];
|
buf[i++] = digits[x % base];
|
||||||
} while ((x /= base) != 0);
|
}while((x /= base) != 0);
|
||||||
if (neg)
|
if(neg)
|
||||||
buf[i++] = '-';
|
buf[i++] = '-';
|
||||||
|
|
||||||
while (--i >= 0)
|
while(--i >= 0)
|
||||||
putc(fd, buf[i]);
|
putc(fd, buf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printptr(int fd, uint64 x) {
|
static void
|
||||||
|
printptr(int fd, uint64 x) {
|
||||||
int i;
|
int i;
|
||||||
putc(fd, '0');
|
putc(fd, '0');
|
||||||
putc(fd, 'x');
|
putc(fd, 'x');
|
||||||
@ -41,58 +48,108 @@ static void printptr(int fd, uint64 x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Print to the given fd. Only understands %d, %x, %p, %s.
|
// Print to the given fd. Only understands %d, %x, %p, %s.
|
||||||
void vprintf(int fd, const char *fmt, va_list ap) {
|
void
|
||||||
|
vprintf(int fd, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
char *s;
|
char *s;
|
||||||
int c, i, state;
|
int c0, c1, c2, i, state;
|
||||||
|
|
||||||
state = 0;
|
state = 0;
|
||||||
for (i = 0; fmt[i]; i++) {
|
for(i = 0; fmt[i]; i++){
|
||||||
c = fmt[i] & 0xff;
|
c0 = fmt[i] & 0xff;
|
||||||
if (state == 0) {
|
if(state == 0){
|
||||||
if (c == '%') {
|
if(c0 == '%'){
|
||||||
state = '%';
|
state = '%';
|
||||||
} else {
|
} else {
|
||||||
putc(fd, c);
|
putc(fd, c0);
|
||||||
}
|
}
|
||||||
} else if (state == '%') {
|
} else if(state == '%'){
|
||||||
if (c == 'd') {
|
c1 = c2 = 0;
|
||||||
|
if(c0) c1 = fmt[i+1] & 0xff;
|
||||||
|
if(c1) c2 = fmt[i+2] & 0xff;
|
||||||
|
if(c0 == 'd'){
|
||||||
printint(fd, va_arg(ap, int), 10, 1);
|
printint(fd, va_arg(ap, int), 10, 1);
|
||||||
} else if (c == 'l') {
|
} else if(c0 == 'l' && c1 == 'd'){
|
||||||
|
printint(fd, va_arg(ap, uint64), 10, 1);
|
||||||
|
i += 1;
|
||||||
|
} else if(c0 == 'l' && c1 == 'l' && c2 == 'd'){
|
||||||
|
printint(fd, va_arg(ap, uint64), 10, 1);
|
||||||
|
i += 2;
|
||||||
|
} else if(c0 == 'u'){
|
||||||
|
printint(fd, va_arg(ap, int), 10, 0);
|
||||||
|
} else if(c0 == 'l' && c1 == 'u'){
|
||||||
printint(fd, va_arg(ap, uint64), 10, 0);
|
printint(fd, va_arg(ap, uint64), 10, 0);
|
||||||
} else if (c == 'x') {
|
i += 1;
|
||||||
|
} else if(c0 == 'l' && c1 == 'l' && c2 == 'u'){
|
||||||
|
printint(fd, va_arg(ap, uint64), 10, 0);
|
||||||
|
i += 2;
|
||||||
|
} else if(c0 == 'x'){
|
||||||
printint(fd, va_arg(ap, int), 16, 0);
|
printint(fd, va_arg(ap, int), 16, 0);
|
||||||
} else if (c == 'p') {
|
} else if(c0 == 'l' && c1 == 'x'){
|
||||||
|
printint(fd, va_arg(ap, uint64), 16, 0);
|
||||||
|
i += 1;
|
||||||
|
} else if(c0 == 'l' && c1 == 'l' && c2 == 'x'){
|
||||||
|
printint(fd, va_arg(ap, uint64), 16, 0);
|
||||||
|
i += 2;
|
||||||
|
} else if(c0 == 'p'){
|
||||||
printptr(fd, va_arg(ap, uint64));
|
printptr(fd, va_arg(ap, uint64));
|
||||||
} else if (c == 's') {
|
} else if(c0 == 's'){
|
||||||
s = va_arg(ap, char *);
|
if((s = va_arg(ap, char*)) == 0)
|
||||||
if (s == 0)
|
|
||||||
s = "(null)";
|
s = "(null)";
|
||||||
while (*s != 0) {
|
for(; *s; s++)
|
||||||
|
putc(fd, *s);
|
||||||
|
} else if(c0 == '%'){
|
||||||
|
putc(fd, '%');
|
||||||
|
} else {
|
||||||
|
// Unknown % sequence. Print it to draw attention.
|
||||||
|
putc(fd, '%');
|
||||||
|
putc(fd, c0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(c == 'd'){
|
||||||
|
printint(fd, va_arg(ap, int), 10, 1);
|
||||||
|
} else if(c == 'l') {
|
||||||
|
printint(fd, va_arg(ap, uint64), 10, 0);
|
||||||
|
} else if(c == 'x') {
|
||||||
|
printint(fd, va_arg(ap, int), 16, 0);
|
||||||
|
} else if(c == 'p') {
|
||||||
|
printptr(fd, va_arg(ap, uint64));
|
||||||
|
} else if(c == 's'){
|
||||||
|
s = va_arg(ap, char*);
|
||||||
|
if(s == 0)
|
||||||
|
s = "(null)";
|
||||||
|
while(*s != 0){
|
||||||
putc(fd, *s);
|
putc(fd, *s);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
} else if (c == 'c') {
|
} else if(c == 'c'){
|
||||||
putc(fd, va_arg(ap, uint));
|
putc(fd, va_arg(ap, uint));
|
||||||
} else if (c == '%') {
|
} else if(c == '%'){
|
||||||
putc(fd, c);
|
putc(fd, c);
|
||||||
} else {
|
} else {
|
||||||
// Unknown % sequence. Print it to draw attention.
|
// Unknown % sequence. Print it to draw attention.
|
||||||
putc(fd, '%');
|
putc(fd, '%');
|
||||||
putc(fd, c);
|
putc(fd, c);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
state = 0;
|
state = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fprintf(int fd, const char *fmt, ...) {
|
void
|
||||||
|
fprintf(int fd, const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vprintf(fd, fmt, ap);
|
vprintf(fd, fmt, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printf(const char *fmt, ...) {
|
void
|
||||||
|
printf(const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|||||||
243
user/sh.c
243
user/sh.c
@ -1,16 +1,15 @@
|
|||||||
// Shell.
|
// Shell.
|
||||||
|
|
||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "kernel/fs.h"
|
|
||||||
#include "kernel/types.h"
|
#include "kernel/types.h"
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
#include "kernel/fcntl.h"
|
||||||
|
|
||||||
// Parsed command representation
|
// Parsed command representation
|
||||||
#define EXEC 1
|
#define EXEC 1
|
||||||
#define REDIR 2
|
#define REDIR 2
|
||||||
#define PIPE 3
|
#define PIPE 3
|
||||||
#define LIST 4
|
#define LIST 4
|
||||||
#define BACK 5
|
#define BACK 5
|
||||||
|
|
||||||
#define MAXARGS 10
|
#define MAXARGS 10
|
||||||
|
|
||||||
@ -50,15 +49,15 @@ struct backcmd {
|
|||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
int fork1(void); // Fork but panics on failure.
|
int fork1(void); // Fork but panics on failure.
|
||||||
void panic(char *);
|
void panic(char*);
|
||||||
struct cmd *parsecmd(char *);
|
struct cmd *parsecmd(char*);
|
||||||
void runcmd(struct cmd *) __attribute__((noreturn));
|
void runcmd(struct cmd*) __attribute__((noreturn));
|
||||||
// void handle_tab_completion(char *buf, int *i, int nbuf);
|
|
||||||
// 尝试添加tab补全功能
|
|
||||||
|
|
||||||
// Execute cmd. Never returns.
|
// Execute cmd. Never returns.
|
||||||
void runcmd(struct cmd *cmd) {
|
void
|
||||||
|
runcmd(struct cmd *cmd)
|
||||||
|
{
|
||||||
int p[2];
|
int p[2];
|
||||||
struct backcmd *bcmd;
|
struct backcmd *bcmd;
|
||||||
struct execcmd *ecmd;
|
struct execcmd *ecmd;
|
||||||
@ -66,25 +65,25 @@ void runcmd(struct cmd *cmd) {
|
|||||||
struct pipecmd *pcmd;
|
struct pipecmd *pcmd;
|
||||||
struct redircmd *rcmd;
|
struct redircmd *rcmd;
|
||||||
|
|
||||||
if (cmd == 0)
|
if(cmd == 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
switch (cmd->type) {
|
switch(cmd->type){
|
||||||
default:
|
default:
|
||||||
panic("runcmd");
|
panic("runcmd");
|
||||||
|
|
||||||
case EXEC:
|
case EXEC:
|
||||||
ecmd = (struct execcmd *)cmd;
|
ecmd = (struct execcmd*)cmd;
|
||||||
if (ecmd->argv[0] == 0)
|
if(ecmd->argv[0] == 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
exec(ecmd->argv[0], ecmd->argv);
|
exec(ecmd->argv[0], ecmd->argv);
|
||||||
fprintf(2, "exec %s failed\n", ecmd->argv[0]);
|
fprintf(2, "exec %s failed\n", ecmd->argv[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REDIR:
|
case REDIR:
|
||||||
rcmd = (struct redircmd *)cmd;
|
rcmd = (struct redircmd*)cmd;
|
||||||
close(rcmd->fd);
|
close(rcmd->fd);
|
||||||
if (open(rcmd->file, rcmd->mode) < 0) {
|
if(open(rcmd->file, rcmd->mode) < 0){
|
||||||
fprintf(2, "open %s failed\n", rcmd->file);
|
fprintf(2, "open %s failed\n", rcmd->file);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -92,25 +91,25 @@ void runcmd(struct cmd *cmd) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LIST:
|
case LIST:
|
||||||
lcmd = (struct listcmd *)cmd;
|
lcmd = (struct listcmd*)cmd;
|
||||||
if (fork1() == 0)
|
if(fork1() == 0)
|
||||||
runcmd(lcmd->left);
|
runcmd(lcmd->left);
|
||||||
wait(0);
|
wait(0);
|
||||||
runcmd(lcmd->right);
|
runcmd(lcmd->right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIPE:
|
case PIPE:
|
||||||
pcmd = (struct pipecmd *)cmd;
|
pcmd = (struct pipecmd*)cmd;
|
||||||
if (pipe(p) < 0)
|
if(pipe(p) < 0)
|
||||||
panic("pipe");
|
panic("pipe");
|
||||||
if (fork1() == 0) {
|
if(fork1() == 0){
|
||||||
close(1);
|
close(1);
|
||||||
dup(p[1]);
|
dup(p[1]);
|
||||||
close(p[0]);
|
close(p[0]);
|
||||||
close(p[1]);
|
close(p[1]);
|
||||||
runcmd(pcmd->left);
|
runcmd(pcmd->left);
|
||||||
}
|
}
|
||||||
if (fork1() == 0) {
|
if(fork1() == 0){
|
||||||
close(0);
|
close(0);
|
||||||
dup(p[0]);
|
dup(p[0]);
|
||||||
close(p[0]);
|
close(p[0]);
|
||||||
@ -124,82 +123,90 @@ void runcmd(struct cmd *cmd) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BACK:
|
case BACK:
|
||||||
bcmd = (struct backcmd *)cmd;
|
bcmd = (struct backcmd*)cmd;
|
||||||
if (fork1() == 0)
|
if(fork1() == 0)
|
||||||
runcmd(bcmd->cmd);
|
runcmd(bcmd->cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getcmd(char *buf, int nbuf) {
|
int
|
||||||
|
getcmd(char *buf, int nbuf)
|
||||||
|
{
|
||||||
write(2, "$ ", 2);
|
write(2, "$ ", 2);
|
||||||
memset(buf, 0, nbuf);
|
memset(buf, 0, nbuf);
|
||||||
gets(buf, nbuf);
|
gets(buf, nbuf);
|
||||||
if (buf[0] == 0) // EOF
|
if(buf[0] == 0) // EOF
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
static char buf[100];
|
static char buf[100];
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
// Ensure that three file descriptors are open.
|
// Ensure that three file descriptors are open.
|
||||||
while ((fd = open("console", O_RDWR)) >= 0) {
|
while((fd = open("console", O_RDWR)) >= 0){
|
||||||
if (fd >= 3) {
|
if(fd >= 3){
|
||||||
close(fd);
|
close(fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and run input commands.
|
// Read and run input commands.
|
||||||
while (getcmd(buf, sizeof(buf)) >= 0) {
|
while(getcmd(buf, sizeof(buf)) >= 0){
|
||||||
if (strcmp(buf, "exit\n") == 0) {
|
if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
if (buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ') {
|
|
||||||
// Chdir must be called by the parent, not the child.
|
// Chdir must be called by the parent, not the child.
|
||||||
buf[strlen(buf) - 1] = 0; // chop \n
|
buf[strlen(buf)-1] = 0; // chop \n
|
||||||
if (chdir(buf + 3) < 0)
|
if(chdir(buf+3) < 0)
|
||||||
fprintf(2, "cannot cd %s\n", buf + 3);
|
fprintf(2, "cannot cd %s\n", buf+3);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fork1() == 0)
|
if(fork1() == 0)
|
||||||
runcmd(parsecmd(buf));
|
runcmd(parsecmd(buf));
|
||||||
wait(0);
|
wait(0);
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void panic(char *s) {
|
void
|
||||||
|
panic(char *s)
|
||||||
|
{
|
||||||
fprintf(2, "%s\n", s);
|
fprintf(2, "%s\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fork1(void) {
|
int
|
||||||
|
fork1(void)
|
||||||
|
{
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == -1)
|
if(pid == -1)
|
||||||
panic("fork");
|
panic("fork");
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PAGEBREAK!
|
//PAGEBREAK!
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
struct cmd *execcmd(void) {
|
struct cmd*
|
||||||
|
execcmd(void)
|
||||||
|
{
|
||||||
struct execcmd *cmd;
|
struct execcmd *cmd;
|
||||||
|
|
||||||
cmd = malloc(sizeof(*cmd));
|
cmd = malloc(sizeof(*cmd));
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->type = EXEC;
|
cmd->type = EXEC;
|
||||||
return (struct cmd *)cmd;
|
return (struct cmd*)cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *redircmd(struct cmd *subcmd, char *file, char *efile, int mode,
|
struct cmd*
|
||||||
int fd) {
|
redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)
|
||||||
|
{
|
||||||
struct redircmd *cmd;
|
struct redircmd *cmd;
|
||||||
|
|
||||||
cmd = malloc(sizeof(*cmd));
|
cmd = malloc(sizeof(*cmd));
|
||||||
@ -210,10 +217,12 @@ struct cmd *redircmd(struct cmd *subcmd, char *file, char *efile, int mode,
|
|||||||
cmd->efile = efile;
|
cmd->efile = efile;
|
||||||
cmd->mode = mode;
|
cmd->mode = mode;
|
||||||
cmd->fd = fd;
|
cmd->fd = fd;
|
||||||
return (struct cmd *)cmd;
|
return (struct cmd*)cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *pipecmd(struct cmd *left, struct cmd *right) {
|
struct cmd*
|
||||||
|
pipecmd(struct cmd *left, struct cmd *right)
|
||||||
|
{
|
||||||
struct pipecmd *cmd;
|
struct pipecmd *cmd;
|
||||||
|
|
||||||
cmd = malloc(sizeof(*cmd));
|
cmd = malloc(sizeof(*cmd));
|
||||||
@ -221,10 +230,12 @@ struct cmd *pipecmd(struct cmd *left, struct cmd *right) {
|
|||||||
cmd->type = PIPE;
|
cmd->type = PIPE;
|
||||||
cmd->left = left;
|
cmd->left = left;
|
||||||
cmd->right = right;
|
cmd->right = right;
|
||||||
return (struct cmd *)cmd;
|
return (struct cmd*)cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *listcmd(struct cmd *left, struct cmd *right) {
|
struct cmd*
|
||||||
|
listcmd(struct cmd *left, struct cmd *right)
|
||||||
|
{
|
||||||
struct listcmd *cmd;
|
struct listcmd *cmd;
|
||||||
|
|
||||||
cmd = malloc(sizeof(*cmd));
|
cmd = malloc(sizeof(*cmd));
|
||||||
@ -232,35 +243,39 @@ struct cmd *listcmd(struct cmd *left, struct cmd *right) {
|
|||||||
cmd->type = LIST;
|
cmd->type = LIST;
|
||||||
cmd->left = left;
|
cmd->left = left;
|
||||||
cmd->right = right;
|
cmd->right = right;
|
||||||
return (struct cmd *)cmd;
|
return (struct cmd*)cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *backcmd(struct cmd *subcmd) {
|
struct cmd*
|
||||||
|
backcmd(struct cmd *subcmd)
|
||||||
|
{
|
||||||
struct backcmd *cmd;
|
struct backcmd *cmd;
|
||||||
|
|
||||||
cmd = malloc(sizeof(*cmd));
|
cmd = malloc(sizeof(*cmd));
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->type = BACK;
|
cmd->type = BACK;
|
||||||
cmd->cmd = subcmd;
|
cmd->cmd = subcmd;
|
||||||
return (struct cmd *)cmd;
|
return (struct cmd*)cmd;
|
||||||
}
|
}
|
||||||
// PAGEBREAK!
|
//PAGEBREAK!
|
||||||
// Parsing
|
// Parsing
|
||||||
|
|
||||||
char whitespace[] = " \t\r\n\v";
|
char whitespace[] = " \t\r\n\v";
|
||||||
char symbols[] = "<|>&;()";
|
char symbols[] = "<|>&;()";
|
||||||
|
|
||||||
int gettoken(char **ps, char *es, char **q, char **eq) {
|
int
|
||||||
|
gettoken(char **ps, char *es, char **q, char **eq)
|
||||||
|
{
|
||||||
char *s;
|
char *s;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
s = *ps;
|
s = *ps;
|
||||||
while (s < es && strchr(whitespace, *s))
|
while(s < es && strchr(whitespace, *s))
|
||||||
s++;
|
s++;
|
||||||
if (q)
|
if(q)
|
||||||
*q = s;
|
*q = s;
|
||||||
ret = *s;
|
ret = *s;
|
||||||
switch (*s) {
|
switch(*s){
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case '|':
|
case '|':
|
||||||
@ -273,49 +288,53 @@ int gettoken(char **ps, char *es, char **q, char **eq) {
|
|||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
s++;
|
s++;
|
||||||
if (*s == '>') {
|
if(*s == '>'){
|
||||||
ret = '+';
|
ret = '+';
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = 'a';
|
ret = 'a';
|
||||||
while (s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
|
while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
|
||||||
s++;
|
s++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (eq)
|
if(eq)
|
||||||
*eq = s;
|
*eq = s;
|
||||||
|
|
||||||
while (s < es && strchr(whitespace, *s))
|
while(s < es && strchr(whitespace, *s))
|
||||||
s++;
|
s++;
|
||||||
*ps = s;
|
*ps = s;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int peek(char **ps, char *es, char *toks) {
|
int
|
||||||
|
peek(char **ps, char *es, char *toks)
|
||||||
|
{
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
s = *ps;
|
s = *ps;
|
||||||
while (s < es && strchr(whitespace, *s))
|
while(s < es && strchr(whitespace, *s))
|
||||||
s++;
|
s++;
|
||||||
*ps = s;
|
*ps = s;
|
||||||
return *s && strchr(toks, *s);
|
return *s && strchr(toks, *s);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *parseline(char **, char *);
|
struct cmd *parseline(char**, char*);
|
||||||
struct cmd *parsepipe(char **, char *);
|
struct cmd *parsepipe(char**, char*);
|
||||||
struct cmd *parseexec(char **, char *);
|
struct cmd *parseexec(char**, char*);
|
||||||
struct cmd *nulterminate(struct cmd *);
|
struct cmd *nulterminate(struct cmd*);
|
||||||
|
|
||||||
struct cmd *parsecmd(char *s) {
|
struct cmd*
|
||||||
|
parsecmd(char *s)
|
||||||
|
{
|
||||||
char *es;
|
char *es;
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
|
|
||||||
es = s + strlen(s);
|
es = s + strlen(s);
|
||||||
cmd = parseline(&s, es);
|
cmd = parseline(&s, es);
|
||||||
peek(&s, es, "");
|
peek(&s, es, "");
|
||||||
if (s != es) {
|
if(s != es){
|
||||||
fprintf(2, "leftovers: %s\n", s);
|
fprintf(2, "leftovers: %s\n", s);
|
||||||
panic("syntax");
|
panic("syntax");
|
||||||
}
|
}
|
||||||
@ -323,92 +342,102 @@ struct cmd *parsecmd(char *s) {
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *parseline(char **ps, char *es) {
|
struct cmd*
|
||||||
|
parseline(char **ps, char *es)
|
||||||
|
{
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
|
|
||||||
cmd = parsepipe(ps, es);
|
cmd = parsepipe(ps, es);
|
||||||
while (peek(ps, es, "&")) {
|
while(peek(ps, es, "&")){
|
||||||
gettoken(ps, es, 0, 0);
|
gettoken(ps, es, 0, 0);
|
||||||
cmd = backcmd(cmd);
|
cmd = backcmd(cmd);
|
||||||
}
|
}
|
||||||
if (peek(ps, es, ";")) {
|
if(peek(ps, es, ";")){
|
||||||
gettoken(ps, es, 0, 0);
|
gettoken(ps, es, 0, 0);
|
||||||
cmd = listcmd(cmd, parseline(ps, es));
|
cmd = listcmd(cmd, parseline(ps, es));
|
||||||
}
|
}
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *parsepipe(char **ps, char *es) {
|
struct cmd*
|
||||||
|
parsepipe(char **ps, char *es)
|
||||||
|
{
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
|
|
||||||
cmd = parseexec(ps, es);
|
cmd = parseexec(ps, es);
|
||||||
if (peek(ps, es, "|")) {
|
if(peek(ps, es, "|")){
|
||||||
gettoken(ps, es, 0, 0);
|
gettoken(ps, es, 0, 0);
|
||||||
cmd = pipecmd(cmd, parsepipe(ps, es));
|
cmd = pipecmd(cmd, parsepipe(ps, es));
|
||||||
}
|
}
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *parseredirs(struct cmd *cmd, char **ps, char *es) {
|
struct cmd*
|
||||||
|
parseredirs(struct cmd *cmd, char **ps, char *es)
|
||||||
|
{
|
||||||
int tok;
|
int tok;
|
||||||
char *q, *eq;
|
char *q, *eq;
|
||||||
|
|
||||||
while (peek(ps, es, "<>")) {
|
while(peek(ps, es, "<>")){
|
||||||
tok = gettoken(ps, es, 0, 0);
|
tok = gettoken(ps, es, 0, 0);
|
||||||
if (gettoken(ps, es, &q, &eq) != 'a')
|
if(gettoken(ps, es, &q, &eq) != 'a')
|
||||||
panic("missing file for redirection");
|
panic("missing file for redirection");
|
||||||
switch (tok) {
|
switch(tok){
|
||||||
case '<':
|
case '<':
|
||||||
cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
|
cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
cmd = redircmd(cmd, q, eq, O_WRONLY | O_CREATE | O_TRUNC, 1);
|
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE|O_TRUNC, 1);
|
||||||
break;
|
break;
|
||||||
case '+': // >>
|
case '+': // >>
|
||||||
cmd = redircmd(cmd, q, eq, O_WRONLY | O_CREATE, 1);
|
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *parseblock(char **ps, char *es) {
|
struct cmd*
|
||||||
|
parseblock(char **ps, char *es)
|
||||||
|
{
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
|
|
||||||
if (!peek(ps, es, "("))
|
if(!peek(ps, es, "("))
|
||||||
panic("parseblock");
|
panic("parseblock");
|
||||||
gettoken(ps, es, 0, 0);
|
gettoken(ps, es, 0, 0);
|
||||||
cmd = parseline(ps, es);
|
cmd = parseline(ps, es);
|
||||||
if (!peek(ps, es, ")"))
|
if(!peek(ps, es, ")"))
|
||||||
panic("syntax - missing )");
|
panic("syntax - missing )");
|
||||||
gettoken(ps, es, 0, 0);
|
gettoken(ps, es, 0, 0);
|
||||||
cmd = parseredirs(cmd, ps, es);
|
cmd = parseredirs(cmd, ps, es);
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd *parseexec(char **ps, char *es) {
|
struct cmd*
|
||||||
|
parseexec(char **ps, char *es)
|
||||||
|
{
|
||||||
char *q, *eq;
|
char *q, *eq;
|
||||||
int tok, argc;
|
int tok, argc;
|
||||||
struct execcmd *cmd;
|
struct execcmd *cmd;
|
||||||
struct cmd *ret;
|
struct cmd *ret;
|
||||||
|
|
||||||
if (peek(ps, es, "("))
|
if(peek(ps, es, "("))
|
||||||
return parseblock(ps, es);
|
return parseblock(ps, es);
|
||||||
|
|
||||||
ret = execcmd();
|
ret = execcmd();
|
||||||
cmd = (struct execcmd *)ret;
|
cmd = (struct execcmd*)ret;
|
||||||
|
|
||||||
argc = 0;
|
argc = 0;
|
||||||
ret = parseredirs(ret, ps, es);
|
ret = parseredirs(ret, ps, es);
|
||||||
while (!peek(ps, es, "|)&;")) {
|
while(!peek(ps, es, "|)&;")){
|
||||||
if ((tok = gettoken(ps, es, &q, &eq)) == 0)
|
if((tok=gettoken(ps, es, &q, &eq)) == 0)
|
||||||
break;
|
break;
|
||||||
if (tok != 'a')
|
if(tok != 'a')
|
||||||
panic("syntax");
|
panic("syntax");
|
||||||
cmd->argv[argc] = q;
|
cmd->argv[argc] = q;
|
||||||
cmd->eargv[argc] = eq;
|
cmd->eargv[argc] = eq;
|
||||||
argc++;
|
argc++;
|
||||||
if (argc >= MAXARGS)
|
if(argc >= MAXARGS)
|
||||||
panic("too many args");
|
panic("too many args");
|
||||||
ret = parseredirs(ret, ps, es);
|
ret = parseredirs(ret, ps, es);
|
||||||
}
|
}
|
||||||
@ -418,7 +447,9 @@ struct cmd *parseexec(char **ps, char *es) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NUL-terminate all the counted strings.
|
// NUL-terminate all the counted strings.
|
||||||
struct cmd *nulterminate(struct cmd *cmd) {
|
struct cmd*
|
||||||
|
nulterminate(struct cmd *cmd)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
struct backcmd *bcmd;
|
struct backcmd *bcmd;
|
||||||
struct execcmd *ecmd;
|
struct execcmd *ecmd;
|
||||||
@ -426,36 +457,36 @@ struct cmd *nulterminate(struct cmd *cmd) {
|
|||||||
struct pipecmd *pcmd;
|
struct pipecmd *pcmd;
|
||||||
struct redircmd *rcmd;
|
struct redircmd *rcmd;
|
||||||
|
|
||||||
if (cmd == 0)
|
if(cmd == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (cmd->type) {
|
switch(cmd->type){
|
||||||
case EXEC:
|
case EXEC:
|
||||||
ecmd = (struct execcmd *)cmd;
|
ecmd = (struct execcmd*)cmd;
|
||||||
for (i = 0; ecmd->argv[i]; i++)
|
for(i=0; ecmd->argv[i]; i++)
|
||||||
*ecmd->eargv[i] = 0;
|
*ecmd->eargv[i] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REDIR:
|
case REDIR:
|
||||||
rcmd = (struct redircmd *)cmd;
|
rcmd = (struct redircmd*)cmd;
|
||||||
nulterminate(rcmd->cmd);
|
nulterminate(rcmd->cmd);
|
||||||
*rcmd->efile = 0;
|
*rcmd->efile = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIPE:
|
case PIPE:
|
||||||
pcmd = (struct pipecmd *)cmd;
|
pcmd = (struct pipecmd*)cmd;
|
||||||
nulterminate(pcmd->left);
|
nulterminate(pcmd->left);
|
||||||
nulterminate(pcmd->right);
|
nulterminate(pcmd->right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LIST:
|
case LIST:
|
||||||
lcmd = (struct listcmd *)cmd;
|
lcmd = (struct listcmd*)cmd;
|
||||||
nulterminate(lcmd->left);
|
nulterminate(lcmd->left);
|
||||||
nulterminate(lcmd->right);
|
nulterminate(lcmd->right);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BACK:
|
case BACK:
|
||||||
bcmd = (struct backcmd *)cmd;
|
bcmd = (struct backcmd*)cmd;
|
||||||
nulterminate(bcmd->cmd);
|
nulterminate(bcmd->cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
119
user/ulib.c
119
user/ulib.c
@ -1,133 +1,139 @@
|
|||||||
#include "kernel/fcntl.h"
|
|
||||||
#include "kernel/stat.h"
|
|
||||||
#include "kernel/types.h"
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/stat.h"
|
||||||
|
#include "kernel/fcntl.h"
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
#include "kernel/riscv.h"
|
||||||
|
#include "kernel/memlayout.h"
|
||||||
|
#endif
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// wrapper so that it's OK if main() does not call exit().
|
// wrapper so that it's OK if main() does not call exit().
|
||||||
//
|
//
|
||||||
void _main() {
|
void
|
||||||
|
start()
|
||||||
|
{
|
||||||
extern int main();
|
extern int main();
|
||||||
main();
|
main();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strcpy(char *s, const char *t) {
|
char*
|
||||||
|
strcpy(char *s, const char *t)
|
||||||
|
{
|
||||||
char *os;
|
char *os;
|
||||||
|
|
||||||
os = s;
|
os = s;
|
||||||
while ((*s++ = *t++) != 0)
|
while((*s++ = *t++) != 0)
|
||||||
;
|
;
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strncpy(char *s, const char *t, int n) {
|
int
|
||||||
char *os;
|
strcmp(const char *p, const char *q)
|
||||||
|
{
|
||||||
os = s;
|
while(*p && *p == *q)
|
||||||
if (n <= 0)
|
|
||||||
return os;
|
|
||||||
while (--n > 0 && (*s++ = *t++) != 0)
|
|
||||||
;
|
|
||||||
while (n-- > 0)
|
|
||||||
*s++ = 0;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
int strcmp(const char *p, const char *q) {
|
|
||||||
while (*p && *p == *q)
|
|
||||||
p++, q++;
|
p++, q++;
|
||||||
return (uchar)*p - (uchar)*q;
|
return (uchar)*p - (uchar)*q;
|
||||||
}
|
}
|
||||||
|
|
||||||
int strncmp(const char *p, const char *q, int n) {
|
uint
|
||||||
while (n > 0 && *p && *p == *q)
|
strlen(const char *s)
|
||||||
p++, q++, n--;
|
{
|
||||||
if (n == 0)
|
|
||||||
return 0;
|
|
||||||
return (uchar)*p - (uchar)*q;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint strlen(const char *s) {
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
for (n = 0; s[n]; n++)
|
for(n = 0; s[n]; n++)
|
||||||
;
|
;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memset(void *dst, int c, uint n) {
|
void*
|
||||||
char *cdst = (char *)dst;
|
memset(void *dst, int c, uint n)
|
||||||
|
{
|
||||||
|
char *cdst = (char *) dst;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < n; i++) {
|
for(i = 0; i < n; i++){
|
||||||
cdst[i] = c;
|
cdst[i] = c;
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strchr(const char *s, char c) {
|
char*
|
||||||
for (; *s; s++)
|
strchr(const char *s, char c)
|
||||||
if (*s == c)
|
{
|
||||||
return (char *)s;
|
for(; *s; s++)
|
||||||
|
if(*s == c)
|
||||||
|
return (char*)s;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *gets(char *buf, int max) {
|
char*
|
||||||
|
gets(char *buf, int max)
|
||||||
|
{
|
||||||
int i, cc;
|
int i, cc;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
for (i = 0; i + 1 < max;) {
|
for(i=0; i+1 < max; ){
|
||||||
cc = read(0, &c, 1);
|
cc = read(0, &c, 1);
|
||||||
if (cc < 1)
|
if(cc < 1)
|
||||||
break;
|
break;
|
||||||
buf[i++] = c;
|
buf[i++] = c;
|
||||||
if (c == '\n' || c == '\r')
|
if(c == '\n' || c == '\r')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buf[i] = '\0';
|
buf[i] = '\0';
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int stat(const char *n, struct stat *st) {
|
int
|
||||||
|
stat(const char *n, struct stat *st)
|
||||||
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
fd = open(n, O_RDONLY);
|
fd = open(n, O_RDONLY);
|
||||||
if (fd < 0)
|
if(fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
r = fstat(fd, st);
|
r = fstat(fd, st);
|
||||||
close(fd);
|
close(fd);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int atoi(const char *s) {
|
int
|
||||||
|
atoi(const char *s)
|
||||||
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
while ('0' <= *s && *s <= '9')
|
while('0' <= *s && *s <= '9')
|
||||||
n = n * 10 + *s++ - '0';
|
n = n*10 + *s++ - '0';
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memmove(void *vdst, const void *vsrc, int n) {
|
void*
|
||||||
|
memmove(void *vdst, const void *vsrc, int n)
|
||||||
|
{
|
||||||
char *dst;
|
char *dst;
|
||||||
const char *src;
|
const char *src;
|
||||||
|
|
||||||
dst = vdst;
|
dst = vdst;
|
||||||
src = vsrc;
|
src = vsrc;
|
||||||
if (src > dst) {
|
if (src > dst) {
|
||||||
while (n-- > 0)
|
while(n-- > 0)
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
} else {
|
} else {
|
||||||
dst += n;
|
dst += n;
|
||||||
src += n;
|
src += n;
|
||||||
while (n-- > 0)
|
while(n-- > 0)
|
||||||
*--dst = *--src;
|
*--dst = *--src;
|
||||||
}
|
}
|
||||||
return vdst;
|
return vdst;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memcmp(const void *s1, const void *s2, uint n) {
|
int
|
||||||
|
memcmp(const void *s1, const void *s2, uint n)
|
||||||
|
{
|
||||||
const char *p1 = s1, *p2 = s2;
|
const char *p1 = s1, *p2 = s2;
|
||||||
while (n-- > 0) {
|
while (n-- > 0) {
|
||||||
if (*p1 != *p2) {
|
if (*p1 != *p2) {
|
||||||
@ -139,6 +145,17 @@ int memcmp(const void *s1, const void *s2, uint n) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memcpy(void *dst, const void *src, uint n) {
|
void *
|
||||||
|
memcpy(void *dst, const void *src, uint n)
|
||||||
|
{
|
||||||
return memmove(dst, src, n);
|
return memmove(dst, src, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
int
|
||||||
|
ugetpid(void)
|
||||||
|
{
|
||||||
|
struct usyscall *u = (struct usyscall *)USYSCALL;
|
||||||
|
return u->pid;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
79
user/user.h
79
user/user.h
@ -1,47 +1,62 @@
|
|||||||
#include "kernel/types.h"
|
#ifdef LAB_MMAP
|
||||||
#include "kernel/sysinfo.h"
|
typedef unsigned long size_t;
|
||||||
|
typedef long int off_t;
|
||||||
|
#endif
|
||||||
struct stat;
|
struct stat;
|
||||||
|
|
||||||
// system calls
|
// system calls
|
||||||
int fork(void);
|
int fork(void);
|
||||||
int exit(int) __attribute__((noreturn));
|
int exit(int) __attribute__((noreturn));
|
||||||
int wait(int *);
|
int wait(int*);
|
||||||
int pipe(int *);
|
int pipe(int*);
|
||||||
int write(int, const void *, int);
|
int write(int, const void*, int);
|
||||||
int read(int, void *, int);
|
int read(int, void*, int);
|
||||||
int close(int);
|
int close(int);
|
||||||
int kill(int);
|
int kill(int);
|
||||||
int exec(const char *, char **);
|
int exec(const char*, char**);
|
||||||
int open(const char *, int);
|
int open(const char*, int);
|
||||||
int mknod(const char *, short, short);
|
int mknod(const char*, short, short);
|
||||||
int unlink(const char *);
|
int unlink(const char*);
|
||||||
int fstat(int fd, struct stat *);
|
int fstat(int fd, struct stat*);
|
||||||
int link(const char *, const char *);
|
int link(const char*, const char*);
|
||||||
int mkdir(const char *);
|
int mkdir(const char*);
|
||||||
int chdir(const char *);
|
int chdir(const char*);
|
||||||
int dup(int);
|
int dup(int);
|
||||||
int getpid(void);
|
int getpid(void);
|
||||||
char *sbrk(int);
|
char* sbrk(int);
|
||||||
int sleep(int);
|
int sleep(int);
|
||||||
int uptime(void);
|
int uptime(void);
|
||||||
int trace(int);
|
#ifdef LAB_NET
|
||||||
int sysinfo(struct sysinfo*);
|
int bind(uint32);
|
||||||
|
int unbind(uint32);
|
||||||
|
int send(uint32, uint32, uint32, char *, uint32);
|
||||||
|
int recv(uint32, uint32*, uint32*, char *, uint32);
|
||||||
|
#endif
|
||||||
|
#ifdef LAB_PGTBL
|
||||||
|
int ugetpid(void);
|
||||||
|
uint64 pgpte(void*);
|
||||||
|
void kpgtbl(void);
|
||||||
|
int pgaccess(void *base, int len, void *mask);
|
||||||
|
#endif
|
||||||
|
|
||||||
// ulib.c
|
// ulib.c
|
||||||
int stat(const char *, struct stat *);
|
int stat(const char*, struct stat*);
|
||||||
char *strcpy(char *, const char *);
|
char* strcpy(char*, const char*);
|
||||||
char *strncpy(char *, const char *, int);
|
void *memmove(void*, const void*, int);
|
||||||
void *memmove(void *, const void *, int);
|
char* strchr(const char*, char c);
|
||||||
char *strchr(const char *, char c);
|
int strcmp(const char*, const char*);
|
||||||
int strcmp(const char *, const char *);
|
void fprintf(int, const char*, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
int strncmp(const char *, const char *, int);
|
void printf(const char*, ...) __attribute__ ((format (printf, 1, 2)));
|
||||||
void fprintf(int, const char *, ...);
|
char* gets(char*, int max);
|
||||||
void printf(const char *, ...);
|
uint strlen(const char*);
|
||||||
char *gets(char *, int max);
|
void* memset(void*, int, uint);
|
||||||
uint strlen(const char *);
|
int atoi(const char*);
|
||||||
void *memset(void *, int, uint);
|
|
||||||
void *malloc(uint);
|
|
||||||
void free(void *);
|
|
||||||
int atoi(const char *);
|
|
||||||
int memcmp(const void *, const void *, uint);
|
int memcmp(const void *, const void *, uint);
|
||||||
void *memcpy(void *, const void *, uint);
|
void *memcpy(void *, const void *, uint);
|
||||||
|
#ifdef LAB_LOCK
|
||||||
|
int statistics(void*, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// umalloc.c
|
||||||
|
void* malloc(uint);
|
||||||
|
void free(void*);
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
OUTPUT_ARCH( "riscv" )
|
OUTPUT_ARCH( "riscv" )
|
||||||
ENTRY( _main )
|
|
||||||
|
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
@ -15,9 +13,14 @@ SECTIONS
|
|||||||
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
|
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
. = ALIGN(0x1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.eh_frame : {
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.eh_frame.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(0x1000);
|
||||||
.data : {
|
.data : {
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
|
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
|
||||||
|
|||||||
121
user/usertests.c
121
user/usertests.c
@ -32,9 +32,10 @@ char buf[BUFSZ];
|
|||||||
void
|
void
|
||||||
copyin(char *s)
|
copyin(char *s)
|
||||||
{
|
{
|
||||||
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
|
uint64 addrs[] = { 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||||
|
0xffffffffffffffff };
|
||||||
|
|
||||||
for(int ai = 0; ai < 2; ai++){
|
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||||
uint64 addr = addrs[ai];
|
uint64 addr = addrs[ai];
|
||||||
|
|
||||||
int fd = open("copyin1", O_CREATE|O_WRONLY);
|
int fd = open("copyin1", O_CREATE|O_WRONLY);
|
||||||
@ -44,7 +45,7 @@ copyin(char *s)
|
|||||||
}
|
}
|
||||||
int n = write(fd, (void*)addr, 8192);
|
int n = write(fd, (void*)addr, 8192);
|
||||||
if(n >= 0){
|
if(n >= 0){
|
||||||
printf("write(fd, %p, 8192) returned %d, not -1\n", addr, n);
|
printf("write(fd, %p, 8192) returned %d, not -1\n", (void*)addr, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -52,7 +53,7 @@ copyin(char *s)
|
|||||||
|
|
||||||
n = write(1, (char*)addr, 8192);
|
n = write(1, (char*)addr, 8192);
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
printf("write(1, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
printf("write(1, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ copyin(char *s)
|
|||||||
}
|
}
|
||||||
n = write(fds[1], (char*)addr, 8192);
|
n = write(fds[1], (char*)addr, 8192);
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
printf("write(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
printf("write(pipe, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
@ -76,9 +77,10 @@ copyin(char *s)
|
|||||||
void
|
void
|
||||||
copyout(char *s)
|
copyout(char *s)
|
||||||
{
|
{
|
||||||
uint64 addrs[] = { 0LL, 0x80000000LL, 0xffffffffffffffff };
|
uint64 addrs[] = { 0LL, 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||||
|
0xffffffffffffffff };
|
||||||
|
|
||||||
for(int ai = 0; ai < 2; ai++){
|
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||||
uint64 addr = addrs[ai];
|
uint64 addr = addrs[ai];
|
||||||
|
|
||||||
int fd = open("README", 0);
|
int fd = open("README", 0);
|
||||||
@ -88,7 +90,7 @@ copyout(char *s)
|
|||||||
}
|
}
|
||||||
int n = read(fd, (void*)addr, 8192);
|
int n = read(fd, (void*)addr, 8192);
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
printf("read(fd, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
printf("read(fd, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -105,7 +107,7 @@ copyout(char *s)
|
|||||||
}
|
}
|
||||||
n = read(fds[0], (void*)addr, 8192);
|
n = read(fds[0], (void*)addr, 8192);
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
printf("read(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
printf("read(pipe, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
@ -117,14 +119,15 @@ copyout(char *s)
|
|||||||
void
|
void
|
||||||
copyinstr1(char *s)
|
copyinstr1(char *s)
|
||||||
{
|
{
|
||||||
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
|
uint64 addrs[] = { 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||||
|
0xffffffffffffffff };
|
||||||
|
|
||||||
for(int ai = 0; ai < 2; ai++){
|
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||||
uint64 addr = addrs[ai];
|
uint64 addr = addrs[ai];
|
||||||
|
|
||||||
int fd = open((char *)addr, O_CREATE|O_WRONLY);
|
int fd = open((char *)addr, O_CREATE|O_WRONLY);
|
||||||
if(fd >= 0){
|
if(fd >= 0){
|
||||||
printf("open(%p) returned %d, not -1\n", addr, fd);
|
printf("open(%p) returned %d, not -1\n", (void*)addr, fd);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +267,7 @@ rwsbrk()
|
|||||||
}
|
}
|
||||||
n = write(fd, (void*)(a+4096), 1024);
|
n = write(fd, (void*)(a+4096), 1024);
|
||||||
if(n >= 0){
|
if(n >= 0){
|
||||||
printf("write(fd, %p, 1024) returned %d, not -1\n", a+4096, n);
|
printf("write(fd, %p, 1024) returned %d, not -1\n", (void*)a+4096, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -277,7 +280,7 @@ rwsbrk()
|
|||||||
}
|
}
|
||||||
n = read(fd, (void*)(a+4096), 10);
|
n = read(fd, (void*)(a+4096), 10);
|
||||||
if(n >= 0){
|
if(n >= 0){
|
||||||
printf("read(fd, %p, 10) returned %d, not -1\n", a+4096, n);
|
printf("read(fd, %p, 10) returned %d, not -1\n", (void*)a+4096, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -589,7 +592,7 @@ writebig(char *s)
|
|||||||
for(i = 0; i < MAXFILE; i++){
|
for(i = 0; i < MAXFILE; i++){
|
||||||
((int*)buf)[0] = i;
|
((int*)buf)[0] = i;
|
||||||
if(write(fd, buf, BSIZE) != BSIZE){
|
if(write(fd, buf, BSIZE) != BSIZE){
|
||||||
printf("%s: error: write big file failed\n", s, i);
|
printf("%s: error: write big file failed i=%d\n", s, i);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -606,7 +609,7 @@ writebig(char *s)
|
|||||||
for(;;){
|
for(;;){
|
||||||
i = read(fd, buf, BSIZE);
|
i = read(fd, buf, BSIZE);
|
||||||
if(i == 0){
|
if(i == 0){
|
||||||
if(n == MAXFILE - 1){
|
if(n != MAXFILE){
|
||||||
printf("%s: read only %d blocks from big", s, n);
|
printf("%s: read only %d blocks from big", s, n);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -773,7 +776,7 @@ pipe1(char *s)
|
|||||||
cc = sizeof(buf);
|
cc = sizeof(buf);
|
||||||
}
|
}
|
||||||
if(total != N * SZ){
|
if(total != N * SZ){
|
||||||
printf("%s: pipe1 oops 3 total %d\n", total);
|
printf("%s: pipe1 oops 3 total %d\n", s, total);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
@ -1069,7 +1072,7 @@ mem(char *s)
|
|||||||
}
|
}
|
||||||
m1 = malloc(1024*20);
|
m1 = malloc(1024*20);
|
||||||
if(m1 == 0){
|
if(m1 == 0){
|
||||||
printf("couldn't allocate mem?!!\n", s);
|
printf("%s: couldn't allocate mem?!!\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
free(m1);
|
free(m1);
|
||||||
@ -1161,14 +1164,14 @@ fourfiles(char *s)
|
|||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid < 0){
|
if(pid < 0){
|
||||||
printf("fork failed\n", s);
|
printf("%s: fork failed\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
fd = open(fname, O_CREATE | O_RDWR);
|
fd = open(fname, O_CREATE | O_RDWR);
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
printf("create failed\n", s);
|
printf("%s: create failed\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1197,7 +1200,7 @@ fourfiles(char *s)
|
|||||||
while((n = read(fd, buf, sizeof(buf))) > 0){
|
while((n = read(fd, buf, sizeof(buf))) > 0){
|
||||||
for(j = 0; j < n; j++){
|
for(j = 0; j < n; j++){
|
||||||
if(buf[j] != '0'+i){
|
if(buf[j] != '0'+i){
|
||||||
printf("wrong char\n", s);
|
printf("%s: wrong char\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1223,7 +1226,7 @@ createdelete(char *s)
|
|||||||
for(pi = 0; pi < NCHILD; pi++){
|
for(pi = 0; pi < NCHILD; pi++){
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid < 0){
|
if(pid < 0){
|
||||||
printf("fork failed\n", s);
|
printf("%s: fork failed\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1277,7 +1280,7 @@ createdelete(char *s)
|
|||||||
|
|
||||||
for(i = 0; i < N; i++){
|
for(i = 0; i < N; i++){
|
||||||
for(pi = 0; pi < NCHILD; pi++){
|
for(pi = 0; pi < NCHILD; pi++){
|
||||||
name[0] = 'p' + i;
|
name[0] = 'p' + pi;
|
||||||
name[1] = '0' + i;
|
name[1] = '0' + i;
|
||||||
unlink(name);
|
unlink(name);
|
||||||
}
|
}
|
||||||
@ -1544,7 +1547,7 @@ subdir(char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(mkdir("/dd/dd") != 0){
|
if(mkdir("/dd/dd") != 0){
|
||||||
printf("subdir mkdir dd/dd failed\n", s);
|
printf("%s: subdir mkdir dd/dd failed\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1569,7 +1572,7 @@ subdir(char *s)
|
|||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if(link("dd/dd/ff", "dd/dd/ffff") != 0){
|
if(link("dd/dd/ff", "dd/dd/ffff") != 0){
|
||||||
printf("link dd/dd/ff dd/dd/ffff failed\n", s);
|
printf("%s: link dd/dd/ff dd/dd/ffff failed\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1591,7 +1594,7 @@ subdir(char *s)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(chdir("dd/../../../dd") != 0){
|
if(chdir("dd/../../../dd") != 0){
|
||||||
printf("chdir dd/../../dd failed\n", s);
|
printf("%s: chdir dd/../../../dd failed\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(chdir("./..") != 0){
|
if(chdir("./..") != 0){
|
||||||
@ -2034,7 +2037,7 @@ sbrkbasic(char *s)
|
|||||||
for(i = 0; i < 5000; i++){
|
for(i = 0; i < 5000; i++){
|
||||||
b = sbrk(1);
|
b = sbrk(1);
|
||||||
if(b != a){
|
if(b != a){
|
||||||
printf("%s: sbrk test failed %d %x %x\n", s, i, a, b);
|
printf("%s: sbrk test failed %d %p %p\n", s, i, a, b);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
*b = 1;
|
*b = 1;
|
||||||
@ -2092,7 +2095,7 @@ sbrkmuch(char *s)
|
|||||||
}
|
}
|
||||||
c = sbrk(0);
|
c = sbrk(0);
|
||||||
if(c != a - PGSIZE){
|
if(c != a - PGSIZE){
|
||||||
printf("%s: sbrk deallocation produced wrong address, a %x c %x\n", s, a, c);
|
printf("%s: sbrk deallocation produced wrong address, a %p c %p\n", s, a, c);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2100,7 +2103,7 @@ sbrkmuch(char *s)
|
|||||||
a = sbrk(0);
|
a = sbrk(0);
|
||||||
c = sbrk(PGSIZE);
|
c = sbrk(PGSIZE);
|
||||||
if(c != a || sbrk(0) != a + PGSIZE){
|
if(c != a || sbrk(0) != a + PGSIZE){
|
||||||
printf("%s: sbrk re-allocation failed, a %x c %x\n", s, a, c);
|
printf("%s: sbrk re-allocation failed, a %p c %p\n", s, a, c);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(*lastaddr == 99){
|
if(*lastaddr == 99){
|
||||||
@ -2112,7 +2115,7 @@ sbrkmuch(char *s)
|
|||||||
a = sbrk(0);
|
a = sbrk(0);
|
||||||
c = sbrk(-(sbrk(0) - oldbrk));
|
c = sbrk(-(sbrk(0) - oldbrk));
|
||||||
if(c != a){
|
if(c != a){
|
||||||
printf("%s: sbrk downsize failed, a %x c %x\n", s, a, c);
|
printf("%s: sbrk downsize failed, a %p c %p\n", s, a, c);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2131,7 +2134,7 @@ kernmem(char *s)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
printf("%s: oops could read %x = %x\n", s, a, *a);
|
printf("%s: oops could read %p = %x\n", s, a, *a);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int xstatus;
|
int xstatus;
|
||||||
@ -2155,7 +2158,7 @@ MAXVAplus(char *s)
|
|||||||
}
|
}
|
||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
*(char*)a = 99;
|
*(char*)a = 99;
|
||||||
printf("%s: oops wrote %x\n", s, a);
|
printf("%s: oops wrote %p\n", s, (void*)a);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int xstatus;
|
int xstatus;
|
||||||
@ -2307,9 +2310,14 @@ bigargtest(char *s)
|
|||||||
if(pid == 0){
|
if(pid == 0){
|
||||||
static char *args[MAXARG];
|
static char *args[MAXARG];
|
||||||
int i;
|
int i;
|
||||||
|
char big[400];
|
||||||
|
memset(big, ' ', sizeof(big));
|
||||||
|
big[sizeof(big)-1] = '\0';
|
||||||
for(i = 0; i < MAXARG-1; i++)
|
for(i = 0; i < MAXARG-1; i++)
|
||||||
args[i] = "bigargs test: failed\n ";
|
args[i] = big;
|
||||||
args[MAXARG-1] = 0;
|
args[MAXARG-1] = 0;
|
||||||
|
// this exec() should fail (and return) because the
|
||||||
|
// arguments are too large.
|
||||||
exec("echo", args);
|
exec("echo", args);
|
||||||
fd = open("bigarg-ok", O_CREATE);
|
fd = open("bigarg-ok", O_CREATE);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -2406,9 +2414,9 @@ stacktest(char *s)
|
|||||||
pid = fork();
|
pid = fork();
|
||||||
if(pid == 0) {
|
if(pid == 0) {
|
||||||
char *sp = (char *) r_sp();
|
char *sp = (char *) r_sp();
|
||||||
sp -= PGSIZE;
|
sp -= USERSTACK*PGSIZE;
|
||||||
// the *sp should cause a trap.
|
// the *sp should cause a trap.
|
||||||
printf("%s: stacktest: read below stack %p\n", s, *sp);
|
printf("%s: stacktest: read below stack %d\n", s, *sp);
|
||||||
exit(1);
|
exit(1);
|
||||||
} else if(pid < 0){
|
} else if(pid < 0){
|
||||||
printf("%s: fork failed\n", s);
|
printf("%s: fork failed\n", s);
|
||||||
@ -2421,27 +2429,34 @@ stacktest(char *s)
|
|||||||
exit(xstatus);
|
exit(xstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that writes to text segment fault
|
// check that writes to a few forbidden addresses
|
||||||
|
// cause a fault, e.g. process's text and TRAMPOLINE.
|
||||||
void
|
void
|
||||||
textwrite(char *s)
|
nowrite(char *s)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
int xstatus;
|
int xstatus;
|
||||||
|
uint64 addrs[] = { 0, 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||||
|
0xffffffffffffffff };
|
||||||
|
|
||||||
pid = fork();
|
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||||
if(pid == 0) {
|
pid = fork();
|
||||||
volatile int *addr = (int *) 0;
|
if(pid == 0) {
|
||||||
*addr = 10;
|
volatile int *addr = (int *) addrs[ai];
|
||||||
exit(1);
|
*addr = 10;
|
||||||
} else if(pid < 0){
|
printf("%s: write to %p did not fail!\n", s, addr);
|
||||||
printf("%s: fork failed\n", s);
|
exit(0);
|
||||||
exit(1);
|
} else if(pid < 0){
|
||||||
|
printf("%s: fork failed\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
wait(&xstatus);
|
||||||
|
if(xstatus == 0){
|
||||||
|
// kernel did not kill child!
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wait(&xstatus);
|
exit(0);
|
||||||
if(xstatus == -1) // kernel killed child?
|
|
||||||
exit(0);
|
|
||||||
else
|
|
||||||
exit(xstatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// regression test. copyin(), copyout(), and copyinstr() used to cast
|
// regression test. copyin(), copyout(), and copyinstr() used to cast
|
||||||
@ -2629,7 +2644,7 @@ struct test {
|
|||||||
{bigargtest, "bigargtest"},
|
{bigargtest, "bigargtest"},
|
||||||
{argptest, "argptest"},
|
{argptest, "argptest"},
|
||||||
{stacktest, "stacktest"},
|
{stacktest, "stacktest"},
|
||||||
{textwrite, "textwrite"},
|
{nowrite, "nowrite"},
|
||||||
{pgbug, "pgbug" },
|
{pgbug, "pgbug" },
|
||||||
{sbrkbugs, "sbrkbugs" },
|
{sbrkbugs, "sbrkbugs" },
|
||||||
{sbrklast, "sbrklast"},
|
{sbrklast, "sbrklast"},
|
||||||
@ -2666,7 +2681,7 @@ bigdir(char *s)
|
|||||||
name[2] = '0' + (i % 64);
|
name[2] = '0' + (i % 64);
|
||||||
name[3] = '\0';
|
name[3] = '\0';
|
||||||
if(link("bd", name) != 0){
|
if(link("bd", name) != 0){
|
||||||
printf("%s: bigdir link(bd, %s) failed\n", s, name);
|
printf("%s: bigdir i=%d link(bd, %s) failed\n", s, i, name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2868,7 +2883,7 @@ diskfull(char *s)
|
|||||||
|
|
||||||
// this mkdir() is expected to fail.
|
// this mkdir() is expected to fail.
|
||||||
if(mkdir("diskfulldir") == 0)
|
if(mkdir("diskfulldir") == 0)
|
||||||
printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n");
|
printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n", s);
|
||||||
|
|
||||||
unlink("diskfulldir");
|
unlink("diskfulldir");
|
||||||
|
|
||||||
|
|||||||
@ -36,5 +36,10 @@ entry("getpid");
|
|||||||
entry("sbrk");
|
entry("sbrk");
|
||||||
entry("sleep");
|
entry("sleep");
|
||||||
entry("uptime");
|
entry("uptime");
|
||||||
entry("trace");
|
entry("bind");
|
||||||
entry("sysinfo");
|
entry("unbind");
|
||||||
|
entry("send");
|
||||||
|
entry("recv");
|
||||||
|
entry("pgpte");
|
||||||
|
entry("kpgtbl");
|
||||||
|
entry("pgaccess");
|
||||||
|
|||||||
Reference in New Issue
Block a user