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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CosmOS-rootfs
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,15 @@ run-la: check-kernel-la $(LA_BOOTLOADER_ELF) $(DISK_LA_IMG) prepare-run-test-fs-
fast-run: check-kernel
$(QEMU) -machine virt -kernel kernel-rv -m $(MEM) -nographic -smp $(SMP) -bios default $(QEMU_COMP_BLK_ARGS) -device virtio-net-device,netdev=net -netdev $(FAST_RUN_QEMU_NETDEV) -no-reboot -rtc base=utc $(QEMU_COMP_EXTRA_BLK_ARGS) $(QEMU_TRACE_ARGS)

fast-run-trace: check-kernel
$(QEMU) -machine virt -kernel kernel-rv -m $(MEM) -nographic -smp $(SMP) -bios default $(QEMU_COMP_BLK_ARGS) -device virtio-net-device,netdev=net -netdev $(FAST_RUN_QEMU_NETDEV) -no-reboot -rtc base=utc $(QEMU_COMP_EXTRA_BLK_ARGS) $(QEMU_TRACE_ARGS) -d int,in_asm -D qemu.log

fast-run-la: check-kernel-la $(LA_BOOTLOADER_ELF)
$(QEMU_LA) -machine virt -cpu la464 -kernel $(LA_BOOTLOADER_ELF) -device loader,file=kernel-la,addr=$(LA_KERNEL_ENTRY_PA) -m $(MEM_LA) -nographic -smp $(SMP) $(QEMU_LA_BLK_ARGS) -device virtio-net-pci,netdev=net0,id=net0 -netdev $(QEMU_LA_NETDEV) -no-reboot -rtc base=utc $(QEMU_LA_EXTRA_BLK_ARGS)

fast-run-la-trace: check-kernel-la $(LA_BOOTLOADER_ELF)
$(QEMU_LA) -machine virt -cpu la464 -kernel $(LA_BOOTLOADER_ELF) -device loader,file=kernel-la,addr=$(LA_KERNEL_ENTRY_PA) -m $(MEM_LA) -nographic -smp $(SMP) $(QEMU_LA_BLK_ARGS) -device virtio-net-pci,netdev=net0,id=net0 -netdev $(QEMU_LA_NETDEV) -no-reboot -rtc base=utc $(QEMU_LA_EXTRA_BLK_ARGS) -d int,in_asm -D qemu.log

run-trace: QEMU_TRACE_ARGS = -d int,in_asm -D qemu.log
run-trace: run

Expand Down
5 changes: 3 additions & 2 deletions bootloader/loongarch64-direct/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const UART_THR: usize = 0x00;
const UART_LSR: usize = 0x05;
const UART_LSR_THRE: u8 = 1 << 5;
const KERNEL_ENTRY: usize = 0x9000_0000_9000_0000;
const FDT_BASE: usize = 0x0010_0000;

#[unsafe(no_mangle)]
static mut BOOT_STACK: [u8; 4096] = [0; 4096];
Expand Down Expand Up @@ -45,8 +46,8 @@ extern "C" fn boot_main(hart_id: usize) -> ! {
puts("[boot] jumping to kernel @ 0x90000000\r\n");
}
unsafe {
let entry: extern "C" fn(usize) -> ! = core::mem::transmute(KERNEL_ENTRY);
entry(hart_id);
let entry: extern "C" fn(usize, usize) -> ! = core::mem::transmute(KERNEL_ENTRY);
entry(hart_id, FDT_BASE);
}
}

Expand Down
5 changes: 4 additions & 1 deletion os/src/arch/loongarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ pub mod trap;

pub use hart::{read_time, set_timer_deadline, LoongArchHartId};
pub use paging::LoongArchPaging;
pub use trap::{LoongArchInterruptControl, LoongArchTrapContextAbi, LoongArchTrapMachine};
pub use trap::{
LoongArchInterruptControl, LoongArchSignalAbi, LoongArchSyscallAbi, LoongArchTrapContextAbi,
LoongArchTrapMachine,
};
40 changes: 36 additions & 4 deletions os/src/arch/loongarch64/trap.S
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,50 @@ __restore:
.globl __trap_from_kernel
.align 3
__trap_from_kernel:
# Save all caller-saved GPRs (LoongArch ELF ABI: ra, a0-a7, t0-t8).
# The Rust trap_from_kernel and its callees freely clobber these
# registers; failing to preserve them corrupts the interrupted
# kernel code when the handler returns via ertn.
addi.d $sp, $sp, -256
st.d $ra, $sp, 0
st.d $a0, $sp, 8
st.d $a1, $sp, 16
st.d $t0, $sp, 24
st.d $t1, $sp, 32
st.d $a2, $sp, 24
st.d $a3, $sp, 32
st.d $a4, $sp, 40
st.d $a5, $sp, 48
st.d $a6, $sp, 56
st.d $a7, $sp, 64
st.d $t0, $sp, 72
st.d $t1, $sp, 80
st.d $t2, $sp, 88
st.d $t3, $sp, 96
st.d $t4, $sp, 104
st.d $t5, $sp, 112
st.d $t6, $sp, 120
st.d $t7, $sp, 128
st.d $t8, $sp, 136

