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 mut rflags: u64 = 0; 83 local_irq_save(&mut rflags); 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 local_irq_restore(&rflags); 116 } 117 118 /// @brief 从内核态返回用户态时,恢复浮点寄存器,并开启浮点功能 119 pub fn fp_state_restore(pcb: &mut process_control_block) { 120 // 该过程中不允许中断 121 let mut rflags: u64 = 0; 122 local_irq_save(&mut rflags); 123 124 if pcb.fp_state == null_mut() { 125 panic!("fp_state_restore: fp_state is null. pid={}", pcb.pid); 126 } 127 128 unsafe { 129 asm! { 130 "mov rax, cr0", 131 "and ax, 0FFFBh",//[2]->0 132 "or ax,02h",//[1]->1 133 "mov cr0,rax", 134 "mov rax, cr4", 135 "or ax,3<<9", 136 "mov cr4, rax", 137 "clts", 138 "fninit" 139 } 140 } 141 142 let fp = unsafe { (pcb.fp_state as usize as *mut FpState).as_mut().unwrap() }; 143 fp.restore(); 144 fp.clear(); 145 146 local_irq_restore(&rflags); 147 } 148