Implement context save/restore asm for x86_64
This commit is contained in:
parent
c9385a3f21
commit
5ecb44d1e3
3
src/arch/mod.rs
Normal file
3
src/arch/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod x86_64;
|
||||||
|
|
||||||
|
pub use x86_64::*;
|
127
src/arch/x86_64.rs
Normal file
127
src/arch/x86_64.rs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use core::ops;
|
||||||
|
use gimli::{Register, X86_64};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct Context {
|
||||||
|
pub registers: [usize; 16],
|
||||||
|
pub ra: usize,
|
||||||
|
pub mcxsr: usize,
|
||||||
|
pub fcw: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Context {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let mut fmt = fmt.debug_struct("Context");
|
||||||
|
for i in 0..=15 {
|
||||||
|
fmt.field(
|
||||||
|
X86_64::register_name(Register(i as _)).unwrap(),
|
||||||
|
&self.registers[i],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fmt.field("ra", &self.ra)
|
||||||
|
.field("mcxsr", &self.mcxsr)
|
||||||
|
.field("fcw", &self.fcw)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Index<Register> for Context {
|
||||||
|
type Output = usize;
|
||||||
|
|
||||||
|
fn index(&self, reg: Register) -> &usize {
|
||||||
|
match reg {
|
||||||
|
Register(0..=15) => &self.registers[reg.0 as usize],
|
||||||
|
X86_64::RA => &self.ra,
|
||||||
|
X86_64::MXCSR => &self.mcxsr,
|
||||||
|
X86_64::FCW => &self.fcw,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::IndexMut<gimli::Register> for Context {
|
||||||
|
fn index_mut(&mut self, reg: Register) -> &mut usize {
|
||||||
|
match reg {
|
||||||
|
Register(0..=15) => &mut self.registers[reg.0 as usize],
|
||||||
|
X86_64::RA => &mut self.ra,
|
||||||
|
X86_64::MXCSR => &mut self.mcxsr,
|
||||||
|
X86_64::FCW => &mut self.fcw,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub extern "C-unwind" fn save_context() -> Context {
|
||||||
|
// No need to save caller-saved registers here.
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"
|
||||||
|
mov rax, rdi
|
||||||
|
mov [rax + 0x18], rbx
|
||||||
|
mov [rax + 0x30], rbp
|
||||||
|
|
||||||
|
/* Adjust the stack to account for the return address */
|
||||||
|
lea rdi, [rsp + 8]
|
||||||
|
mov [rax + 0x38], rdi
|
||||||
|
|
||||||
|
mov [rax + 0x60], r12
|
||||||
|
mov [rax + 0x68], r13
|
||||||
|
mov [rax + 0x70], r14
|
||||||
|
mov [rax + 0x78], r15
|
||||||
|
mov rdx, [rsp]
|
||||||
|
mov [rax + 0x80], rdx
|
||||||
|
stmxcsr [rax + 0x88]
|
||||||
|
fnstcw [rax + 0x90]
|
||||||
|
ret
|
||||||
|
",
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
||||||
|
// No need to save caller-saved registers here.
|
||||||
|
asm!(
|
||||||
|
"
|
||||||
|
/* Restore stack */
|
||||||
|
mov rsp, [rdi + 0x38]
|
||||||
|
|
||||||
|
/* Restore callee-saved control registers */
|
||||||
|
ldmxcsr [rdi + 0x88]
|
||||||
|
fldcw [rdi + 0x90]
|
||||||
|
|
||||||
|
/* Restore return address */
|
||||||
|
mov rax, [rdi + 0x80]
|
||||||
|
push rax
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore general-purpose registers. Non-callee-saved registers are
|
||||||
|
* also restored because sometimes it's used to pass unwind arguments.
|
||||||
|
*/
|
||||||
|
mov rax, [rdi + 0x00]
|
||||||
|
mov rdx, [rdi + 0x08]
|
||||||
|
mov rcx, [rdi + 0x10]
|
||||||
|
mov rbx, [rdi + 0x18]
|
||||||
|
mov rsi, [rdi + 0x20]
|
||||||
|
mov rbp, [rdi + 0x30]
|
||||||
|
mov r8 , [rdi + 0x40]
|
||||||
|
mov r9 , [rdi + 0x48]
|
||||||
|
mov r10, [rdi + 0x50]
|
||||||
|
mov r11, [rdi + 0x58]
|
||||||
|
mov r12, [rdi + 0x60]
|
||||||
|
mov r13, [rdi + 0x68]
|
||||||
|
mov r14, [rdi + 0x70]
|
||||||
|
mov r15, [rdi + 0x78]
|
||||||
|
|
||||||
|
/* RDI resotred last */
|
||||||
|
mov rdi, [rdi + 0x28]
|
||||||
|
|
||||||
|
ret
|
||||||
|
",
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
|
mod arch;
|
||||||
mod find_fde;
|
mod find_fde;
|
||||||
mod util;
|
mod util;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user