good_os_framework/task/
context.rs1use x86_64::structures::gdt::SegmentSelector;
2use x86_64::{PhysAddr, VirtAddr};
3
4#[derive(Debug, Clone, Copy, Default)]
5#[repr(packed)]
6pub struct Context {
7 pub cr3: usize,
8 pub r15: usize,
9 pub r14: usize,
10 pub r13: usize,
11
12 pub r12: usize,
13 pub r11: usize,
14 pub r10: usize,
15 pub r9: usize,
16
17 pub r8: usize,
18 pub rbp: usize,
19 pub rsi: usize,
20 pub rdi: usize,
21
22 pub rdx: usize,
23 pub rcx: usize,
24 pub rbx: usize,
25 pub rax: usize,
26
27 pub rip: usize,
28 pub cs: usize,
29 pub rflags: usize,
30 pub rsp: usize,
31 pub ss: usize,
32}
33
34impl Context {
35 pub fn init(
36 &mut self,
37 entry_point: usize,
38 stack_end_address: VirtAddr,
39 page_table_address: PhysAddr,
40 segment_selectors: (SegmentSelector, SegmentSelector),
41 ) {
42 self.rflags = 0x200;
43 self.rip = entry_point;
44 self.rsp = stack_end_address.as_u64() as usize;
45 self.cr3 = page_table_address.as_u64() as usize;
46
47 let (code_selector, data_selector) = segment_selectors;
48 self.cs = code_selector.0 as usize;
49 self.ss = data_selector.0 as usize;
50 }
51
52 #[inline]
53 pub fn address(&self) -> VirtAddr {
54 VirtAddr::new(self as *const Context as u64)
55 }
56
57 #[inline]
58 pub fn from_address(address: VirtAddr) -> Context {
59 unsafe { *&mut *(address.as_u64() as *mut Context) }
60 }
61}
62
63#[macro_export]
64macro_rules! push_context {
65 () => {
66 concat!(
67 r#"
68 push rax
69 push rbx
70 push rcx
71 push rdx
72 push rdi
73 push rsi
74 push rbp
75 push r8
76 push r9
77 push r10
78 push r11
79 push r12
80 push r13
81 push r14
82 push r15
83 mov r15, cr3
84 push r15
85 "#,
86 )
87 };
88}
89
90#[macro_export]
91macro_rules! pop_context {
92 () => {
93 concat!(
94 r#"
95 pop r15
96 mov cr3, r15
97 pop r15
98 pop r14
99 pop r13
100 pop r12
101 pop r11
102 pop r10
103 pop r9
104 pop r8
105 pop rbp
106 pop rsi
107 pop rdi
108 pop rdx
109 pop rcx
110 pop rbx
111 pop rax
112 "#
113 )
114 };
115}