Skip to main content

rustubs/arch/x86_64/
arch_regs.rs

1//! both [Context64] and [TrapFrame] define architecture specific registers and
2//! combine into the full execution context of a thread.
3//! [Context64] includes the callee saved registers plus FP state, and
4//! [TrapFrame] includes caller saved registers.
5
6use core::arch::asm;
7#[repr(C)]
8#[repr(packed)]
9#[derive(Debug)]
10/// the Context64 is part of the task struct; it's saved and restored explicitly
11/// on context swap.
12pub struct Context64 {
13	pub rbx: u64,
14	pub r12: u64,
15	pub r13: u64,
16	pub r14: u64,
17	pub r15: u64,
18	pub rbp: u64,
19	pub rsp: u64,
20	pub fpu: [u8; 108],
21}
22
23impl Default for Context64 {
24	fn default() -> Context64 {
25		Context64 {
26			rbx: 0,
27			r12: 0,
28			r13: 0,
29			r14: 0,
30			r15: 0,
31			rbp: 0,
32			rsp: 0,
33			fpu: [0; 108],
34		}
35	}
36}
37
38/// `TrapFrame` is saved and restored by the interrupt handler assembly code
39/// upon interrupt entry and exit.
40///
41/// The complete picture (in pushing sequence, addr from high to low)
42#[repr(C)]
43#[repr(packed)]
44#[derive(Debug)]
45pub struct TrapFrame {
46	// TODO the stack may need 16 byte alignment. Sanitize it!
47	// these are what we manually push in the vector wrapper.
48	// the "callee saved registers". See the documentations in vector.s
49	pub rbx: u64,
50	pub r12: u64,
51	pub r13: u64,
52	pub r14: u64,
53	pub r15: u64,
54	pub rbp: u64,
55	// the mandatory "caller saved registers"
56	// also the "caller saved registers"
57	pub r11: u64,
58	pub r10: u64,
59	pub r9: u64,
60	pub r8: u64,
61	pub rsi: u64,
62	pub rdi: u64,
63	pub rdx: u64,
64	pub rcx: u64,
65	pub rax: u64,
66	// below are automatically pushed by the CPU.
67	/// for some exceptions, the CPU automatically pushes an error code (see
68	/// `docs/interrupt.txt`) to the stack. For those who don't have error code,
69	/// we manually push a dummy value (0)
70	pub err_code: u64,
71	pub rip: u64,
72	pub cs: u64,
73	pub rflags: u64,
74	pub rsp: u64, // user stack
75	pub ss: u64,  // all user segments share the same selector
76}
77
78/// get the current stack pointer
79#[inline]
80pub fn get_sp() -> u64 {
81	let sp: u64;
82	unsafe {
83		asm!("mov {}, rsp", out(reg) sp);
84	}
85	sp
86}
87
88impl TrapFrame {
89	/// get rpl from auto-pushed cs register
90	pub fn from_user(&self) -> bool { return (self.cs & 0b11) == 3; }
91}