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 { 39 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)] 57 pub fn new() -> Self { 58 assert!(core::mem::size_of::<Self>() == 512); 59 return Self::default(); 60 } 61 #[allow(dead_code)] 62 pub fn save(&mut self) { 63 unsafe { 64 _fxsave64(self as *mut FpState as *mut u8); 65 } 66 } 67 #[allow(dead_code)] 68 pub fn restore(&self) { 69 unsafe { 70 _fxrstor64(self as *const FpState as *const u8); 71 } 72 } 73 74 /// @brief 清空fp_state 75 pub fn clear(&mut self) { 76 *self = Self::default(); 77 } 78 } 79 80 /// @brief 从用户态进入内核时,保存浮点寄存器,并关闭浮点功能 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 从内核态返回用户态时,恢复浮点寄存器,并开启浮点功能 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