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>
This commit is contained in:
LoGin
2025-04-20 18:51:45 +08:00
committed by GitHub
parent 167d272792
commit e80796eb82
91 changed files with 2299 additions and 118 deletions

View File

@ -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
if [[ "$ARCH" == "x86_64" ]]; then
export DragonOS_GCC=$HOME/opt/dragonos-gcc/gcc-x86_64-unknown-none/bin
fi
sed -i 's/arch = ".*"/arch = "${{ env.ARCH }}"/' dadk-manifest.toml
make all -j $(nproc)
build-riscv64:
runs-on: ubuntu-latest
container: dragonos/dragonos-dev:v1.9
steps:
- run: echo "Running in dragonos/dragonos-dev:v1.9"
- uses: actions/checkout@v3
with:
submodules: "recursive"
- name: build the DragonOS
shell: bash -ileo pipefail {0}
env:
ARCH: riscv64
HOME: /root
run: |
source ~/.bashrc && source ~/.cargo/env
sed -i 's/arch = ".*"/arch = "${{ env.ARCH }}"/' dadk-manifest.toml
make kernel -j $(nproc)
make ${{ matrix.make_target }} -j $(nproc)

View File

@ -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": [

View File

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

View File

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

View File

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

View File

@ -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),
}
}

View File

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

View File

@ -3,6 +3,7 @@ extern crate lazy_static;
extern crate cc;
mod cfiles;
mod constant;
mod kconfig;
mod utils;

View File

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

View File

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

View File

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

3
env.mk
View File

@ -1,6 +1,7 @@
ifeq ($(ARCH), )
# 在这里设置ARCH可选 x86_64 和 riscv64
# 在这里设置ARCH可选:
# x86_64, riscv64, loongarch64
# !!!!!!!如果不同时调整这里以及vscode的settings.json那么自动补全和检查将会失效
export ARCH?=x86_64
endif

31
kernel/Cargo.lock generated
View File

@ -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",
]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}
}
}

View File

@ -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");
}

View File

@ -0,0 +1,6 @@
use crate::exception::ipi::{IpiKind, IpiTarget};
#[inline(always)]
pub fn send_ipi(kind: IpiKind, target: IpiTarget) {
todo!("la64: send_ipi")
}

View File

@ -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()")
}
}

View File

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

View File

@ -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"),
}
}
}

View File

@ -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");
}
}

View File

@ -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) */
}
}

View File

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

View File

@ -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")
}
}

View File

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

View File

@ -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() {}

View File

@ -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()")
}

View File

@ -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());
}
}

View File

@ -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")
}
}

View File

@ -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();
}
}
}
}

View File

@ -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()")
}
}

View File

@ -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");
}
}

View File

@ -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")
}
}

View File

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

View File

@ -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")
}
}

View File

@ -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()")
}
}

View File

@ -0,0 +1,8 @@
use system_error::SystemError;
pub mod nr;
/// 系统调用初始化
pub fn arch_syscall_init() -> Result<(), SystemError> {
todo!("la64:arch_syscall_init");
}

View File

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

View File

@ -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");
}

View File

@ -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里的函数

View File

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

View File

@ -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();
}

View File

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

View File

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

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

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

View File

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

View File

@ -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();
}
}

View File

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

View File

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

View File

@ -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");
}

View File

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

View File

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

View File

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

View File

@ -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()")
}
}
}

View File

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

View File

@ -97,6 +97,11 @@ impl ProcessManager {
}
return VirtAddr::new(stack_ptr);
}
#[cfg(target_arch = "loongarch64")]
{
todo!("la64: stack_ptr() not implemented yet")
}
}
/// 获取idle进程数组的引用

View File

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

View File

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

View File

@ -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]),

View File

@ -86,7 +86,7 @@ impl PosixTimeSpec {
}
}
#[cfg(target_arch = "riscv64")]
#[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))]
{
return PosixTimeSpec::new(0, 0);
}

1
tools/.gitignore vendored
View File

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

View File

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

7
tools/bootstrap.sh Normal file → Executable file
View File

@ -252,6 +252,9 @@ rustInstall() {
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)

0
tools/build_gcc_toolchain.sh Normal file → Executable file
View File

2
tools/build_in_docker.sh Normal file → Executable file
View File

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

0
tools/change_rust_src.sh Normal file → Executable file
View File

0
tools/check_arch.sh Normal file → Executable file
View File

0
tools/configure_network.sh Normal file → Executable file
View File

0
tools/docker-entrypoint.sh Normal file → Executable file
View File

0
tools/dump_kernel.sh Normal file → Executable file
View File

0
tools/grub_auto_install.sh Normal file → Executable file
View File

0
tools/init_rust_toolchain.sh Normal file → Executable file
View File

View File

@ -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
tools/qemu/.gitignore vendored Normal file
View File

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

View File

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

36
tools/run-qemu.sh Normal file → Executable file
View File

@ -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 "
@ -165,6 +187,8 @@ if [ ${QEMU_NOGRAPHIC} == true ]; then
if [ ${ARCH} == "x86_64" ]; then
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

0
tools/write_disk_image.sh Normal file → Executable file
View File

View File

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