Ver Fonte

feat: la64 boot (#1132)

* la64能够进入到kernel_main
* ci: 添加为ubuntu编译qemu-loongarch64的脚本
* feat: la64能输出hello world
* la64 安装gcc && 配置github ci
* chore: 更新CI工作流和构建脚本中的Docker镜像版本至v1.10

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin há 1 dia atrás
pai
commit
e80796eb82
82 ficheiros alterados com 2299 adições e 118 exclusões
  1. 32 38
      .github/workflows/makefile.yml
  2. 1 0
      .vscode/settings.json
  3. 2 0
      Makefile
  4. 10 0
      build-scripts/kernel_build/src/bindgen/arch/loongarch64.rs
  5. 29 0
      build-scripts/kernel_build/src/cfiles/arch/loongarch64.rs
  6. 3 0
      build-scripts/kernel_build/src/cfiles/arch/mod.rs
  7. 5 0
      build-scripts/kernel_build/src/constant.rs
  8. 1 0
      build-scripts/kernel_build/src/lib.rs
  9. 2 0
      build-scripts/kernel_build/src/utils/cargo_handler.rs
  10. 50 0
      build-scripts/kernel_build/src/utils/mod.rs
  11. 1 1
      dadk-manifest.toml
  12. 2 1
      env.mk
  13. 11 20
      kernel/Cargo.lock
  14. 15 7
      kernel/Cargo.toml
  15. 4 0
      kernel/Makefile
  16. 2 0
      kernel/crates/kprobe/src/arch/loongarch64/mod.rs
  17. 6 0
      kernel/env.mk
  18. 36 3
      kernel/src/Makefile
  19. 14 0
      kernel/src/arch/loongarch64/asm/bitops.rs
  20. 98 0
      kernel/src/arch/loongarch64/asm/boot.rs
  21. 2 0
      kernel/src/arch/loongarch64/asm/mod.rs
  22. 15 0
      kernel/src/arch/loongarch64/cpu.rs
  23. 10 0
      kernel/src/arch/loongarch64/elf.rs
  24. 1 0
      kernel/src/arch/loongarch64/include/asm/asm.h
  25. 54 0
      kernel/src/arch/loongarch64/init/boot.rs
  26. 24 0
      kernel/src/arch/loongarch64/init/mod.rs
  27. 6 0
      kernel/src/arch/loongarch64/interrupt/ipi.rs
  28. 123 0
      kernel/src/arch/loongarch64/interrupt/mod.rs
  29. 1 0
      kernel/src/arch/loongarch64/ipc/mod.rs
  30. 64 0
      kernel/src/arch/loongarch64/ipc/signal.rs
  31. 19 0
      kernel/src/arch/loongarch64/kprobe.rs
  32. 104 0
      kernel/src/arch/loongarch64/link.ld
  33. 21 0
      kernel/src/arch/loongarch64/loongarch64-unknown-none.json
  34. 7 0
      kernel/src/arch/loongarch64/mm/bump.rs
  35. 207 0
      kernel/src/arch/loongarch64/mm/mod.rs
  36. 30 0
      kernel/src/arch/loongarch64/mod.rs
  37. 24 0
      kernel/src/arch/loongarch64/msi.rs
  38. 20 0
      kernel/src/arch/loongarch64/pci/mod.rs
  39. 35 0
      kernel/src/arch/loongarch64/pio.rs
  40. 31 0
      kernel/src/arch/loongarch64/process/idle.rs
  41. 27 0
      kernel/src/arch/loongarch64/process/kthread.rs
  42. 90 0
      kernel/src/arch/loongarch64/process/mod.rs
  43. 28 0
      kernel/src/arch/loongarch64/process/syscall.rs
  44. 5 0
      kernel/src/arch/loongarch64/rand.rs
  45. 17 0
      kernel/src/arch/loongarch64/sched.rs
  46. 29 0
      kernel/src/arch/loongarch64/smp/mod.rs
  47. 8 0
      kernel/src/arch/loongarch64/syscall/mod.rs
  48. 307 0
      kernel/src/arch/loongarch64/syscall/nr.rs
  49. 24 0
      kernel/src/arch/loongarch64/time.rs
  50. 5 0
      kernel/src/arch/mod.rs
  51. 1 3
      kernel/src/arch/riscv64/ipc/signal.rs
  52. 3 11
      kernel/src/arch/riscv64/rand.rs
  53. 20 4
      kernel/src/debug/panic/hook.rs
  54. 3 0
      kernel/src/debug/panic/mod.rs
  55. 13 2
      kernel/src/driver/serial/serial8250/mod.rs
  56. 69 0
      kernel/src/driver/serial/serial8250/serial8250_la64.rs
  57. 1 1
      kernel/src/driver/video/mod.rs
  58. 2 2
      kernel/src/init/boot.rs
  59. 1 0
      kernel/src/init/init.rs
  60. 206 0
      kernel/src/ipc/generic_signal.rs
  61. 1 0
      kernel/src/ipc/mod.rs
  62. 3 2
      kernel/src/lib.rs
  63. 21 1
      kernel/src/libs/elf.rs
  64. 16 0
      kernel/src/libs/rand.rs
  65. 0 3
      kernel/src/libs/rwlock.rs
  66. 0 1
      kernel/src/mm/mmio_buddy.rs
  67. 25 0
      kernel/src/mm/page.rs
  68. 3 0
      kernel/src/mm/percpu.rs
  69. 5 0
      kernel/src/process/idle.rs
  70. 3 0
      kernel/src/process/syscall.rs
  71. 1 1
      kernel/src/sched/clock.rs
  72. 6 1
      kernel/src/syscall/mod.rs
  73. 1 1
      kernel/src/time/mod.rs
  74. 1 0
      tools/.gitignore
  75. 1 1
      tools/BUILD_CONTAINER_VERSION
  76. 7 2
      tools/bootstrap.sh
  77. 1 1
      tools/build_gcc_toolchain.sh
  78. 30 2
      tools/change_rust_src.sh
  79. 3 0
      tools/qemu/.gitignore
  80. 155 0
      tools/qemu/build-qemu-la64-for-ubuntu.sh
  81. 32 6
      tools/run-qemu.sh
  82. 3 3
      tools/write_disk_image.sh

+ 32 - 38
.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
-          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
+          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 kernel -j $(nproc)
+          make ${{ matrix.make_target }} -j $(nproc)

+ 1 - 0
.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": [

+ 2 - 0
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

+ 10 - 0
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作为目标,按理来说问题不大
+    }
+}

