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