Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"rust-analyzer.server.path": "rust-analyzer",
"rust-analyzer.linkedProjects": [
"os/Cargo.toml",
"user/init/Cargo.toml",
"user/hello/Cargo.toml"
],
"rust-analyzer.cargo.allTargets": false,
"rust-analyzer.check.allTargets": false,
"rust-analyzer.cargo.targetDir": "target/rust-analyzer",
"rust-analyzer.diagnostics.enable": false
}
59 changes: 57 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,23 @@ else
PROFILE_DIR := release
endif

# 评测内核默认启用 oscomp 特性:启动时探测双盘、把测试镜像挂到 /tests,
# 由 rootfs 的 rcS 自动跑测试并主动关机(赛题要求“自动运行 + 自动关闭”)。
# 本地交互式开发请用 `make run`(os/Makefile,不带 oscomp)。
OSCOMP_FEATURE ?= --features oscomp

# 本地复现评测用 QEMU 参数(可在命令行覆盖,如 `make run-oscomp-rv OSCOMP_RV_MEM=2G`)。
# 测试镜像默认取仓库根的 sdcard-{rv,la}.img;rootfs 用 make all 产出的 disk{,-la}.img。
TESTIMG_RV ?= sdcard-rv.img
TESTIMG_LA ?= sdcard-la.img
OSCOMP_RV_MEM ?= 4G
OSCOMP_RV_SMP ?= 1
OSCOMP_LA_MEM ?= 4G
OSCOMP_LA_SMP ?= 1

.PHONY: docker build_docker fmt run build clean clean-all gdb
.PHONY: all kernel-rv kernel-la os-cargo-config
.PHONY: run-oscomp-rv run-oscomp-la prepare-testimg-rv prepare-testimg-la

docker:
docker run --rm -it -v ${PWD}:/mnt -w /mnt --name comix ${DOCKER_TAG} bash
Expand Down Expand Up @@ -96,12 +111,12 @@ all: os-cargo-config kernel-rv kernel-la disk.img disk-la.img

kernel-rv: os-cargo-config
@echo "[OSCOMP] 构建 RISC-V 内核 (ELF, $(PROFILE_DIR)): kernel-rv"
cd $(OS_DIR) && ARCH=riscv cargo build $(CARGO_PROFILE_FLAG) --target $(RV_TARGET)
cd $(OS_DIR) && ARCH=riscv cargo build $(CARGO_PROFILE_FLAG) --target $(RV_TARGET) $(OSCOMP_FEATURE)
cp -f $(OS_DIR)/target/$(RV_TARGET)/$(PROFILE_DIR)/$(OS_BIN) kernel-rv

kernel-la: os-cargo-config
@echo "[OSCOMP] 构建 LoongArch 内核 (ELF, $(PROFILE_DIR)): kernel-la"
cd $(OS_DIR) && ARCH=loongarch cargo build $(CARGO_PROFILE_FLAG) --target $(LA_TARGET)
cd $(OS_DIR) && ARCH=loongarch cargo build $(CARGO_PROFILE_FLAG) --target $(LA_TARGET) $(OSCOMP_FEATURE)
cp -f $(OS_DIR)/target/$(LA_TARGET)/$(PROFILE_DIR)/$(OS_BIN) kernel-la

# rootfs 镜像由 os/build.rs 在对应内核构建时生成(os/fs-{arch}.img),此处拷到根目录。
Expand All @@ -115,6 +130,46 @@ disk-la.img: kernel-la
@test -f $(OS_DIR)/fs-loongarch.img
cp -f $(OS_DIR)/fs-loongarch.img disk-la.img

# ------------------------------------------------------------
# 本地复现评测:启动 QEMU,挂测试镜像(x0) + 我们的 rootfs(x1),
# 内核自动跑测试并主动关机;-no-reboot 让关机时 QEMU 退出。
# 设备型号对齐 os/qemu-run.sh(riscv: virtio-mmio)与 os/qemu-loongarch-run.sh(loongarch: pci)。
# ------------------------------------------------------------
prepare-testimg-rv:
@test -f "$(TESTIMG_RV)" || ( \
echo "[OSCOMP] 缺少 RISC-V 测试镜像: $(TESTIMG_RV)"; \
echo "[OSCOMP] 请把官方测试镜像放到该路径,或用 TESTIMG_RV=... 覆盖。"; \
exit 1; )
@echo "[OSCOMP] 使用 RISC-V 测试镜像: $(TESTIMG_RV)"