+ 29 - 0
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<PathBuf>) {}
+
+    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))
+}

+ 3 - 0
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),
     }
 }

+ 5 - 0
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";

+ 1 - 0
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;
 

+ 2 - 0
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,

+ 50 - 0
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<PathBuf> {
+        let mut queue: Vec<PathBuf> = 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;
+    }
+}

+ 1 - 1
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

+ 2 - 1
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

+ 11 - 20
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",
 ]
 

+ 15 - 7
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]

+ 4 - 0
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

+ 2 - 0
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)
     }
 }
 

+ 6 - 0
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)

+ 36 - 3
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

+ 14 - 0
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
+}

+ 98 - 0
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) }
+}

+ 2 - 0
kernel/src/arch/loongarch64/asm/mod.rs

@@ -0,0 +1,2 @@
+pub mod bitops;
+pub mod boot;

+ 15 - 0
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)
+}

+ 10 - 0
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;
+}

+ 1 - 0
kernel/src/arch/loongarch64/include/asm/asm.h

@@ -0,0 +1 @@
+#pragma once

+ 54 - 0
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::<u128>();
+        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::<u128>();
+        if remaining_bytes > 0 {
+            let remaining_start = bss_start.add(u128_count * core::mem::size_of::<u128>());
+            let remaining_slice = core::slice::from_raw_parts_mut(remaining_start, remaining_bytes);
+            remaining_slice.fill(0);
+        }
+    }
+}

+ 24 - 0
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");
+}

+ 6 - 0
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")
+}

+ 123 - 0
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::<TrapFrame>();
+
+    /// 判断当前中断是否来自用户模式
+    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::<Self>::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()")
+    }
+}

