Clean up `trapframe` items

This commit is contained in:
Ruihan Li 2025-07-01 23:05:34 +08:00 committed by Tate, Hongliang Tian
parent 6f2725419f
commit 0fce977b40
10 changed files with 118 additions and 256 deletions

View File

@ -3,7 +3,7 @@
use alloc::{format, string::String};
use ostd::{
cpu::context::{CpuExceptionInfo, RawGeneralRegs, UserContext},
cpu::context::{CpuExceptionInfo, GeneralRegs, UserContext},
Pod,
};
@ -122,11 +122,11 @@ macro_rules! copy_gp_regs {
}
impl GpRegs {
pub fn copy_to_raw(&self, dst: &mut RawGeneralRegs) {
pub fn copy_to_raw(&self, dst: &mut GeneralRegs) {
copy_gp_regs!(self, dst);
}
pub fn copy_from_raw(&mut self, src: &RawGeneralRegs) {
pub fn copy_from_raw(&mut self, src: &GeneralRegs) {
copy_gp_regs!(src, self);
}
}

View File

@ -7,7 +7,7 @@ use alloc::{
};
use ostd::{
cpu::context::{cpuid, CpuException, CpuExceptionInfo, RawGeneralRegs, UserContext},
cpu::context::{cpuid, CpuException, CpuExceptionInfo, GeneralRegs, UserContext},
Pod,
};
@ -102,11 +102,11 @@ macro_rules! copy_gp_regs {
}
impl GpRegs {
pub fn copy_to_raw(&self, dst: &mut RawGeneralRegs) {
pub fn copy_to_raw(&self, dst: &mut GeneralRegs) {
copy_gp_regs!(self, dst);
}
pub fn copy_from_raw(&mut self, src: &RawGeneralRegs) {
pub fn copy_from_raw(&mut self, src: &GeneralRegs) {
copy_gp_regs!(src, self);
}
}

View File

@ -2,7 +2,7 @@
use aster_rights::WriteOp;
use ostd::{
cpu::context::{FpuState, RawGeneralRegs, UserContext},
cpu::context::{FpuState, GeneralRegs, UserContext},
user::UserContextApi,
};
@ -149,7 +149,7 @@ fn do_execve(
// set signal disposition to default
process.sig_dispositions().lock().inherit();
// set cpu context to default
*user_context.general_regs_mut() = RawGeneralRegs::default();
*user_context.general_regs_mut() = GeneralRegs::default();
user_context.set_tls_pointer(0);
*user_context.fpu_state_mut() = FpuState::default();
// FIXME: how to reset the FPU state correctly? Before returning to the user space,

View File

@ -6,16 +6,15 @@ use core::fmt::Debug;
use riscv::register::scause::{Exception, Interrupt, Trap};
pub use crate::arch::trap::GeneralRegs as RawGeneralRegs;
use crate::{
arch::{
timer::handle_timer_interrupt,
trap::{TrapFrame, UserContext as RawUserContext},
trap::{RawUserContext, TrapFrame},
},
user::{ReturnReason, UserContextApi, UserContextApiInternal},
};
/// Cpu context, including both general-purpose registers and FPU state.
/// Userspace CPU context, including both general-purpose registers and FPU state.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct UserContext {
@ -25,6 +24,45 @@ pub struct UserContext {
cpu_exception_info: CpuExceptionInfo,
}
/// General registers.
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
#[expect(missing_docs)]
pub struct GeneralRegs {
pub zero: usize,
pub ra: usize,
pub sp: usize,
pub gp: usize,
pub tp: usize,
pub t0: usize,
pub t1: usize,
pub t2: usize,
pub s0: usize,
pub s1: 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 s2: usize,
pub s3: usize,
pub s4: usize,
pub s5: usize,
pub s6: usize,
pub s7: usize,
pub s8: usize,
pub s9: usize,
pub s10: usize,
pub s11: usize,
pub t3: usize,
pub t4: usize,
pub t5: usize,
pub t6: usize,
}
/// CPU exception information.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
@ -66,12 +104,12 @@ impl CpuExceptionInfo {
impl UserContext {
/// Returns a reference to the general registers.
pub fn general_regs(&self) -> &RawGeneralRegs {
pub fn general_regs(&self) -> &GeneralRegs {
&self.user_context.general
}
/// Returns a mutable reference to the general registers
pub fn general_regs_mut(&mut self) -> &mut RawGeneralRegs {
pub fn general_regs_mut(&mut self) -> &mut GeneralRegs {
&mut self.user_context.general
}
@ -166,15 +204,15 @@ impl UserContextApi for UserContext {
}
fn set_instruction_pointer(&mut self, ip: usize) {
self.user_context.set_ip(ip);
self.user_context.sepc = ip;
}
fn stack_pointer(&self) -> usize {
self.user_context.get_sp()
self.sp()
}
fn set_stack_pointer(&mut self, sp: usize) {
self.user_context.set_sp(sp);
self.set_sp(sp);
}
}

View File

@ -6,7 +6,8 @@ mod trap;
use riscv::register::scause::Interrupt;
use spin::Once;
pub use trap::{GeneralRegs, TrapFrame, UserContext};
pub(super) use trap::RawUserContext;
pub use trap::TrapFrame;
use super::cpu::context::CpuExceptionInfo;
use crate::cpu_local_cell;
@ -15,8 +16,8 @@ cpu_local_cell! {
static IS_KERNEL_INTERRUPTED: bool = false;
}
/// Initialize interrupt handling on RISC-V.
pub unsafe fn init() {
/// Initializes interrupt handling on RISC-V.
pub(crate) unsafe fn init() {
self::trap::init();
}

View File

@ -16,7 +16,7 @@
use core::arch::{asm, global_asm};
use crate::Pod;
use crate::arch::cpu::context::GeneralRegs;
#[cfg(target_arch = "riscv32")]
global_asm!(
@ -86,136 +86,29 @@ pub struct TrapFrame {
}
/// Saved registers on a trap.
#[derive(Debug, Default, Clone, Copy, Pod)]
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct UserContext {
pub(in crate::arch) struct RawUserContext {
/// General registers
pub general: GeneralRegs,
pub(in crate::arch) general: GeneralRegs,
/// Supervisor Status
pub sstatus: usize,
pub(in crate::arch) sstatus: usize,
/// Supervisor Exception Program Counter
pub sepc: usize,
pub(in crate::arch) sepc: usize,
}
impl UserContext {
/// Go to user space with the context, and come back when a trap occurs.
impl RawUserContext {
/// Goes to user space with the context, and comes back when a trap occurs.
///
/// On return, the context will be reset to the status before the trap.
/// Trap reason and error code will be returned.
///
/// # Example
/// ```no_run
/// use trapframe::{UserContext, GeneralRegs};
///
/// // init user space context
/// let mut context = UserContext {
/// general: GeneralRegs {
/// sp: 0x10000,
/// ..Default::default()
/// },
/// sepc: 0x1000,
/// ..Default::default()
/// };
/// // go to user
/// context.run();
/// // back from user
/// println!("back from user: {:#x?}", context);
/// ```
pub fn run(&mut self) {
/// Trap reason and error code will be placed at `scause` and `stval`.
pub(in crate::arch) fn run(&mut self) {
unsafe { run_user(self) }
}
}
/// General registers
#[derive(Debug, Default, Clone, Copy, Pod)]
#[repr(C)]
#[expect(missing_docs)]
pub struct GeneralRegs {
pub zero: usize,
pub ra: usize,
pub sp: usize,
pub gp: usize,
pub tp: usize,
pub t0: usize,
pub t1: usize,
pub t2: usize,
pub s0: usize,
pub s1: 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 s2: usize,
pub s3: usize,
pub s4: usize,
pub s5: usize,
pub s6: usize,
pub s7: usize,
pub s8: usize,
pub s9: usize,
pub s10: usize,
pub s11: usize,
pub t3: usize,
pub t4: usize,
pub t5: usize,
pub t6: usize,
}
impl UserContext {
/// Get number of syscall
pub fn get_syscall_num(&self) -> usize {
self.general.a7
}
/// Get return value of syscall
pub fn get_syscall_ret(&self) -> usize {
self.general.a0
}
/// Set return value of syscall
pub fn set_syscall_ret(&mut self, ret: usize) {
self.general.a0 = ret;
}
/// Get syscall args
pub fn get_syscall_args(&self) -> [usize; 6] {
[
self.general.a0,
self.general.a1,
self.general.a2,
self.general.a3,
self.general.a4,
self.general.a5,
]
}
/// Set instruction pointer
pub fn set_ip(&mut self, ip: usize) {
self.sepc = ip;
}
/// Set stack pointer
pub fn set_sp(&mut self, sp: usize) {
self.general.sp = sp;
}
/// Get stack pointer
pub fn get_sp(&self) -> usize {
self.general.sp
}
/// Set tls pointer
pub fn set_tls(&mut self, tls: usize) {
self.general.gp = tls;
}
}
#[expect(improper_ctypes)]
extern "C" {
fn trap_entry();
fn run_user(regs: &mut UserContext);
fn run_user(regs: &mut RawUserContext);
}

View File

@ -22,7 +22,10 @@ use x86_64::registers::{
};
use crate::{
arch::CPU_FEATURES,
arch::{
trap::{RawUserContext, TrapFrame},
CPU_FEATURES,
},
task::scheduler,
trap::call_irq_callback_functions,
user::{ReturnReason, UserContextApi, UserContextApiInternal},
@ -38,11 +41,7 @@ cfg_if! {
pub use x86::cpuid;
pub use crate::arch::trap::{
GeneralRegs as RawGeneralRegs, TrapFrame, UserContext as RawUserContext,
};
/// Cpu context, including both general-purpose registers and FPU state.
/// Userspace CPU context, including both general-purpose registers and FPU state.
#[derive(Clone, Default, Debug)]
#[repr(C)]
pub struct UserContext {
@ -51,6 +50,33 @@ pub struct UserContext {
cpu_exception_info: CpuExceptionInfo,
}
/// General registers.
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
#[repr(C)]
#[expect(missing_docs)]
pub struct GeneralRegs {
pub rax: usize,
pub rbx: usize,
pub rcx: usize,
pub rdx: usize,
pub rsi: usize,
pub rdi: usize,
pub rbp: usize,
pub rsp: usize,
pub r8: usize,
pub r9: usize,
pub r10: usize,
pub r11: usize,
pub r12: usize,
pub r13: usize,
pub r14: usize,
pub r15: usize,
pub rip: usize,
pub rflags: usize,
pub fsbase: usize,
pub gsbase: usize,
}
/// CPU exception information.
#[derive(Clone, Default, Copy, Debug)]
#[repr(C)]
@ -65,12 +91,12 @@ pub struct CpuExceptionInfo {
impl UserContext {
/// Returns a reference to the general registers.
pub fn general_regs(&self) -> &RawGeneralRegs {
pub fn general_regs(&self) -> &GeneralRegs {
&self.user_context.general
}
/// Returns a mutable reference to the general registers
pub fn general_regs_mut(&mut self) -> &mut RawGeneralRegs {
pub fn general_regs_mut(&mut self) -> &mut GeneralRegs {
&mut self.user_context.general
}

View File

@ -4,7 +4,7 @@ use tdx_guest::{
handle_virtual_exception as do_handle_virtual_exception, tdcall, TdgVeInfo, TdxTrapFrame,
};
use crate::cpu::context::{RawGeneralRegs, UserContext};
use super::{GeneralRegs, UserContext};
pub(crate) struct VirtualizationExceptionHandler {
ve_info: TdgVeInfo,
@ -34,7 +34,7 @@ impl VirtualizationExceptionHandler {
}
}
struct GeneralRegsWrapper<'a>(&'a mut RawGeneralRegs);
struct GeneralRegsWrapper<'a>(&'a mut GeneralRegs);
impl TdxTrapFrame for GeneralRegsWrapper<'_> {
fn rax(&self) -> usize {

View File

@ -25,7 +25,7 @@ use cfg_if::cfg_if;
use log::debug;
use spin::Once;
use super::ex_table::ExTable;
use super::{cpu::context::GeneralRegs, ex_table::ExTable};
use crate::{
arch::{
if_tdx_enabled,
@ -103,7 +103,7 @@ pub struct TrapFrame {
pub rflags: usize,
}
/// Initialize interrupt handling on x86_64.
/// Initializes interrupt handling on x86_64.
///
/// This function will:
/// - Switch to a new, CPU-local [GDT].
@ -119,7 +119,7 @@ pub struct TrapFrame {
/// # Safety
///
/// This method must be called only in the boot context of each available processor.
pub unsafe fn init() {
pub(crate) unsafe fn init() {
// SAFETY: We're in the boot context, so no preemption can occur.
unsafe { gdt::init() };
@ -129,90 +129,13 @@ pub unsafe fn init() {
unsafe { syscall::init() };
}
/// User space context.
/// Userspace context.
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
#[repr(C)]
#[expect(missing_docs)]
pub struct UserContext {
pub general: GeneralRegs,
pub trap_num: usize,
pub error_code: usize,
}
/// General registers.
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
#[repr(C)]
#[expect(missing_docs)]
pub struct GeneralRegs {
pub rax: usize,
pub rbx: usize,
pub rcx: usize,
pub rdx: usize,
pub rsi: usize,
pub rdi: usize,
pub rbp: usize,
pub rsp: usize,
pub r8: usize,
pub r9: usize,
pub r10: usize,
pub r11: usize,
pub r12: usize,
pub r13: usize,
pub r14: usize,
pub r15: usize,
pub rip: usize,
pub rflags: usize,
pub fsbase: usize,
pub gsbase: usize,
}
impl UserContext {
/// Get number of syscall.
pub fn get_syscall_num(&self) -> usize {
self.general.rax
}
/// Get return value of syscall.
pub fn get_syscall_ret(&self) -> usize {
self.general.rax
}
/// Set return value of syscall.
pub fn set_syscall_ret(&mut self, ret: usize) {
self.general.rax = ret;
}
/// Get syscall args.
pub fn get_syscall_args(&self) -> [usize; 6] {
[
self.general.rdi,
self.general.rsi,
self.general.rdx,
self.general.r10,
self.general.r8,
self.general.r9,
]
}
/// Set instruction pointer.
pub fn set_ip(&mut self, ip: usize) {
self.general.rip = ip;
}
/// Set stack pointer.
pub fn set_sp(&mut self, sp: usize) {
self.general.rsp = sp;
}
/// Get stack pointer.
pub fn get_sp(&self) -> usize {
self.general.rsp
}
/// Set thread-local storage pointer.
pub fn set_tls(&mut self, tls: usize) {
self.general.fsbase = tls;
}
pub(super) struct RawUserContext {
pub(super) general: GeneralRegs,
pub(super) trap_num: usize,
pub(super) error_code: usize,
}
/// Returns true if this function is called within the context of an IRQ handler

View File

@ -28,7 +28,7 @@ use x86_64::{
VirtAddr,
};
use super::UserContext;
use super::RawUserContext;
global_asm!(
include_str!("syscall.S"),
@ -80,11 +80,11 @@ pub(super) unsafe fn init() {
extern "sysv64" {
fn syscall_entry();
fn syscall_return(regs: &mut UserContext);
fn syscall_return(regs: &mut RawUserContext);
}
impl UserContext {
/// Go to user space with the context, and come back when a trap occurs.
impl RawUserContext {
/// Goes to user space with the context, and comes back when a trap occurs.
///
/// On return, the context will be reset to the status before the trap.
/// Trap reason and error code will be placed at `trap_num` and `error_code`.
@ -93,26 +93,7 @@ impl UserContext {
///
/// If `trap_num` is `0x100`, it will go user by `sysret` (`rcx` and `r11` are dropped),
/// otherwise it will use `iret`.
///
/// # Example
/// ```no_run
/// use trapframe::{UserContext, GeneralRegs};
///
/// // init user space context
/// let mut context = UserContext {
/// general: GeneralRegs {
/// rip: 0x1000,
/// rsp: 0x10000,
/// ..Default::default()
/// },
/// ..Default::default()
/// };
/// // go to user
/// context.run();
/// // back from user
/// println!("back from user: {:#x?}", context);
/// ```
pub fn run(&mut self) {
pub(in crate::arch) fn run(&mut self) {
unsafe {
syscall_return(self);
}