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