1 use core::{
2 arch::{
3 asm,
4 x86_64::{_fxrstor64, _fxsave64},
5 },
6 ffi::c_void,
7 ptr::null_mut,
8 };
9
10 use alloc::boxed::Box;
11
12 use crate::{exception::InterruptArch, include::bindings::bindings::process_control_block};
13
14 use crate::arch::CurrentIrqArch;
15
16 /// https://www.felixcloutier.com/x86/fxsave#tbl-3-47
17 #[repr(C, align(16))]
18 #[derive(Debug, Copy, Clone)]
19 pub struct FpState {
20 //0
21 fcw: u16,
22 fsw: u16,
23 ftw: u16,
24 fop: u16,
25 word2: u64,
26 //16
27 word3: u64,
28 mxcsr: u32,
29 mxcsr_mask: u32,
30 //32
31 mm: [u64; 16],
32 //160
33 xmm: [u64; 32],
34 //416
35 rest: [u64; 12],
36 }
37
38 impl Default for FpState {
default() -> Self39 fn default() -> Self {
40 Self {
41 fcw: 0x037f,
42 fsw: Default::default(),
43 ftw: Default::default(),
44 fop: Default::default(),
45 word2: Default::default(),
46 word3: Default::default(),
47 mxcsr: 0x1f80,
48 mxcsr_mask: Default::default(),
49 mm: Default::default(),
50 xmm: Default::default(),
51 rest: Default::default(),
52 }
53 }
54 }
55 impl FpState {
56 #[allow(dead_code)]
new() -> Self57 pub fn new() -> Self {
58 assert!(core::mem::size_of::<Self>() == 512);
59 return Self::default();
60 }
61 #[allow(dead_code)]
save(&mut self)62 pub fn save(&mut self) {
63 unsafe {
64 _fxsave64(self as *mut FpState as *mut u8);
65 }
66 }
67 #[allow(dead_code)]
restore(&self)68 pub fn restore(&self) {
69 unsafe {
70 _fxrstor64(self as *const FpState as *const u8);
71 }
72 }
73
74 /// @brief 清空fp_state
clear(&mut self)75 pub fn clear(&mut self) {
76 *self = Self::default();
77 }
78 }
79
80 /// @brief 从用户态进入内核时,保存浮点寄存器,并关闭浮点功能
fp_state_save(pcb: &mut process_control_block)81 pub fn fp_state_save(pcb: &mut process_control_block) {
82 // 该过程中不允许中断
83 let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
84
85 let fp: &mut FpState = if pcb.fp_state == null_mut() {
86 let f = Box::leak(Box::new(FpState::default()));
87 pcb.fp_state = f as *mut FpState as usize as *mut c_void;
88 f
89 } else {
90 unsafe { (pcb.fp_state as usize as *mut FpState).as_mut().unwrap() }
91 };
92
93 // 保存浮点寄存器
94 fp.save();
95
96 // 关闭浮点功能
97 unsafe {
98 asm!(
99 "mov rax, cr4",
100 "and ax,~(3<<9)", //[9][10]->0
101 "mov cr4,rax",
102 "mov rax, cr0",
103 "and ax,~(02h)", //[1]->0
104 "or ax, ~(0FFFBh)", //[2]->1
105 "mov cr0, rax" /*
106 "mov rax, cr0",
107 "and ax, 0xFFFB",
108 "or ax,0x2",
109 "mov cr0,rax",
110 "mov rax, cr4",
111 "or ax,3<<9",
112 "mov cr4, rax" */
113 )
114 }
115 drop(guard);
116 }
117
118 /// @brief 从内核态返回用户态时,恢复浮点寄存器,并开启浮点功能
fp_state_restore(pcb: &mut process_control_block)119 pub fn fp_state_restore(pcb: &mut process_control_block) {
120 // 该过程中不允许中断
121 let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
122
123 if pcb.fp_state == null_mut() {
124 panic!("fp_state_restore: fp_state is null. pid={}", pcb.pid);
125 }
126
127 unsafe {
128 asm! {
129 "mov rax, cr0",
130 "and ax, 0FFFBh",//[2]->0
131 "or ax,02h",//[1]->1
132 "mov cr0,rax",
133 "mov rax, cr4",
134 "or ax,3<<9",
135 "mov cr4, rax",
136 "clts",
137 "fninit"
138 }
139 }
140
141 let fp = unsafe { (pcb.fp_state as usize as *mut FpState).as_mut().unwrap() };
142 fp.restore();
143 fp.clear();
144
145 drop(guard);
146 }
147