github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/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 // The value for XCR0 is defined to xsave/xrstor everything except for PKRU and 26 // AMX regions. 27 // TODO(gvisor.dev/issues/9896): Implement AMX support. 28 // TODO(gvisor.dev/issues/10087): Implement PKRU support. 29 #define XCR0_DISABLED_MASK ((1 << 9) | (1 << 17) | (1 << 18)) 30 #define XCR0_EAX (0xffffffff ^ XCR0_DISABLED_MASK) 31 #define XCR0_EDX 0xffffffff 32 33 // initX86FPState initializes floating point state. 34 // 35 // func initX86FPState(data *FloatingPointData, useXsave bool) 36 // 37 // We need to clear out and initialize an empty fp state area since the sentry, 38 // or any previous loader, may have left sensitive information in the floating 39 // point registers. 40 // 41 // Preconditions: data is zeroed. 42 TEXT ·initX86FPState(SB), $24-9 43 // Save MXCSR (callee-save) 44 STMXCSR mxcsr-8(SP) 45 46 // Save x87 CW (callee-save) 47 FSTCW cw-16(SP) 48 49 MOVQ data+0(FP), DI 50 51 // Do we use xsave? 52 MOVBQZX useXsave+8(FP), AX 53 TESTQ AX, AX 54 JZ no_xsave 55 56 // Use XRSTOR to clear all FP state to an initial state. 57 // 58 // The fpState XSAVE area is zeroed on function entry, meaning 59 // XSTATE_BV is zero. 60 // 61 // "If RFBM[i] = 1 and bit i is clear in the XSTATE_BV field in the 62 // XSAVE header, XRSTOR initializes state component i." 63 // 64 // Initialization is defined in SDM Vol 1, Chapter 13.3. It puts all 65 // the registers in a reasonable initial state, except MXCSR: 66 // 67 // "The MXCSR register is part of state component 1, SSE state (see 68 // Section 13.5.2). However, the standard form of XRSTOR loads the 69 // MXCSR register from memory whenever the RFBM[1] (SSE) or RFBM[2] 70 // (AVX) is set, regardless of the values of XSTATE_BV[1] and 71 // XSTATE_BV[2]." 72 73 // Set MXCSR to the default value. 74 MOVL $MXCSR_DEFAULT, MXCSR_OFFSET(DI) 75 76 // Initialize registers with XRSTOR. 77 MOVL $XCR0_EAX, AX 78 MOVL $XCR0_EDX, DX 79 BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x2f // XRSTOR64 0(DI) 80 81 // Now that all the state has been reset, write it back out to the 82 // XSAVE area. 83 BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x27 // XSAVE64 0(DI) 84 85 JMP out 86 87 no_xsave: 88 // Clear out existing X values. 89 PXOR X0, X0 90 MOVO X0, X1 91 MOVO X0, X2 92 MOVO X0, X3 93 MOVO X0, X4 94 MOVO X0, X5 95 MOVO X0, X6 96 MOVO X0, X7 97 MOVO X0, X8 98 MOVO X0, X9 99 MOVO X0, X10 100 MOVO X0, X11 101 MOVO X0, X12 102 MOVO X0, X13 103 MOVO X0, X14 104 MOVO X0, X15 105 106 // Zero out %rax and store into MMX registers. MMX registers are 107 // an alias of 8x64 bits of the 8x80 bits used for the original 108 // x87 registers. Storing zero into them will reset the FPU registers 109 // to bits [63:0] = 0, [79:64] = 1. But the contents aren't too 110 // important, just the fact that we have reset them to a known value. 111 XORQ AX, AX 112 MOVQ AX, M0 113 MOVQ AX, M1 114 MOVQ AX, M2 115 MOVQ AX, M3 116 MOVQ AX, M4 117 MOVQ AX, M5 118 MOVQ AX, M6 119 MOVQ AX, M7 120 121 // The Go assembler doesn't support FNINIT, so we use BYTE. 122 // This will: 123 // - Reset FPU control word to 0x037f 124 // - Clear FPU status word 125 // - Reset FPU tag word to 0xffff 126 // - Clear FPU data pointer 127 // - Clear FPU instruction pointer 128 BYTE $0xDB; BYTE $0xE3; // FNINIT 129 130 // Reset MXCSR. 131 MOVL $MXCSR_DEFAULT, tmpmxcsr-24(SP) 132 LDMXCSR tmpmxcsr-24(SP) 133 134 // Save the floating point state with fxsave. 135 FXSAVE64 0(DI) 136 137 out: 138 // Restore MXCSR. 139 LDMXCSR mxcsr-8(SP) 140 141 // Restore x87 CW. 142 FLDCW cw-16(SP) 143 144 RET