prepare-testimg-la:
@test -f "$(TESTIMG_LA)" || ( \
echo "[OSCOMP] 缺少 LoongArch 测试镜像: $(TESTIMG_LA)"; \
echo "[OSCOMP] 请把官方测试镜像放到该路径,或用 TESTIMG_LA=... 覆盖。"; \
exit 1; )
@echo "[OSCOMP] 使用 LoongArch 测试镜像: $(TESTIMG_LA)"

run-oscomp-rv: kernel-rv disk.img prepare-testimg-rv
@echo "[OSCOMP] 运行 RISC-V QEMU(测试镜像 + rootfs,自动跑测试并关机)"
qemu-system-riscv64 -machine virt -kernel kernel-rv -m $(OSCOMP_RV_MEM) -nographic \
-smp $(OSCOMP_RV_SMP) -bios default -no-reboot -rtc base=utc \
-drive file=$(TESTIMG_RV),if=none,format=raw,id=x0 \
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 \
-drive file=disk.img,if=none,format=raw,id=x1 \
-device virtio-blk-device,drive=x1,bus=virtio-mmio-bus.1 \
-device virtio-net-device,netdev=net -netdev user,id=net

run-oscomp-la: kernel-la disk-la.img prepare-testimg-la
@echo "[OSCOMP] 运行 LoongArch QEMU(测试镜像 + rootfs,自动跑测试并关机)"
qemu-system-loongarch64 -machine virt -kernel kernel-la -m $(OSCOMP_LA_MEM) -nographic \
-smp $(OSCOMP_LA_SMP) -no-reboot -rtc base=utc \
-drive file=$(TESTIMG_LA),if=none,format=raw,id=x0 \
-device virtio-blk-pci,drive=x0 \
-drive file=disk-la.img,if=none,format=raw,id=x1 \
-device virtio-blk-pci,drive=x1 \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::5555-:5555,hostfwd=udp::5555-:5555

# 清理 OS 构建产物
clean:
cd os && cargo clean
Expand Down
77 changes: 77 additions & 0 deletions data/loongarch_musl/etc/init.d/rcS
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,82 @@ echo "Mounting file systems via fstab..."

echo "System initialization finished."

run_oscomp_tests_if_present() {
# 评测测试镜像由内核挂到 /tests(init_oscomp_filesystems())。
# 检测到官方测试脚本就非交互地依次执行,跑完主动关机。
[ -d /tests ] || return 1

# 官方测试二进制硬编码了 ELF 解释器路径(如 /lib64/ld-linux-*.so.*)。
# 我们是 musl rootfs,把测试镜像里的 glibc loader/库软链到常见 ABI libdir 以便加载。
if [ -d /tests/glibc/lib ]; then
[ -d /lib ] || /bin/mkdir -p /lib
[ -d /lib64 ] || /bin/mkdir -p /lib64
for f in /tests/glibc/lib/ld-linux-*.so.*; do
[ -f "$f" ] || continue
base="${f##*/}"
/bin/ln -sf "$f" "/lib/$base"
/bin/ln -sf "$f" "/lib64/$base"
done
for base in libc.so.6 libm.so.6 libpthread.so.0 libdl.so.2 librt.so.1 libresolv.so.2; do
if [ -f "/tests/glibc/lib/$base" ]; then
/bin/ln -sf "/tests/glibc/lib/$base" "/lib/$base"
/bin/ln -sf "/tests/glibc/lib/$base" "/lib64/$base"
fi
done
Comment thread
a6d9a6m marked this conversation as resolved.
fi

scripts=""
add_script() {
# 简单去重,避免 VFS 把 /tests 暴露成 /tests/tests 之类的病态情况。
case " $scripts " in
*" $1 "*) return 0 ;;
esac
scripts="$scripts $1"
}

# 1) /tests 根下的脚本。
for f in /tests/*_testcode.sh; do
[ -f "$f" ] || continue
add_script "$f"
done

# 2) 下一层:/tests/*/*,匹配官方镜像布局 /tests/glibc/*.sh、/tests/musl/*.sh。
for d in /tests/*; do
[ -d "$d" ] || continue
[ "$d" = "/tests/tests" ] && continue
for f in "$d"/*_testcode.sh; do
[ -f "$f" ] || continue
add_script "$f"
done
done
[ -n "$scripts" ] || return 1

echo "[OSCOMP] detected test scripts under /tests; running in rcS"
export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/tests"
export HOME="/"

for f in $scripts; do
dir="${f%/*}"
base="${f##*/}"
echo "[OSCOMP] running $f"
(
cd "$dir" || exit 1
# 用 "." 执行避免依赖内核 shebang/ENOEXEC 行为;重定向 stdin 避免阻塞。
. "./$base" </dev/null
)
rc=$?
echo "[OSCOMP] finished $f (rc=$rc)"
done