la.local $t0, trap_from_kernel
jirl $ra, $t0, 0

ld.d $ra, $sp, 0
ld.d $a0, $sp, 8
ld.d $a1, $sp, 16
ld.d $t0, $sp, 24
ld.d $t1, $sp, 32
ld.d $a2, $sp, 24
ld.d $a3, $sp, 32
ld.d $a4, $sp, 40
ld.d $a5, $sp, 48
ld.d $a6, $sp, 56
ld.d $a7, $sp, 64
ld.d $t0, $sp, 72
ld.d $t1, $sp, 80
ld.d $t2, $sp, 88
ld.d $t3, $sp, 96
ld.d $t4, $sp, 104
ld.d $t5, $sp, 112
ld.d $t6, $sp, 120
ld.d $t7, $sp, 128
ld.d $t8, $sp, 136
addi.d $sp, $sp, 256
ertn
193 changes: 192 additions & 1 deletion os/src/arch/loongarch64/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
use core::arch::{asm, global_asm};

use crate::config::TRAMPOLINE;
use crate::hal::traits::{InterruptControl, TrapCause, TrapContextAbi, TrapInfo, TrapMachine};
use crate::hal::traits::{
CloneArgs, InterruptControl, NamedReg, SyscallAbi, TrapCause, TrapContextAbi, TrapInfo,
TrapMachine,
};
use crate::signal::{SignalAbi, SignalAction, SignalBit, SigSetT, StackT};
use crate::syscall::Pod;
use crate::trap::TrapContext;

global_asm!(include_str!("trap.S"));

Expand Down Expand Up @@ -50,6 +56,12 @@ pub struct LoongArchTrapMachine;
/// LoongArch64 register-layout helpers for the common trap context.
pub struct LoongArchTrapContextAbi;

/// LoongArch64 Linux signal ABI implementation.
pub struct LoongArchSignalAbi;

/// LoongArch64 legacy Linux syscall ABI implementation.
pub struct LoongArchSyscallAbi;

/// LoongArch64 trap frame layout shared with `trap.S`.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
Expand All @@ -65,6 +77,66 @@ pub struct LoongArchTrapContextFrame {
pub fcsr: usize,
}

/// LoongArch musl raw `rt_sigaction` syscall layout:
/// handler, flags, and the low 64 bits of sigset_t.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct LoongArchUserSigAction {
pub handler: usize,
pub sa_flags: usize,
pub sa_mask: u64,
}

impl Pod for LoongArchUserSigAction {}

impl SyscallAbi for LoongArchSyscallAbi {
fn decode_clone_args(args: [usize; 6]) -> CloneArgs {
// Linux LoongArch does not select CONFIG_CLONE_BACKWARDS:
// clone(flags, stack, parent_tidptr, child_tidptr, tls).
CloneArgs {
flags: args[0],
stack: args[1],
parent_tid: args[2],
tls: args[4],
child_tid: args[3],
}
}
}

/// LoongArch musl `mcontext_t`.
///
/// Verified against the local LoongArch musl headers:
/// size = 272, align = 16, pc at 0, gregs at 8, flags at 264.
#[repr(C, align(16))]
#[derive(Debug, Clone, Copy)]
pub struct LoongArchMContext {
pub pc: usize,
pub gregs: [usize; 32],
pub flags: u32,
pub _pad: u32,
}

impl Pod for LoongArchMContext {}

const _: [(); 272] = [(); core::mem::size_of::<LoongArchMContext>()];
const _: [(); 16] = [(); core::mem::align_of::<LoongArchMContext>()];

#[repr(C, align(16))]
#[derive(Debug, Clone, Copy)]
pub struct LoongArchUContext {
pub uc_flags: usize,
pub uc_link: usize,
pub uc_stack: StackT,
pub uc_sigmask: SigSetT,
pub uc_pad: isize,
pub uc_mcontext: LoongArchMContext,
}

impl Pod for LoongArchUContext {}

const _: [(); 448] = [(); core::mem::size_of::<LoongArchUContext>()];
const _: [(); 16] = [(); core::mem::align_of::<LoongArchUContext>()];

/// 用户态 `rt_sigreturn` trampoline 机器码。
///
/// 等价指令序列:
Expand Down Expand Up @@ -201,6 +273,89 @@ impl TrapMachine for LoongArchTrapMachine {
}
}

