Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/ring0/defs_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ type CPUArchState struct {
hasXSAVE bool
hasXSAVEOPT bool
hasFSGSBASE bool
hasAVX bool
xcr0Eax uint32
}

// ErrorCode returns the last error code.
Expand Down
52 changes: 52 additions & 0 deletions pkg/ring0/entry_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#define CPU_HAS_XSAVE CPU_ARCH_STATE+48 // +checkoffset . CPUArchState.hasXSAVE
#define CPU_HAS_XSAVEOPT CPU_ARCH_STATE+49 // +checkoffset . CPUArchState.hasXSAVEOPT
#define CPU_HAS_FSGSBASE CPU_ARCH_STATE+50 // +checkoffset . CPUArchState.hasFSGSBASE
#define CPU_HAS_AVX CPU_ARCH_STATE+51 // +checkoffset . CPUArchState.hasAVX
#define CPU_XCR0 CPU_ARCH_STATE+52 // +checkoffset . CPUArchState.xcr0Eax

#define ENTRY_SCRATCH0 256 // +checkoffset . kernelEntry.scratch0
#define ENTRY_STACK_TOP 264 // +checkoffset . kernelEntry.stackTop
Expand Down Expand Up @@ -318,6 +320,15 @@ fpsave_done:
BYTE $0xDB; BYTE $0xE2; // FNCLEX
FLDCW cw-8(SP)

MOVB ·hasAVX(SB), BX
TESTB BX, BX
JZ no_avx_switch
VXORPS X15, X15, X15
JMP avx_done_switch
no_avx_switch:
XORPS X15, X15
avx_done_switch:

RET

// See entry_amd64.go.
Expand Down Expand Up @@ -438,6 +449,29 @@ TEXT ·start(SB),NOSPLIT|NOFRAME,$0
POPQ BX
SWAP_GS()

// Initialize FPU state before calling any Go code.
BYTE $0xdb; BYTE $0xe3 // fninit

// Sync XCR0 if XSAVE is enabled.
MOVQ 0(SP), AX // Pointer to CPU.
CMPB CPU_HAS_XSAVE(AX), $0
JE no_xsetbv_start
MOVL CPU_XCR0(AX), AX
MOVL $0, DX
MOVL $0, CX
BYTE $0x0f; BYTE $0x01; BYTE $0xd1 // xsetbv
no_xsetbv_start:

// Zero X15 before entering Go code.
MOVQ 0(SP), AX // Pointer to CPU.
CMPB CPU_HAS_AVX(AX), $0
JZ no_avx_start
VXORPS X15, X15, X15
JMP avx_done_start
no_avx_start:
XORPS X15, X15
avx_done_start:

// First argument (CPU) already at bottom of stack.
CALL ·startGo(SB) // Call Go hook.
JMP ·resume(SB) // Restore to registers.
Expand Down Expand Up @@ -584,6 +618,15 @@ fpsave_done:
LOAD_KERNEL_STACK(GS)
MOVQ ENTRY_CPU_SELF(GS), AX // AX contains the vCPU.
PUSHQ AX // First argument (vCPU).
MOVB CPU_HAS_AVX(AX), BX
TESTB BX, BX
JZ no_avx_syscall
VXORPS X15, X15, X15
JMP avx_done_syscall
no_avx_syscall:
XORPS X15, X15
avx_done_syscall:
CALL ·jumpToUser(SB)
CALL ·kernelSyscall(SB) // Call the trampoline.
POPQ AX // Pop vCPU.

Expand Down Expand Up @@ -717,6 +760,15 @@ fpsave_done:
MOVQ ENTRY_CPU_SELF(GS), AX // AX contains the vCPU.
PUSHQ BX // Second argument (vector).
PUSHQ AX // First argument (vCPU).
MOVB CPU_HAS_AVX(AX), BX
TESTB BX, BX
JZ no_avx_exception
VXORPS X15, X15, X15
JMP avx_done_exception
no_avx_exception:
XORPS X15, X15
avx_done_exception:
CALL ·jumpToUser(SB)
CALL ·kernelException(SB) // Call the trampoline.
POPQ BX // Pop vector.
POPQ AX // Pop vCPU.
Expand Down
20 changes: 4 additions & 16 deletions pkg/ring0/kernel_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ func (c *CPU) init(cpuID int) {
c.hasXSAVE = hasXSAVE
c.hasXSAVEOPT = hasXSAVEOPT
c.hasFSGSBASE = hasFSGSBASE
c.hasAVX = hasAVX
if hasXSAVE {
c.xcr0Eax = uint32(localXCR0 &^ (cpuid.XSAVEFeatureBNDCSR | cpuid.XSAVEFeatureBNDREGS))
}
}

