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
3 changes: 3 additions & 0 deletions kernel/src/arch/loongarch64/interrupt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod entry;
mod handle;
pub mod ipi;
pub mod ptrace;

use core::any::Any;

Expand Down Expand Up @@ -141,3 +142,5 @@ impl crate::process::rseq::RseqTrapFrame for TrapFrame {
self.csr_era = ip;
}
}

pub use ptrace::UserRegsStruct;
122 changes: 122 additions & 0 deletions kernel/src/arch/loongarch64/interrupt/ptrace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/// LoongArch64 ptrace 支持
///
/// 参考 Linux 6.6.21: arch/loongarch/include/uapi/asm/ptrace.h
/// https://code.dragonos.org.cn/xref/linux-6.6.21/arch/loongarch/include/uapi/asm/ptrace.h#30

use super::TrapFrame;

/// Linux 兼容的用户寄存器结构体 (LoongArch64)
///
/// 该结构体用于 ptrace 系统调用向用户空间暴露寄存器信息。
/// 字段顺序和类型与 Linux 6.6.21 的 user_pt_regs 完全一致。
#[repr(C, align(8))]
#[derive(Debug, Clone, Copy, Default)]
pub struct UserRegsStruct {
/// 主处理器寄存器 (r0-r31)
pub regs: [usize; 32],
/// 原始系统调用参数 a0
pub orig_a0: usize,
/// CSR ERA (Exception Return Address)
pub csr_era: usize,
/// CSR BADV (Bad Virtual Address)
pub csr_badv: usize,
/// 保留字段
pub reserved: [usize; 10],
}

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

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

/// 将 UserRegsStruct 的值写回 TrapFrame
///
/// 用于 PTRACE_SETREGS 操作,允许调试器修改被跟踪进程的寄存器。
///
/// 参考 Linux 6.6.21: arch/loongarch/kernel/ptrace.c 中的 `user_regset_set`
pub fn write_to_trap_frame(&self, trap_frame: &mut TrapFrame) {
trap_frame.r0 = self.regs[0];
trap_frame.ra = self.regs[1];
trap_frame.tp = self.regs[2];
trap_frame.usp = self.regs[3];
trap_frame.a0 = self.regs[4];
trap_frame.a1 = self.regs[5];
trap_frame.a2 = self.regs[6];
trap_frame.a3 = self.regs[7];
trap_frame.a4 = self.regs[8];
trap_frame.a5 = self.regs[9];
trap_frame.a6 = self.regs[10];
trap_frame.a7 = self.regs[11];
trap_frame.t0 = self.regs[12];
trap_frame.t1 = self.regs[13];
trap_frame.t2 = self.regs[14];
trap_frame.t3 = self.regs[15];
trap_frame.t4 = self.regs[16];
trap_frame.t5 = self.regs[17];
trap_frame.t6 = self.regs[18];
trap_frame.t7 = self.regs[19];
trap_frame.t8 = self.regs[20];
trap_frame.r21 = self.regs[21];
trap_frame.fp = self.regs[22];
trap_frame.s0 = self.regs[23];
trap_frame.s1 = self.regs[24];
trap_frame.s2 = self.regs[25];
trap_frame.s3 = self.regs[26];
trap_frame.s4 = self.regs[27];
trap_frame.s5 = self.regs[28];
trap_frame.s6 = self.regs[29];
trap_frame.s7 = self.regs[30];
trap_frame.s8 = self.regs[31];
trap_frame.orig_a0 = self.orig_a0;
trap_frame.csr_era = self.csr_era;
trap_frame.csr_badvaddr = self.csr_badv;
}
}
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;
}
3 changes: 3 additions & 0 deletions kernel/src/arch/riscv64/interrupt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use super::cpu::STACK_ALIGN;
pub(super) mod entry;
mod handle;
pub mod ipi;
pub mod ptrace;

pub struct RiscV64InterruptArch;

Expand Down Expand Up @@ -198,3 +199,5 @@ impl crate::process::rseq::RseqTrapFrame for TrapFrame {
self.epc = ip;
}
}

pub use ptrace::UserRegsStruct;
Loading
Loading