impl SignalAbi for LoongArchSignalAbi {
type UserSigAction = LoongArchUserSigAction;
type UContext = LoongArchUContext;

fn decode_user_sigaction(action: Self::UserSigAction) -> SignalAction {
SignalAction {
handler: action.handler,
sa_flags: action.sa_flags as u32,
sa_restorer: 0,
sa_mask: SignalBit::from_user_bits(action.sa_mask).bits(),
}
}

fn encode_user_sigaction(action: SignalAction) -> Self::UserSigAction {
Self::UserSigAction {
handler: action.handler,
sa_flags: action.sa_flags as usize,
sa_mask: SignalBit::from_bits(action.sa_mask)
.unwrap_or(SignalBit::empty())
.user_bits(),
}
}

fn user_sigaction_parts(action: &Self::UserSigAction) -> (usize, usize, usize, u64) {
(action.handler, action.sa_flags, 0, action.sa_mask)
}

fn build_ucontext(trap_cx: &TrapContext, old_mask: u64) -> Self::UContext {
let mut gregs = [0usize; 32];
for (idx, reg) in gregs.iter_mut().enumerate() {
*reg = trap_cx.reg(idx);
}
gregs[0] = 0;

Self::UContext {
uc_flags: 0,
uc_link: 0,
uc_stack: StackT {
ss_sp: 0,
ss_flags: 0,
ss_size: 0,
},
uc_sigmask: SigSetT::from_signal_bits(old_mask),
uc_pad: 0,
uc_mcontext: LoongArchMContext {
pc: trap_cx.user_pc(),
gregs,
flags: 0,
_pad: 0,
},
}
}

fn signal_mask(ucontext: &Self::UContext) -> u64 {
ucontext.uc_sigmask.low_bits()
}

fn restore_ucontext(ucontext: &Self::UContext, trap_cx: &mut TrapContext) {
trap_cx.set_user_pc(ucontext.uc_mcontext.pc);
for idx in 1..32 {
trap_cx.set_reg(idx, ucontext.uc_mcontext.gregs[idx]);
}
}

fn saved_pc(ucontext: &Self::UContext) -> usize {
ucontext.uc_mcontext.pc
}

fn set_saved_pc(ucontext: &mut Self::UContext, pc: usize) {
ucontext.uc_mcontext.pc = pc;
}

fn saved_arg0(ucontext: &Self::UContext) -> usize {
let index = <LoongArchTrapContextAbi as TrapContextAbi>::signal_gpr_arg0_index();
ucontext.uc_mcontext.gregs[index]
}

fn set_saved_arg0(ucontext: &mut Self::UContext, value: usize) {
let index = <LoongArchTrapContextAbi as TrapContextAbi>::signal_gpr_arg0_index();
ucontext.uc_mcontext.gregs[index] = value;
}
}

impl TrapContextAbi for LoongArchTrapContextAbi {
type Frame = LoongArchTrapContextFrame;

Expand Down Expand Up @@ -323,6 +478,42 @@ impl TrapContextAbi for LoongArchTrapContextAbi {
frame.f.copy_from_slice(fpregs);
frame.fcsr = fcsr as usize;
}

fn fault_dump_summary(frame: &Self::Frame) -> [NamedReg; 7] {
[
NamedReg { name: "ra", value: frame.r[1] },
NamedReg { name: "sp", value: frame.r[3] },
NamedReg { name: "fp", value: frame.r[22] },
NamedReg { name: "tp", value: frame.r[2] },
NamedReg { name: "a0", value: frame.r[4] },
NamedReg { name: "a1", value: frame.r[5] },
NamedReg { name: "a7", value: frame.r[11] },
]
}

fn fault_dump_detail(frame: &Self::Frame) -> [NamedReg; 19] {
[
NamedReg { name: "a2", value: frame.r[6] },
NamedReg { name: "a3", value: frame.r[7] },
NamedReg { name: "a4", value: frame.r[8] },
NamedReg { name: "a5", value: frame.r[9] },
NamedReg { name: "a6", value: frame.r[10] },
NamedReg { name: "t0", value: frame.r[12] },
NamedReg { name: "t1", value: frame.r[13] },
NamedReg { name: "t2", value: frame.r[14] },
NamedReg { name: "t3", value: frame.r[15] },
NamedReg { name: "t4", value: frame.r[16] },
NamedReg { name: "t5", value: frame.r[17] },
NamedReg { name: "t6", value: frame.r[18] },
NamedReg { name: "t7", value: frame.r[19] },
NamedReg { name: "t8", value: frame.r[20] },
NamedReg { name: "u0", value: frame.r[21] },
NamedReg { name: "s0", value: frame.r[23] },
NamedReg { name: "s1", value: frame.r[24] },
NamedReg { name: "s2", value: frame.r[25] },
NamedReg { name: "s3", value: frame.r[26] },
]
}
}

#[inline]
Expand Down
5 changes: 4 additions & 1 deletion os/src/arch/riscv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ pub mod trap;

pub use hart::RiscvHartId;
pub use paging::Sv39Paging;
pub use trap::{RiscvInterruptControl, RiscvTrapContextAbi, RiscvTrapMachine};
pub use trap::{
RiscvInterruptControl, RiscvSignalAbi, RiscvSyscallAbi, RiscvTrapContextAbi,
RiscvTrapMachine,
};
Loading
Loading