+ 1 - 0
kernel/src/arch/loongarch64/ipc/mod.rs

@@ -0,0 +1 @@
+pub mod signal;

+ 64 - 0
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"),
+        }
+    }
+}

+ 19 - 0
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");
+    }
+}

+ 104 - 0
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) */
+		
+	}
+}

+ 21 - 0
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"
+}

+ 7 - 0
kernel/src/arch/loongarch64/mm/bump.rs

@@ -0,0 +1,7 @@
+use crate::mm::{allocator::bump::BumpAllocator, MemoryManagementArch, PhysMemoryArea};
+
+impl<MMA: MemoryManagementArch> BumpAllocator<MMA> {
+    pub unsafe fn arch_remain_areas(_ret_areas: &mut [PhysMemoryArea], res_count: usize) -> usize {
+        todo!("la64: arch_remain_areas")
+    }
+}

+ 207 - 0
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<LoongArch64MMArch, LockedFrameAllocator>;
+
+/// 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<Self>; 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<crate::mm::ucontext::UserMapper, system_error::SystemError>
+    {
+        todo!()
+    }
+
+    fn make_entry(paddr: crate::mm::PhysAddr, page_flags: usize) -> usize {
+        todo!()
+    }
+}
+
+/// 获取内核地址默认的页面标志
+pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> EntryFlags<A> {
+    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<MMArch>; 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
+}

+ 30 - 0
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() {}

+ 24 - 0
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()")
+}

+ 20 - 0
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());
+    }
+}

+ 35 - 0
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")
+    }
+}

+ 31 - 0
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();
+            }
+        }
+    }
+}

+ 27 - 0
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<KernelThreadCreateInfo>,
+        clone_flags: CloneFlags,
+    ) -> Result<Pid, SystemError> {
+        // 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()")
+    }
+}

+ 90 - 0
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<Self> {
+        todo!("la64: arch_current_pcb")
+    }
+}
+
+impl ProcessManager {
+    pub fn arch_init() {
+        // do nothing
+    }
+    /// fork的过程中复制线程
+    ///
+    /// 由于这个过程与具体的架构相关,所以放在这里
+    pub fn copy_thread(
+        current_pcb: &Arc<ProcessControlBlock>,
+        new_pcb: &Arc<ProcessControlBlock>,
+        clone_args: &KernelCloneArgs,
+        current_trapframe: &TrapFrame,
+    ) -> Result<(), SystemError> {
+        todo!("la64: copy_thread")
+    }
+
+    /// 切换进程
+    ///
+    /// ## 参数
+    ///
+    /// - `prev`:上一个进程的pcb
+    /// - `next`:下一个进程的pcb
+    pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
+        assert!(!CurrentIrqArch::is_irq_enabled());
+        todo!("la64: switch_process");
+    }
+}

+ 28 - 0
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<usize, SystemError> {
+        todo!("la64:arch_prctl")
+    }
+}

+ 5 - 0
kernel/src/arch/loongarch64/rand.rs

@@ -0,0 +1,5 @@
+use crate::libs::rand::soft_rand;
+
+pub fn rand() -> usize {
+    return soft_rand();
+}

+ 17 - 0
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")
+    }
+}

+ 29 - 0
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()")
+    }
+}

+ 8 - 0
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");
+}

+ 307 - 0
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;

+ 24 - 0
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");
+}

+ 5 - 0
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里的函数

+ 1 - 3
kernel/src/arch/riscv64/ipc/signal.rs

@@ -95,9 +95,7 @@ impl From<i32> for Signal {
 
 impl Into<SigSet> for Signal {
     fn into(self) -> SigSet {
-        SigSet {
-            bits: (1 << (self as usize - 1) as u64),
-        }
+        self.into_sigset()
     }
 }
 impl Signal {

+ 3 - 11
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::<usize>()];
-    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();
 }

