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
113 changes: 113 additions & 0 deletions kernel/src/arch/loongarch64/interrupt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,116 @@ impl crate::process::rseq::RseqTrapFrame for TrapFrame {
self.csr_era = ip;
}
}

/// Linux 兼容的用户寄存器结构体 (LoongArch64)
///
/// 严格按照 Linux 6.6.21 的 `arch/loongarch/include/uapi/asm/ptrace.h` 中的
///
/// 该结构体用于 ptrace 系统调用向用户空间暴露寄存器信息。
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/uapi/asm/ptrace.h#30
#[repr(C, align(8))]
#[derive(Debug, Clone, Copy, Default)]
pub struct UserRegsStruct {
/// 主处理器寄存器 (r0-r31)
pub regs: [u64; 32],
/// 原始系统调用参数 a0
pub orig_a0: u64,
/// CSR ERA (Exception Return Address)
pub csr_era: u64,
/// CSR BADV (Bad Virtual Address)
pub csr_badv: u64,
/// 保留字段
pub reserved: [u64; 10],
}

impl UserRegsStruct {
/// 从 TrapFrame 创建 UserRegsStruct
///
/// 这对应 Linux 中从 pt_regs 构建 user_pt_regs 的过程。
pub fn from_trap_frame(trap_frame: &TrapFrame) -> Self {
let mut regs = [0u64; 32];
// 按照 LoongArch 寄存器编号映射
regs[0] = trap_frame.r0 as u64;
regs[1] = trap_frame.ra as u64;
regs[2] = trap_frame.tp as u64;
regs[3] = trap_frame.usp as u64;
regs[4] = trap_frame.a0 as u64;
regs[5] = trap_frame.a1 as u64;
regs[6] = trap_frame.a2 as u64;
regs[7] = trap_frame.a3 as u64;
regs[8] = trap_frame.a4 as u64;
regs[9] = trap_frame.a5 as u64;
regs[10] = trap_frame.a6 as u64;
regs[11] = trap_frame.a7 as u64;
regs[12] = trap_frame.t0 as u64;
regs[13] = trap_frame.t1 as u64;
regs[14] = trap_frame.t2 as u64;
regs[15] = trap_frame.t3 as u64;
regs[16] = trap_frame.t4 as u64;
regs[17] = trap_frame.t5 as u64;
regs[18] = trap_frame.t6 as u64;
regs[19] = trap_frame.t7 as u64;
regs[20] = trap_frame.t8 as u64;
regs[21] = trap_frame.r21 as u64;
regs[22] = trap_frame.fp as u64;
regs[23] = trap_frame.s0 as u64;
regs[24] = trap_frame.s1 as u64;
regs[25] = trap_frame.s2 as u64;
regs[26] = trap_frame.s3 as u64;
regs[27] = trap_frame.s4 as u64;
regs[28] = trap_frame.s5 as u64;
regs[29] = trap_frame.s6 as u64;
regs[30] = trap_frame.s7 as u64;
regs[31] = trap_frame.s8 as u64;

Self {
regs,
orig_a0: trap_frame.orig_a0 as u64,
csr_era: trap_frame.csr_era as u64,
csr_badv: trap_frame.csr_badvaddr as u64,
reserved: [0; 10],
}
}

/// 将 UserRegsStruct 的值写回 TrapFrame
///
/// 用于 PTRACE_SETREGS 操作,允许调试器修改被跟踪进程的寄存器。
pub fn write_to_trap_frame(&self, trap_frame: &mut TrapFrame) {
trap_frame.r0 = self.regs[0] as usize;
trap_frame.ra = self.regs[1] as usize;
trap_frame.tp = self.regs[2] as usize;
trap_frame.usp = self.regs[3] as usize;
trap_frame.a0 = self.regs[4] as usize;
trap_frame.a1 = self.regs[5] as usize;
trap_frame.a2 = self.regs[6] as usize;
trap_frame.a3 = self.regs[7] as usize;
trap_frame.a4 = self.regs[8] as usize;
trap_frame.a5 = self.regs[9] as usize;
trap_frame.a6 = self.regs[10] as usize;
trap_frame.a7 = self.regs[11] as usize;
trap_frame.t0 = self.regs[12] as usize;
trap_frame.t1 = self.regs[13] as usize;
trap_frame.t2 = self.regs[14] as usize;
trap_frame.t3 = self.regs[15] as usize;
trap_frame.t4 = self.regs[16] as usize;
trap_frame.t5 = self.regs[17] as usize;
trap_frame.t6 = self.regs[18] as usize;
trap_frame.t7 = self.regs[19] as usize;
trap_frame.t8 = self.regs[20] as usize;
trap_frame.r21 = self.regs[21] as usize;
trap_frame.fp = self.regs[22] as usize;
trap_frame.s0 = self.regs[23] as usize;
trap_frame.s1 = self.regs[24] as usize;
trap_frame.s2 = self.regs[25] as usize;
trap_frame.s3 = self.regs[26] as usize;
trap_frame.s4 = self.regs[27] as usize;
trap_frame.s5 = self.regs[28] as usize;
trap_frame.s6 = self.regs[29] as usize;
trap_frame.s7 = self.regs[30] as usize;
trap_frame.s8 = self.regs[31] as usize;
trap_frame.orig_a0 = self.orig_a0 as usize;
trap_frame.csr_era = self.csr_era as usize;
trap_frame.csr_badvaddr = self.csr_badv as usize;
}
}
133 changes: 129 additions & 4 deletions kernel/src/arch/loongarch64/kprobe.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,144 @@
use crate::arch::interrupt::TrapFrame;

