From e80796eb827de1201d51de10a60a82b29905398d Mon Sep 17 00:00:00 2001 From: LoGin Date: Sun, 20 Apr 2025 18:51:45 +0800 Subject: [PATCH] feat: la64 boot (#1132) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * la64能够进入到kernel_main * ci: 添加为ubuntu编译qemu-loongarch64的脚本 * feat: la64能输出hello world * la64 安装gcc && 配置github ci * chore: 更新CI工作流和构建脚本中的Docker镜像版本至v1.10 Signed-off-by: longjin --- .github/workflows/makefile.yml | 70 ++-- .vscode/settings.json | 1 + Makefile | 2 + .../src/bindgen/arch/loongarch64.rs | 10 + .../src/cfiles/arch/loongarch64.rs | 29 ++ .../kernel_build/src/cfiles/arch/mod.rs | 3 + build-scripts/kernel_build/src/constant.rs | 5 + build-scripts/kernel_build/src/lib.rs | 1 + .../kernel_build/src/utils/cargo_handler.rs | 2 + build-scripts/kernel_build/src/utils/mod.rs | 50 +++ dadk-manifest.toml | 2 +- env.mk | 3 +- kernel/Cargo.lock | 31 +- kernel/Cargo.toml | 22 +- kernel/Makefile | 4 + .../crates/kprobe/src/arch/loongarch64/mod.rs | 2 + kernel/env.mk | 6 + kernel/src/Makefile | 39 ++- kernel/src/arch/loongarch64/asm/bitops.rs | 14 + kernel/src/arch/loongarch64/asm/boot.rs | 98 ++++++ kernel/src/arch/loongarch64/asm/mod.rs | 2 + kernel/src/arch/loongarch64/cpu.rs | 15 + kernel/src/arch/loongarch64/elf.rs | 10 + kernel/src/arch/loongarch64/include/asm/asm.h | 1 + kernel/src/arch/loongarch64/init/boot.rs | 54 +++ kernel/src/arch/loongarch64/init/mod.rs | 24 ++ kernel/src/arch/loongarch64/interrupt/ipi.rs | 6 + kernel/src/arch/loongarch64/interrupt/mod.rs | 123 +++++++ kernel/src/arch/loongarch64/ipc/mod.rs | 1 + kernel/src/arch/loongarch64/ipc/signal.rs | 64 ++++ kernel/src/arch/loongarch64/kprobe.rs | 19 ++ kernel/src/arch/loongarch64/link.ld | 104 ++++++ .../loongarch64/loongarch64-unknown-none.json | 21 ++ kernel/src/arch/loongarch64/mm/bump.rs | 7 + kernel/src/arch/loongarch64/mm/mod.rs | 207 ++++++++++++ kernel/src/arch/loongarch64/mod.rs | 30 ++ kernel/src/arch/loongarch64/msi.rs | 24 ++ kernel/src/arch/loongarch64/pci/mod.rs | 20 ++ kernel/src/arch/loongarch64/pio.rs | 35 ++ kernel/src/arch/loongarch64/process/idle.rs | 31 ++ .../src/arch/loongarch64/process/kthread.rs | 27 ++ kernel/src/arch/loongarch64/process/mod.rs | 90 +++++ .../src/arch/loongarch64/process/syscall.rs | 28 ++ kernel/src/arch/loongarch64/rand.rs | 5 + kernel/src/arch/loongarch64/sched.rs | 17 + kernel/src/arch/loongarch64/smp/mod.rs | 29 ++ kernel/src/arch/loongarch64/syscall/mod.rs | 8 + kernel/src/arch/loongarch64/syscall/nr.rs | 307 ++++++++++++++++++ kernel/src/arch/loongarch64/time.rs | 24 ++ kernel/src/arch/mod.rs | 5 + kernel/src/arch/riscv64/ipc/signal.rs | 4 +- kernel/src/arch/riscv64/rand.rs | 14 +- kernel/src/debug/panic/hook.rs | 24 +- kernel/src/debug/panic/mod.rs | 3 + kernel/src/driver/serial/serial8250/mod.rs | 15 +- .../serial/serial8250/serial8250_la64.rs | 69 ++++ kernel/src/driver/video/mod.rs | 2 +- kernel/src/init/boot.rs | 4 +- kernel/src/init/init.rs | 1 + kernel/src/ipc/generic_signal.rs | 206 ++++++++++++ kernel/src/ipc/mod.rs | 1 + kernel/src/lib.rs | 5 +- kernel/src/libs/elf.rs | 22 +- kernel/src/libs/rand.rs | 16 + kernel/src/libs/rwlock.rs | 3 - kernel/src/mm/mmio_buddy.rs | 1 - kernel/src/mm/page.rs | 25 ++ kernel/src/mm/percpu.rs | 3 + kernel/src/process/idle.rs | 5 + kernel/src/process/syscall.rs | 3 + kernel/src/sched/clock.rs | 2 +- kernel/src/syscall/mod.rs | 7 +- kernel/src/time/mod.rs | 2 +- tools/.gitignore | 1 + tools/BUILD_CONTAINER_VERSION | 2 +- tools/bootstrap.sh | 9 +- tools/build_gcc_toolchain.sh | 0 tools/build_in_docker.sh | 2 +- tools/change_rust_src.sh | 0 tools/check_arch.sh | 0 tools/configure_network.sh | 0 tools/docker-entrypoint.sh | 0 tools/dump_kernel.sh | 0 tools/grub_auto_install.sh | 0 tools/init_rust_toolchain.sh | 0 ...stall_musl_gcc.sh => install_cross_gcc.sh} | 32 +- tools/qemu/.gitignore | 3 + tools/qemu/build-qemu-la64-for-ubuntu.sh | 155 +++++++++ tools/run-qemu.sh | 38 ++- tools/write_disk_image.sh | 0 user/Makefile | 6 +- 91 files changed, 2299 insertions(+), 118 deletions(-) create mode 100644 build-scripts/kernel_build/src/bindgen/arch/loongarch64.rs create mode 100644 build-scripts/kernel_build/src/cfiles/arch/loongarch64.rs create mode 100644 build-scripts/kernel_build/src/constant.rs create mode 100644 kernel/src/arch/loongarch64/asm/bitops.rs create mode 100644 kernel/src/arch/loongarch64/asm/boot.rs create mode 100644 kernel/src/arch/loongarch64/asm/mod.rs create mode 100644 kernel/src/arch/loongarch64/cpu.rs create mode 100644 kernel/src/arch/loongarch64/elf.rs create mode 100644 kernel/src/arch/loongarch64/include/asm/asm.h create mode 100644 kernel/src/arch/loongarch64/init/boot.rs create mode 100644 kernel/src/arch/loongarch64/init/mod.rs create mode 100644 kernel/src/arch/loongarch64/interrupt/ipi.rs create mode 100644 kernel/src/arch/loongarch64/interrupt/mod.rs create mode 100644 kernel/src/arch/loongarch64/ipc/mod.rs create mode 100644 kernel/src/arch/loongarch64/ipc/signal.rs create mode 100644 kernel/src/arch/loongarch64/kprobe.rs create mode 100644 kernel/src/arch/loongarch64/link.ld create mode 100644 kernel/src/arch/loongarch64/loongarch64-unknown-none.json create mode 100644 kernel/src/arch/loongarch64/mm/bump.rs create mode 100644 kernel/src/arch/loongarch64/mm/mod.rs create mode 100644 kernel/src/arch/loongarch64/mod.rs create mode 100644 kernel/src/arch/loongarch64/msi.rs create mode 100644 kernel/src/arch/loongarch64/pci/mod.rs create mode 100644 kernel/src/arch/loongarch64/pio.rs create mode 100644 kernel/src/arch/loongarch64/process/idle.rs create mode 100644 kernel/src/arch/loongarch64/process/kthread.rs create mode 100644 kernel/src/arch/loongarch64/process/mod.rs create mode 100644 kernel/src/arch/loongarch64/process/syscall.rs create mode 100644 kernel/src/arch/loongarch64/rand.rs create mode 100644 kernel/src/arch/loongarch64/sched.rs create mode 100644 kernel/src/arch/loongarch64/smp/mod.rs create mode 100644 kernel/src/arch/loongarch64/syscall/mod.rs create mode 100644 kernel/src/arch/loongarch64/syscall/nr.rs create mode 100644 kernel/src/arch/loongarch64/time.rs create mode 100644 kernel/src/driver/serial/serial8250/serial8250_la64.rs create mode 100644 kernel/src/ipc/generic_signal.rs mode change 100644 => 100755 tools/bootstrap.sh mode change 100644 => 100755 tools/build_gcc_toolchain.sh mode change 100644 => 100755 tools/build_in_docker.sh mode change 100644 => 100755 tools/change_rust_src.sh mode change 100644 => 100755 tools/check_arch.sh mode change 100644 => 100755 tools/configure_network.sh mode change 100644 => 100755 tools/docker-entrypoint.sh mode change 100644 => 100755 tools/dump_kernel.sh mode change 100644 => 100755 tools/grub_auto_install.sh mode change 100644 => 100755 tools/init_rust_toolchain.sh rename tools/{install_musl_gcc.sh => install_cross_gcc.sh} (75%) mode change 100644 => 100755 create mode 100644 tools/qemu/.gitignore create mode 100755 tools/qemu/build-qemu-la64-for-ubuntu.sh mode change 100644 => 100755 tools/run-qemu.sh mode change 100644 => 100755 tools/write_disk_image.sh diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index f2696215..614637a9 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -11,14 +11,14 @@ jobs: name: Format check ${{ matrix.arch }} runs-on: ubuntu-latest continue-on-error: true - container: dragonos/dragonos-dev:v1.9 + container: dragonos/dragonos-dev:v1.10 strategy: matrix: - arch: [x86_64, riscv64] + arch: [x86_64, riscv64, loongarch64] steps: - - run: echo "Running in dragonos/dragonos-dev:v1.9" + - run: echo "Running in dragonos/dragonos-dev:v1.10" - uses: actions/checkout@v3 - name: Format check @@ -35,14 +35,14 @@ jobs: name: Kernel static test ${{ matrix.arch }} runs-on: ubuntu-latest continue-on-error: true - container: dragonos/dragonos-dev:v1.9 + container: dragonos/dragonos-dev:v1.10 strategy: matrix: - arch: [x86_64, riscv64] + arch: [x86_64, riscv64, loongarch64] steps: - - run: echo "Running in dragonos/dragonos-dev:v1.9" + - run: echo "Running in dragonos/dragonos-dev:v1.10" - uses: actions/checkout@v3 @@ -53,46 +53,40 @@ jobs: HOME: /root run: bash -c "source /root/.cargo/env && cd kernel && make test && make test-rbpf" - build-x86_64: + build: + name: Build ${{ matrix.arch }} runs-on: ubuntu-latest - container: dragonos/dragonos-dev:v1.9 + container: dragonos/dragonos-dev:v1.10 + strategy: + matrix: + include: + - arch: x86_64 + make_target: all + checkout_params: {} + - arch: riscv64 + make_target: all + checkout_params: + submodules: "recursive" + - arch: loongarch64 + make_target: all + checkout_params: {} steps: - - run: echo "Running in dragonos/dragonos-dev:v1.9" - + - run: echo "Running in dragonos/dragonos-dev:v1.10" + - uses: actions/checkout@v3 - - name: build the DragonOS + with: ${{ matrix.checkout_params }} + + - name: Build the DragonOS env: - ARCH: x86_64 + ARCH: ${{ matrix.arch }} HOME: /root shell: bash -ileo pipefail {0} - run: | source ~/.bashrc source ~/.cargo/env - export DragonOS_GCC=$HOME/opt/dragonos-gcc/gcc-x86_64-unknown-none/bin + if [[ "$ARCH" == "x86_64" ]]; then + export DragonOS_GCC=$HOME/opt/dragonos-gcc/gcc-x86_64-unknown-none/bin + fi sed -i 's/arch = ".*"/arch = "${{ env.ARCH }}"/' dadk-manifest.toml - - make all -j $(nproc) - - build-riscv64: - runs-on: ubuntu-latest - container: dragonos/dragonos-dev:v1.9 - - steps: - - run: echo "Running in dragonos/dragonos-dev:v1.9" - - - uses: actions/checkout@v3 - with: - submodules: "recursive" - - - name: build the DragonOS - shell: bash -ileo pipefail {0} - env: - ARCH: riscv64 - HOME: /root - - run: | - source ~/.bashrc && source ~/.cargo/env - sed -i 's/arch = ".*"/arch = "${{ env.ARCH }}"/' dadk-manifest.toml - make kernel -j $(nproc) + make ${{ matrix.make_target }} -j $(nproc) diff --git a/.vscode/settings.json b/.vscode/settings.json index a7a140db..e422ff23 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "./kernel/Cargo.toml", //"./tools/Cargo.toml", ], + // "rust-analyzer.cargo.target": "loongarch64-unknown-none", // "rust-analyzer.cargo.target": "riscv64gc-unknown-none-elf", "rust-analyzer.cargo.target": "x86_64-unknown-none", "rust-analyzer.check.overrideCommand": [ diff --git a/Makefile b/Makefile index fe38c3c5..83254388 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,8 @@ clean-docs: gdb: ifeq ($(ARCH), x86_64) rust-gdb -n -x tools/.gdbinit +else ifeq ($(ARCH), loongarch64) + loongarch64-unknown-linux-gnu-gdb -n -x tools/.gdbinit else gdb-multiarch -n -x tools/.gdbinit endif diff --git a/build-scripts/kernel_build/src/bindgen/arch/loongarch64.rs b/build-scripts/kernel_build/src/bindgen/arch/loongarch64.rs new file mode 100644 index 00000000..ef458970 --- /dev/null +++ b/build-scripts/kernel_build/src/bindgen/arch/loongarch64.rs @@ -0,0 +1,10 @@ +use super::BindgenArch; + +pub struct LoongArch64BindgenArch; +impl BindgenArch for LoongArch64BindgenArch { + fn generate_bindings(&self, builder: bindgen::Builder) -> bindgen::Builder { + builder + .clang_arg("-I./src/arch/loongarch64/include") + .clang_arg("--target=x86_64-none-none") // 由于clang不支持loongarch64,所以使用x86_64作为目标,按理来说问题不大 + } +} diff --git a/build-scripts/kernel_build/src/cfiles/arch/loongarch64.rs b/build-scripts/kernel_build/src/cfiles/arch/loongarch64.rs new file mode 100644 index 00000000..d07c7879 --- /dev/null +++ b/build-scripts/kernel_build/src/cfiles/arch/loongarch64.rs @@ -0,0 +1,29 @@ +use std::{collections::HashSet, path::PathBuf}; + +use crate::constant::ARCH_DIR_LOONGARCH64; + +use super::CFilesArch; + +pub(super) struct LoongArch64CFilesArch; + +impl CFilesArch for LoongArch64CFilesArch { + fn setup_defines(&self, c: &mut cc::Build) { + c.define("__loongarch64__", None); + c.define("__loongarch", None); + } + + fn setup_files(&self, _c: &mut cc::Build, _files: &mut HashSet) {} + + fn setup_global_flags(&self, c: &mut cc::Build) { + // 在这里设置编译器,不然的话vscode的rust-analyzer会报错 + c.compiler("loongarch64-unknown-linux-gnu-gcc"); + c.flag("-mcmodel=normal"); + + c.flag("-march=loongarch64"); + } +} + +#[allow(dead_code)] +fn arch_path(relative_path: &str) -> PathBuf { + PathBuf::from(format!("{}/{}", ARCH_DIR_LOONGARCH64, relative_path)) +} diff --git a/build-scripts/kernel_build/src/cfiles/arch/mod.rs b/build-scripts/kernel_build/src/cfiles/arch/mod.rs index a26b553d..a8fa7212 100644 --- a/build-scripts/kernel_build/src/cfiles/arch/mod.rs +++ b/build-scripts/kernel_build/src/cfiles/arch/mod.rs @@ -6,6 +6,7 @@ use crate::utils::cargo_handler::{CargoHandler, TargetArch}; use self::x86_64::X86_64CFilesArch; +pub mod loongarch64; pub mod riscv64; pub mod x86_64; @@ -24,6 +25,8 @@ pub(super) fn current_cfiles_arch() -> &'static dyn CFilesArch { match arch { TargetArch::X86_64 => &X86_64CFilesArch, TargetArch::Riscv64 => &riscv64::RiscV64CFilesArch, + TargetArch::LoongArch64 => &loongarch64::LoongArch64CFilesArch, + _ => panic!("Unsupported arch: {:?}", arch), } } diff --git a/build-scripts/kernel_build/src/constant.rs b/build-scripts/kernel_build/src/constant.rs new file mode 100644 index 00000000..10f14a20 --- /dev/null +++ b/build-scripts/kernel_build/src/constant.rs @@ -0,0 +1,5 @@ +#[allow(dead_code)] +pub const ARCH_DIR_X86_64: &str = "src/arch/x86_64"; +#[allow(dead_code)] +pub const ARCH_DIR_RISCV64: &str = "src/arch/riscv64"; +pub const ARCH_DIR_LOONGARCH64: &str = "src/arch/loongarch64"; diff --git a/build-scripts/kernel_build/src/lib.rs b/build-scripts/kernel_build/src/lib.rs index f747282c..75f11386 100644 --- a/build-scripts/kernel_build/src/lib.rs +++ b/build-scripts/kernel_build/src/lib.rs @@ -3,6 +3,7 @@ extern crate lazy_static; extern crate cc; mod cfiles; +mod constant; mod kconfig; mod utils; diff --git a/build-scripts/kernel_build/src/utils/cargo_handler.rs b/build-scripts/kernel_build/src/utils/cargo_handler.rs index 7d196c2f..8f496ba6 100644 --- a/build-scripts/kernel_build/src/utils/cargo_handler.rs +++ b/build-scripts/kernel_build/src/utils/cargo_handler.rs @@ -68,6 +68,7 @@ pub enum TargetArch { Riscv64, Mips64, Powerpc64, + LoongArch64, S390x, Sparc64, Unknown, @@ -85,6 +86,7 @@ impl TargetArch { "riscv64" => TargetArch::Riscv64, "mips64" => TargetArch::Mips64, "powerpc64" => TargetArch::Powerpc64, + "loongarch64" => TargetArch::LoongArch64, "s390x" => TargetArch::S390x, "sparc64" => TargetArch::Sparc64, _ => TargetArch::Unknown, diff --git a/build-scripts/kernel_build/src/utils/mod.rs b/build-scripts/kernel_build/src/utils/mod.rs index 741d8ef3..5c56e689 100644 --- a/build-scripts/kernel_build/src/utils/mod.rs +++ b/build-scripts/kernel_build/src/utils/mod.rs @@ -1 +1,51 @@ +use std::path::PathBuf; + pub mod cargo_handler; + +#[allow(dead_code)] +pub struct FileUtils; + +#[allow(dead_code)] +impl FileUtils { + /// 列出指定目录下的所有文件 + /// + /// ## 参数 + /// + /// - `path` - 指定的目录 + /// - `ext_name` - 文件的扩展名,如果为None,则列出所有文件 + /// - `recursive` - 是否递归列出所有文件 + pub fn list_all_files(path: &PathBuf, ext_name: Option<&str>, recursive: bool) -> Vec { + let mut queue: Vec = Vec::new(); + let mut result = Vec::new(); + queue.push(path.clone()); + + while !queue.is_empty() { + let path = queue.pop().unwrap(); + let d = std::fs::read_dir(path); + if d.is_err() { + continue; + } + let d = d.unwrap(); + + d.for_each(|ent| { + if let Ok(ent) = ent { + if let Ok(file_type) = ent.file_type() { + if file_type.is_file() { + if let Some(e) = ext_name { + if let Some(ext) = ent.path().extension() { + if ext == e { + result.push(ent.path()); + } + } + } + } else if file_type.is_dir() && recursive { + queue.push(ent.path()); + } + } + } + }); + } + + return result; + } +} diff --git a/dadk-manifest.toml b/dadk-manifest.toml index bbb88120..bafabac4 100644 --- a/dadk-manifest.toml +++ b/dadk-manifest.toml @@ -1,7 +1,7 @@ # DADK 总控文件 [metadata] -# Target architecture. Options: x86_64, riscv64 +# Target architecture. Options: x86_64, riscv64, loongarch64 arch = "x86_64" # Hypervisor config path diff --git a/env.mk b/env.mk index facd546e..e499d50b 100644 --- a/env.mk +++ b/env.mk @@ -1,6 +1,7 @@ ifeq ($(ARCH), ) -# !!!!在这里设置ARCH,可选 x86_64 和 riscv64 +# !!!!在这里设置ARCH,可选: +# x86_64, riscv64, loongarch64 # !!!!!!!如果不同时调整这里以及vscode的settings.json,那么自动补全和检查将会失效 export ARCH?=x86_64 endif diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 33bc6034..0588552d 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -361,22 +361,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" -[[package]] -name = "cstr_core" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd98742e4fdca832d40cab219dc2e3048de17d873248f83f17df47c1bea70956" -dependencies = [ - "cty", - "memchr", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - [[package]] name = "defer" version = "0.2.1" @@ -465,6 +449,7 @@ dependencies = [ "lazy_static", "linkme", "log", + "loongArch64", "lru", "multiboot2", "num", @@ -872,6 +857,15 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "loongArch64" +version = "0.2.4" +source = "git+https://github.com/fslongjin/loongArch64?rev=7af150e#7af150e01e7ce3139f519578751c95bbdaf4fb4d" +dependencies = [ + "bit_field", + "bitflags 1.3.2", +] + [[package]] name = "lru" version = "0.12.5" @@ -1089,12 +1083,9 @@ dependencies = [ [[package]] name = "printf-compat" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b002af28ffe3d3d67202ae717810a28125a494d5396debc43de01ee136ac404" +source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/printf-compat?rev=5f5c9cc363#5f5c9cc363f047411a0dccb37e0efb452ffb61d9" dependencies = [ "bitflags 1.3.2", - "cstr_core", - "cty", "itertools", ] diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index f78dd0ae..822aaba2 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -73,18 +73,14 @@ kprobe = { path = "crates/kprobe" } lru = "0.12.3" rbpf = { path = "crates/rbpf" } -printf-compat = { version = "0.1.1", default-features = false } +printf-compat = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/printf-compat", rev = "5f5c9cc363", default-features = false } static-keys = "=0.6.1" -unwinding = { version = "=0.2.3", default-features = false, features = [ - "unwinder", - "fde-gnu-eh-frame-hdr", - "panic", - "personality", -] } + defer = "0.2.1" cfg-if = { version = "1.0.0" } + # target为x86_64时,使用下面的依赖 [target.'cfg(target_arch = "x86_64")'.dependencies] multiboot2 = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/multiboot2", rev = "05739aab40" } @@ -99,6 +95,18 @@ riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.gi ] } sbi-rt = { version = "=0.0.3", features = ["legacy"] } +# target为loongarch64时,使用下面的依赖 +[target.'cfg(target_arch = "loongarch64")'.dependencies] +loongArch64 = { git = "https://github.com/fslongjin/loongArch64", rev = "7af150e" } + +# 由于unwinding库不支持loongarch64架构,因此需要排除该依赖项 +[target.'cfg(not(target_arch = "loongarch64"))'.dependencies] +unwinding = { version = "=0.2.3", default-features = false, features = [ + "unwinder", + "fde-gnu-eh-frame-hdr", + "panic", + "personality", +] } # 构建时依赖项 [build-dependencies] diff --git a/kernel/Makefile b/kernel/Makefile index 6208a17c..9c71c07f 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -7,6 +7,10 @@ ifeq ($(ARCH), x86_64) export TARGET_JSON=arch/x86_64/x86_64-unknown-none.json else ifeq ($(ARCH), riscv64) export TARGET_JSON=arch/riscv64/riscv64gc-unknown-none-elf.json +else ifeq ($(ARCH), loongarch64) + export TARGET_JSON=arch/loongarch64/loongarch64-unknown-none.json +else + $(error "Unsupported ARCH: $(ARCH)") endif export CARGO_ZBUILD=-Z build-std=core,alloc,compiler_builtins -Z build-std-features=compiler-builtins-mem diff --git a/kernel/crates/kprobe/src/arch/loongarch64/mod.rs b/kernel/crates/kprobe/src/arch/loongarch64/mod.rs index 263e7cd7..e05f283d 100644 --- a/kernel/crates/kprobe/src/arch/loongarch64/mod.rs +++ b/kernel/crates/kprobe/src/arch/loongarch64/mod.rs @@ -77,6 +77,7 @@ impl KprobeBuilder { }; let inst_tmp_ptr = point.inst_tmp.as_ptr() as usize; let inst_32 = unsafe { core::ptr::read(address as *const u32) }; + unsafe { core::ptr::write(address as *mut u32, EBREAK_INST); // inst_32 :0-32 @@ -90,6 +91,7 @@ impl KprobeBuilder { self.symbol, inst_32 ); + Arc::new(point) } } diff --git a/kernel/env.mk b/kernel/env.mk index 26295881..42a645a7 100644 --- a/kernel/env.mk +++ b/kernel/env.mk @@ -5,6 +5,10 @@ ifeq ($(ARCH), x86_64) CCPREFIX=x86_64-linux-gnu- else ifeq ($(ARCH), riscv64) CCPREFIX=riscv64-linux-gnu- +else ifeq ($(ARCH), loongarch64) +CCPREFIX=loongarch64-unknown-linux-gnu- +else +$(error "Unsupported ARCH: $(ARCH)") endif export CC=$(CCPREFIX)gcc @@ -24,6 +28,8 @@ ifeq ($(ARCH), x86_64) GLOBAL_CFLAGS += -mcmodel=large -m64 else ifeq ($(ARCH), riscv64) GLOBAL_CFLAGS += -mcmodel=medany -march=rv64gc -mabi=lp64d +else ifeq ($(ARCH), loongarch64) +GLOBAL_CFLAGS += -mcmodel=large -march=loongarch64 endif ifeq ($(DEBUG), DEBUG) diff --git a/kernel/src/Makefile b/kernel/src/Makefile index ab09433e..b8895d68 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -10,17 +10,20 @@ LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns))) # unwind/backtrace related UNWIND_ENABLE ?= yes + +ifeq ($(ARCH), loongarch64) + UNWIND_ENABLE = no +endif + CFLAGS_UNWIND = LDFLAGS_UNWIND = RUSTFLAGS_UNWIND = ifeq ($(UNWIND_ENABLE), yes) CFLAGS_UNWIND = -funwind-tables LDFLAGS_UNWIND = --eh-frame-hdr - RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld -Cpanic=unwind + RUSTFLAGS += -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld -Cpanic=unwind endif -RUSTFLAGS += $(RUSTFLAGS_UNWIND) - CFLAGS = $(GLOBAL_CFLAGS) -fno-pie $(CFLAGS_UNWIND) -I $(shell pwd) -I $(shell pwd)/include ifeq ($(ARCH), x86_64) @@ -48,6 +51,10 @@ ifeq ($(ARCH), x86_64) $(MAKE) __link_x86_64_kernel else ifeq ($(ARCH), riscv64) $(MAKE) __link_riscv64_kernel +else ifeq ($(ARCH), loongarch64) + $(MAKE) __link_loongarch64_kernel +else + $(error Unknown ARCH: $(ARCH)) endif @echo "Kernel Build Done." @@ -113,6 +120,32 @@ else endif rm kernel + +__link_loongarch64_kernel: + @echo "Linking kernel..." + $(LD) -b elf64-loongarch -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/loongarch64-unknown-none/release/libdragonos_kernel.a -T arch/loongarch64/link.ld --no-relax +# 生成kallsyms + current_dir=$(pwd) + + @dbg='debug';for x in $$dbg; do \ + cd $$x;\ + $(MAKE) generate_kallsyms kernel_root_path="$(shell pwd)"||exit 1;\ + cd ..;\ + done + +# 重新链接 + @echo "Re-Linking kernel..." + @echo $(shell find . -name "*.o") + $(LD) -b elf64-loongarch -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/loongarch64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T arch/loongarch64/link.ld --no-relax + @echo "Generating kernel ELF file..." +# 生成内核文件 +ifeq ($(UNWIND_ENABLE), yes) + $(OBJCOPY) -I elf64-loongarch -O elf64-loongarch kernel ../../bin/kernel/kernel.elf +else + $(OBJCOPY) -I elf64-loongarch -O elf64-loongarch -R ".eh_frame" kernel ../../bin/kernel/kernel.elf +endif + rm kernel + __dragon_stub: @echo "Linking dragon_stub..." @mkdir -p $(ROOT_PATH)/bin/sysroot diff --git a/kernel/src/arch/loongarch64/asm/bitops.rs b/kernel/src/arch/loongarch64/asm/bitops.rs new file mode 100644 index 00000000..d5d570cd --- /dev/null +++ b/kernel/src/arch/loongarch64/asm/bitops.rs @@ -0,0 +1,14 @@ +/// 寻找u64中的第一个0所在的位(从第0位开始寻找) +/// +/// 注意:如果x中没有0,那么结果将是未定义的。请确保传入的x至少存在1个0 +/// +/// # 参数 +/// * `x` - 目标u64 +/// +/// # 返回值 +/// 第一个(最低有效位)0位的位号(0..63) +#[inline] +#[allow(dead_code)] +pub fn ffz(x: u64) -> i32 { + (!x).trailing_zeros() as i32 +} diff --git a/kernel/src/arch/loongarch64/asm/boot.rs b/kernel/src/arch/loongarch64/asm/boot.rs new file mode 100644 index 00000000..f781bd0f --- /dev/null +++ b/kernel/src/arch/loongarch64/asm/boot.rs @@ -0,0 +1,98 @@ +/// +/// The earliest entry point for the primary CPU. +/// +/// 这些代码拷贝、修改自 polyhal (https://github.com/Byte-OS/polyhal.git) +use crate::arch::{cpu::current_cpu_id, init::boot::kernel_main}; + +const QEMU_DTB_PADDR: usize = 0x100000; + +/// The earliest entry point for the primary CPU. +/// +/// We can't use bl to jump to higher address, so we use jirl to jump to higher address. +#[naked] +#[no_mangle] +#[link_section = ".text.entry"] +unsafe extern "C" fn _start() -> ! { + core::arch::naked_asm!(" + + ori $t0, $zero, 0x1 # CSR_DMW1_PLV0 + lu52i.d $t0, $t0, -2048 # UC, PLV0, 0x8000 xxxx xxxx xxxx + csrwr $t0, 0x180 # LOONGARCH_CSR_DMWIN0 + ori $t0, $zero, 0x11 # CSR_DMW1_MAT | CSR_DMW1_PLV0 + lu52i.d $t0, $t0, -1792 # CA, PLV0, 0x9000 xxxx xxxx xxxx + csrwr $t0, 0x181 # LOONGARCH_CSR_DMWIN1 + + # Goto 1 if hart is not 0 + csrrd $t1, 0x20 # read cpu from csr + bnez $t1, 1f + + # Enable PG + li.w $t0, 0xb0 # PLV=0, IE=0, PG=1 + csrwr $t0, 0x0 # LOONGARCH_CSR_CRMD + li.w $t0, 0x00 # PLV=0, PIE=0, PWE=0 + csrwr $t0, 0x1 # LOONGARCH_CSR_PRMD + li.w $t0, 0x00 # FPE=0, SXE=0, ASXE=0, BTE=0 + csrwr $t0, 0x2 # LOONGARCH_CSR_EUEN + + + la.global $sp, {boot_stack} + li.d $t0, {boot_stack_size} + add.d $sp, $sp, $t0 # setup boot stack + csrrd $a0, 0x20 # cpuid + la.global $t0, {entry} + jirl $zero,$t0,0 + 1: + li.w $s0, {MBUF0} + iocsrrd.d $t0, $s0 + la.global $t1, {sec_entry} + bne $t0, $t1, 1b + jirl $zero, $t1, 0 + ", + boot_stack_size = const size_of_val(&crate::arch::process::BSP_IDLE_STACK_SPACE), + boot_stack = sym crate::arch::process::BSP_IDLE_STACK_SPACE, + MBUF0 = const loongArch64::consts::LOONGARCH_CSR_MAIL_BUF0, + entry = sym rust_tmp_main, + sec_entry = sym _start_secondary, + ) +} + +/// The earliest entry point for the primary CPU. +/// +/// We can't use bl to jump to higher address, so we use jirl to jump to higher address. +#[naked] +#[no_mangle] +#[link_section = ".text.entry"] +pub(crate) unsafe extern "C" fn _start_secondary() -> ! { + core::arch::naked_asm!( + " + ori $t0, $zero, 0x1 # CSR_DMW1_PLV0 + lu52i.d $t0, $t0, -2048 # UC, PLV0, 0x8000 xxxx xxxx xxxx + csrwr $t0, 0x180 # LOONGARCH_CSR_DMWIN0 + ori $t0, $zero, 0x11 # CSR_DMW1_MAT | CSR_DMW1_PLV0 + lu52i.d $t0, $t0, -1792 # CA, PLV0, 0x9000 xxxx xxxx xxxx + csrwr $t0, 0x181 # LOONGARCH_CSR_DMWIN1 + + li.w $t0, {MBUF1} + iocsrrd.d $sp, $t0 + + csrrd $a0, 0x20 # cpuid + la.global $t0, {entry} + + jirl $zero,$t0,0 + ", + MBUF1 = const loongArch64::consts::LOONGARCH_CSR_MAIL_BUF1, + entry = sym _rust_secondary_main, + ) +} + +/// Rust temporary entry point +/// +/// This function will be called after assembly boot stage. +fn rust_tmp_main(hart_id: usize) { + unsafe { kernel_main(hart_id, QEMU_DTB_PADDR) }; +} + +/// The entry point for the second core. +pub(crate) extern "C" fn _rust_secondary_main() { + unsafe { kernel_main(current_cpu_id().data() as usize, QEMU_DTB_PADDR) } +} diff --git a/kernel/src/arch/loongarch64/asm/mod.rs b/kernel/src/arch/loongarch64/asm/mod.rs new file mode 100644 index 00000000..d8c9eee3 --- /dev/null +++ b/kernel/src/arch/loongarch64/asm/mod.rs @@ -0,0 +1,2 @@ +pub mod bitops; +pub mod boot; diff --git a/kernel/src/arch/loongarch64/cpu.rs b/kernel/src/arch/loongarch64/cpu.rs new file mode 100644 index 00000000..4b7791be --- /dev/null +++ b/kernel/src/arch/loongarch64/cpu.rs @@ -0,0 +1,15 @@ +use crate::smp::cpu::ProcessorId; + +/// 重置cpu +pub unsafe fn cpu_reset() -> ! { + log::warn!("cpu_reset on loongarch64 platform was not implemented!"); + loop { + unsafe { loongArch64::asm::idle() }; + } +} + +/// 获取当前cpu的id +#[inline] +pub fn current_cpu_id() -> ProcessorId { + ProcessorId::new(loongArch64::register::cpuid::read().core_id() as u32) +} diff --git a/kernel/src/arch/loongarch64/elf.rs b/kernel/src/arch/loongarch64/elf.rs new file mode 100644 index 00000000..c3b6a57d --- /dev/null +++ b/kernel/src/arch/loongarch64/elf.rs @@ -0,0 +1,10 @@ +use crate::{arch::MMArch, libs::elf::ElfArch, mm::MemoryManagementArch}; + +#[derive(Debug, Clone, Copy, Hash)] +pub struct LoongArch64ElfArch; + +impl ElfArch for LoongArch64ElfArch { + const ELF_ET_DYN_BASE: usize = MMArch::USER_END_VADDR.data() / 3 * 2; + + const ELF_PAGE_SIZE: usize = MMArch::PAGE_SIZE; +} diff --git a/kernel/src/arch/loongarch64/include/asm/asm.h b/kernel/src/arch/loongarch64/include/asm/asm.h new file mode 100644 index 00000000..6f70f09b --- /dev/null +++ b/kernel/src/arch/loongarch64/include/asm/asm.h @@ -0,0 +1 @@ +#pragma once diff --git a/kernel/src/arch/loongarch64/init/boot.rs b/kernel/src/arch/loongarch64/init/boot.rs new file mode 100644 index 00000000..d284042c --- /dev/null +++ b/kernel/src/arch/loongarch64/init/boot.rs @@ -0,0 +1,54 @@ +use loongArch64::register::{ecfg, eentry}; + +use crate::{init::init::start_kernel, mm::PhysAddr}; + +static mut BOOT_HARTID: u32 = 0; +static mut BOOT_FDT_PADDR: PhysAddr = PhysAddr::new(0); + +#[no_mangle] +pub unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! { + clear_bss(); + + let fdt_paddr = PhysAddr::new(fdt_paddr); + + unsafe { + BOOT_HARTID = hartid as u32; + BOOT_FDT_PADDR = fdt_paddr; + } + setup_trap_vector(); + start_kernel(); +} + +/// 设置中断、异常处理函数 +fn setup_trap_vector() { + // todo!(); + // let ptr = handle_exception as *const () as usize; + // ecfg::set_vs(0); + // eentry::set_eentry(handle_exception as usize); +} + +/// Clear the bss section +fn clear_bss() { + extern "C" { + fn _bss(); + fn _ebss(); + } + unsafe { + let bss_start = _bss as *mut u8; + let bss_end = _ebss as *mut u8; + let bss_size = bss_end as usize - bss_start as usize; + + // Clear in chunks of u128 for efficiency + let u128_count = bss_size / core::mem::size_of::(); + let u128_slice = core::slice::from_raw_parts_mut(bss_start as *mut u128, u128_count); + u128_slice.fill(0); + + // Clear any remaining bytes + let remaining_bytes = bss_size % core::mem::size_of::(); + if remaining_bytes > 0 { + let remaining_start = bss_start.add(u128_count * core::mem::size_of::()); + let remaining_slice = core::slice::from_raw_parts_mut(remaining_start, remaining_bytes); + remaining_slice.fill(0); + } + } +} diff --git a/kernel/src/arch/loongarch64/init/mod.rs b/kernel/src/arch/loongarch64/init/mod.rs new file mode 100644 index 00000000..2a148f87 --- /dev/null +++ b/kernel/src/arch/loongarch64/init/mod.rs @@ -0,0 +1,24 @@ +use system_error::SystemError; +pub mod boot; + +#[derive(Debug)] +pub struct ArchBootParams {} + +impl ArchBootParams { + pub const DEFAULT: Self = ArchBootParams {}; +} + +#[inline(never)] +pub fn early_setup_arch() -> Result<(), SystemError> { + todo!("la64:early_setup_arch"); +} + +#[inline(never)] +pub fn setup_arch() -> Result<(), SystemError> { + todo!("la64:setup_arch"); +} + +#[inline(never)] +pub fn setup_arch_post() -> Result<(), SystemError> { + todo!("la64:setup_arch_post"); +} diff --git a/kernel/src/arch/loongarch64/interrupt/ipi.rs b/kernel/src/arch/loongarch64/interrupt/ipi.rs new file mode 100644 index 00000000..93ed5787 --- /dev/null +++ b/kernel/src/arch/loongarch64/interrupt/ipi.rs @@ -0,0 +1,6 @@ +use crate::exception::ipi::{IpiKind, IpiTarget}; + +#[inline(always)] +pub fn send_ipi(kind: IpiKind, target: IpiTarget) { + todo!("la64: send_ipi") +} diff --git a/kernel/src/arch/loongarch64/interrupt/mod.rs b/kernel/src/arch/loongarch64/interrupt/mod.rs new file mode 100644 index 00000000..59a551e1 --- /dev/null +++ b/kernel/src/arch/loongarch64/interrupt/mod.rs @@ -0,0 +1,123 @@ +pub mod ipi; + +use core::any::Any; + +use kprobe::ProbeArgs; +use loongArch64::register::CpuMode; + +use crate::exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber}; + +pub struct LoongArch64InterruptArch; + +impl InterruptArch for LoongArch64InterruptArch { + unsafe fn arch_irq_init() -> Result<(), system_error::SystemError> { + todo!("arch_irq_init() not implemented for LoongArch64InterruptArch") + } + + unsafe fn interrupt_enable() { + loongArch64::register::crmd::set_ie(true); + } + + unsafe fn interrupt_disable() { + loongArch64::register::crmd::set_ie(false); + } + + fn is_irq_enabled() -> bool { + loongArch64::register::crmd::read().ie() + } + + unsafe fn save_and_disable_irq() -> IrqFlagsGuard { + let ie = loongArch64::register::crmd::read().ie(); + loongArch64::register::crmd::set_ie(false); + IrqFlagsGuard::new(IrqFlags::new(if ie { 1 } else { 0 })) + } + + unsafe fn restore_irq(flags: IrqFlags) { + loongArch64::register::crmd::set_ie(flags.flags() == 1); + } + + fn probe_total_irq_num() -> u32 { + todo!("probe_total_irq_num() not implemented for LoongArch64InterruptArch") + } + + fn ack_bad_irq(irq: IrqNumber) { + todo!("ack_bad_irq() not implemented for LoongArch64InterruptArch") + } +} + +/// 中断栈帧结构体 +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TrapFrame { + pub r0: usize, // 0*8 + pub ra: usize, // 1*8 + pub tp: usize, // 2*8 + pub usp: usize, // 3*8 (user stack pointer) + pub a0: usize, // 4*8 + pub a1: usize, // 5*8 + pub a2: usize, // 6*8 + pub a3: usize, // 7*8 + pub a4: usize, // 8*8 + pub a5: usize, // 9*8 + pub a6: usize, // 10*8 + pub a7: usize, // 11*8 + pub t0: usize, // 12*8 + pub t1: usize, // 13*8 + pub t2: usize, // 14*8 + pub t3: usize, // 15*8 + pub t4: usize, // 16*8 + pub t5: usize, // 17*8 + pub t6: usize, // 18*8 + pub t7: usize, // 19*8 + pub t8: usize, // 20*8 + pub r21: usize, // 21*8 + pub fp: usize, // 22*8 + pub s0: usize, // 23*8 + pub s1: usize, // 24*8 + pub s2: usize, // 25*8 + pub s3: usize, // 26*8 + pub s4: usize, // 27*8 + pub s5: usize, // 28*8 + pub s6: usize, // 29*8 + pub s7: usize, // 30*8 + pub s8: usize, // 31*8 + /// original syscall arg0 + pub orig_a0: usize, + + pub csr_era: usize, + pub csr_badvaddr: usize, + pub csr_crmd: usize, + pub csr_prmd: usize, + pub csr_euen: usize, + pub csr_ecfg: usize, + pub csr_estat: usize, +} + +impl TrapFrame { + /// 中断栈帧结构体的大小 + pub const SIZE: usize = core::mem::size_of::(); + + /// 判断当前中断是否来自用户模式 + pub fn is_from_user(&self) -> bool { + loongArch64::register::crmd::Crmd::from(self.csr_crmd).plv() == CpuMode::Ring3 + } + + #[inline(never)] + pub const fn new() -> Self { + let x = core::mem::MaybeUninit::::zeroed(); + unsafe { x.assume_init() } + } +} + +impl ProbeArgs for TrapFrame { + fn as_any(&self) -> &dyn Any { + self + } + fn break_address(&self) -> usize { + todo!("TrapFrame::break_address()") + } + + fn debug_address(&self) -> usize { + todo!("TrapFrame::debug_address()") + } +} diff --git a/kernel/src/arch/loongarch64/ipc/mod.rs b/kernel/src/arch/loongarch64/ipc/mod.rs new file mode 100644 index 00000000..a3c1b22f --- /dev/null +++ b/kernel/src/arch/loongarch64/ipc/mod.rs @@ -0,0 +1 @@ +pub mod signal; diff --git a/kernel/src/arch/loongarch64/ipc/signal.rs b/kernel/src/arch/loongarch64/ipc/signal.rs new file mode 100644 index 00000000..9ebb34db --- /dev/null +++ b/kernel/src/arch/loongarch64/ipc/signal.rs @@ -0,0 +1,64 @@ +use crate::arch::interrupt::TrapFrame; +pub use crate::ipc::generic_signal::AtomicGenericSignal as AtomicSignal; +pub use crate::ipc::generic_signal::GenericSigChildCode as SigChildCode; +pub use crate::ipc::generic_signal::GenericSigSet as SigSet; +pub use crate::ipc::generic_signal::GenericSignal as Signal; +pub use crate::ipc::generic_signal::GENERIC_MAX_SIG_NUM as MAX_SIG_NUM; +pub use crate::ipc::generic_signal::GENERIC_STACK_ALIGN as STACK_ALIGN; + +pub use crate::ipc::generic_signal::GenericSigFlags as SigFlags; + +use crate::ipc::signal_types::SignalArch; + +pub struct LoongArch64SignalArch; + +impl SignalArch for LoongArch64SignalArch { + // TODO: 为LoongArch64实现信号处理 + // 注意,la64现在在中断/系统调用返回用户态时,没有进入 irqentry_exit() 函数, + // 到时候实现信号处理时,需要修改中断/系统调用返回用户态的代码,进入 irqentry_exit() 函数 + unsafe fn do_signal_or_restart(_frame: &mut TrapFrame) { + todo!("la64:do_signal_or_restart") + } + + fn sys_rt_sigreturn(_trap_frame: &mut TrapFrame) -> u64 { + todo!("la64:sys_rt_sigreturn") + } +} + +/// siginfo中的si_code的可选值 +/// 请注意,当这个值小于0时,表示siginfo来自用户态,否则来自内核态 +#[derive(Copy, Debug, Clone)] +#[repr(i32)] +pub enum SigCode { + /// sent by kill, sigsend, raise + User = 0, + /// sent by kernel from somewhere + Kernel = 0x80, + /// 通过sigqueue发送 + Queue = -1, + /// 定时器过期时发送 + Timer = -2, + /// 当实时消息队列的状态发生改变时发送 + Mesgq = -3, + /// 当异步IO完成时发送 + AsyncIO = -4, + /// sent by queued SIGIO + SigIO = -5, +} + +impl SigCode { + /// 为SigCode这个枚举类型实现从i32转换到枚举类型的转换函数 + #[allow(dead_code)] + pub fn from_i32(x: i32) -> SigCode { + match x { + 0 => Self::User, + 0x80 => Self::Kernel, + -1 => Self::Queue, + -2 => Self::Timer, + -3 => Self::Mesgq, + -4 => Self::AsyncIO, + -5 => Self::SigIO, + _ => panic!("signal code not valid"), + } + } +} diff --git a/kernel/src/arch/loongarch64/kprobe.rs b/kernel/src/arch/loongarch64/kprobe.rs new file mode 100644 index 00000000..1d85e6d9 --- /dev/null +++ b/kernel/src/arch/loongarch64/kprobe.rs @@ -0,0 +1,19 @@ +use crate::arch::interrupt::TrapFrame; + +pub fn setup_single_step(frame: &mut TrapFrame, step_addr: usize) { + todo!("la64: setup_single_step") +} + +pub fn clear_single_step(frame: &mut TrapFrame, return_addr: usize) { + todo!("la64: clear_single_step") +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct KProbeContext {} + +impl From<&TrapFrame> for KProbeContext { + fn from(trap_frame: &TrapFrame) -> Self { + todo!("from trap frame to kprobe context"); + } +} diff --git a/kernel/src/arch/loongarch64/link.ld b/kernel/src/arch/loongarch64/link.ld new file mode 100644 index 00000000..f710ad62 --- /dev/null +++ b/kernel/src/arch/loongarch64/link.ld @@ -0,0 +1,104 @@ +OUTPUT_FORMAT( + "elf64-loongarch", + "elf64-loongarch", + "elf64-loongarch" +) + +OUTPUT_ARCH(loongarch) +ENTRY(_start) + + +SECTIONS +{ + KERNEL_VMA = 0x9000000000200000; + . = KERNEL_VMA; + . = ALIGN(4096); + boot_text_start_pa = .; + .boot.text : + { + KEEP(*(.bootstrap)) + *(.bootstrap) + *(.bootstrap.*) + . = ALIGN(4096); + *(.initial_pgtable_section) + . = ALIGN(4096); + } + + + . = ALIGN(4096); + text_start_pa = .; + __executable_start = .; + .text (text_start_pa): + { + _text = .; + + /* any files' .text */ + *(.text) + + /* any files' .text.*, for example: rust .text._ZN* */ + *(.text.*) + + _etext = .; + __etext = .; + } + . = ALIGN(32768); + data_start_pa = .; + .data (data_start_pa): + { + _data = .; + *(.data) + *(.data.*) + *(.got.plt) + *(.got) + _edata = .; + } + + . = ALIGN(32768); + + rodata_start_pa = .; + .rodata (rodata_start_pa): + { + _rodata = .; + *(.rodata) + *(.rodata.*) + *(.gcc_except_table .gcc_except_table.*) + _erodata = .; + } + + . = ALIGN(32768); + + init_proc_union_start_pa = .; + .data.init_proc_union (init_proc_union_start_pa): + { *(.data.init_proc_union) } + + . = ALIGN(32768); + bss_start_pa = .; + .bss (bss_start_pa): + { + _bss = .; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + _ebss = .; + } + + eh_frame = .; + .eh_frame (eh_frame): + { + __eh_frame_hdr_start = .; + *(.eh_frame_hdr) + __eh_frame_hdr_end = .; + __eh_frame_start = .; + *(.eh_frame) + *(.rela.eh_frame) + __eh_frame_end = .; + } + + _end = .; + + /DISCARD/ : { + /* *(.eh_frame) */ + + } +} diff --git a/kernel/src/arch/loongarch64/loongarch64-unknown-none.json b/kernel/src/arch/loongarch64/loongarch64-unknown-none.json new file mode 100644 index 00000000..56407679 --- /dev/null +++ b/kernel/src/arch/loongarch64/loongarch64-unknown-none.json @@ -0,0 +1,21 @@ +{ + "arch": "loongarch64", + "code-model": "medium", + "crt-objects-fallback": "false", + "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + "features": "+f,+d", + "linker": "rust-lld", + "linker-flavor": "gnu-lld", + "llvm-abiname": "lp64d", + "llvm-target": "loongarch64-unknown-none", + "max-atomic-width": 64, + "metadata": { + "description": "Freestanding/bare-metal LoongArch64", + "host_tools": false, + "std": false, + "tier": 2 + }, + "panic-strategy": "abort", + "relocation-model": "static", + "target-pointer-width": "64" +} \ No newline at end of file diff --git a/kernel/src/arch/loongarch64/mm/bump.rs b/kernel/src/arch/loongarch64/mm/bump.rs new file mode 100644 index 00000000..47cc861e --- /dev/null +++ b/kernel/src/arch/loongarch64/mm/bump.rs @@ -0,0 +1,7 @@ +use crate::mm::{allocator::bump::BumpAllocator, MemoryManagementArch, PhysMemoryArea}; + +impl BumpAllocator { + pub unsafe fn arch_remain_areas(_ret_areas: &mut [PhysMemoryArea], res_count: usize) -> usize { + todo!("la64: arch_remain_areas") + } +} diff --git a/kernel/src/arch/loongarch64/mm/mod.rs b/kernel/src/arch/loongarch64/mm/mod.rs new file mode 100644 index 00000000..48b687ea --- /dev/null +++ b/kernel/src/arch/loongarch64/mm/mod.rs @@ -0,0 +1,207 @@ +pub mod bump; + +use crate::mm::{ + allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}, + page::EntryFlags, + MemoryManagementArch, PhysAddr, VirtAddr, VmFlags, +}; + +use crate::arch::MMArch; + +pub type PageMapper = crate::mm::page::PageMapper; + +/// LoongArch64的内存管理架构结构体 +#[derive(Debug, Clone, Copy, Hash)] +pub struct LoongArch64MMArch; + +impl MemoryManagementArch for LoongArch64MMArch { + const PAGE_FAULT_ENABLED: bool = false; + + const PAGE_SHIFT: usize = 0; + + const PAGE_ENTRY_SHIFT: usize = 0; + + const PAGE_LEVELS: usize = 0; + + const ENTRY_ADDRESS_SHIFT: usize = 0; + + const ENTRY_FLAG_DEFAULT_PAGE: usize = 0; + + const ENTRY_FLAG_DEFAULT_TABLE: usize = 0; + + const ENTRY_FLAG_PRESENT: usize = 0; + + const ENTRY_FLAG_READONLY: usize = 0; + + const ENTRY_FLAG_WRITEABLE: usize = 0; + + const ENTRY_FLAG_READWRITE: usize = 0; + + const ENTRY_FLAG_USER: usize = 0; + + const ENTRY_FLAG_WRITE_THROUGH: usize = 0; + + const ENTRY_FLAG_CACHE_DISABLE: usize = 0; + + const ENTRY_FLAG_NO_EXEC: usize = 0; + + const ENTRY_FLAG_EXEC: usize = 0; + + const ENTRY_FLAG_DIRTY: usize = 0; + + const ENTRY_FLAG_ACCESSED: usize = 0; + + const ENTRY_FLAG_HUGE_PAGE: usize = 0; + + const ENTRY_FLAG_GLOBAL: usize = 0; + + const PHYS_OFFSET: usize = 0x9000_0000_0000_0000; + + const KERNEL_LINK_OFFSET: usize = 0; + + const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0); + + const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0); + + const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0); + + const FIXMAP_START_VADDR: crate::mm::VirtAddr = VirtAddr::new(0); + + const FIXMAP_SIZE: usize = 0; + + const MMIO_BASE: crate::mm::VirtAddr = VirtAddr::new(0); + + const MMIO_SIZE: usize = 0; + + const PAGE_NONE: usize = 0; + + const PAGE_SHARED: usize = 0; + + const PAGE_SHARED_EXEC: usize = 0; + + const PAGE_COPY_NOEXEC: usize = 0; + + const PAGE_COPY_EXEC: usize = 0; + + const PAGE_COPY: usize = 0; + + const PAGE_READONLY: usize = 0; + + const PAGE_READONLY_EXEC: usize = 0; + + const PAGE_READ: usize = 0; + + const PAGE_READ_EXEC: usize = 0; + + const PAGE_WRITE: usize = 0; + + const PAGE_WRITE_EXEC: usize = 0; + + const PAGE_EXEC: usize = 0; + + const PROTECTION_MAP: [crate::mm::page::EntryFlags; 16] = protection_map(); + + unsafe fn init() { + todo!() + } + + unsafe fn invalidate_page(address: crate::mm::VirtAddr) { + todo!() + } + + unsafe fn invalidate_all() { + todo!() + } + + unsafe fn table(table_kind: crate::mm::PageTableKind) -> crate::mm::PhysAddr { + todo!() + } + + unsafe fn set_table(table_kind: crate::mm::PageTableKind, table: crate::mm::PhysAddr) { + todo!() + } + + fn virt_is_valid(virt: crate::mm::VirtAddr) -> bool { + todo!() + } + + fn initial_page_table() -> crate::mm::PhysAddr { + todo!() + } + + fn setup_new_usermapper() -> Result + { + todo!() + } + + fn make_entry(paddr: crate::mm::PhysAddr, page_flags: usize) -> usize { + todo!() + } +} + +/// 获取内核地址默认的页面标志 +pub unsafe fn kernel_page_flags(_virt: VirtAddr) -> EntryFlags { + EntryFlags::from_data(LoongArch64MMArch::ENTRY_FLAG_DEFAULT_PAGE) + .set_user(false) + .set_execute(true) +} + +/// 全局的页帧分配器 +#[derive(Debug, Clone, Copy, Hash)] +pub struct LockedFrameAllocator; + +impl FrameAllocator for LockedFrameAllocator { + unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { + todo!("LockedFrameAllocator::allocate") + } + + unsafe fn free(&mut self, address: PhysAddr, count: PageFrameCount) { + todo!("LockedFrameAllocator::free") + } + + unsafe fn usage(&self) -> PageFrameUsage { + todo!("LockedFrameAllocator::usage") + } +} + +/// 获取保护标志的映射表 +/// +/// +/// ## 返回值 +/// - `[usize; 16]`: 长度为16的映射表 +const fn protection_map() -> [EntryFlags; 16] { + let mut map = [unsafe { EntryFlags::from_data(0) }; 16]; + unsafe { + map[VmFlags::VM_NONE.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE); + map[VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY); + map[VmFlags::VM_WRITE.bits()] = EntryFlags::from_data(MMArch::PAGE_COPY); + map[VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] = + EntryFlags::from_data(MMArch::PAGE_COPY); + map[VmFlags::VM_EXEC.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC); + map[VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] = + EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC); + map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] = + EntryFlags::from_data(MMArch::PAGE_COPY_EXEC); + map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] = + EntryFlags::from_data(MMArch::PAGE_COPY_EXEC); + map[VmFlags::VM_SHARED.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE); + map[VmFlags::VM_SHARED.bits() | VmFlags::VM_READ.bits()] = + EntryFlags::from_data(MMArch::PAGE_READONLY); + map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits()] = + EntryFlags::from_data(MMArch::PAGE_SHARED); + map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] = + EntryFlags::from_data(MMArch::PAGE_SHARED); + map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits()] = + EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC); + map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] = + EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC); + map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] = + EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC); + map[VmFlags::VM_SHARED.bits() + | VmFlags::VM_EXEC.bits() + | VmFlags::VM_WRITE.bits() + | VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC); + } + + map +} diff --git a/kernel/src/arch/loongarch64/mod.rs b/kernel/src/arch/loongarch64/mod.rs new file mode 100644 index 00000000..3b0f5486 --- /dev/null +++ b/kernel/src/arch/loongarch64/mod.rs @@ -0,0 +1,30 @@ +pub mod asm; +pub mod cpu; +pub mod elf; +pub mod init; +pub mod interrupt; +pub mod ipc; +pub mod kprobe; +pub mod mm; +pub mod msi; +pub mod pci; +pub mod pio; +pub mod process; +pub mod rand; +pub mod sched; +pub mod smp; +pub mod syscall; +pub mod time; + +pub use self::elf::LoongArch64ElfArch as CurrentElfArch; +pub use self::interrupt::LoongArch64InterruptArch as CurrentIrqArch; +pub use self::ipc::signal::LoongArch64SignalArch as CurrentSignalArch; +pub use self::mm::LoongArch64MMArch as MMArch; +pub use self::pci::LoongArch64PciArch as PciArch; +pub use self::pio::LoongArch64PortIOArch as CurrentPortIOArch; +pub use self::sched::LoongArch64SchedArch as CurrentSchedArch; +pub use self::smp::LoongArch64SMPArch as CurrentSMPArch; +pub use self::time::LoongArch64TimeArch as CurrentTimeArch; + +pub fn panic_pre_work() {} +pub fn panic_post_work() {} diff --git a/kernel/src/arch/loongarch64/msi.rs b/kernel/src/arch/loongarch64/msi.rs new file mode 100644 index 00000000..863fc8cd --- /dev/null +++ b/kernel/src/arch/loongarch64/msi.rs @@ -0,0 +1,24 @@ +use crate::driver::pci::pci_irq::TriggerMode; + +/// 获得MSI Message Address +/// +/// # 参数 +/// - `processor`: 目标CPU ID号 +/// +/// # 返回值 +/// MSI Message Address +pub fn arch_msi_message_address(_processor: u16) -> u32 { + unimplemented!("loongarch64::arch_msi_message_address()") +} +/// 获得MSI Message Data +/// +/// # 参数 +/// - `vector`: 分配的中断向量号 +/// - `processor`: 目标CPU ID号 +/// - `trigger`: 申请中断的触发模式,MSI默认为边沿触发 +/// +/// # 返回值 +/// MSI Message Address +pub fn arch_msi_message_data(_vector: u16, _processor: u16, _trigger: TriggerMode) -> u32 { + unimplemented!("loongarch64::arch_msi_message_data()") +} diff --git a/kernel/src/arch/loongarch64/pci/mod.rs b/kernel/src/arch/loongarch64/pci/mod.rs new file mode 100644 index 00000000..e2345c4d --- /dev/null +++ b/kernel/src/arch/loongarch64/pci/mod.rs @@ -0,0 +1,20 @@ +use crate::{ + arch::TraitPciArch, + driver::pci::pci::{BusDeviceFunction, PciAddr}, + mm::PhysAddr, +}; + +pub struct LoongArch64PciArch; +impl TraitPciArch for LoongArch64PciArch { + fn read_config(_bus_device_function: &BusDeviceFunction, _offset: u8) -> u32 { + unimplemented!("LoongArch64PciArch::read_config") + } + + fn write_config(_bus_device_function: &BusDeviceFunction, _offset: u8, _data: u32) { + unimplemented!("LoongArch64PciArch pci_root_0().write_config") + } + + fn address_pci_to_physical(pci_address: PciAddr) -> crate::mm::PhysAddr { + return PhysAddr::new(pci_address.data()); + } +} diff --git a/kernel/src/arch/loongarch64/pio.rs b/kernel/src/arch/loongarch64/pio.rs new file mode 100644 index 00000000..0d6ad4bd --- /dev/null +++ b/kernel/src/arch/loongarch64/pio.rs @@ -0,0 +1,35 @@ +use crate::arch::io::PortIOArch; + +pub struct LoongArch64PortIOArch; + +impl PortIOArch for LoongArch64PortIOArch { + #[inline(always)] + unsafe fn in8(_port: u16) -> u8 { + unimplemented!("LoongArch64PortIOArch::in8") + } + + #[inline(always)] + unsafe fn in16(_port: u16) -> u16 { + unimplemented!("LoongArch64PortIOArch::in16") + } + + #[inline(always)] + unsafe fn in32(_port: u16) -> u32 { + unimplemented!("LoongArch64PortIOArch::in32") + } + + #[inline(always)] + unsafe fn out8(_port: u16, _data: u8) { + unimplemented!("LoongArch64PortIOArch::out8") + } + + #[inline(always)] + unsafe fn out16(_port: u16, _data: u16) { + unimplemented!("LoongArch64PortIOArch::out16") + } + + #[inline(always)] + unsafe fn out32(_port: u16, _data: u32) { + unimplemented!("LoongArch64PortIOArch::out32") + } +} diff --git a/kernel/src/arch/loongarch64/process/idle.rs b/kernel/src/arch/loongarch64/process/idle.rs new file mode 100644 index 00000000..e5149680 --- /dev/null +++ b/kernel/src/arch/loongarch64/process/idle.rs @@ -0,0 +1,31 @@ +use core::hint::spin_loop; + +use log::error; + +use crate::{ + arch::CurrentIrqArch, + exception::InterruptArch, + process::{ProcessFlags, ProcessManager}, + sched::{SchedMode, __schedule}, +}; + +impl ProcessManager { + /// 每个核的idle进程 + pub fn arch_idle_func() -> ! { + loop { + let pcb = ProcessManager::current_pcb(); + if pcb.flags().contains(ProcessFlags::NEED_SCHEDULE) { + __schedule(SchedMode::SM_NONE); + } + if CurrentIrqArch::is_irq_enabled() { + todo!("la64: arch_idle_func"); + // unsafe { + // x86::halt(); + // } + } else { + error!("Idle process should not be scheduled with IRQs disabled."); + spin_loop(); + } + } + } +} diff --git a/kernel/src/arch/loongarch64/process/kthread.rs b/kernel/src/arch/loongarch64/process/kthread.rs new file mode 100644 index 00000000..161f61a5 --- /dev/null +++ b/kernel/src/arch/loongarch64/process/kthread.rs @@ -0,0 +1,27 @@ +use system_error::SystemError; + +use alloc::sync::Arc; + +use crate::process::{ + fork::CloneFlags, + kthread::{KernelThreadCreateInfo, KernelThreadMechanism}, + Pid, +}; + +impl KernelThreadMechanism { + /// 伪造trapframe,创建内核线程 + /// + /// ## 返回值 + /// + /// 返回创建的内核线程的pid + pub fn __inner_create( + info: &Arc, + clone_flags: CloneFlags, + ) -> Result { + // WARNING: If create failed, we must drop the info manually or it will cause memory leak. (refcount will not decrease when create failed) + let create_info: *const KernelThreadCreateInfo = + KernelThreadCreateInfo::generate_unsafe_arc_ptr(info.clone()); + + todo!("la64:__inner_create()") + } +} diff --git a/kernel/src/arch/loongarch64/process/mod.rs b/kernel/src/arch/loongarch64/process/mod.rs new file mode 100644 index 00000000..5952b5af --- /dev/null +++ b/kernel/src/arch/loongarch64/process/mod.rs @@ -0,0 +1,90 @@ +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::{ + arch::CurrentIrqArch, + exception::InterruptArch, + mm::VirtAddr, + process::{fork::KernelCloneArgs, KernelStack, ProcessControlBlock, ProcessManager}, +}; + +use super::interrupt::TrapFrame; + +pub mod idle; +pub mod kthread; +pub mod syscall; + +#[repr(align(32768))] +pub union InitProcUnion { + /// 用于存放idle进程的内核栈 + idle_stack: [u8; 32768], +} + +#[link_section = ".data.init_proc_union"] +#[no_mangle] +pub(super) static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion { + idle_stack: [0; 32768], +}; + +pub unsafe fn arch_switch_to_user(trap_frame: TrapFrame) -> ! { + // 以下代码不能发生中断 + CurrentIrqArch::interrupt_disable(); + + todo!("la64: arch_switch_to_user") +} + +/// PCB中与架构相关的信息 +#[derive(Debug, Clone, Copy)] +#[allow(dead_code)] +#[repr(C)] +pub struct ArchPCBInfo {} + +impl ArchPCBInfo { + /// 创建一个新的ArchPCBInfo + /// + /// ## 参数 + /// + /// - `kstack`:内核栈的引用 + /// + /// ## 返回值 + /// + /// 返回一个新的ArchPCBInfo + pub fn new(kstack: &KernelStack) -> Self { + todo!("la64: ArchPCBInfo::new") + } +} + +impl ProcessControlBlock { + /// 获取当前进程的pcb + pub fn arch_current_pcb() -> Arc { + todo!("la64: arch_current_pcb") + } +} + +impl ProcessManager { + pub fn arch_init() { + // do nothing + } + /// fork的过程中复制线程 + /// + /// 由于这个过程与具体的架构相关,所以放在这里 + pub fn copy_thread( + current_pcb: &Arc, + new_pcb: &Arc, + clone_args: &KernelCloneArgs, + current_trapframe: &TrapFrame, + ) -> Result<(), SystemError> { + todo!("la64: copy_thread") + } + + /// 切换进程 + /// + /// ## 参数 + /// + /// - `prev`:上一个进程的pcb + /// - `next`:下一个进程的pcb + pub unsafe fn switch_process(prev: Arc, next: Arc) { + assert!(!CurrentIrqArch::is_irq_enabled()); + todo!("la64: switch_process"); + } +} diff --git a/kernel/src/arch/loongarch64/process/syscall.rs b/kernel/src/arch/loongarch64/process/syscall.rs new file mode 100644 index 00000000..e9fcbdf3 --- /dev/null +++ b/kernel/src/arch/loongarch64/process/syscall.rs @@ -0,0 +1,28 @@ +use system_error::SystemError; + +use crate::{ + arch::interrupt::TrapFrame, + mm::VirtAddr, + process::{ + exec::{BinaryLoaderResult, ExecParam}, + ProcessManager, + }, + syscall::Syscall, +}; + +impl Syscall { + pub fn arch_do_execve( + regs: &mut TrapFrame, + param: &ExecParam, + load_result: &BinaryLoaderResult, + user_sp: VirtAddr, + argv_ptr: VirtAddr, + ) -> Result<(), SystemError> { + todo!("la64:arch_do_execve not unimplemented"); + } + + /// ## 用于控制和查询与体系结构相关的进程特定选项 + pub fn arch_prctl(option: usize, arg2: usize) -> Result { + todo!("la64:arch_prctl") + } +} diff --git a/kernel/src/arch/loongarch64/rand.rs b/kernel/src/arch/loongarch64/rand.rs new file mode 100644 index 00000000..af25319d --- /dev/null +++ b/kernel/src/arch/loongarch64/rand.rs @@ -0,0 +1,5 @@ +use crate::libs::rand::soft_rand; + +pub fn rand() -> usize { + return soft_rand(); +} diff --git a/kernel/src/arch/loongarch64/sched.rs b/kernel/src/arch/loongarch64/sched.rs new file mode 100644 index 00000000..96e715d8 --- /dev/null +++ b/kernel/src/arch/loongarch64/sched.rs @@ -0,0 +1,17 @@ +use crate::sched::SchedArch; + +pub struct LoongArch64SchedArch; + +impl SchedArch for LoongArch64SchedArch { + fn enable_sched_local() { + todo!("LoongArch64::enable_sched_local") + } + + fn disable_sched_local() { + todo!("LoongArch64::disable_sched_local") + } + + fn initial_setup_sched_local() { + todo!("LoongArch64::initial_setup_sched_local") + } +} diff --git a/kernel/src/arch/loongarch64/smp/mod.rs b/kernel/src/arch/loongarch64/smp/mod.rs new file mode 100644 index 00000000..a9d3f1f5 --- /dev/null +++ b/kernel/src/arch/loongarch64/smp/mod.rs @@ -0,0 +1,29 @@ +use log::warn; +use system_error::SystemError; + +use crate::smp::{ + cpu::{CpuHpCpuState, ProcessorId, SmpCpuManager}, + SMPArch, +}; + +pub struct LoongArch64SMPArch; + +impl SMPArch for LoongArch64SMPArch { + #[inline(never)] + fn prepare_cpus() -> Result<(), SystemError> { + warn!("LoongArch64SMPArch::prepare_cpus() is not implemented"); + Ok(()) + } + + fn start_cpu(_cpu_id: ProcessorId, _hp_state: &CpuHpCpuState) -> Result<(), SystemError> { + warn!("LoongArch64SMPArch::start_cpu() is not implemented"); + Ok(()) + } +} + +impl SmpCpuManager { + pub fn arch_init(_boot_cpu: ProcessorId) { + // todo: 读取所有可用的CPU + todo!("la64:SmpCpuManager::arch_init()") + } +} diff --git a/kernel/src/arch/loongarch64/syscall/mod.rs b/kernel/src/arch/loongarch64/syscall/mod.rs new file mode 100644 index 00000000..80bebe15 --- /dev/null +++ b/kernel/src/arch/loongarch64/syscall/mod.rs @@ -0,0 +1,8 @@ +use system_error::SystemError; + +pub mod nr; + +/// 系统调用初始化 +pub fn arch_syscall_init() -> Result<(), SystemError> { + todo!("la64:arch_syscall_init"); +} diff --git a/kernel/src/arch/loongarch64/syscall/nr.rs b/kernel/src/arch/loongarch64/syscall/nr.rs new file mode 100644 index 00000000..2f47fffa --- /dev/null +++ b/kernel/src/arch/loongarch64/syscall/nr.rs @@ -0,0 +1,307 @@ +#![allow(dead_code)] + +pub const SYS_IO_SETUP: usize = 0; +pub const SYS_IO_DESTROY: usize = 1; +pub const SYS_IO_SUBMIT: usize = 2; +pub const SYS_IO_CANCEL: usize = 3; +pub const SYS_IO_GETEVENTS: usize = 4; +pub const SYS_SETXATTR: usize = 5; +pub const SYS_LSETXATTR: usize = 6; +pub const SYS_FSETXATTR: usize = 7; +pub const SYS_GETXATTR: usize = 8; +pub const SYS_LGETXATTR: usize = 9; +pub const SYS_FGETXATTR: usize = 10; +pub const SYS_LISTXATTR: usize = 11; +pub const SYS_LLISTXATTR: usize = 12; +pub const SYS_FLISTXATTR: usize = 13; +pub const SYS_REMOVEXATTR: usize = 14; +pub const SYS_LREMOVEXATTR: usize = 15; +pub const SYS_FREMOVEXATTR: usize = 16; +pub const SYS_GETCWD: usize = 17; +pub const SYS_LOOKUP_DCOOKIE: usize = 18; +pub const SYS_EVENTFD2: usize = 19; +pub const SYS_EPOLL_CREATE1: usize = 20; +pub const SYS_EPOLL_CTL: usize = 21; +pub const SYS_EPOLL_PWAIT: usize = 22; +pub const SYS_DUP: usize = 23; +pub const SYS_DUP3: usize = 24; +pub const SYS_FCNTL: usize = 25; +pub const SYS_INOTIFY_INIT1: usize = 26; +pub const SYS_INOTIFY_ADD_WATCH: usize = 27; +pub const SYS_INOTIFY_RM_WATCH: usize = 28; +pub const SYS_IOCTL: usize = 29; +pub const SYS_IOPRIO_SET: usize = 30; +pub const SYS_IOPRIO_GET: usize = 31; +pub const SYS_FLOCK: usize = 32; +pub const SYS_MKNODAT: usize = 33; +pub const SYS_MKDIRAT: usize = 34; +pub const SYS_UNLINKAT: usize = 35; +pub const SYS_SYMLINKAT: usize = 36; +pub const SYS_LINKAT: usize = 37; +pub const SYS_UMOUNT2: usize = 39; +pub const SYS_MOUNT: usize = 40; +pub const SYS_PIVOT_ROOT: usize = 41; +pub const SYS_NFSSERVCTL: usize = 42; +pub const SYS_STATFS: usize = 43; +pub const SYS_FSTATFS: usize = 44; +pub const SYS_TRUNCATE: usize = 45; +pub const SYS_FTRUNCATE: usize = 46; +pub const SYS_FALLOCATE: usize = 47; +pub const SYS_FACCESSAT: usize = 48; +pub const SYS_CHDIR: usize = 49; +pub const SYS_FCHDIR: usize = 50; +pub const SYS_CHROOT: usize = 51; +pub const SYS_FCHMOD: usize = 52; +pub const SYS_FCHMODAT: usize = 53; +pub const SYS_FCHOWNAT: usize = 54; +pub const SYS_FCHOWN: usize = 55; +pub const SYS_OPENAT: usize = 56; +pub const SYS_CLOSE: usize = 57; +pub const SYS_VHANGUP: usize = 58; +pub const SYS_PIPE2: usize = 59; +pub const SYS_QUOTACTL: usize = 60; +pub const SYS_GETDENTS64: usize = 61; +pub const SYS_LSEEK: usize = 62; +pub const SYS_READ: usize = 63; +pub const SYS_WRITE: usize = 64; +pub const SYS_READV: usize = 65; +pub const SYS_WRITEV: usize = 66; +pub const SYS_PREAD64: usize = 67; +pub const SYS_PWRITE64: usize = 68; +pub const SYS_PREADV: usize = 69; +pub const SYS_PWRITEV: usize = 70; +pub const SYS_SENDFILE: usize = 71; +pub const SYS_PSELECT6: usize = 72; +pub const SYS_PPOLL: usize = 73; +pub const SYS_SIGNALFD4: usize = 74; +pub const SYS_VMSPLICE: usize = 75; +pub const SYS_SPLICE: usize = 76; +pub const SYS_TEE: usize = 77; +pub const SYS_READLINKAT: usize = 78; +pub const SYS_SYNC: usize = 81; +pub const SYS_FSYNC: usize = 82; +pub const SYS_FDATASYNC: usize = 83; +pub const SYS_SYNC_FILE_RANGE: usize = 84; +pub const SYS_TIMERFD_CREATE: usize = 85; +pub const SYS_TIMERFD_SETTIME: usize = 86; +pub const SYS_TIMERFD_GETTIME: usize = 87; +pub const SYS_UTIMENSAT: usize = 88; +pub const SYS_ACCT: usize = 89; +pub const SYS_CAPGET: usize = 90; +pub const SYS_CAPSET: usize = 91; +pub const SYS_PERSONALITY: usize = 92; +pub const SYS_EXIT: usize = 93; +pub const SYS_EXIT_GROUP: usize = 94; +pub const SYS_WAITID: usize = 95; +pub const SYS_SET_TID_ADDRESS: usize = 96; +pub const SYS_UNSHARE: usize = 97; +pub const SYS_FUTEX: usize = 98; +pub const SYS_SET_ROBUST_LIST: usize = 99; +pub const SYS_GET_ROBUST_LIST: usize = 100; +pub const SYS_NANOSLEEP: usize = 101; +pub const SYS_GETITIMER: usize = 102; +pub const SYS_SETITIMER: usize = 103; +pub const SYS_KEXEC_LOAD: usize = 104; +pub const SYS_INIT_MODULE: usize = 105; +pub const SYS_DELETE_MODULE: usize = 106; +pub const SYS_TIMER_CREATE: usize = 107; +pub const SYS_TIMER_GETTIME: usize = 108; +pub const SYS_TIMER_GETOVERRUN: usize = 109; +pub const SYS_TIMER_SETTIME: usize = 110; +pub const SYS_TIMER_DELETE: usize = 111; +pub const SYS_CLOCK_SETTIME: usize = 112; +pub const SYS_CLOCK_GETTIME: usize = 113; +pub const SYS_CLOCK_GETRES: usize = 114; +pub const SYS_CLOCK_NANOSLEEP: usize = 115; +pub const SYS_SYSLOG: usize = 116; +pub const SYS_PTRACE: usize = 117; +pub const SYS_SCHED_SETPARAM: usize = 118; +pub const SYS_SCHED_SETSCHEDULER: usize = 119; +pub const SYS_SCHED_GETSCHEDULER: usize = 120; +pub const SYS_SCHED_GETPARAM: usize = 121; +pub const SYS_SCHED_SETAFFINITY: usize = 122; +pub const SYS_SCHED_GETAFFINITY: usize = 123; +pub const SYS_SCHED_YIELD: usize = 124; +pub const SYS_SCHED_GET_PRIORITY_MAX: usize = 125; +pub const SYS_SCHED_GET_PRIORITY_MIN: usize = 126; +pub const SYS_SCHED_RR_GET_INTERVAL: usize = 127; +pub const SYS_RESTART_SYSCALL: usize = 128; +pub const SYS_KILL: usize = 129; +pub const SYS_TKILL: usize = 130; +pub const SYS_TGKILL: usize = 131; +pub const SYS_SIGALTSTACK: usize = 132; +pub const SYS_RT_SIGSUSPEND: usize = 133; +pub const SYS_RT_SIGACTION: usize = 134; +pub const SYS_RT_SIGPROCMASK: usize = 135; +pub const SYS_RT_SIGPENDING: usize = 136; +pub const SYS_RT_SIGTIMEDWAIT: usize = 137; +pub const SYS_RT_SIGQUEUEINFO: usize = 138; +pub const SYS_RT_SIGRETURN: usize = 139; +pub const SYS_SETPRIORITY: usize = 140; +pub const SYS_GETPRIORITY: usize = 141; +pub const SYS_REBOOT: usize = 142; +pub const SYS_SETREGID: usize = 143; +pub const SYS_SETGID: usize = 144; +pub const SYS_SETREUID: usize = 145; +pub const SYS_SETUID: usize = 146; +pub const SYS_SETRESUID: usize = 147; +pub const SYS_GETRESUID: usize = 148; +pub const SYS_SETRESGID: usize = 149; +pub const SYS_GETRESGID: usize = 150; +pub const SYS_SETFSUID: usize = 151; +pub const SYS_SETFSGID: usize = 152; +pub const SYS_TIMES: usize = 153; +pub const SYS_SETPGID: usize = 154; +pub const SYS_GETPGID: usize = 155; +pub const SYS_GETSID: usize = 156; +pub const SYS_SETSID: usize = 157; +pub const SYS_GETGROUPS: usize = 158; +pub const SYS_SETGROUPS: usize = 159; +pub const SYS_UNAME: usize = 160; +pub const SYS_SETHOSTNAME: usize = 161; +pub const SYS_SETDOMAINNAME: usize = 162; +pub const SYS_GETRUSAGE: usize = 165; +pub const SYS_UMASK: usize = 166; +pub const SYS_PRCTL: usize = 167; +pub const SYS_GETCPU: usize = 168; +pub const SYS_GETTIMEOFDAY: usize = 169; +pub const SYS_SETTIMEOFDAY: usize = 170; +pub const SYS_ADJTIMEX: usize = 171; +pub const SYS_GETPID: usize = 172; +pub const SYS_GETPPID: usize = 173; +pub const SYS_GETUID: usize = 174; +pub const SYS_GETEUID: usize = 175; +pub const SYS_GETGID: usize = 176; +pub const SYS_GETEGID: usize = 177; +pub const SYS_GETTID: usize = 178; +pub const SYS_SYSINFO: usize = 179; +pub const SYS_MQ_OPEN: usize = 180; +pub const SYS_MQ_UNLINK: usize = 181; +pub const SYS_MQ_TIMEDSEND: usize = 182; +pub const SYS_MQ_TIMEDRECEIVE: usize = 183; +pub const SYS_MQ_NOTIFY: usize = 184; +pub const SYS_MQ_GETSETATTR: usize = 185; +pub const SYS_MSGGET: usize = 186; +pub const SYS_MSGCTL: usize = 187; +pub const SYS_MSGRCV: usize = 188; +pub const SYS_MSGSND: usize = 189; +pub const SYS_SEMGET: usize = 190; +pub const SYS_SEMCTL: usize = 191; +pub const SYS_SEMTIMEDOP: usize = 192; +pub const SYS_SEMOP: usize = 193; +pub const SYS_SHMGET: usize = 194; +pub const SYS_SHMCTL: usize = 195; +pub const SYS_SHMAT: usize = 196; +pub const SYS_SHMDT: usize = 197; +pub const SYS_SOCKET: usize = 198; +pub const SYS_SOCKETPAIR: usize = 199; +pub const SYS_BIND: usize = 200; +pub const SYS_LISTEN: usize = 201; +pub const SYS_ACCEPT: usize = 202; +pub const SYS_CONNECT: usize = 203; +pub const SYS_GETSOCKNAME: usize = 204; +pub const SYS_GETPEERNAME: usize = 205; +pub const SYS_SENDTO: usize = 206; +pub const SYS_RECVFROM: usize = 207; +pub const SYS_SETSOCKOPT: usize = 208; +pub const SYS_GETSOCKOPT: usize = 209; +pub const SYS_SHUTDOWN: usize = 210; +pub const SYS_SENDMSG: usize = 211; +pub const SYS_RECVMSG: usize = 212; +pub const SYS_READAHEAD: usize = 213; +pub const SYS_BRK: usize = 214; +pub const SYS_MUNMAP: usize = 215; +pub const SYS_MREMAP: usize = 216; +pub const SYS_ADD_KEY: usize = 217; +pub const SYS_REQUEST_KEY: usize = 218; +pub const SYS_KEYCTL: usize = 219; +pub const SYS_CLONE: usize = 220; +pub const SYS_EXECVE: usize = 221; +pub const SYS_MMAP: usize = 222; +pub const SYS_FADVISE64: usize = 223; +pub const SYS_SWAPON: usize = 224; +pub const SYS_SWAPOFF: usize = 225; +pub const SYS_MPROTECT: usize = 226; +pub const SYS_MSYNC: usize = 227; +pub const SYS_MLOCK: usize = 228; +pub const SYS_MUNLOCK: usize = 229; +pub const SYS_MLOCKALL: usize = 230; +pub const SYS_MUNLOCKALL: usize = 231; +pub const SYS_MINCORE: usize = 232; +pub const SYS_MADVISE: usize = 233; +pub const SYS_REMAP_FILE_PAGES: usize = 234; +pub const SYS_MBIND: usize = 235; +pub const SYS_GET_MEMPOLICY: usize = 236; +pub const SYS_SET_MEMPOLICY: usize = 237; +pub const SYS_MIGRATE_PAGES: usize = 238; +pub const SYS_MOVE_PAGES: usize = 239; +pub const SYS_RT_TGSIGQUEUEINFO: usize = 240; +pub const SYS_PERF_EVENT_OPEN: usize = 241; +pub const SYS_ACCEPT4: usize = 242; +pub const SYS_RECVMMSG: usize = 243; +//pub const SYS_ARCH_SPECIFIC_SYSCALL: usize = 244; +pub const SYS_WAIT4: usize = 260; +pub const SYS_PRLIMIT64: usize = 261; +pub const SYS_FANOTIFY_INIT: usize = 262; +pub const SYS_FANOTIFY_MARK: usize = 263; +pub const SYS_NAME_TO_HANDLE_AT: usize = 264; +pub const SYS_OPEN_BY_HANDLE_AT: usize = 265; +pub const SYS_CLOCK_ADJTIME: usize = 266; +pub const SYS_SYNCFS: usize = 267; +pub const SYS_SETNS: usize = 268; +pub const SYS_SENDMMSG: usize = 269; +pub const SYS_PROCESS_VM_READV: usize = 270; +pub const SYS_PROCESS_VM_WRITEV: usize = 271; +pub const SYS_KCMP: usize = 272; +pub const SYS_FINIT_MODULE: usize = 273; +pub const SYS_SCHED_SETATTR: usize = 274; +pub const SYS_SCHED_GETATTR: usize = 275; +pub const SYS_RENAMEAT2: usize = 276; +pub const SYS_SECCOMP: usize = 277; +pub const SYS_GETRANDOM: usize = 278; +pub const SYS_MEMFD_CREATE: usize = 279; +pub const SYS_BPF: usize = 280; +pub const SYS_EXECVEAT: usize = 281; +pub const SYS_USERFAULTFD: usize = 282; +pub const SYS_MEMBARRIER: usize = 283; +pub const SYS_MLOCK2: usize = 284; +pub const SYS_COPY_FILE_RANGE: usize = 285; +pub const SYS_PREADV2: usize = 286; +pub const SYS_PWRITEV2: usize = 287; +pub const SYS_PKEY_MPROTECT: usize = 288; +pub const SYS_PKEY_ALLOC: usize = 289; +pub const SYS_PKEY_FREE: usize = 290; +pub const SYS_STATX: usize = 291; +pub const SYS_IO_PGETEVENTS: usize = 292; +pub const SYS_RSEQ: usize = 293; +pub const SYS_KEXEC_FILE_LOAD: usize = 294; +pub const SYS_PIDFD_SEND_SIGNAL: usize = 424; +pub const SYS_IO_URING_SETUP: usize = 425; +pub const SYS_IO_URING_ENTER: usize = 426; +pub const SYS_IO_URING_REGISTER: usize = 427; +pub const SYS_OPEN_TREE: usize = 428; +pub const SYS_MOVE_MOUNT: usize = 429; +pub const SYS_FSOPEN: usize = 430; +pub const SYS_FSCONFIG: usize = 431; +pub const SYS_FSMOUNT: usize = 432; +pub const SYS_FSPICK: usize = 433; +pub const SYS_PIDFD_OPEN: usize = 434; +pub const SYS_CLONE3: usize = 435; +pub const SYS_CLOSE_RANGE: usize = 436; +pub const SYS_OPENAT2: usize = 437; +pub const SYS_PIDFD_GETFD: usize = 438; +pub const SYS_FACCESSAT2: usize = 439; +pub const SYS_PROCESS_MADVISE: usize = 440; +pub const SYS_EPOLL_PWAIT2: usize = 441; +pub const SYS_MOUNT_SETATTR: usize = 442; +pub const SYS_QUOTACTL_FD: usize = 443; +pub const SYS_LANDLOCK_CREATE_RULESET: usize = 444; +pub const SYS_LANDLOCK_ADD_RULE: usize = 445; +pub const SYS_LANDLOCK_RESTRICT_SELF: usize = 446; +pub const SYS_PROCESS_MRELEASE: usize = 448; +pub const SYS_FUTEX_WAITV: usize = 449; +pub const SYS_SET_MEMPOLICY_HOME_NODE: usize = 450; + +// ===以下是为了代码一致性,才定义的调用号=== + +pub const SYS_GETDENTS: usize = SYS_GETDENTS64; diff --git a/kernel/src/arch/loongarch64/time.rs b/kernel/src/arch/loongarch64/time.rs new file mode 100644 index 00000000..28f1613d --- /dev/null +++ b/kernel/src/arch/loongarch64/time.rs @@ -0,0 +1,24 @@ +use crate::time::{clocksource::HZ, TimeArch}; + +/// 这个是系统jiffies时钟源的固有频率(不是调频之后的) +pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000; + +pub struct LoongArch64TimeArch; + +impl TimeArch for LoongArch64TimeArch { + fn get_cycles() -> usize { + todo!("LoongArch64TimeArch::get_cycles") + } + + fn cal_expire_cycles(ns: usize) -> usize { + todo!("LoongArch64TimeArch::cal_expire_cycles") + } + + fn cycles2ns(cycles: usize) -> usize { + todo!("LoongArch64TimeArch::cycles2ns") + } +} + +pub fn time_init() { + todo!("la64:time_init"); +} diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 4deb8843..88e7837e 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -13,6 +13,11 @@ pub mod riscv64; #[cfg(target_arch = "riscv64")] pub use self::riscv64::*; // 公开riscv64架构下的函数,使外界接口统一 +#[cfg(target_arch = "loongarch64")] +pub mod loongarch64; +#[cfg(target_arch = "loongarch64")] +pub use self::loongarch64::*; // 公开loongarch64架构下的函数,使外界接口统一 + pub mod io; /// TraitPciArch Pci架构相关函数,任何架构都应独立实现trait里的函数 diff --git a/kernel/src/arch/riscv64/ipc/signal.rs b/kernel/src/arch/riscv64/ipc/signal.rs index befb23e2..92d280d5 100644 --- a/kernel/src/arch/riscv64/ipc/signal.rs +++ b/kernel/src/arch/riscv64/ipc/signal.rs @@ -95,9 +95,7 @@ impl From for Signal { impl Into for Signal { fn into(self) -> SigSet { - SigSet { - bits: (1 << (self as usize - 1) as u64), - } + self.into_sigset() } } impl Signal { diff --git a/kernel/src/arch/riscv64/rand.rs b/kernel/src/arch/riscv64/rand.rs index 17edfa82..af25319d 100644 --- a/kernel/src/arch/riscv64/rand.rs +++ b/kernel/src/arch/riscv64/rand.rs @@ -1,13 +1,5 @@ +use crate::libs::rand::soft_rand; + pub fn rand() -> usize { - static mut SEED: u64 = 0xdead_beef_cafe_babe; - let mut buf = [0u8; size_of::()]; - for x in buf.iter_mut() { - unsafe { - // from musl - SEED = SEED.wrapping_mul(0x5851_f42d_4c95_7f2d); - *x = (SEED >> 33) as u8; - } - } - let x: usize = unsafe { core::mem::transmute(buf) }; - return x; + return soft_rand(); } diff --git a/kernel/src/debug/panic/hook.rs b/kernel/src/debug/panic/hook.rs index 8f9995ba..271dc157 100644 --- a/kernel/src/debug/panic/hook.rs +++ b/kernel/src/debug/panic/hook.rs @@ -1,10 +1,26 @@ -use crate::debug::traceback::lookup_kallsyms; use crate::libs::spinlock::SpinLock; -use core::ffi::c_void; -use unwinding::abi::{UnwindContext, UnwindReasonCode, _Unwind_Backtrace, _Unwind_GetIP}; +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(not(target_arch = "loongarch64"))] + { + use unwinding::abi::{UnwindContext, UnwindReasonCode, _Unwind_Backtrace, _Unwind_GetIP}; + use core::ffi::c_void; + use crate::debug::traceback::lookup_kallsyms; + } +} + +static GLOBAL_LOCK: SpinLock<()> = SpinLock::new(()); + +#[cfg(target_arch = "loongarch64")] +pub fn print_stack_trace() { + let _lock = GLOBAL_LOCK.lock(); + println!("This Arch does not support stack trace printing."); +} + +#[cfg(not(target_arch = "loongarch64"))] pub fn print_stack_trace() { - static GLOBAL_LOCK: SpinLock<()> = SpinLock::new(()); let _lock = GLOBAL_LOCK.lock(); println!("Rust Panic Backtrace:"); struct CallbackData { diff --git a/kernel/src/debug/panic/mod.rs b/kernel/src/debug/panic/mod.rs index 915ecd5d..8a6425b8 100644 --- a/kernel/src/debug/panic/mod.rs +++ b/kernel/src/debug/panic/mod.rs @@ -63,6 +63,7 @@ pub fn panic(info: &PanicInfo) -> ! { loop {} } + #[cfg(not(target_arch = "loongarch64"))] if info.can_unwind() { let guard = Box::new(PanicGuard::new()); hook::print_stack_trace(); @@ -79,6 +80,7 @@ pub fn panic(info: &PanicInfo) -> ! { /// The wrapper of `unwinding::panic::begin_panic`. If the panic is /// caught, it will return the result of the function. /// If the panic is not caught, it will return an error. +#[cfg(not(target_arch = "loongarch64"))] pub fn kernel_catch_unwind R>(f: F) -> Result { let res = unwinding::panic::catch_unwind(f); match res { @@ -90,6 +92,7 @@ pub fn kernel_catch_unwind R>(f: F) -> Result } } +#[cfg(not(target_arch = "loongarch64"))] #[allow(unused)] pub fn test_unwind() { struct UnwindTest; diff --git a/kernel/src/driver/serial/serial8250/mod.rs b/kernel/src/driver/serial/serial8250/mod.rs index 257b4bc3..4fc220dd 100644 --- a/kernel/src/driver/serial/serial8250/mod.rs +++ b/kernel/src/driver/serial/serial8250/mod.rs @@ -43,6 +43,9 @@ use super::{uart_manager, UartDriver, UartManager, UartPort, TTY_SERIAL_DEFAULT_ #[cfg(target_arch = "x86_64")] mod serial8250_pio; +#[cfg(target_arch = "loongarch64")] +mod serial8250_la64; + static mut SERIAL8250_ISA_DEVICES: Option> = None; static mut SERIAL8250_ISA_DRIVER: Option> = None; @@ -75,8 +78,11 @@ impl Serial8250Manager { /// 初始化串口设备(在内存管理初始化之前) pub fn early_init(&self) -> Result<(), SystemError> { // todo: riscv64: 串口设备初始化 - #[cfg(not(target_arch = "riscv64"))] + #[cfg(target_arch = "x86_64")] serial8250_pio_port_early_init()?; + + #[cfg(target_arch = "loongarch64")] + serial8250_la64::early_la64_seria8250_init()?; return Ok(()); } @@ -127,7 +133,7 @@ impl Serial8250Manager { return Ok(()); } - #[cfg(target_arch = "riscv64")] + #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))] fn serial_tty_init(&self) -> Result<(), SystemError> { Ok(()) } @@ -564,4 +570,9 @@ pub fn send_to_default_serial8250_port(s: &[u8]) { { crate::arch::driver::sbi::console_putstr(s); } + + #[cfg(target_arch = "loongarch64")] + { + serial8250_la64::send_to_default_serial8250_la64_port(s); + } } diff --git a/kernel/src/driver/serial/serial8250/serial8250_la64.rs b/kernel/src/driver/serial/serial8250/serial8250_la64.rs new file mode 100644 index 00000000..ee11674d --- /dev/null +++ b/kernel/src/driver/serial/serial8250/serial8250_la64.rs @@ -0,0 +1,69 @@ +use system_error::SystemError; + +use crate::{ + arch::MMArch, + libs::spinlock::SpinLock, + mm::{MemoryManagementArch, PhysAddr, VirtAddr}, +}; + +const UART_PADDR_COM1: PhysAddr = PhysAddr::new(0x01FE001E0); + +static mut UART_PORT_COM1: Option> = None; + +struct Serial8250LA64Port { + base_address: VirtAddr, +} + +impl Serial8250LA64Port { + pub fn new(base_address: PhysAddr) -> Self { + Self { + base_address: unsafe { MMArch::phys_2_virt(base_address).unwrap() }, + } + } + + pub fn putchar(&mut self, c: u8) { + let ptr = self.base_address.as_ptr() as *mut u8; + loop { + unsafe { + if ptr.add(5).read_volatile() & (1 << 5) != 0 { + break; + } + } + } + unsafe { + ptr.add(0).write_volatile(c); + } + } + + pub fn getchar(&mut self) -> Option { + let ptr = self.base_address.as_ptr() as *mut u8; + unsafe { + if ptr.add(5).read_volatile() & 1 == 0 { + // The DR bit is 0, meaning no data + None + } else { + // The DR bit is 1, meaning data! + Some(ptr.add(0).read_volatile()) + } + } + } +} + +#[inline(never)] +pub(super) fn early_la64_seria8250_init() -> Result<(), SystemError> { + let port = Serial8250LA64Port::new(UART_PADDR_COM1); + unsafe { + UART_PORT_COM1 = Some(SpinLock::new(port)); + } + send_to_default_serial8250_la64_port(b"[DragonOS] loongarch64 debug uart port initialized!\n"); + Ok(()) +} + +pub(super) fn send_to_default_serial8250_la64_port(s: &[u8]) { + if let Some(com) = unsafe { UART_PORT_COM1.as_ref() } { + let mut cg = com.lock_irqsave(); + for c in s.iter() { + cg.putchar(*c); + } + } +} diff --git a/kernel/src/driver/video/mod.rs b/kernel/src/driver/video/mod.rs index 229e456e..09fede63 100644 --- a/kernel/src/driver/video/mod.rs +++ b/kernel/src/driver/video/mod.rs @@ -155,7 +155,7 @@ impl VideoRefreshManager { } /// 在riscv64平台下暂时不支持 - #[cfg(target_arch = "riscv64")] + #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))] pub unsafe fn video_init() -> Result<(), SystemError> { return Err(SystemError::ENOSYS); } diff --git a/kernel/src/init/boot.rs b/kernel/src/init/boot.rs index ec345fd2..d455d02a 100644 --- a/kernel/src/init/boot.rs +++ b/kernel/src/init/boot.rs @@ -102,7 +102,7 @@ impl BootParams { #[cfg(target_arch = "riscv64")] return Some(self.arch.arch_fdt()); - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", target_arch = "loongarch64"))] return None; } @@ -112,7 +112,7 @@ impl BootParams { #[cfg(target_arch = "riscv64")] return Some(self.arch.fdt_paddr); - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", target_arch = "loongarch64"))] return None; } } diff --git a/kernel/src/init/init.rs b/kernel/src/init/init.rs index 0be5bce2..bdb81276 100644 --- a/kernel/src/init/init.rs +++ b/kernel/src/init/init.rs @@ -103,6 +103,7 @@ fn do_start_kernel() { #[inline(never)] fn init_before_mem_init() { serial_early_init().expect("serial early init failed"); + let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() }; scm_init(video_ok); diff --git a/kernel/src/ipc/generic_signal.rs b/kernel/src/ipc/generic_signal.rs new file mode 100644 index 00000000..9aba1f24 --- /dev/null +++ b/kernel/src/ipc/generic_signal.rs @@ -0,0 +1,206 @@ +use num_traits::FromPrimitive; + +use crate::arch::ipc::signal::{SigSet, MAX_SIG_NUM}; + +/// 信号处理的栈的栈指针的最小对齐 +#[allow(dead_code)] +pub const GENERIC_STACK_ALIGN: u64 = 16; +/// 信号最大值 +#[allow(dead_code)] +pub const GENERIC_MAX_SIG_NUM: usize = 64; + +#[allow(dead_code)] +#[derive(Eq, PartialEq, FromPrimitive)] +#[repr(usize)] +#[allow(non_camel_case_types)] +#[atomic_enum] +pub enum GenericSignal { + INVALID = 0, + SIGHUP = 1, + SIGINT, + SIGQUIT, + SIGILL, + SIGTRAP, + /// SIGABRT和SIGIOT共用这个号码 + SIGABRT_OR_IOT, + SIGBUS, + SIGFPE, + SIGKILL, + SIGUSR1, + + SIGSEGV = 11, + SIGUSR2, + SIGPIPE, + SIGALRM, + SIGTERM, + SIGSTKFLT, + SIGCHLD, + SIGCONT, + SIGSTOP, + SIGTSTP, + + SIGTTIN = 21, + SIGTTOU, + SIGURG, + SIGXCPU, + SIGXFSZ, + SIGVTALRM, + SIGPROF, + SIGWINCH, + /// SIGIO和SIGPOLL共用这个号码 + SIGIO_OR_POLL, + SIGPWR, + + SIGSYS = 31, + + SIGRTMIN = 32, + SIGRTMAX = 64, +} + +impl GenericSignal { + /// 判断一个数字是否为可用的信号 + #[inline] + pub fn is_valid(&self) -> bool { + return (*self) as usize <= MAX_SIG_NUM; + } + + /// const convertor between `Signal` and `SigSet` + pub const fn into_sigset(self) -> SigSet { + SigSet::from_bits_truncate(1 << (self as usize - 1)) + } + + /// 判断一个信号是不是实时信号 + /// + /// ## 返回值 + /// + /// - `true` 这个信号是实时信号 + /// - `false` 这个信号不是实时信号 + #[inline] + pub fn is_rt_signal(&self) -> bool { + return (*self) as usize >= Self::SIGRTMIN.into(); + } +} + +impl From for usize { + fn from(val: GenericSignal) -> Self { + val as usize + } +} + +impl From for GenericSignal { + fn from(value: usize) -> Self { + ::from_usize(value).unwrap_or(GenericSignal::INVALID) + } +} + +impl From for GenericSignal { + fn from(value: i32) -> Self { + if value < 0 { + log::error!("Try to convert an invalid number to GenericSignal"); + return GenericSignal::INVALID; + } else { + return Self::from(value as usize); + } + } +} + +impl From for GenericSigSet { + fn from(val: GenericSignal) -> Self { + GenericSigSet { + bits: (1 << (val as usize - 1) as u64), + } + } +} + +/// SIGCHLD si_codes +#[derive(Debug, Clone, Copy, PartialEq, Eq, ToPrimitive)] +#[allow(dead_code)] +pub enum GenericSigChildCode { + /// child has exited + /// + /// CLD_EXITED + Exited = 1, + /// child was killed + /// + /// CLD_KILLED + Killed = 2, + /// child terminated abnormally + /// + /// CLD_DUMPED + Dumped = 3, + /// traced child has trapped + /// + /// CLD_TRAPPED + Trapped = 4, + /// child has stopped + /// + /// CLD_STOPPED + Stopped = 5, + /// stopped child has continued + /// + /// CLD_CONTINUED + Continued = 6, +} + +impl From for i32 { + fn from(value: GenericSigChildCode) -> Self { + value as i32 + } +} + +bitflags! { + /// 请注意,sigset 这个bitmap, 第0位表示sig=1的信号。也就是说,Signal-1才是sigset_t中对应的位 + #[derive(Default)] + pub struct GenericSigSet:u64 { + const SIGHUP = 1<<0; + const SIGINT = 1<<1; + const SIGQUIT = 1<<2; + const SIGILL = 1<<3; + const SIGTRAP = 1<<4; + /// SIGABRT和SIGIOT共用这个号码 + const SIGABRT_OR_IOT = 1<<5; + const SIGBUS = 1<<6; + const SIGFPE = 1<<7; + const SIGKILL = 1<<8; + const SIGUSR = 1<<9; + const SIGSEGV = 1<<10; + const SIGUSR2 = 1<<11; + const SIGPIPE = 1<<12; + const SIGALRM = 1<<13; + const SIGTERM = 1<<14; + const SIGSTKFLT= 1<<15; + const SIGCHLD = 1<<16; + const SIGCONT = 1<<17; + const SIGSTOP = 1<<18; + const SIGTSTP = 1<<19; + const SIGTTIN = 1<<20; + const SIGTTOU = 1<<21; + const SIGURG = 1<<22; + const SIGXCPU = 1<<23; + const SIGXFSZ = 1<<24; + const SIGVTALRM= 1<<25; + const SIGPROF = 1<<26; + const SIGWINCH = 1<<27; + /// SIGIO和SIGPOLL共用这个号码 + const SIGIO_OR_POLL = 1<<28; + const SIGPWR = 1<<29; + const SIGSYS = 1<<30; + const SIGRTMIN = 1<<31; + // TODO 写上实时信号 + const SIGRTMAX = 1 << (GENERIC_MAX_SIG_NUM-1); + } + + #[repr(C,align(8))] + #[derive(Default)] + pub struct GenericSigFlags:u32{ + const SA_NOCLDSTOP = 1; + const SA_NOCLDWAIT = 2; + const SA_SIGINFO = 4; + const SA_ONSTACK = 0x08000000; + const SA_RESTART = 0x10000000; + const SA_NODEFER = 0x40000000; + const SA_RESETHAND = 0x80000000; + const SA_RESTORER =0x04000000; + const SA_ALL = Self::SA_NOCLDSTOP.bits()|Self::SA_NOCLDWAIT.bits()|Self::SA_NODEFER.bits()|Self::SA_ONSTACK.bits()|Self::SA_RESETHAND.bits()|Self::SA_RESTART.bits()|Self::SA_SIGINFO.bits()|Self::SA_RESTORER.bits(); + } +} diff --git a/kernel/src/ipc/mod.rs b/kernel/src/ipc/mod.rs index 8f794a65..3ff869cd 100644 --- a/kernel/src/ipc/mod.rs +++ b/kernel/src/ipc/mod.rs @@ -1,3 +1,4 @@ +pub mod generic_signal; pub mod pipe; pub mod shm; pub mod signal; diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 6c8ace08..ca4968e2 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,13 +1,16 @@ #![no_main] // <1> #![no_std] #![feature(alloc_error_handler)] +#![feature(asm_goto)] #![feature(new_zeroed_alloc)] #![feature(allocator_api)] #![feature(arbitrary_self_types)] #![feature(concat_idents)] #![feature(const_for)] +#![feature(const_size_of_val)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] +#![feature(c_variadic)] #![feature(c_void_variant)] #![feature(extract_if)] #![feature(fn_align)] @@ -18,8 +21,6 @@ #![feature(slice_ptr_get)] #![feature(sync_unsafe_cell)] #![feature(vec_into_raw_parts)] -#![feature(c_variadic)] -#![feature(asm_goto)] #![feature(linkage)] #![feature(panic_can_unwind)] #![allow(static_mut_refs, non_local_definitions, internal_features)] diff --git a/kernel/src/libs/elf.rs b/kernel/src/libs/elf.rs index f1c660c6..fc531125 100644 --- a/kernel/src/libs/elf.rs +++ b/kernel/src/libs/elf.rs @@ -106,6 +106,19 @@ impl ElfLoader { return self.inner_probe_common(param, ehdr); } + #[cfg(target_arch = "loongarch64")] + pub fn probe_loongarch( + &self, + param: &ExecParam, + ehdr: &FileHeader, + ) -> Result<(), ExecError> { + // 判断架构是否匹配 + if ElfMachine::from(ehdr.e_machine) != ElfMachine::LoongArch { + return Err(ExecError::WrongArchitecture); + } + return self.inner_probe_common(param, ehdr); + } + /// 设置用户堆空间,映射[start, end)区间的虚拟地址,并把brk指针指向end /// /// ## 参数 @@ -512,7 +525,14 @@ impl BinaryLoader for ElfLoader { #[cfg(target_arch = "riscv64")] return self.probe_riscv(param, &ehdr); - #[cfg(not(any(target_arch = "x86_64", target_arch = "riscv64")))] + #[cfg(target_arch = "loongarch64")] + return self.probe_loongarch(param, &ehdr); + + #[cfg(not(any( + target_arch = "x86_64", + target_arch = "riscv64", + target_arch = "loongarch64" + )))] compile_error!("BinaryLoader: Unsupported architecture"); } diff --git a/kernel/src/libs/rand.rs b/kernel/src/libs/rand.rs index 581a0465..2bd3c810 100644 --- a/kernel/src/libs/rand.rs +++ b/kernel/src/libs/rand.rs @@ -5,3 +5,19 @@ bitflags! { const GRND_INSECURE = 0x0004; } } + +// 软件实现的随机数生成器 +#[allow(dead_code)] +pub fn soft_rand() -> usize { + static mut SEED: u64 = 0xdead_beef_cafe_babe; + let mut buf = [0u8; size_of::()]; + for x in buf.iter_mut() { + unsafe { + // from musl + SEED = SEED.wrapping_mul(0x5851_f42d_4c95_7f2d); + *x = (SEED >> 33) as u8; + } + } + let x: usize = unsafe { core::mem::transmute(buf) }; + return x; +} diff --git a/kernel/src/libs/rwlock.rs b/kernel/src/libs/rwlock.rs index 2fabd5c2..10eac058 100644 --- a/kernel/src/libs/rwlock.rs +++ b/kernel/src/libs/rwlock.rs @@ -202,7 +202,6 @@ impl RwLock { return (self.lock.load(Ordering::Relaxed) & WRITER) / WRITER; } - #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] #[allow(dead_code)] #[inline] /// @brief 尝试获得WRITER守卫 @@ -216,7 +215,6 @@ impl RwLock { return r; } //当架构为arm时,有些代码需要作出调整compare_exchange=>compare_exchange_weak - #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] #[allow(dead_code)] #[inline] pub fn try_write_irqsave(&self) -> Option> { @@ -233,7 +231,6 @@ impl RwLock { return r; } - #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] #[allow(dead_code)] fn inner_try_write(&self) -> Option> { let res: bool = self diff --git a/kernel/src/mm/mmio_buddy.rs b/kernel/src/mm/mmio_buddy.rs index ce03c949..0487072b 100644 --- a/kernel/src/mm/mmio_buddy.rs +++ b/kernel/src/mm/mmio_buddy.rs @@ -488,7 +488,6 @@ impl MmioBuddyMemPool { return Err(SystemError::EPERM); } // 计算前导0 - #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] let mut size_exp: u32 = 63 - size.leading_zeros(); // debug!("create_mmio: size_exp: {}", size_exp); // 记录最终申请的空间大小 diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index 0b84aaba..a62df68e 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -927,6 +927,11 @@ impl PageEntry { let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1); super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address() } + + #[cfg(target_arch = "loongarch64")] + { + todo!("la64: PageEntry::address") + } }; if self.present() { @@ -1055,6 +1060,11 @@ impl EntryFlags { // riscv64指向下一级页表的页表项,不应设置R/W/X权限位 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) } + + #[cfg(target_arch = "loongarch64")] + { + Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) + } }; #[cfg(target_arch = "x86_64")] @@ -1070,6 +1080,11 @@ impl EntryFlags { { r } + + #[cfg(target_arch = "loongarch64")] + { + todo!("loongarch64: new_page_table") + } }; } @@ -1147,6 +1162,11 @@ impl EntryFlags { .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false); } } + + #[cfg(target_arch = "loongarch64")] + { + todo!("la64: set_write") + } } /// 当前页表项是否可写 @@ -1280,6 +1300,11 @@ impl EntryFlags { .set_execute(true) .set_page_global(true) } + + #[cfg(target_arch = "loongarch64")] + { + todo!("la64: mmio_flags()") + } } } diff --git a/kernel/src/mm/percpu.rs b/kernel/src/mm/percpu.rs index 58757727..7c2ee513 100644 --- a/kernel/src/mm/percpu.rs +++ b/kernel/src/mm/percpu.rs @@ -25,6 +25,9 @@ impl PerCpu { #[cfg(target_arch = "riscv64")] pub const MAX_CPU_NUM: u32 = 64; + #[cfg(target_arch = "loongarch64")] + pub const MAX_CPU_NUM: u32 = 128; + /// # 初始化PerCpu /// /// 该函数应该在内核初始化时调用一次。 diff --git a/kernel/src/process/idle.rs b/kernel/src/process/idle.rs index 9849326f..ba282118 100644 --- a/kernel/src/process/idle.rs +++ b/kernel/src/process/idle.rs @@ -97,6 +97,11 @@ impl ProcessManager { } return VirtAddr::new(stack_ptr); } + + #[cfg(target_arch = "loongarch64")] + { + todo!("la64: stack_ptr() not implemented yet") + } } /// 获取idle进程数组的引用 diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index ddcb9620..c2e889bb 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -64,6 +64,9 @@ impl PosixOldUtsName { #[cfg(target_arch = "riscv64")] const MACHINE: &[u8] = b"riscv64"; + #[cfg(target_arch = "loongarch64")] + const MACHINE: &[u8] = b"longarch64"; + let mut r = Self { sysname: [0; 65], nodename: [0; 65], diff --git a/kernel/src/sched/clock.rs b/kernel/src/sched/clock.rs index c1eed405..8f75c968 100644 --- a/kernel/src/sched/clock.rs +++ b/kernel/src/sched/clock.rs @@ -16,7 +16,7 @@ impl SchedClock { return CurrentTimeArch::cycles2ns(CurrentTimeArch::get_cycles()) as u64; } - #[cfg(target_arch = "riscv64")] + #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))] { return CurrentTimeArch::cycles2ns(CurrentTimeArch::get_cycles()) as u64; } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 3d052dbe..73ef97cd 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -5,7 +5,6 @@ use core::{ use crate::{ arch::{ipc::signal::SigSet, syscall::nr::*}, - debug::panic::kernel_catch_unwind, filesystem::vfs::syscall::{PosixStatfs, PosixStatx}, ipc::shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey}, libs::{futex::constant::FutexFlag, rand::GRandFlags}, @@ -78,11 +77,13 @@ impl Syscall { /// 系统调用分发器,用于分发系统调用。 /// /// 与[handle]不同,这个函数会捕获系统调用处理函数的panic,返回错误码。 + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] pub fn catch_handle( syscall_num: usize, args: &[usize], frame: &mut TrapFrame, ) -> Result { + use crate::debug::panic::kernel_catch_unwind; let res = kernel_catch_unwind(|| Self::handle(syscall_num, args, frame))?; res } @@ -669,6 +670,8 @@ impl Syscall { SYS_GETPGID => Self::getpgid(Pid::new(args[0])).map(|pid| pid.into()), SYS_GETPPID => Self::getppid().map(|pid| pid.into()), + + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] SYS_FSTAT => { let fd = args[0] as i32; let kstat: *mut PosixKstat = args[1] as *mut PosixKstat; @@ -1130,6 +1133,7 @@ impl Syscall { return Ok(0); } + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] SYS_NEWFSTATAT => { // todo: 这个系统调用还没有实现 @@ -1228,6 +1232,7 @@ impl Syscall { let flags = args[4] as u32; Self::sys_perf_event_open(attr, pid, cpu, group_fd, flags) } + #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] SYS_SETRLIMIT => Ok(0), SYS_RESTART_SYSCALL => Self::restart_syscall(), SYS_RT_SIGPENDING => Self::rt_sigpending(args[0], args[1]), diff --git a/kernel/src/time/mod.rs b/kernel/src/time/mod.rs index 214bf118..004d6283 100644 --- a/kernel/src/time/mod.rs +++ b/kernel/src/time/mod.rs @@ -86,7 +86,7 @@ impl PosixTimeSpec { } } - #[cfg(target_arch = "riscv64")] + #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))] { return PosixTimeSpec::new(0, 0); } diff --git a/tools/.gitignore b/tools/.gitignore index 832dff97..0634b300 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -5,5 +5,6 @@ arch/i386/efi/grub/* arch/x86_64/efi/grub/* *.tar.gz +*.tar.xz build/* target/ \ No newline at end of file diff --git a/tools/BUILD_CONTAINER_VERSION b/tools/BUILD_CONTAINER_VERSION index 12068070..d4a29ee5 100644 --- a/tools/BUILD_CONTAINER_VERSION +++ b/tools/BUILD_CONTAINER_VERSION @@ -1 +1 @@ -v1.9 \ No newline at end of file +v1.10 \ No newline at end of file diff --git a/tools/bootstrap.sh b/tools/bootstrap.sh old mode 100644 new mode 100755 index b8847168..c1d98975 --- a/tools/bootstrap.sh +++ b/tools/bootstrap.sh @@ -251,7 +251,10 @@ rustInstall() { rustup target add riscv64imac-unknown-none-elf --toolchain $RUST_VERSION_OLD-riscv64gc-unknown-linux-gnu rustup target add riscv64gc-unknown-linux-musl --toolchain $RUST_VERSION-riscv64gc-unknown-linux-gnu rustup target add riscv64gc-unknown-linux-musl --toolchain $RUST_VERSION_OLD-riscv64gc-unknown-linux-gnu - + + rustup target add loongarch64-unknown-none --toolchain $RUST_VERSION-x86_64-unknown-linux-gnu + rustup target add loongarch64-unknown-none --toolchain $RUST_VERSION_OLD-x86_64-unknown-linux-gnu + rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu rustup component add rust-src rustup component add llvm-tools-preview @@ -269,6 +272,8 @@ install_python_pkg() } + + ############# 脚本开始 ############## # 读取参数及选项,使用 -help 参数查看详细选项 while true; do @@ -341,7 +346,7 @@ cargo install dadk || exit 1 bashpath=$(cd `dirname $0`; pwd) # 编译安装musl交叉编译工具链 -$SHELL ${bashpath}/install_musl_gcc.sh || (echo "musl交叉编译工具链安装失败" && exit 1) +$SHELL ${bashpath}/install_cross_gcc.sh || (echo "musl交叉编译工具链安装失败" && exit 1) # 编译安装grub $SHELL ${bashpath}/grub_auto_install.sh || (echo "grub安装失败" && exit 1) diff --git a/tools/build_gcc_toolchain.sh b/tools/build_gcc_toolchain.sh old mode 100644 new mode 100755 diff --git a/tools/build_in_docker.sh b/tools/build_in_docker.sh old mode 100644 new mode 100755 index ecfcbbee..f24fdfed --- a/tools/build_in_docker.sh +++ b/tools/build_in_docker.sh @@ -1,6 +1,6 @@ docker rm -f dragonos-build || echo "No existed container" cpu_count=$(cat /proc/cpuinfo |grep "processor"|wc -l) -docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.9 bash << EOF +docker run --rm --privileged=true --cap-add SYS_ADMIN --cap-add MKNOD -v $(pwd):/data -v /dev:/dev -v dragonos-build-cargo:/root/.cargo/registry --name dragonos-build -i dragonos/dragonos-dev:v1.10 bash << EOF source ~/.cargo/env source ~/.bashrc cd /data diff --git a/tools/change_rust_src.sh b/tools/change_rust_src.sh old mode 100644 new mode 100755 diff --git a/tools/check_arch.sh b/tools/check_arch.sh old mode 100644 new mode 100755 diff --git a/tools/configure_network.sh b/tools/configure_network.sh old mode 100644 new mode 100755 diff --git a/tools/docker-entrypoint.sh b/tools/docker-entrypoint.sh old mode 100644 new mode 100755 diff --git a/tools/dump_kernel.sh b/tools/dump_kernel.sh old mode 100644 new mode 100755 diff --git a/tools/grub_auto_install.sh b/tools/grub_auto_install.sh old mode 100644 new mode 100755 diff --git a/tools/init_rust_toolchain.sh b/tools/init_rust_toolchain.sh old mode 100644 new mode 100755 diff --git a/tools/install_musl_gcc.sh b/tools/install_cross_gcc.sh old mode 100644 new mode 100755 similarity index 75% rename from tools/install_musl_gcc.sh rename to tools/install_cross_gcc.sh index 1809f3e7..7e98fa47 --- a/tools/install_musl_gcc.sh +++ b/tools/install_cross_gcc.sh @@ -1,3 +1,5 @@ +#! /bin/bash + ######################################################################### # 这个脚本用于安装musl交叉编译工具链 # 该脚本会自动下载musl交叉编译工具链,并将其添加到PATH中 @@ -12,8 +14,13 @@ MUSL_GCC_VERSION="9.4.0" MUSL_GCC_X86_64_TAR= MUSL_GCC_RISCV64_TAR= +LA64_GCC_VERSION="loongarch64-cross-14.2.0" +LA64_GCC_TAR="${LA64_GCC_VERSION}.tar.xz" + MUSL_GCC_X86_64_DOWNLOAD_URL="" MUSL_GCC_RISCV64_DOWNLOAD_URL="" +LA64_GCC_DOWNLOAD_URL="https://mirrors.dragonos.org.cn/pub/third_party/toolchain/gcc/${LA64_GCC_TAR}" + if [ $USE_GITHUB -eq 1 ]; then echo "Download from github" @@ -21,7 +28,6 @@ if [ $USE_GITHUB -eq 1 ]; then MUSL_GCC_RISCV64_TAR=riscv64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}.tar.xz MUSL_GCC_X86_64_DOWNLOAD_URL="https://github.com/DragonOS-Community/musl-cross-make/releases/download/${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}/${MUSL_GCC_X86_64_TAR}" MUSL_GCC_RISCV64_DOWNLOAD_URL="https://github.com/DragonOS-Community/musl-cross-make/releases/download/${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}/${MUSL_GCC_RISCV64_TAR}" - https://github.com/DragonOS-Community/musl-cross-make/releases/download/9.4.0-231114/riscv64-linux-musl-cross-gcc-9.4.0.tar.xz else echo "Download from mirrors.dragonos.org.cn" MUSL_GCC_X86_64_TAR="x86_64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}.tar.xz" @@ -50,6 +56,7 @@ get_shell_rc_file() trap_handler(){ rm -f $MUSL_GCC_X86_64_TAR rm -f $MUSL_GCC_RISCV64_TAR + rm -f $LA64_GCC_TAR } trap trap_handler EXIT @@ -59,6 +66,20 @@ trap trap_handler SIGINT SHELL_RC=$(get_shell_rc_file) source $SHELL_RC +install_loongarch64_gcc() +{ + echo "正在安装 loongarch64-unknown-linux-gnu 工具链" + + wget ${LA64_GCC_DOWNLOAD_URL} || exit 1 + echo "正在解压 loongarch64-unknown-linux-gnu 工具链" + tar xf $LA64_GCC_TAR -C $INSTALL_POS || exit 1 + echo "正在将 loongarch64-unknown-linux-gnu 工具链添加到 PATH 环境变量中" + echo "export PATH=\$PATH:$INSTALL_POS/${LA64_GCC_VERSION}/bin" >> $SHELL_RC + + echo "loongarch64-unknown-linux-gnu 工具链已成功安装!请运行 source $SHELL_RC 以使更改生效!" + rm -rf $LA64_GCC_TAR || exit 1 +} + # 下载musl交叉编译工具链 # 如果x86_64-linux-musl-gcc或x86_64-linux-musl-g++不存在,则下载 @@ -68,7 +89,7 @@ if [ ! -n "$(which x86_64-linux-musl-gcc)" ] || [ ! -n "$(which x86_64-linux-mus echo "下载完成" echo "开始解压x86_64-linux-musl-gcc" tar xvf $MUSL_GCC_X86_64_TAR -C $INSTALL_POS || exit 1 - echo "PATH=\$PATH:$INSTALL_POS/x86_64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}/bin" >> $SHELL_RC + echo "export PATH=\$PATH:$INSTALL_POS/x86_64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}/bin" >> $SHELL_RC echo "安装完成" echo "开始清理x86_64-linux-musl-gcc的下载缓存" rm -rf $MUSL_GCC_X86_64_TAR || exit 1 @@ -93,6 +114,13 @@ else echo "riscv64-linux-musl-gcc已经安装" fi +if [ ! -n "$(which loongarch64-unknown-linux-gnu-gcc)" ] || [ ! -n "$(which loongarch64-unknown-linux-gnu-g++)" ]; then + install_loongarch64_gcc || exit 1 +else + echo "loongarch64-unknown-linux-gnu-gcc已经安装" +fi + + source $SHELL_RC echo "musl交叉编译工具链安装完成,请运行 source $SHELL_RC 以使musl交叉编译工具链在当前窗口生效!" diff --git a/tools/qemu/.gitignore b/tools/qemu/.gitignore new file mode 100644 index 00000000..f91f5825 --- /dev/null +++ b/tools/qemu/.gitignore @@ -0,0 +1,3 @@ +/source_packages +/build_dir +*.log \ No newline at end of file diff --git a/tools/qemu/build-qemu-la64-for-ubuntu.sh b/tools/qemu/build-qemu-la64-for-ubuntu.sh new file mode 100755 index 00000000..25fe9534 --- /dev/null +++ b/tools/qemu/build-qemu-la64-for-ubuntu.sh @@ -0,0 +1,155 @@ +#!/bin/bash +set -e + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +# 默认参数 +QEMU_VERSION="9.2.1" +TARGET_LIST="loongarch64-softmmu" +USE_MIRROR=0 +DEST_DIR="${HOME}/opt/qemu-${QEMU_VERSION}" +SOURCE_PACKAGES_DIR="$SCRIPT_DIR/source_packages" +BUILD_DIR="$SCRIPT_DIR/build_dir" + +SUDO=sudo +FORCE=0 + +# 检查是否为root用户 +if [ "$(id -u)" -eq 0 ]; then + SUDO="" +fi + +# 参数解析 +while [[ $# -gt 0 ]]; do + case "$1" in + --version) + QEMU_VERSION="$2" + shift 2 + DEST_DIR="${HOME}/opt/qemu-${QEMU_VERSION}" # 更新默认路径 + ;; + --target-list) + TARGET_LIST="$2" + shift 2 + ;; + --use-mirror) + USE_MIRROR=1 + shift + ;; + --dest-dir) + DEST_DIR="$2" + shift 2 + ;; + -f|--force) + FORCE=1 + shift + ;; + *) + echo "未知参数: $1" + exit 1 + ;; + esac +done + +# 检查是否已存在qemu-system-loongarch64 +QEMU_BINARY="${DEST_DIR}/bin/qemu-system-loongarch64" +if [ -f "$QEMU_BINARY" ] && [ "$FORCE" -eq 0 ]; then + echo "检测到已存在 qemu-system-loongarch64 在 ${QEMU_BINARY}" + echo "如需强制重新构建,请使用 -f 或 --force 参数" + exit 1 +fi + +# 依赖检查函数 +check_dependency() { + if ! dpkg -l | grep -q "^ii $1 "; then + echo "安装依赖: $1" + ${SUDO} apt-get install -y "$1" + fi +} + +# 镜像源设置 +if [[ $USE_MIRROR -eq 1 ]]; then + echo "使用国内镜像源..." + # APT镜像 + ${SUDO} sed -i \ + 's|//.*archive.ubuntu.com|//mirrors.ustc.edu.cn|g' \ + /etc/apt/sources.list + + # PyPI镜像 + PIP_MIRROR="https://pypi.mirrors.ustc.edu.cn/simple" +else + PIP_MIRROR="https://pypi.org/simple" +fi + +# 更新源 +${SUDO} apt-get update + +# 安装基础依赖 +check_dependency build-essential +check_dependency ninja-build +check_dependency meson +check_dependency pkg-config +check_dependency libglib2.0-dev +check_dependency libslirp-dev +check_dependency wget +check_dependency git + +# Python环境配置 +if ! command -v python3 &> /dev/null; then + ${SUDO} apt-get install -y python3 python3-pip +elif ! command -v pip3 &> /dev/null; then + ${SUDO} apt-get install -y python3-pip +fi + +if ! pip3 show tomli &> /dev/null; then + pip3 install --user -i $PIP_MIRROR tomli +fi + +# 创建目录结构 +mkdir -p "$DEST_DIR" +mkdir -p $SOURCE_PACKAGES_DIR +mkdir -p $BUILD_DIR + +# 下载源码包 +QEMU_TAR="qemu-${QEMU_VERSION}.tar.xz" +QEMU_SRC_DIR="$SOURCE_PACKAGES_DIR/qemu-${QEMU_VERSION}" + +if [ ! -f "$SOURCE_PACKAGES_DIR/${QEMU_TAR}" ]; then + echo "正在下载QEMU源码包..." + wget "https://download.qemu.org/${QEMU_TAR}" -O "$SOURCE_PACKAGES_DIR/${QEMU_TAR}" +fi + +# 解压源码 +if [ ! -d "${QEMU_SRC_DIR}" ]; then + echo "解压QEMU源码..." + tar xf "$SOURCE_PACKAGES_DIR/${QEMU_TAR}" -C $SOURCE_PACKAGES_DIR +fi + +# 配置构建目录 +BUILD_DIR="$BUILD_DIR/qemu-${QEMU_VERSION}_${TARGET_LIST//,/}" +mkdir -p "${BUILD_DIR}" + +pushd $(pwd) + +cd "${BUILD_DIR}" + +# 运行配置 +echo "配置编译参数..." +"${QEMU_SRC_DIR}/configure" \ + --prefix="$DEST_DIR" \ + --enable-slirp \ + --target-list="$TARGET_LIST" \ + --enable-kvm + +# 编译和安装 +echo "开始编译(使用$(nproc)线程)..." +make -j "$(nproc)" +make install + +popd +# 清理 +rm -rf "./${BUILD_DIR}" +rm -rf "${QEMU_SRC_DIR}" + +echo -e "\n编译完成!安装路径: ${DEST_DIR}" +echo -e "运行以下命令使用QEMU:" +echo -e " 或者将其添加到你的shell配置文件中(例如~/.bashrc或~/.zshrc):" +echo "export PATH=\"${DEST_DIR}/bin:\$PATH\"" diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh old mode 100644 new mode 100755 index 9df94cc5..a97a34f0 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -6,6 +6,16 @@ check_dependencies() exit 1 fi + if [ -z "$(which ${QEMU})" ]; then + if [ "$ARCH" == "loongarch64" ]; then + echo -e "\nPlease install qemu-system-loongarch64 first!" + echo -e "\nYou can install it by running: (if you are using ubuntu)" + echo -e " ${ROOT_PATH}/tools/qemu/build-qemu-la64-for-ubuntu.sh" + echo -e "" + exit 1 + fi + fi + # Check if brctl is installed if [ -z "$(which brctl)" ]; then echo "Please install bridge-utils first!" @@ -26,7 +36,6 @@ check_dependencies() } -check_dependencies # 进行启动前检查 flag_can_run=1 @@ -38,6 +47,8 @@ allflags= # 设置ARCH环境变量,如果没有设置,就默认为x86_64 export ARCH=${ARCH:=x86_64} echo "ARCH=${ARCH}" + + #ARCH="i386" # 请根据自己的需要,在-d 后方加入所需的 trace 事件 @@ -67,7 +78,7 @@ RISCV64_UBOOT_PATH="arch/riscv64/u-boot-${UBOOT_VERSION}-riscv64" DISK_NAME="disk-image-${ARCH}.img" -QEMU=qemu-system-${ARCH} +QEMU=$(which qemu-system-${ARCH}) QEMU_DISK_IMAGE="../bin/${DISK_NAME}" QEMU_MEMORY="512M" QEMU_MEMORY_BACKEND="dragonos-qemu-shm.ram" @@ -85,6 +96,9 @@ QEMU_ACCELARATE="" QEMU_ARGUMENT=" -no-reboot " QEMU_DEVICES="" + +check_dependencies + # 设置无图形界面模式 QEMU_NOGRAPHIC=false @@ -93,6 +107,7 @@ KERNEL_CMDLINE=" " BIOS_TYPE="" #这个变量为true则使用virtio磁盘 VIRTIO_BLK_DEVICE=true + # 如果qemu_accel不为空 if [ -n "${qemu_accel}" ]; then QEMU_ACCELARATE=" -machine accel=${qemu_accel} " @@ -111,10 +126,15 @@ if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then QEMU_DEVICES_DISK="-device virtio-blk-pci,drive=disk -device pci-bridge,chassis_nr=1,id=pci.1 -device pcie-root-port " fi -else +elif [ ${ARCH} == "riscv64" ]; then QEMU_MACHINE=" -machine virt,memory-backend=${QEMU_MEMORY_BACKEND} -cpu sifive-u54 " QEMU_DEVICES_DISK="-device virtio-blk-device,drive=disk " - +elif [ ${ARCH} == "loongarch64" ]; then + QEMU_MACHINE=" -machine virt" + QEMU_DEVICES_DISK="-device virtio-blk-pci,drive=disk -device pci-bridge,chassis_nr=1,id=pci.1 -device pcie-root-port " +else + echo "Unsupported architecture: ${ARCH}" + exit 1 fi if [ ${ARCH} == "riscv64" ]; then @@ -153,7 +173,9 @@ if [ ${QEMU_NOGRAPHIC} == true ]; then QEMU_SERIAL=" -serial chardev:mux -monitor chardev:mux -chardev stdio,id=mux,mux=on,signal=off,logfile=${QEMU_SERIAL_LOG_FILE} " # 添加 virtio console 设备 - if [${ARCH} == "x86_64" ]; then + if [ ${ARCH} == "x86_64" ]; then + QEMU_DEVICES+=" -device virtio-serial -device virtconsole,chardev=mux " + elif [ ${ARCH} == "loongarch64" ]; then QEMU_DEVICES+=" -device virtio-serial -device virtconsole,chardev=mux " elif [ ${ARCH} == "riscv64" ]; then QEMU_DEVICES+=" -device virtio-serial-device -device virtconsole,chardev=mux " @@ -164,7 +186,9 @@ if [ ${QEMU_NOGRAPHIC} == true ]; then QEMU_ARGUMENT+=" --nographic " if [ ${ARCH} == "x86_64" ]; then - QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf " + QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf " + elif [ ${ARCH} == "loongarch64" ]; then + QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf " fi fi @@ -245,6 +269,8 @@ else # 如果是riscv64架构,就与efi启动一样 install_riscv_uboot sudo ${QEMU} -kernel ${RISCV64_UBOOT_PATH}/u-boot.bin ${QEMU_ARGUMENT} -append "${KERNEL_CMDLINE}" + elif [ ${ARCH} == loongarch64 ] ;then + sudo ${QEMU} ${QEMU_ARGUMENT} else echo "不支持的架构: ${ARCH}" fi diff --git a/tools/write_disk_image.sh b/tools/write_disk_image.sh old mode 100644 new mode 100755 diff --git a/user/Makefile b/user/Makefile index c21d6179..0b9c3a98 100644 --- a/user/Makefile +++ b/user/Makefile @@ -2,7 +2,7 @@ user_sub_dirs = apps DADK_VERSION=$(shell dadk -V | awk 'END {print $$2}') # 最小的DADK版本 -MIN_DADK_VERSION = 0.2.0 +MIN_DADK_VERSION = 0.3.0 DADK_CACHE_DIR = $(ROOT_PATH)/bin/dadk_cache ECHO: @@ -17,7 +17,7 @@ ifeq ("$(DADK_VERSION)", "") @echo "\nYou can install dadk by running the following command:" @echo "\n\tcargo install dadk" @echo "\nOr you can install dadk from source by running the following command:" - @echo "\n\tcargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION)" + @echo "\n\tcargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION)" --locked @echo "\n" @echo "Auto installing dadk..." cargo install dadk @@ -28,7 +28,7 @@ else ifneq ($(shell printf '%s\n%s' "$(DADK_VERSION)" "$(MIN_DADK_VERSION)" | sort -V | head -n1), $(MIN_DADK_VERSION)) @echo "dadk version is too low, please update to $(MIN_DADK_VERSION) or higher version" @echo "Updating dadk..." - cargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION) || (echo "dadk update failed" && exit 1) + cargo install --git https://git.mirrors.dragonos.org.cn/DragonOS-Community/DADK.git --tag v$(MIN_DADK_VERSION) --locked || (echo "dadk update failed" && exit 1) @echo "dadk updated" endif endif