+ 20 - 4
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 {

+ 3 - 0
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: FnOnce() -> R>(f: F) -> Result<R, SystemError> {
     let res = unwinding::panic::catch_unwind(f);
     match res {
@@ -90,6 +92,7 @@ pub fn kernel_catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, SystemError>
     }
 }
 
+#[cfg(not(target_arch = "loongarch64"))]
 #[allow(unused)]
 pub fn test_unwind() {
     struct UnwindTest;

+ 13 - 2
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<Arc<Serial8250ISADevices>> = None;
 static mut SERIAL8250_ISA_DRIVER: Option<Arc<Serial8250ISADriver>> = 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);
+    }
 }

+ 69 - 0
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<SpinLock<Serial8250LA64Port>> = 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<u8> {
+        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);
+        }
+    }
+}

+ 1 - 1
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);
     }

+ 2 - 2
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;
     }
 }

+ 1 - 0
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);
 

+ 206 - 0
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<GenericSignal> for usize {
+    fn from(val: GenericSignal) -> Self {
+        val as usize
+    }
+}
+
+impl From<usize> for GenericSignal {
+    fn from(value: usize) -> Self {
+        <Self as FromPrimitive>::from_usize(value).unwrap_or(GenericSignal::INVALID)
+    }
+}
+
+impl From<i32> 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<GenericSignal> 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<GenericSigChildCode> 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();
+    }
+}

+ 1 - 0
kernel/src/ipc/mod.rs

@@ -1,3 +1,4 @@
+pub mod generic_signal;
 pub mod pipe;
 pub mod shm;
 pub mod signal;

+ 3 - 2
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)]

+ 21 - 1
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<AnyEndian>,
+    ) -> 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");
     }
 

+ 16 - 0
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::<usize>()];
+    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;
+}

+ 0 - 3
kernel/src/libs/rwlock.rs

@@ -202,7 +202,6 @@ impl<T> RwLock<T> {
         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<T> RwLock<T> {
         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<RwLockWriteGuard<T>> {
@@ -233,7 +231,6 @@ impl<T> RwLock<T> {
         return r;
     }
 
-    #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
     #[allow(dead_code)]
     fn inner_try_write(&self) -> Option<RwLockWriteGuard<T>> {
         let res: bool = self

+ 0 - 1
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);
         // 记录最终申请的空间大小

+ 25 - 0
kernel/src/mm/page.rs

@@ -927,6 +927,11 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
                 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<Arch: MemoryManagementArch> EntryFlags<Arch> {
                     // 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<Arch: MemoryManagementArch> EntryFlags<Arch> {
             {
                 r
             }
+
+            #[cfg(target_arch = "loongarch64")]
+            {
+                todo!("loongarch64: new_page_table")
+            }
         };
     }
 
@@ -1147,6 +1162,11 @@ impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
                     .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false);
             }
         }
+
+        #[cfg(target_arch = "loongarch64")]
+        {
+            todo!("la64: set_write")
+        }
     }
 
     /// 当前页表项是否可写
@@ -1280,6 +1300,11 @@ impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
                 .set_execute(true)
                 .set_page_global(true)
         }
+
+        #[cfg(target_arch = "loongarch64")]
+        {
+            todo!("la64: mmio_flags()")
+        }
     }
 }
 

+ 3 - 0
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
     ///
     /// 该函数应该在内核初始化时调用一次。

+ 5 - 0
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进程数组的引用

+ 3 - 0
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],

+ 1 - 1
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;
         }

+ 6 - 1
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<usize, SystemError> {
+        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]),

+ 1 - 1
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);
         }

+ 1 - 0
tools/.gitignore

@@ -5,5 +5,6 @@ arch/i386/efi/grub/*
 arch/x86_64/efi/grub/*
 
 *.tar.gz
+*.tar.xz
 build/*
 target/

+ 1 - 1
tools/BUILD_CONTAINER_VERSION

@@ -1 +1 @@
-v1.9
+v1.10

+ 7 - 2
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)
 

+ 1 - 1
tools/build_gcc_toolchain.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

+ 30 - 2
tools/change_rust_src.sh → tools/change_rust_src.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交叉编译工具链在当前窗口生效!"

+ 3 - 0
tools/qemu/.gitignore

@@ -0,0 +1,3 @@
+/source_packages
+/build_dir
+*.log

+ 155 - 0
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\""

+ 32 - 6
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

+ 3 - 3
tools/write_disk_image.sh

@@ -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