echo "[OSCOMP] all tests finished; powering off"
/sbin/poweroff -f || /sbin/reboot -f || true
echo "[OSCOMP] poweroff returned unexpectedly; sleeping"
while true; do sleep 3600; done
}

if run_oscomp_tests_if_present; then
exit 0
fi

echo "rcS finished; spawning shell on ttyS0 via inittab"
exit 0
74 changes: 74 additions & 0 deletions data/risc-v_musl/etc/init.d/rcS
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,79 @@ echo "Mounting file systems via fstab..."

echo "System initialization finished."

run_oscomp_tests_if_present() {
# 评测测试镜像由内核挂到 /tests(init_oscomp_filesystems())。
# 检测到官方测试脚本就非交互地依次执行,跑完主动关机。
[ -d /tests ] || return 1

# 官方测试二进制硬编码了 ELF 解释器路径(如 /lib/ld-linux-*.so.*)。
# 我们是 musl rootfs,把测试镜像里的 glibc loader/库软链到 /lib 以便加载。
if [ -d /tests/glibc/lib ]; then
[ -d /lib ] || /bin/mkdir -p /lib
for f in /tests/glibc/lib/ld-linux-*.so.*; do
[ -f "$f" ] || continue
base="${f##*/}"
/bin/ln -sf "$f" "/lib/$base"
done
for base in libc.so.6 libm.so.6 libpthread.so.0 libdl.so.2 librt.so.1 libresolv.so.2; do
if [ -f "/tests/glibc/lib/$base" ]; then
/bin/ln -sf "/tests/glibc/lib/$base" "/lib/$base"
fi
done
Comment thread
a6d9a6m marked this conversation as resolved.
fi

scripts=""
add_script() {
# 简单去重,避免 VFS 把 /tests 暴露成 /tests/tests 之类的病态情况。
case " $scripts " in
*" $1 "*) return 0 ;;
esac
scripts="$scripts $1"
}

# 1) /tests 根下的脚本。
for f in /tests/*_testcode.sh; do
[ -f "$f" ] || continue
add_script "$f"
done

# 2) 下一层:/tests/*/*,匹配官方镜像布局 /tests/glibc/*.sh、/tests/musl/*.sh。
for d in /tests/*; do
[ -d "$d" ] || continue
[ "$d" = "/tests/tests" ] && continue
for f in "$d"/*_testcode.sh; do
[ -f "$f" ] || continue
add_script "$f"
done
done
[ -n "$scripts" ] || return 1

echo "[OSCOMP] detected test scripts under /tests; running in rcS"
export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/tests"
export HOME="/"

for f in $scripts; do
dir="${f%/*}"
base="${f##*/}"
echo "[OSCOMP] running $f"
(
cd "$dir" || exit 1
# 用 "." 执行避免依赖内核 shebang/ENOEXEC 行为;重定向 stdin 避免阻塞。
. "./$base" </dev/null
)
rc=$?
echo "[OSCOMP] finished $f (rc=$rc)"
done

echo "[OSCOMP] all tests finished; powering off"
/sbin/poweroff -f || /sbin/reboot -f || true
echo "[OSCOMP] poweroff returned unexpectedly; sleeping"
while true; do sleep 3600; done
}

if run_oscomp_tests_if_present; then
exit 0
fi

echo "rcS finished; spawning shell on ttyS0 via inittab"
exit 0
4 changes: 4 additions & 0 deletions os/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ fs = ["proc", "device", "dep:ext4_rs"]
proc_vm = ["paging", "fs"]
net = ["sync", "device", "dep:smoltcp"]
proto-ipv6 = []
# oscomp: 评测模式。启用后内核在启动时探测双盘(rootfs + 评测测试镜像),
# 把测试镜像挂到 /tests,由 rootfs 的 rcS 自动跑测试并主动关机。
# 不启用时保持原有单盘启动 + 交互式 shell 的本地开发行为。
oscomp = []

# RISC-V 架构特定依赖
[target.'cfg(target_arch = "riscv64")'.dependencies]
Expand Down
Loading
Loading