mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Remove ring0 floating point save/load functions on amd64.
ring0.Save/LoadFloatingPoint() are only usable if the caller can ensure that Go will not clobber floating point registers before/after calling them respectively. Due to regabig in Go 1.17, this is no longer the case; regabig (among other things) maintains a zeroed XMM15 during ABIInternal execution, including by zeroing it after ABI0-to-ABIInternal transitions. In ring0.sysenter/exception, this happens in ring0.kernelSyscall/kernelException.abi0 respectively; in ring0.CPU.SwitchToUser, this happens after returning from ring0.sysret/iret.abi0. Delete these functions and do floating point save/load in assembly. While arm64 doesn't appear to be immediately affected (so this CL permits us to resume usage of Go 1.17), its use of Save/LoadFloatingPoint() still seems to be incorrect for the same fundamental reason (Go code can't sanely assume what registers the Go compiler will or won't use) and should be fixed eventually. PiperOrigin-RevId: 401895658
This commit is contained in:
@@ -77,6 +77,9 @@ type CPU struct {
|
||||
// calls and exceptions via the Registers function.
|
||||
registers arch.Registers
|
||||
|
||||
// floatingPointState holds floating point state.
|
||||
floatingPointState fpu.State
|
||||
|
||||
// hooks are kernel hooks.
|
||||
hooks Hooks
|
||||
}
|
||||
@@ -90,6 +93,15 @@ func (c *CPU) Registers() *arch.Registers {
|
||||
return &c.registers
|
||||
}
|
||||
|
||||
// FloatingPointState returns the kernel floating point state.
|
||||
//
|
||||
// This is explicitly safe to call during KernelException and KernelSyscall.
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *CPU) FloatingPointState() *fpu.State {
|
||||
return &c.floatingPointState
|
||||
}
|
||||
|
||||
// SwitchOpts are passed to the Switch function.
|
||||
type SwitchOpts struct {
|
||||
// Registers are the user register state.
|
||||
|
||||
@@ -116,6 +116,11 @@ type CPUArchState struct {
|
||||
errorType uintptr
|
||||
|
||||
*kernelEntry
|
||||
|
||||
// Copies of global variables, stored in CPU so that they can be used by
|
||||
// syscall and exception handlers (in the upper address space).
|
||||
hasXSAVE bool
|
||||
hasXSAVEOPT bool
|
||||
}
|
||||
|
||||
// ErrorCode returns the last error code.
|
||||
|
||||
@@ -39,11 +39,6 @@ func sysenter()
|
||||
// assembly to get the ABI0 (i.e., primary) address.
|
||||
func addrOfSysenter() uintptr
|
||||
|
||||
// swapgs swaps the current GS value.
|
||||
//
|
||||
// This must be called prior to sysret/iret.
|
||||
func swapgs()
|
||||
|
||||
// jumpToKernel jumps to the kernel version of the current RIP.
|
||||
func jumpToKernel()
|
||||
|
||||
|
||||
+166
-11
@@ -142,8 +142,103 @@ TEXT ·jumpToUser(SB),NOSPLIT,$0
|
||||
MOVQ AX, 0(SP)
|
||||
RET
|
||||
|
||||
// See kernel_amd64.go.
|
||||
//
|
||||
// The 16-byte frame size is for the saved values of MXCSR and the x87 control
|
||||
// word.
|
||||
TEXT ·doSwitchToUser(SB),NOSPLIT,$16-48
|
||||
// We are passed pointers to heap objects, but do not store them in our
|
||||
// local frame.
|
||||
NO_LOCAL_POINTERS
|
||||
|
||||
// MXCSR and the x87 control word are the only floating point state
|
||||
// that is callee-save and thus we must save.
|
||||
STMXCSR mxcsr-0(SP)
|
||||
FSTCW cw-8(SP)
|
||||
|
||||
// Restore application floating point state.
|
||||
MOVQ cpu+0(FP), SI
|
||||
MOVQ fpState+16(FP), DI
|
||||
MOVB ·hasXSAVE(SB), BX
|
||||
TESTB BX, BX
|
||||
JZ no_xrstor
|
||||
// Use xrstor to restore all available fp state. For now, we restore
|
||||
// everything unconditionally by setting the implicit operand edx:eax
|
||||
// (the "requested feature bitmap") to all 1's.
|
||||
MOVL $0xffffffff, AX
|
||||
MOVL $0xffffffff, DX
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x2f // XRSTOR64 0(DI)
|
||||
JMP fprestore_done
|
||||
no_xrstor:
|
||||
// Fall back to fxrstor if xsave is not available.
|
||||
FXRSTOR64 0(DI)
|
||||
fprestore_done:
|
||||
|
||||
// Set application GS.
|
||||
MOVQ regs+8(FP), R8
|
||||
SWAP_GS()
|
||||
MOVQ PTRACE_GS_BASE(R8), AX
|
||||
PUSHQ AX
|
||||
CALL ·writeGS(SB)
|
||||
POPQ AX
|
||||
|
||||
// Call sysret() or iret().
|
||||
MOVQ userCR3+24(FP), CX
|
||||
MOVQ needIRET+32(FP), R9
|
||||
ADDQ $-32, SP
|
||||
MOVQ SI, 0(SP) // cpu
|
||||
MOVQ R8, 8(SP) // regs
|
||||
MOVQ CX, 16(SP) // userCR3
|
||||
TESTQ R9, R9
|
||||
JNZ do_iret
|
||||
CALL ·sysret(SB)
|
||||
JMP done_sysret_or_iret
|
||||
do_iret:
|
||||
CALL ·iret(SB)
|
||||
done_sysret_or_iret:
|
||||
MOVQ 24(SP), AX // vector
|
||||
ADDQ $32, SP
|
||||
MOVQ AX, vector+40(FP)
|
||||
|
||||
// Save application floating point state.
|
||||
MOVQ fpState+16(FP), DI
|
||||
MOVB ·hasXSAVE(SB), BX
|
||||
MOVB ·hasXSAVEOPT(SB), CX
|
||||
TESTB BX, BX
|
||||
JZ no_xsave
|
||||
// Use xsave/xsaveopt to save all extended state.
|
||||
// We save everything unconditionally by setting RFBM to all 1's.
|
||||
MOVL $0xffffffff, AX
|
||||
MOVL $0xffffffff, DX
|
||||
TESTB CX, CX
|
||||
JZ no_xsaveopt
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x37; // XSAVEOPT64 0(DI)
|
||||
JMP fpsave_done
|
||||
no_xsaveopt:
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x27; // XSAVE64 0(DI)
|
||||
JMP fpsave_done
|
||||
no_xsave:
|
||||
FXSAVE64 0(DI)
|
||||
fpsave_done:
|
||||
|
||||
// Restore MXCSR and the x87 control word after one of the two floating
|
||||
// point save cases above, to ensure the application versions are saved
|
||||
// before being clobbered here.
|
||||
LDMXCSR mxcsr-0(SP)
|
||||
|
||||
// FLDCW is a "waiting" x87 instruction, meaning it checks for pending
|
||||
// unmasked exceptions before executing. Thus if userspace has unmasked
|
||||
// an exception and has one pending, it can be raised by FLDCW even
|
||||
// though the new control word will mask exceptions. To prevent this,
|
||||
// we must first clear pending exceptions (which will be restored by
|
||||
// XRSTOR, et al).
|
||||
BYTE $0xDB; BYTE $0xE2; // FNCLEX
|
||||
FLDCW cw-8(SP)
|
||||
|
||||
RET
|
||||
|
||||
// See entry_amd64.go.
|
||||
TEXT ·sysret(SB),NOSPLIT,$0-24
|
||||
TEXT ·sysret(SB),NOSPLIT,$0-32
|
||||
// Set application FS. We can't do this in Go because Go code needs FS.
|
||||
MOVQ regs+8(FP), AX
|
||||
MOVQ PTRACE_FS_BASE(AX), AX
|
||||
@@ -182,9 +277,11 @@ TEXT ·sysret(SB),NOSPLIT,$0-24
|
||||
POPQ AX // Restore AX.
|
||||
POPQ SP // Restore SP.
|
||||
SYSRET64()
|
||||
// sysenter or exception will write our return value and return to our
|
||||
// caller.
|
||||
|
||||
// See entry_amd64.go.
|
||||
TEXT ·iret(SB),NOSPLIT,$0-24
|
||||
TEXT ·iret(SB),NOSPLIT,$0-32
|
||||
// Set application FS. We can't do this in Go because Go code needs FS.
|
||||
MOVQ regs+8(FP), AX
|
||||
MOVQ PTRACE_FS_BASE(AX), AX
|
||||
@@ -220,6 +317,8 @@ TEXT ·iret(SB),NOSPLIT,$0-24
|
||||
WRITE_CR3() // Switch to userCR3.
|
||||
POPQ AX // Restore AX.
|
||||
IRET()
|
||||
// sysenter or exception will write our return value and return to our
|
||||
// caller.
|
||||
|
||||
// See entry_amd64.go.
|
||||
TEXT ·resume(SB),NOSPLIT,$0
|
||||
@@ -324,11 +423,39 @@ kernel:
|
||||
MOVQ $0, CPU_ERROR_CODE(AX) // Clear error code.
|
||||
MOVQ $0, CPU_ERROR_TYPE(AX) // Set error type to kernel.
|
||||
|
||||
// Save floating point state. CPU.floatingPointState is a slice, so the
|
||||
// first word of CPU.floatingPointState is a pointer to the destination
|
||||
// array.
|
||||
MOVQ CPU_FPU_STATE(AX), DI
|
||||
MOVB CPU_HAS_XSAVE(AX), BX
|
||||
MOVB CPU_HAS_XSAVEOPT(AX), CX
|
||||
TESTB BX, BX
|
||||
JZ no_xsave
|
||||
// Use xsave/xsaveopt to save all extended state.
|
||||
// We save everything unconditionally by setting RFBM to all 1's.
|
||||
MOVL $0xffffffff, AX
|
||||
MOVL $0xffffffff, DX
|
||||
TESTB CX, CX
|
||||
JZ no_xsaveopt
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x37; // XSAVEOPT64 0(DI)
|
||||
JMP fpsave_done
|
||||
no_xsaveopt:
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x27; // XSAVE64 0(DI)
|
||||
JMP fpsave_done
|
||||
no_xsave:
|
||||
FXSAVE64 0(DI)
|
||||
fpsave_done:
|
||||
|
||||
// Call the syscall trampoline.
|
||||
LOAD_KERNEL_STACK(GS)
|
||||
PUSHQ AX // First argument (vCPU).
|
||||
CALL ·kernelSyscall(SB) // Call the trampoline.
|
||||
POPQ AX // Pop vCPU.
|
||||
MOVQ ENTRY_CPU_SELF(GS), AX // AX contains the vCPU.
|
||||
PUSHQ AX // First argument (vCPU).
|
||||
CALL ·kernelSyscall(SB) // Call the trampoline.
|
||||
POPQ AX // Pop vCPU.
|
||||
|
||||
// We only trigger a bluepill entry in the bluepill function, and can
|
||||
// therefore be guaranteed that there is no floating point state to be
|
||||
// loaded on resuming from halt.
|
||||
JMP ·resume(SB)
|
||||
|
||||
ADDR_OF_FUNC(·addrOfSysenter(SB), ·sysenter(SB));
|
||||
@@ -416,15 +543,43 @@ kernel:
|
||||
MOVQ 8(SP), BX // Load the error code.
|
||||
MOVQ BX, CPU_ERROR_CODE(AX) // Copy out to the CPU.
|
||||
MOVQ $0, CPU_ERROR_TYPE(AX) // Set error type to kernel.
|
||||
MOVQ 0(SP), BX // BX contains the vector.
|
||||
|
||||
// Save floating point state. CPU.floatingPointState is a slice, so the
|
||||
// first word of CPU.floatingPointState is a pointer to the destination
|
||||
// array.
|
||||
MOVQ CPU_FPU_STATE(AX), DI
|
||||
MOVB CPU_HAS_XSAVE(AX), BX
|
||||
MOVB CPU_HAS_XSAVEOPT(AX), CX
|
||||
TESTB BX, BX
|
||||
JZ no_xsave
|
||||
// Use xsave/xsaveopt to save all extended state.
|
||||
// We save everything unconditionally by setting RFBM to all 1's.
|
||||
MOVL $0xffffffff, AX
|
||||
MOVL $0xffffffff, DX
|
||||
TESTB CX, CX
|
||||
JZ no_xsaveopt
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x37; // XSAVEOPT64 0(DI)
|
||||
JMP fpsave_done
|
||||
no_xsaveopt:
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x27; // XSAVE64 0(DI)
|
||||
JMP fpsave_done
|
||||
no_xsave:
|
||||
FXSAVE64 0(DI)
|
||||
fpsave_done:
|
||||
|
||||
// Call the exception trampoline.
|
||||
MOVQ 0(SP), BX // BX contains the vector.
|
||||
LOAD_KERNEL_STACK(GS)
|
||||
PUSHQ BX // Second argument (vector).
|
||||
PUSHQ AX // First argument (vCPU).
|
||||
CALL ·kernelException(SB) // Call the trampoline.
|
||||
POPQ BX // Pop vector.
|
||||
POPQ AX // Pop vCPU.
|
||||
MOVQ ENTRY_CPU_SELF(GS), AX // AX contains the vCPU.
|
||||
PUSHQ BX // Second argument (vector).
|
||||
PUSHQ AX // First argument (vCPU).
|
||||
CALL ·kernelException(SB) // Call the trampoline.
|
||||
POPQ BX // Pop vector.
|
||||
POPQ AX // Pop vCPU.
|
||||
|
||||
// We only trigger a bluepill entry in the bluepill function, and can
|
||||
// therefore be guaranteed that there is no floating point state to be
|
||||
// loaded on resuming from halt.
|
||||
JMP ·resume(SB)
|
||||
|
||||
#define EXCEPTION_WITH_ERROR(value, symbol, addr) \
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
|
||||
package ring0
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
|
||||
)
|
||||
|
||||
// Init initializes a new kernel.
|
||||
//
|
||||
//go:nosplit
|
||||
@@ -80,6 +84,7 @@ func (c *CPU) Init(k *Kernel, cpuID int, hooks Hooks) {
|
||||
c.self = c // Set self reference.
|
||||
c.kernel = k // Set kernel reference.
|
||||
c.init(cpuID) // Perform architectural init.
|
||||
c.floatingPointState = fpu.NewState()
|
||||
|
||||
// Require hooks.
|
||||
if hooks != nil {
|
||||
|
||||
@@ -143,6 +143,9 @@ func (c *CPU) init(cpuID int) {
|
||||
|
||||
// Set mandatory flags.
|
||||
c.registers.Eflags = KernelFlagsSet
|
||||
|
||||
c.hasXSAVE = hasXSAVE
|
||||
c.hasXSAVEOPT = hasXSAVEOPT
|
||||
}
|
||||
|
||||
// StackTop returns the kernel's stack address.
|
||||
@@ -248,19 +251,21 @@ func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
|
||||
regs.Ss = uint64(Udata) // Ditto.
|
||||
|
||||
// Perform the switch.
|
||||
swapgs() // GS will be swapped on return.
|
||||
WriteGS(uintptr(regs.Gs_base)) // escapes: no. Set application GS.
|
||||
LoadFloatingPoint(switchOpts.FloatingPointState.BytePointer()) // escapes: no. Copy in floating point.
|
||||
needIRET := uint64(0)
|
||||
if switchOpts.FullRestore {
|
||||
vector = iret(c, regs, uintptr(userCR3))
|
||||
} else {
|
||||
vector = sysret(c, regs, uintptr(userCR3))
|
||||
needIRET = 1
|
||||
}
|
||||
SaveFloatingPoint(switchOpts.FloatingPointState.BytePointer()) // escapes: no. Copy out floating point.
|
||||
RestoreKernelFPState() // escapes: no. Restore kernel MXCSR.
|
||||
vector = doSwitchToUser(c, regs, switchOpts.FloatingPointState.BytePointer(), userCR3, needIRET) // escapes: no.
|
||||
return
|
||||
}
|
||||
|
||||
func doSwitchToUser(
|
||||
cpu *CPU, // +0(FP)
|
||||
regs *arch.Registers, // +8(FP)
|
||||
fpState *byte, // +16(FP)
|
||||
userCR3 uint64, // +24(FP)
|
||||
needIRET uint64) Vector // +32(FP), +40(FP)
|
||||
|
||||
var (
|
||||
sentryXCR0 uintptr
|
||||
sentryXCR0Once sync.Once
|
||||
@@ -287,7 +292,7 @@ func initSentryXCR0() {
|
||||
//go:nosplit
|
||||
func startGo(c *CPU) {
|
||||
// Save per-cpu.
|
||||
WriteGS(kernelAddr(c.kernelEntry))
|
||||
writeGS(kernelAddr(c.kernelEntry))
|
||||
|
||||
//
|
||||
// TODO(mpratt): Note that per the note above, this should be done
|
||||
|
||||
+2
-40
@@ -21,29 +21,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/cpuid"
|
||||
)
|
||||
|
||||
// LoadFloatingPoint loads floating point state by the most efficient mechanism
|
||||
// available (set by Init).
|
||||
var LoadFloatingPoint func(*byte)
|
||||
|
||||
// SaveFloatingPoint saves floating point state by the most efficient mechanism
|
||||
// available (set by Init).
|
||||
var SaveFloatingPoint func(*byte)
|
||||
|
||||
// fxrstor uses fxrstor64 to load floating point state.
|
||||
func fxrstor(*byte)
|
||||
|
||||
// xrstor uses xrstor to load floating point state.
|
||||
func xrstor(*byte)
|
||||
|
||||
// fxsave uses fxsave64 to save floating point state.
|
||||
func fxsave(*byte)
|
||||
|
||||
// xsave uses xsave to save floating point state.
|
||||
func xsave(*byte)
|
||||
|
||||
// xsaveopt uses xsaveopt to save floating point state.
|
||||
func xsaveopt(*byte)
|
||||
|
||||
// writeFS sets the FS base address (selects one of wrfsbase or wrfsmsr).
|
||||
func writeFS(addr uintptr)
|
||||
|
||||
@@ -53,8 +30,8 @@ func wrfsbase(addr uintptr)
|
||||
// wrfsmsr writes to the GS_BASE MSR.
|
||||
func wrfsmsr(addr uintptr)
|
||||
|
||||
// WriteGS sets the GS address (set by init).
|
||||
var WriteGS func(addr uintptr)
|
||||
// writeGS sets the GS address (selects one of wrgsbase or wrgsmsr).
|
||||
func writeGS(addr uintptr)
|
||||
|
||||
// wrgsbase writes to the GS base address.
|
||||
func wrgsbase(addr uintptr)
|
||||
@@ -106,19 +83,4 @@ func Init(featureSet *cpuid.FeatureSet) {
|
||||
hasXSAVE = featureSet.UseXsave()
|
||||
hasFSGSBASE = featureSet.HasFeature(cpuid.X86FeatureFSGSBase)
|
||||
validXCR0Mask = uintptr(featureSet.ValidXCR0Mask())
|
||||
if hasXSAVEOPT {
|
||||
SaveFloatingPoint = xsaveopt
|
||||
LoadFloatingPoint = xrstor
|
||||
} else if hasXSAVE {
|
||||
SaveFloatingPoint = xsave
|
||||
LoadFloatingPoint = xrstor
|
||||
} else {
|
||||
SaveFloatingPoint = fxsave
|
||||
LoadFloatingPoint = fxrstor
|
||||
}
|
||||
if hasFSGSBASE {
|
||||
WriteGS = wrgsbase
|
||||
} else {
|
||||
WriteGS = wrgsmsr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +128,29 @@ TEXT ·wrfsmsr(SB),NOSPLIT,$0-8
|
||||
BYTE $0x0f; BYTE $0x30;
|
||||
RET
|
||||
|
||||
// writeGS writes to the GS base.
|
||||
//
|
||||
// This is written in assembly because it must be callable from assembly (ABI0)
|
||||
// without an intermediate transition to ABIInternal.
|
||||
//
|
||||
// Preconditions: must be running in the lower address space, as it accesses
|
||||
// global data.
|
||||
TEXT ·writeGS(SB),NOSPLIT,$8-8
|
||||
MOVQ addr+0(FP), AX
|
||||
|
||||
CMPB ·hasFSGSBASE(SB), $1
|
||||
JNE msr
|
||||
|
||||
PUSHQ AX
|
||||
CALL ·wrgsbase(SB)
|
||||
POPQ AX
|
||||
RET
|
||||
msr:
|
||||
PUSHQ AX
|
||||
CALL ·wrgsmsr(SB)
|
||||
POPQ AX
|
||||
RET
|
||||
|
||||
// wrgsbase writes to the GS base.
|
||||
//
|
||||
// The code corresponds to:
|
||||
|
||||
@@ -35,6 +35,9 @@ func Emit(w io.Writer) {
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_CODE 0x%02x\n", reflect.ValueOf(&c.errorCode).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_TYPE 0x%02x\n", reflect.ValueOf(&c.errorType).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ENTRY 0x%02x\n", reflect.ValueOf(&c.kernelEntry).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_HAS_XSAVE 0x%02x\n", reflect.ValueOf(&c.hasXSAVE).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_HAS_XSAVEOPT 0x%02x\n", reflect.ValueOf(&c.hasXSAVEOPT).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_FPU_STATE 0x%02x\n", reflect.ValueOf(&c.floatingPointState).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
|
||||
e := &kernelEntry{}
|
||||
fmt.Fprintf(w, "\n// CPU entry offsets.\n")
|
||||
|
||||
@@ -71,10 +71,6 @@ func (c *vCPU) KernelSyscall() {
|
||||
if regs.Rax != ^uint64(0) {
|
||||
regs.Rip -= 2 // Rewind.
|
||||
}
|
||||
// We only trigger a bluepill entry in the bluepill function, and can
|
||||
// therefore be guaranteed that there is no floating point state to be
|
||||
// loaded on resuming from halt. We only worry about saving on exit.
|
||||
ring0.SaveFloatingPoint(c.floatingPointState.BytePointer()) // escapes: no.
|
||||
// N.B. Since KernelSyscall is called when the kernel makes a syscall,
|
||||
// FS_BASE is already set for correct execution of this function.
|
||||
//
|
||||
@@ -112,8 +108,6 @@ func (c *vCPU) KernelException(vector ring0.Vector) {
|
||||
regs.Rip = 0
|
||||
}
|
||||
// See above.
|
||||
ring0.SaveFloatingPoint(c.floatingPointState.BytePointer()) // escapes: no.
|
||||
// See above.
|
||||
ring0.HaltAndWriteFSBase(regs) // escapes: no, reload host segment.
|
||||
}
|
||||
|
||||
@@ -144,5 +138,5 @@ func bluepillArchExit(c *vCPU, context *arch.SignalContext64) {
|
||||
// Set the context pointer to the saved floating point state. This is
|
||||
// where the guest data has been serialized, the kernel will restore
|
||||
// from this new pointer value.
|
||||
context.Fpstate = uint64(uintptrValue(c.floatingPointState.BytePointer()))
|
||||
context.Fpstate = uint64(uintptrValue(c.FloatingPointState().BytePointer())) // escapes: no.
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func bluepillArchExit(c *vCPU, context *arch.SignalContext64) {
|
||||
|
||||
lazyVfp := c.GetLazyVFP()
|
||||
if lazyVfp != 0 {
|
||||
fpsimd := fpsimdPtr(c.floatingPointState.BytePointer())
|
||||
fpsimd := fpsimdPtr(c.FloatingPointState().BytePointer()) // escapes: no
|
||||
context.Fpsimd64.Fpsr = fpsimd.Fpsr
|
||||
context.Fpsimd64.Fpcr = fpsimd.Fpcr
|
||||
context.Fpsimd64.Vregs = fpsimd.Vregs
|
||||
@@ -90,12 +90,12 @@ func (c *vCPU) KernelSyscall() {
|
||||
|
||||
fpDisableTrap := ring0.CPACREL1()
|
||||
if fpDisableTrap != 0 {
|
||||
fpsimd := fpsimdPtr(c.floatingPointState.BytePointer())
|
||||
fpsimd := fpsimdPtr(c.FloatingPointState().BytePointer()) // escapes: no
|
||||
fpcr := ring0.GetFPCR()
|
||||
fpsr := ring0.GetFPSR()
|
||||
fpsimd.Fpcr = uint32(fpcr)
|
||||
fpsimd.Fpsr = uint32(fpsr)
|
||||
ring0.SaveVRegs(c.floatingPointState.BytePointer())
|
||||
ring0.SaveVRegs(c.FloatingPointState().BytePointer()) // escapes: no
|
||||
}
|
||||
|
||||
ring0.Halt()
|
||||
@@ -114,12 +114,12 @@ func (c *vCPU) KernelException(vector ring0.Vector) {
|
||||
|
||||
fpDisableTrap := ring0.CPACREL1()
|
||||
if fpDisableTrap != 0 {
|
||||
fpsimd := fpsimdPtr(c.floatingPointState.BytePointer())
|
||||
fpsimd := fpsimdPtr(c.FloatingPointState().BytePointer()) // escapes: no
|
||||
fpcr := ring0.GetFPCR()
|
||||
fpsr := ring0.GetFPSR()
|
||||
fpsimd.Fpcr = uint32(fpcr)
|
||||
fpsimd.Fpsr = uint32(fpsr)
|
||||
ring0.SaveVRegs(c.floatingPointState.BytePointer())
|
||||
ring0.SaveVRegs(c.FloatingPointState().BytePointer()) // escapes: no
|
||||
}
|
||||
|
||||
ring0.Halt()
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/ring0"
|
||||
"gvisor.dev/gvisor/pkg/ring0/pagetables"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
|
||||
"gvisor.dev/gvisor/pkg/sentry/platform"
|
||||
ktime "gvisor.dev/gvisor/pkg/sentry/time"
|
||||
)
|
||||
@@ -72,10 +71,6 @@ type vCPUArchState struct {
|
||||
//
|
||||
// This starts above fixedKernelPCID.
|
||||
PCIDs *pagetables.PCIDs
|
||||
|
||||
// floatingPointState is the floating point state buffer used in guest
|
||||
// to host transitions. See usage in bluepill_amd64.go.
|
||||
floatingPointState fpu.State
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -152,12 +147,6 @@ func (c *vCPU) initArchState() error {
|
||||
return fmt.Errorf("error setting user registers: %v", errno)
|
||||
}
|
||||
|
||||
// Allocate some floating point state save area for the local vCPU.
|
||||
// This will be saved prior to leaving the guest, and we restore from
|
||||
// this always. We cannot use the pointer in the context alone because
|
||||
// we don't know how large the area there is in reality.
|
||||
c.floatingPointState = fpu.NewState()
|
||||
|
||||
// Set the time offset to the host native time.
|
||||
return c.setSystemTime()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/ring0"
|
||||
"gvisor.dev/gvisor/pkg/ring0/pagetables"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
|
||||
"gvisor.dev/gvisor/pkg/sentry/platform"
|
||||
)
|
||||
|
||||
@@ -40,10 +39,6 @@ type vCPUArchState struct {
|
||||
//
|
||||
// This starts above fixedKernelPCID.
|
||||
PCIDs *pagetables.PCIDs
|
||||
|
||||
// floatingPointState is the floating point state buffer used in guest
|
||||
// to host transitions. See usage in bluepill_arm64.go.
|
||||
floatingPointState fpu.State
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/ring0"
|
||||
"gvisor.dev/gvisor/pkg/ring0/pagetables"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
|
||||
"gvisor.dev/gvisor/pkg/sentry/platform"
|
||||
ktime "gvisor.dev/gvisor/pkg/sentry/time"
|
||||
)
|
||||
@@ -159,8 +158,6 @@ func (c *vCPU) initArchState() error {
|
||||
c.PCIDs = pagetables.NewPCIDs(fixedKernelPCID+1, poolPCIDs)
|
||||
}
|
||||
|
||||
c.floatingPointState = fpu.NewState()
|
||||
|
||||
return c.setSystemTime()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user