Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
95adf96
增加对 Loongarch64 架构的支持,添加上下文、宏和异常处理功能
SiyuanSun0736 Apr 28, 2025
03c10fa
更新 .gitignore 文件以包含 oscamp-ci 目录,修改 Makefile 以简化 run 目标
SiyuanSun0736 Apr 28, 2025
4f8a7cb
修复调试命令中的函数名,增强数据异常处理的调试信息,更新启动代码以支持不同架构,调整 pflash 地址常量,更新 Rust 工具链版本
SiyuanSun0736 May 7, 2025
58d514b
增强对不同架构的支持,更新 Makefile 和汇编代码以适应架构变化,简化系统调用实现
SiyuanSun0736 May 8, 2025
99526da
增加对系统调用参数的支持,扩展 UspaceContext 的构造函数以适应不同架构,更新主函数以正确初始化用户任务
SiyuanSun0736 May 8, 2025
7b1e966
优化 Makefile 中的构建命令顺序,确保正确传递架构参数;修复 skernel 中的汇编代码格式,增强可读性
SiyuanSun0736 May 8, 2025
5660c2f
修复 AArch64 系统调用实现,确保正确处理栈操作和系统调用号
SiyuanSun0736 May 17, 2025
0dd05d6
增强 AArch64 系统调用实现,修正栈操作并添加用户任务生成的调试信息
SiyuanSun0736 May 17, 2025
b7ae169
增强 AArch64 任务指针缓存功能,添加调试信息以提高可追踪性
SiyuanSun0736 May 17, 2025
817404a
在 Cargo.toml 中添加 axlog 依赖,并在 task.rs 中增加调试信息以增强任务管理的可追踪性
SiyuanSun0736 May 17, 2025
027efdd
在 cpu.rs 中添加调试信息以输出 SP_EL0 的值;在 api.rs 中记录任务退出时的退出代码
SiyuanSun0736 May 17, 2025
9f8b70b
在 trap.S 中添加对用户空间的信任恢复逻辑;在 trap.rs 中更新全局汇编以包含缓存当前任务指针的符号
SiyuanSun0736 May 17, 2025
32936e4
在 Cargo.toml 中添加 axlog 依赖;在 alloc.rs 中增加调试信息以跟踪页面故障处理;在多个 Makefile 中添…
SiyuanSun0736 May 17, 2025
b71be0b
在 trap.rs 中处理 Trapped FP 异常并增加调试信息;在 loader.rs 中添加加载 ELF 头信息的调试输出;在 s…
SiyuanSun0736 May 23, 2025
78219dd
移除多个文件中的调试输出,包括 axlog 的打印语句,以清理代码并提高可读性
SiyuanSun0736 May 23, 2025
5cf0bb4
Merge remote-tracking branch 'upstream/main'
SiyuanSun0736 May 23, 2025
cbe262b
移除 .gitignore 中的 oscamp-ci 目录,以清理不必要的忽略项
SiyuanSun0736 May 23, 2025
927db33
fix u_4
SiyuanSun0736 May 24, 2025
46c6b9d
fix m_3_1
SiyuanSun0736 May 24, 2025
73dc132
modify mk_pflash using argument
SiyuanSun0736 May 25, 2025
d624d5e
fix m_1_1
SiyuanSun0736 May 25, 2025
19c8a86
Submit the Dockerfile and instructions for its use.
SiyuanSun0736 May 25, 2025
cb8bfb2
fix util.mk and force build payload
SiyuanSun0736 May 26, 2025
223150e
try modify ci
SiyuanSun0736 May 26, 2025
6dc5c68
fix ci
SiyuanSun0736 May 26, 2025
a362dc7
test ci
SiyuanSun0736 May 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions arceos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ members = [
"exercises/sys_map",
"exercises/simple_hv",
"exercises/ramfs_rename",

"examples/helloworld",
"examples/httpserver",
]

[workspace.package]
Expand Down
39 changes: 39 additions & 0 deletions arceos/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
FROM rust:slim

RUN echo /etc/apt/sources.list << deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm main
RUN wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc

