1 /* $OpenBSD: fpu.h,v 1.17 2019/11/29 22:34:09 mortimer Exp $ */ 2 /* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ 3 4 #ifndef _MACHINE_FPU_H_ 5 #define _MACHINE_FPU_H_ 6 7 #include <sys/types.h> 8 9 /* 10 * If the CPU supports xsave/xrstor then we use them so that we can provide 11 * AVX support. Otherwise we require fxsave/fxrstor, as the SSE registers 12 * are part of the ABI for passing floating point values. 13 * While fxsave/fxrstor only required 16-byte alignment for the save area, 14 * xsave/xrstor requires the save area to have 64-byte alignment. 15 */ 16 17 struct fxsave64 { 18 u_int16_t fx_fcw; 19 u_int16_t fx_fsw; 20 u_int8_t fx_ftw; 21 u_int8_t fx_unused1; 22 u_int16_t fx_fop; 23 u_int64_t fx_rip; 24 u_int64_t fx_rdp; 25 u_int32_t fx_mxcsr; 26 u_int32_t fx_mxcsr_mask; 27 u_int64_t fx_st[8][2]; /* 8 normal FP regs */ 28 u_int64_t fx_xmm[16][2]; /* 16 SSE2 registers */ 29 u_int8_t fx_unused3[96]; 30 } __packed; 31 32 struct xstate_hdr { 33 uint64_t xstate_bv; 34 uint64_t xstate_xcomp_bv; 35 uint8_t xstate_rsrv0[8]; 36 uint8_t xstate_rsrv[40]; 37 } __packed; 38 39 struct savefpu { 40 struct fxsave64 fp_fxsave; /* see above */ 41 struct xstate_hdr fp_xstate; 42 u_int64_t fp_ymm[16][2]; 43 u_int16_t fp_ex_sw; /* saved status from last exception */ 44 u_int16_t fp_ex_tw; /* saved tag from last exception */ 45 }; 46 47 /* 48 * The i387 defaults to Intel extended precision mode and round to nearest, 49 * with all exceptions masked. 50 */ 51 #define __INITIAL_NPXCW__ 0x037f 52 #define __INITIAL_MXCSR__ 0x1f80 53 #define __INITIAL_MXCSR_MASK__ 0xffbf 54 55 #ifdef _KERNEL 56 /* 57 * XXX 58 */ 59 struct trapframe; 60 struct cpu_info; 61 62 extern size_t fpu_save_len; 63 extern uint32_t fpu_mxcsr_mask; 64 extern uint64_t xsave_mask; 65 66 void fpuinit(struct cpu_info *); 67 int fputrap(int _type); 68 void fpusave(struct savefpu *); 69 void fpusavereset(struct savefpu *); 70 void fpu_kernel_enter(void); 71 void fpu_kernel_exit(void); 72 73 int xrstor_user(struct savefpu *_addr, uint64_t _mask); 74 #define fpureset() \ 75 xrstor_user(&proc0.p_addr->u_pcb.pcb_savefpu, xsave_mask) 76 int xsetbv_user(uint32_t _reg, uint64_t _mask); 77 78 #define fninit() __asm("fninit") 79 #define fwait() __asm("fwait") 80 /* should be fxsave64, but where we use this it doesn't matter */ 81 #define fxsave(addr) __asm("fxsave %0" : "=m" (*addr)) 82 #define ldmxcsr(addr) __asm("ldmxcsr %0" : : "m" (*addr)) 83 #define fldcw(addr) __asm("fldcw %0" : : "m" (*addr)) 84 85 static inline void 86 xsave(struct savefpu *addr, uint64_t mask) 87 { 88 uint32_t lo, hi; 89 90 lo = mask; 91 hi = mask >> 32; 92 /* should be xsave64, but where we use this it doesn't matter */ 93 __asm volatile("xsave %0" : "=m" (*addr) : "a" (lo), "d" (hi) : 94 "memory"); 95 } 96 97 #endif 98 99 #endif /* _MACHINE_FPU_H_ */ 100