pub fn setup_single_step(frame: &mut TrapFrame, step_addr: usize) {
todo!("la64: setup_single_step")
// LoongArch64 单步调试需要设置 CSR.FWPS 寄存器
// 目前先设置 PC 到目标地址
frame.csr_era = step_addr;
}

pub fn clear_single_step(frame: &mut TrapFrame, return_addr: usize) {
todo!("la64: clear_single_step")
// 清除单步调试状态并设置返回地址
frame.csr_era = return_addr;
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct KProbeContext {}
pub struct KProbeContext {
pub r0: usize,
pub ra: usize,
pub tp: usize,
pub sp: usize,
pub a0: usize,
pub a1: usize,
pub a2: usize,
pub a3: usize,
pub a4: usize,
pub a5: usize,
pub a6: usize,
pub a7: usize,
pub t0: usize,
pub t1: usize,
pub t2: usize,
pub t3: usize,
pub t4: usize,
pub t5: usize,
pub t6: usize,
pub t7: usize,
pub t8: usize,
pub r21: usize,
pub fp: usize,
pub s0: usize,
pub s1: usize,
pub s2: usize,
pub s3: usize,
pub s4: usize,
pub s5: usize,
pub s6: usize,
pub s7: usize,
pub s8: usize,
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 From<&TrapFrame> for KProbeContext {
fn from(trap_frame: &TrapFrame) -> Self {
todo!("from trap frame to kprobe context");
Self {
r0: trap_frame.r0,
ra: trap_frame.ra,
tp: trap_frame.tp,
sp: trap_frame.usp,
a0: trap_frame.a0,
a1: trap_frame.a1,
a2: trap_frame.a2,
a3: trap_frame.a3,
a4: trap_frame.a4,
a5: trap_frame.a5,
a6: trap_frame.a6,
a7: trap_frame.a7,
t0: trap_frame.t0,
t1: trap_frame.t1,
t2: trap_frame.t2,
t3: trap_frame.t3,
t4: trap_frame.t4,
t5: trap_frame.t5,
t6: trap_frame.t6,
t7: trap_frame.t7,
t8: trap_frame.t8,
r21: trap_frame.r21,
fp: trap_frame.fp,
s0: trap_frame.s0,
s1: trap_frame.s1,
s2: trap_frame.s2,
s3: trap_frame.s3,
s4: trap_frame.s4,
s5: trap_frame.s5,
s6: trap_frame.s6,
s7: trap_frame.s7,
s8: trap_frame.s8,
orig_a0: trap_frame.orig_a0,
csr_era: trap_frame.csr_era,
csr_badvaddr: trap_frame.csr_badvaddr,
csr_crmd: trap_frame.csr_crmd,
csr_prmd: trap_frame.csr_prmd,
csr_euen: trap_frame.csr_euen,
csr_ecfg: trap_frame.csr_ecfg,
csr_estat: trap_frame.csr_estat,
}
}
}

// LoongArch 64-bit 架构标识 (EM_LOONGARCH = 258, 64-bit)
const AUDIT_ARCH_LOONGARCH64: u32 = 0xC000_0102;

/// 获取当前架构标识
pub fn syscall_get_arch() -> u32 {
AUDIT_ARCH_LOONGARCH64
}

/// 从 KProbeContext 获取指令指针 (csr_era)
pub fn instruction_pointer(ctx: &KProbeContext) -> u64 {
ctx.csr_era as u64
}

/// 从 KProbeContext 获取用户栈指针 (sp)
pub fn user_stack_pointer(ctx: &KProbeContext) -> u64 {
ctx.sp as u64
}

/// 从 KProbeContext 获取系统调用号 (a7)
/// LoongArch64 使用 a7 寄存器传递系统调用号
pub fn syscall_get_nr(ctx: &KProbeContext) -> u64 {
ctx.a7 as u64
}

/// 从 KProbeContext 获取系统调用返回值 (a0)
pub fn syscall_get_return_value(ctx: &KProbeContext) -> i64 {
ctx.a0 as i64
}

/// 从 KProbeContext 获取系统调用的前 6 个参数
/// LoongArch64 使用 a0-a5 寄存器传递系统调用参数
pub fn syscall_get_arguments(ctx: &KProbeContext, args: &mut [u64; 6]) {
args[0] = ctx.a0 as u64;
args[1] = ctx.a1 as u64;
args[2] = ctx.a2 as u64;
args[3] = ctx.a3 as u64;
args[4] = ctx.a4 as u64;
args[5] = ctx.a5 as u64;
}
123 changes: 123 additions & 0 deletions kernel/src/arch/riscv64/interrupt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,126 @@ impl crate::process::rseq::RseqTrapFrame for TrapFrame {
self.epc = ip;
}
}

/// Linux 兼容的用户寄存器结构体 (RISC-V 64)
///
/// 该结构体用于 ptrace 系统调用向用户空间暴露寄存器信息。
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/uapi/asm/ptrace.h#24
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct UserRegsStruct {
pub pc: u64,
pub ra: u64,
pub sp: u64,
pub gp: u64,
pub tp: u64,
pub t0: u64,
pub t1: u64,
pub t2: u64,
pub s0: u64,
pub s1: u64,
pub a0: u64,
pub a1: u64,
pub a2: u64,
pub a3: u64,
pub a4: u64,
pub a5: u64,
pub a6: u64,
pub a7: u64,
pub s2: u64,
pub s3: u64,
pub s4: u64,
pub s5: u64,
pub s6: u64,
pub s7: u64,
pub s8: u64,
pub s9: u64,
pub s10: u64,
pub s11: u64,
pub t3: u64,
pub t4: u64,
pub t5: u64,
pub t6: u64,
}

impl UserRegsStruct {
/// 从 TrapFrame 创建 UserRegsStruct
///
/// 这对应 Linux 中从 pt_regs 构建 user_regs_struct 的过程。
/// RISC-V 的 user_regs_struct 是 pt_regs 的前缀。
pub fn from_trap_frame(trap_frame: &TrapFrame) -> Self {
Self {
pc: trap_frame.epc as u64,
ra: trap_frame.ra as u64,
sp: trap_frame.sp as u64,
gp: trap_frame.gp as u64,
tp: trap_frame.tp as u64,
t0: trap_frame.t0 as u64,
t1: trap_frame.t1 as u64,
t2: trap_frame.t2 as u64,
s0: trap_frame.s0 as u64,
s1: trap_frame.s1 as u64,
a0: trap_frame.a0 as u64,
a1: trap_frame.a1 as u64,
a2: trap_frame.a2 as u64,
a3: trap_frame.a3 as u64,
a4: trap_frame.a4 as u64,
a5: trap_frame.a5 as u64,
a6: trap_frame.a6 as u64,
a7: trap_frame.a7 as u64,
s2: trap_frame.s2 as u64,
s3: trap_frame.s3 as u64,
s4: trap_frame.s4 as u64,
s5: trap_frame.s5 as u64,
s6: trap_frame.s6 as u64,
s7: trap_frame.s7 as u64,
s8: trap_frame.s8 as u64,
s9: trap_frame.s9 as u64,
s10: trap_frame.s10 as u64,
s11: trap_frame.s11 as u64,
t3: trap_frame.t3 as u64,
t4: trap_frame.t4 as u64,
t5: trap_frame.t5 as u64,
t6: trap_frame.t6 as u64,
}
}

/// 将 UserRegsStruct 的值写回 TrapFrame
///
/// 用于 PTRACE_SETREGS 操作,允许调试器修改被跟踪进程的寄存器。
pub fn write_to_trap_frame(&self, trap_frame: &mut TrapFrame) {
trap_frame.epc = self.pc as usize;
trap_frame.ra = self.ra as usize;
trap_frame.sp = self.sp as usize;
trap_frame.gp = self.gp as usize;
trap_frame.tp = self.tp as usize;
trap_frame.t0 = self.t0 as usize;
trap_frame.t1 = self.t1 as usize;
trap_frame.t2 = self.t2 as usize;
trap_frame.s0 = self.s0 as usize;
trap_frame.s1 = self.s1 as usize;
trap_frame.a0 = self.a0 as usize;
trap_frame.a1 = self.a1 as usize;
trap_frame.a2 = self.a2 as usize;
trap_frame.a3 = self.a3 as usize;
trap_frame.a4 = self.a4 as usize;
trap_frame.a5 = self.a5 as usize;
trap_frame.a6 = self.a6 as usize;
trap_frame.a7 = self.a7 as usize;
trap_frame.s2 = self.s2 as usize;
trap_frame.s3 = self.s3 as usize;
trap_frame.s4 = self.s4 as usize;
trap_frame.s5 = self.s5 as usize;
trap_frame.s6 = self.s6 as usize;
trap_frame.s7 = self.s7 as usize;
trap_frame.s8 = self.s8 as usize;
trap_frame.s9 = self.s9 as usize;
trap_frame.s10 = self.s10 as usize;
trap_frame.s11 = self.s11 as usize;
trap_frame.t3 = self.t3 as usize;
trap_frame.t4 = self.t4 as usize;
trap_frame.t5 = self.t5 as usize;
trap_frame.t6 = self.t6 as usize;
}
}
Loading
Loading