RUN apt-get update \
&& apt-get install -y --no-install-recommends wget libclang-16-dev make python3 \
xz-utils python3-venv ninja-build bzip2 meson dosfstools xxd\
pkg-config libglib2.0-dev git libslirp-dev vim-common sudo\
&& rm -rf /var/lib/apt/lists/*

RUN cargo install cargo-binutils axconfig-gen

COPY rust-toolchain.toml /rust-toolchain.toml

RUN rustc --version

RUN wget https://musl.cc/aarch64-linux-musl-cross.tgz \
&& wget https://musl.cc/riscv64-linux-musl-cross.tgz \
&& wget https://musl.cc/x86_64-linux-musl-cross.tgz \
&& wget https://github.com/LoongsonLab/oscomp-toolchains-for-oskernel/releases/download/loongarch64-linux-musl-cross-gcc-13.2.0/loongarch64-linux-musl-cross.tgz \
&& tar zxf aarch64-linux-musl-cross.tgz \
&& tar zxf riscv64-linux-musl-cross.tgz \
&& tar zxf x86_64-linux-musl-cross.tgz \
&& tar zxf loongarch64-linux-musl-cross.tgz \
&& rm -f *.tgz

RUN wget https://download.qemu.org/qemu-9.2.1.tar.xz \
&& tar xf qemu-9.2.1.tar.xz \
&& cd qemu-9.2.1 \
&& ./configure --prefix=/qemu-bin-9.2.1 \
--target-list=loongarch64-softmmu,riscv64-softmmu,aarch64-softmmu,x86_64-softmmu \
--enable-gcov --enable-debug --enable-slirp \
&& make -j$(nproc) \
&& make install
RUN rm -rf qemu-9.2.1 qemu-9.2.1.tar.xz

ENV PATH="/x86_64-linux-musl-cross/bin:/aarch64-linux-musl-cross/bin:/riscv64-linux-musl-cross/bin:/loongarch64-linux-musl-cross/bin:$PATH"
ENV PATH="/qemu-bin-9.2.1/bin:$PATH"
4 changes: 2 additions & 2 deletions arceos/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ debug: build
sleep 1
$(GDB) $(OUT_ELF) \
-ex 'target remote localhost:1234' \
-ex 'b rust_entry' \
-ex 'b rust_main' \
-ex 'continue' \
-ex 'disp /16i $$pc'

Expand Down Expand Up @@ -223,7 +223,7 @@ pflash_img:
$(call mk_pflash,$(PFLASH_IMG))

payload:
@make -C ./payload
@make ARCH=$(ARCH) -C ./payload

clean: clean_c
rm -rf $(APP)/*.bin $(APP)/*.elf
Expand Down
56 changes: 54 additions & 2 deletions arceos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Install `libclang-dev`:
sudo apt install libclang-dev
```

Currently, the aarch64 architecture supports u_* and m_* under arceos/tour, but m_3_* requires libclang-*-dev version less than or equal to 16. You can use conda to generate a specified clangdev version for successful compilation. Or use dockerfile directly.

Download & install [musl](https://musl.cc) toolchains:

```bash
Expand Down Expand Up @@ -72,6 +74,8 @@ brew install qemu

Other systems and arch please refer to [Qemu Download](https://www.qemu.org/download/#linux)

For qemu version, it is recommended to use version 9.2.0 or later, otherwise unexpected problems may occur.

### 2. Build & Run

```bash
Expand All @@ -80,8 +84,8 @@ make A=path/to/app ARCH=<arch> LOG=<log>
# e.g. run app in arceos directory
make run A=path/to/app ARCH=<arch> LOG=<log>
# e.g. build&run oscamp tour app tour/u_1_0
make pflash_img
make disk_img
make pflash_img ARCH=<arch>
make disk_img ARCH=<arch>
make run A=tour/u_1_0
# e.g. try to build&run oscamp tour apps
./test_tour.sh
Expand All @@ -93,6 +97,8 @@ Where `path/to/app` is the relative path to the application. Examples applicatio

`<log>` should be one of `off`, `error`, `warn`, `info`, `debug`, `trace`.

If the above command does not specify ARCH, it defaults to risc-V64.

More arguments and targets can be found in [Makefile](Makefile).

For example, to run the [httpserver](examples/httpserver/) on `qemu-system-aarch64` with 4 cores and log level `info`:
Expand All @@ -103,6 +109,52 @@ make A=examples/httpserver ARCH=aarch64 LOG=info SMP=4 run NET=y

Note that the `NET=y` argument is required to enable the network device in QEMU. These arguments (`BLK`, `GRAPHIC`, etc.) only take effect at runtime not build time.


For example, the complete process for tour/m_1_0, aarch64 architecture:
``` bash
make
make ARCH=aarch64
rm -f pflash.img
rm -f disk.img
make pflash_img ARCH=aarch64
make disk_img ARCH=aarch64
make payload ARCH=aarch64
./update_disk.sh ./payload/origin/origin
make run A=tour/m_1_0 ARCH=aarch64 LOG=debug BLK=y
```
For tour/m_1_0,risc-V64 architecture:
``` bash
make
rm -f pflash.img
rm -f disk.img
make pflash_img
make disk_img
make payload
./update_disk.sh ./payload/origin/origin
make run A=tour/m_1_0 LOG=debug BLK=y
```

## Build and Run through Docker
Install [Docker](https://www.docker.com/) in your system.

Then build all dependencies through provided dockerfile:
```bash
docker build -t oscamp -f Dockerfile .
```
Create a container and build/run app:
``` bash
docker run -it --privileged \
-v ~/oscamp:/oscamp \
-w /oscamp/arceos \
oscamp bash
```
"By default, Docker containers are isolated, and for security reasons, they run with a restricted set of Linux Capabilities. The `make disk_img` rule requires the `mount` command, and the `mount` command (as well as `umount`) needs the `CAP_SYS_ADMIN` Linux Capability. By default, Docker containers do not possess this capability, even if you are the `root` user inside the container.

**Solution:**
Use the `--privileged` flag (not recommended for production environments, but convenient for development and debugging).
This flag grants the container almost all Linux Capabilities, including `CAP_SYS_ADMIN`, allowing it to perform operations typically reserved for the `root` user, such as mounting file systems."
# Now build/run app in the container
make A=examples/helloworld ARCH=aarch64 run
## How to write ArceOS apps

You can write and build your custom applications outside the ArceOS source tree.
Expand Down
175 changes: 171 additions & 4 deletions arceos/modules/axhal/src/arch/aarch64/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,149 @@ pub struct TrapFrame {
pub spsr: u64,
}

impl TrapFrame {
/// Gets the 0th syscall argument.
pub const fn arg0(&self) -> usize {
self.r[0] as _
}

/// Gets the 1st syscall argument.
pub const fn arg1(&self) -> usize {
self.r[1] as _
}

/// Gets the 2nd syscall argument.
pub const fn arg2(&self) -> usize {
self.r[2] as _
}

/// Gets the 3rd syscall argument.
pub const fn arg3(&self) -> usize {
self.r[3] as _
}

/// Gets the 4th syscall argument.
pub const fn arg4(&self) -> usize {
self.r[4] as _
}

/// Gets the 5th syscall argument.
pub const fn arg5(&self) -> usize {
self.r[5] as _
}
}

/// Context to enter user space.
#[cfg(feature = "uspace")]
pub struct UspaceContext(TrapFrame);

#[cfg(feature = "uspace")]
impl UspaceContext {
/// Creates an empty context with all registers set to zero.
pub const fn empty() -> Self {
unsafe { core::mem::MaybeUninit::zeroed().assume_init() }
}

/// Creates a new context with the given entry point, user stack pointer,
/// and the argument.
pub fn new(entry: usize, ustack_top: VirtAddr, arg0: usize) -> Self {
use aarch64_cpu::registers::SPSR_EL1;
let mut regs = [0; 31];
regs[0] = arg0 as _;
Self(TrapFrame {
r: regs,
usp: ustack_top.as_usize() as _,
elr: entry as _,
spsr: (SPSR_EL1::M::EL0t
+ SPSR_EL1::D::Masked
+ SPSR_EL1::A::Masked
+ SPSR_EL1::I::Unmasked
+ SPSR_EL1::F::Masked)
.value,
})
}

/// Creates a new context from the given [`TrapFrame`].
pub const fn from(trap_frame: &TrapFrame) -> Self {
Self(*trap_frame)
}

/// Gets the instruction pointer.
pub const fn get_ip(&self) -> usize {
self.0.elr as _
}

/// Gets the stack pointer.
pub const fn get_sp(&self) -> usize {
self.0.usp as _
}

/// Sets the instruction pointer.
pub const fn set_ip(&mut self, pc: usize) {
self.0.elr = pc as _;
}

/// Sets the stack pointer.
pub const fn set_sp(&mut self, sp: usize) {
self.0.usp = sp as _;
}

/// Sets the return value register.
pub const fn set_retval(&mut self, r0: usize) {
self.0.r[0] = r0 as _;
}

/// Enters user space.
///
/// It restores the user registers and jumps to the user entry point
/// (saved in `elr`).
/// When an exception or syscall occurs, the kernel stack pointer is
/// switched to `kstack_top`.
///
/// # Safety
///
/// This function is unsafe because it changes processor mode and the stack.
#[inline(never)]
#[unsafe(no_mangle)]
pub unsafe fn enter_uspace(&self, kstack_top: VirtAddr) -> ! {
super::disable_irqs();
// We do not handle traps that occur at the current exception level,
// so the kstack ptr(`sp_el1`) will not change during running in user space.
// Then we don't need to save the `sp_el1` to the taskctx.
unsafe {
core::arch::asm!(
"
mov sp, x1
ldp x30, x9, [x0, 30 * 8]
ldp x10, x11, [x0, 32 * 8]
msr sp_el0, x9
msr elr_el1, x10
msr spsr_el1, x11

ldp x28, x29, [x0, 28 * 8]
ldp x26, x27, [x0, 26 * 8]
ldp x24, x25, [x0, 24 * 8]
ldp x22, x23, [x0, 22 * 8]
ldp x20, x21, [x0, 20 * 8]
ldp x18, x19, [x0, 18 * 8]
ldp x16, x17, [x0, 16 * 8]
ldp x14, x15, [x0, 14 * 8]
ldp x12, x13, [x0, 12 * 8]
ldp x10, x11, [x0, 10 * 8]
ldp x8, x9, [x0, 8 * 8]
ldp x6, x7, [x0, 6 * 8]
ldp x4, x5, [x0, 4 * 8]
ldp x2, x3, [x0, 2 * 8]
ldp x0, x1, [x0]
eret",
in("x0") &self.0,
in("x1") kstack_top.as_usize() ,
options(noreturn),
)
}
}
}

/// FP & SIMD registers.
#[repr(C, align(16))]
#[derive(Debug, Default)]
Expand Down Expand Up @@ -47,7 +190,7 @@ impl FpState {
/// and the next task restores its context from memory to CPU.
#[allow(missing_docs)]
#[repr(C)]
#[derive(Debug)]
#[derive(Debug, Default)]
pub struct TaskContext {
pub sp: u64,
pub tpidr_el0: u64,
Expand All @@ -63,31 +206,55 @@ pub struct TaskContext {
pub r28: u64,
pub r29: u64,
pub lr: u64, // r30
/// The `ttbr0_el1` register value, i.e., the page table root.
#[cfg(feature = "uspace")]
pub ttbr0_el1: memory_addr::PhysAddr,
#[cfg(feature = "fp_simd")]
pub fp_state: FpState,
}

impl TaskContext {
/// Creates a new default context for a new task.
pub const fn new() -> Self {
unsafe { core::mem::MaybeUninit::zeroed().assume_init() }
/// Creates a dummy context for a new task.
///
/// Note the context is not initialized, it will be filled by [`switch_to`]
/// (for initial tasks) and [`init`] (for regular tasks) methods.
///
/// [`init`]: TaskContext::init
/// [`switch_to`]: TaskContext::switch_to
pub fn new() -> Self {
Self::default()
}

/// Initializes the context for a new task, with the given entry point and
/// kernel stack.
pub fn init(&mut self, entry: usize, kstack_top: VirtAddr, tls_area: VirtAddr) {
self.sp = kstack_top.as_usize() as u64;
self.lr = entry as u64;
// When under `uspace` feature, kernel will not use this register.
self.tpidr_el0 = tls_area.as_usize() as u64;
}

/// Changes the page table root for user space (`ttbr0_el1` register for aarch64 in el1 level).
///
/// If not set, it means that this task is a kernel task and only `ttbr1_el1` register will be used.
#[cfg(feature = "uspace")]
pub fn set_page_table_root(&mut self, ttbr0_el1: memory_addr::PhysAddr) {
self.ttbr0_el1 = ttbr0_el1;
}

/// Switches to another task.
///
/// It first saves the current task's context from CPU to this place, and then
/// restores the next task's context from `next_ctx` to CPU.
pub fn switch_to(&mut self, next_ctx: &Self) {
#[cfg(feature = "fp_simd")]
self.fp_state.switch_to(&next_ctx.fp_state);
#[cfg(feature = "uspace")]
{
if self.ttbr0_el1 != next_ctx.ttbr0_el1 {
unsafe { super::write_page_table_root0(next_ctx.ttbr0_el1) };
}
}
unsafe { context_switch(self, next_ctx) }
}
}
Expand Down
Loading