github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/arch/fpu/fpu_amd64.s (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "textflag.h" 16 17 // MXCSR_DEFAULT is the reset value of MXCSR (Intel SDM Vol. 2, Ch. 3.2 18 // "LDMXCSR") 19 #define MXCSR_DEFAULT 0x1f80 20 21 // MXCSR_OFFSET is the offset in bytes of the MXCSR field from the start of the 22 // FXSAVE/XSAVE area. (Intel SDM Vol. 1, Table 10-2 "Format of an FXSAVE Area") 23 #define MXCSR_OFFSET 24 24 25 // initX86FPState initializes floating point state. 26 // 27 // func initX86FPState(data *FloatingPointData, useXsave bool) 28 // 29 // We need to clear out and initialize an empty fp state area since the sentry, 30 // or any previous loader, may have left sensitive information in the floating 31 // point registers. 32 // 33 // Preconditions: data is zeroed. 34 TEXT ·initX86FPState(SB), $24-16 35 // Save MXCSR (callee-save) 36 STMXCSR mxcsr-8(SP) 37 38 // Save x87 CW (callee-save) 39 FSTCW cw-16(SP) 40 41 MOVQ fpState+0(FP), DI 42 43 // Do we use xsave? 44 MOVBQZX useXsave+8(FP), AX 45 TESTQ AX, AX 46 JZ no_xsave 47 48 // Use XRSTOR to clear all FP state to an initial state. 49 // 50 // The fpState XSAVE area is zeroed on function entry, meaning 51 // XSTATE_BV is zero. 52 // 53 // "If RFBM[i] = 1 and bit i is clear in the XSTATE_BV field in the 54 // XSAVE header, XRSTOR initializes state component i." 55 // 56 // Initialization is defined in SDM Vol 1, Chapter 13.3. It puts all 57 // the registers in a reasonable initial state, except MXCSR: 58 // 59 // "The MXCSR register is part of state component 1, SSE state (see 60 // Section 13.5.2). However, the standard form of XRSTOR loads the 61 // MXCSR register from memory whenever the RFBM[1] (SSE) or RFBM[2] 62 // (AVX) is set, regardless of the values of XSTATE_BV[1] and 63 // XSTATE_BV[2]." 64 65 // Set MXCSR to the default value. 66 MOVL $MXCSR_DEFAULT, MXCSR_OFFSET(DI) 67 68 // Initialize registers with XRSTOR. 69 MOVL $0xffffffff, AX 70 MOVL $0xffffffff, DX 71 BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x2f // XRSTOR64 0(DI) 72 73 // Now that all the state has been reset, write it back out to the 74 // XSAVE area. 75 BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x27 // XSAVE64 0(DI) 76 77 JMP out 78 79 no_xsave: 80 // Clear out existing X values. 81 PXOR X0, X0 82 MOVO X0, X1 83 MOVO X0, X2 84 MOVO X0, X3 85 MOVO X0, X4 86 MOVO X0, X5 87 MOVO X0, X6 88 MOVO X0, X7 89 MOVO X0, X8 90 MOVO X0, X9 91 MOVO X0, X10 92 MOVO X0, X11 93 MOVO X0, X12 94 MOVO X0, X13 95 MOVO X0, X14 96 MOVO X0, X15 97 98 // Zero out %rax and store into MMX registers. MMX registers are 99 // an alias of 8x64 bits of the 8x80 bits used for the original 100 // x87 registers. Storing zero into them will reset the FPU registers 101 // to bits [63:0] = 0, [79:64] = 1. But the contents aren't too 102 // important, just the fact that we have reset them to a known value. 103 XORQ AX, AX 104 MOVQ AX, M0 105 MOVQ AX, M1 106 MOVQ AX, M2 107 MOVQ AX, M3 108 MOVQ AX, M4 109 MOVQ AX, M5 110 MOVQ AX, M6 111 MOVQ AX, M7 112 113 // The Go assembler doesn't support FNINIT, so we use BYTE. 114 // This will: 115 // - Reset FPU control word to 0x037f 116 // - Clear FPU status word 117 // - Reset FPU tag word to 0xffff 118 // - Clear FPU data pointer 119 // - Clear FPU instruction pointer 120 BYTE $0xDB; BYTE $0xE3; // FNINIT 121 122 // Reset MXCSR. 123 MOVL $MXCSR_DEFAULT, tmpmxcsr-24(SP) 124 LDMXCSR tmpmxcsr-24(SP) 125 126 // Save the floating point state with fxsave. 127 FXSAVE64 0(DI) 128 129 out: 130 // Restore MXCSR. 131 LDMXCSR mxcsr-8(SP) 132 133 // Restore x87 CW. 134 FLDCW cw-16(SP) 135 136 RET