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 = 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