// StackTop returns the kernel's stack address.
Expand Down Expand Up @@ -291,22 +295,6 @@ func startGo(c *CPU) {
// Save per-cpu.
writeGS(kernelAddr(c.kernelEntry))

//
// TODO(mpratt): Note that per the note above, this should be done
// before entering Go code. However for simplicity we leave it here for
// now, since the small critical sections with undefined FPU state
// should only contain very limited use of floating point instructions
// (notably, use of XMM15 as a zero register).
fninit()
// Need to sync XCR0 with the host, because xsave and xrstor can be
// called from different contexts.
if hasXSAVE {
// Exclude MPX bits. MPX has been deprecated and we have seen
// cases when it isn't supported in VM.
xcr0 := localXCR0 &^ (cpuid.XSAVEFeatureBNDCSR | cpuid.XSAVEFeatureBNDREGS)
xsetbv(0, xcr0)
}

// Set the syscall target.
wrmsr(_MSR_LSTAR, kernelFunc(addrOfSysenter()))
wrmsr(_MSR_SYSCALL_MASK, KernelFlagsClear|_RFLAGS_DF)
Expand Down
2 changes: 2 additions & 0 deletions pkg/ring0/lib_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ var (
hasXSAVE bool
hasFSGSBASE bool
hasLA57 bool
hasAVX bool
validXCR0Mask uintptr
localXCR0 uintptr
)
Expand Down Expand Up @@ -119,6 +120,7 @@ func Init(fs cpuid.FeatureSet) {
hasXSAVE = fs.UseXsave()
hasFSGSBASE = fs.HasFeature(cpuid.X86FeatureFSGSBase)
hasLA57 = fs.HasFeature(cpuid.X86FeatureLA57)
hasAVX = fs.HasFeature(cpuid.X86FeatureAVX)
validXCR0Mask = uintptr(fs.ValidXCR0Mask())
if hasXSAVE {
XCR0DisabledMask := uintptr((1 << 9) | (1 << 17) | (1 << 18))
Expand Down
2 changes: 2 additions & 0 deletions pkg/safecopy/memcpy_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
TEXT handleMemcpyFault(SB), NOSPLIT|NOFRAME, $0-36
MOVQ AX, addr+24(FP)
MOVL DI, sig+32(FP)
XORPS X15, X15
RET

// memcpy copies data from src to dst. If a SIGSEGV or SIGBUS signal is received
Expand Down Expand Up @@ -216,6 +217,7 @@ move_129through256:
MOVOU X14, -32(DI)(BX*1)
MOVOU -16(SI)(BX*1), X15
MOVOU X15, -16(DI)(BX*1)
XORPS X15, X15
RET

// func addrOfMemcpy() uintptr
Expand Down
1 change: 1 addition & 0 deletions pkg/sigframe/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/abi/linux",
"//pkg/cpuid",
"//pkg/hostarch",
"//pkg/hostsyscall",
"//pkg/sentry/arch",
Expand Down
7 changes: 7 additions & 0 deletions pkg/sigframe/sigframe_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,11 @@ TEXT ·Sigreturn(SB),NOSPLIT,$0-8
TEXT ·retjmp(SB),NOSPLIT,$0-0
MOVQ 8(SP), BP
ADDQ $0x10,SP
MOVB ·hasAVX(SB), AX
TESTB AX, AX
JZ no_avx
VXORPS X15, X15, X15
RET
no_avx:
XORPS X15, X15
RET
8 changes: 8 additions & 0 deletions pkg/sigframe/sigframe_amd64_unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,19 @@ import (

"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/cpuid"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/hostsyscall"
"gvisor.dev/gvisor/pkg/sentry/arch"
)

var hasAVX bool

func init() {
cpuid.Initialize()
hasAVX = cpuid.HostFeatureSet().HasFeature(cpuid.X86FeatureAVX)
}

func callWithSignalFrame(stack uintptr, handler uintptr, sigframe *arch.UContext64)

//go:linkname throw runtime.throw
Expand Down
Loading