mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Exclude AMX extended state from being xsave/xrstor'd.
For now we are going to completely disable using AMX, so we will always subtract extended state size reserved from AMX from the rest of the extended state size, and hardcode the AMX XCR0 bits to be always off. Fixes #9750. PiperOrigin-RevId: 599302059
This commit is contained in:
committed by
gVisor bot
parent
1ae5fca498
commit
e9bdc76c02
@@ -361,8 +361,22 @@ func (fs FeatureSet) Intel() bool {
|
||||
// If xSaveInfo isn't supported, cpuid will not fault but will
|
||||
// return bogus values.
|
||||
var (
|
||||
xsaveSize = native(In{Eax: uint32(xSaveInfo)}).Ebx
|
||||
maxXsaveSize = native(In{Eax: uint32(xSaveInfo)}).Ecx
|
||||
xsaveSize = native(In{Eax: uint32(xSaveInfo)}).Ebx
|
||||
maxXsaveSize = native(In{Eax: uint32(xSaveInfo)}).Ecx
|
||||
amxTileCfgSize = native(In{Eax: uint32(xSaveInfo), Ecx: 17}).Eax
|
||||
amxTileDataSize = native(In{Eax: uint32(xSaveInfo), Ecx: 18}).Eax
|
||||
)
|
||||
|
||||
const (
|
||||
// XCR0AMXMask are the bits that enable xsave to operate on AMX TILECFG
|
||||
// and TILEDATA.
|
||||
//
|
||||
// Note: TILECFG and TILEDATA are always either both enabled or both
|
||||
// disabled.
|
||||
//
|
||||
// See Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol.1
|
||||
// section 13.3 for details.
|
||||
XCR0AMXMask = uint64((1 << 17) | (1 << 18))
|
||||
)
|
||||
|
||||
// ExtendedStateSize returns the number of bytes needed to save the "extended
|
||||
@@ -370,13 +384,17 @@ var (
|
||||
// Extended state includes floating point registers, and other cpu state that's
|
||||
// not associated with the normal task context.
|
||||
//
|
||||
// We do not support enabling AMX within gVisor, therefore always exclude
|
||||
// AMXExtendedStateSize.
|
||||
// TODO(gvisor.dev/issues/9896): Implement AMX Support.
|
||||
//
|
||||
// Note: the return value matches the size of signal FP state frames.
|
||||
// Look at check_xstate_in_sigframe() in the kernel sources for more details.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) ExtendedStateSize() (size, align uint) {
|
||||
if fs.UseXsave() {
|
||||
return uint(xsaveSize), 64
|
||||
return uint(xsaveSize) - fs.AMXExtendedStateSize(), 64
|
||||
}
|
||||
|
||||
// If we don't support xsave, we fall back to fxsave, which requires
|
||||
@@ -384,15 +402,28 @@ func (fs FeatureSet) ExtendedStateSize() (size, align uint) {
|
||||
return 512, 16
|
||||
}
|
||||
|
||||
// AMXExtendedStateSize returns the number of bytes within the "extended state"
|
||||
// area that is used for AMX.
|
||||
func (fs FeatureSet) AMXExtendedStateSize() uint {
|
||||
xcr0 := xgetbv(0)
|
||||
if (xcr0 & XCR0AMXMask) != 0 {
|
||||
return uint(amxTileCfgSize + amxTileDataSize)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// ValidXCR0Mask returns the valid bits in control register XCR0.
|
||||
//
|
||||
// Always exclude AMX bits, because we do not support it.
|
||||
// TODO(gvisor.dev/issues/9896): Implement AMX Support.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) ValidXCR0Mask() uint64 {
|
||||
if !fs.HasFeature(X86FeatureXSAVE) {
|
||||
return 0
|
||||
}
|
||||
ax, _, _, dx := fs.query(xSaveInfo)
|
||||
return uint64(dx)<<32 | uint64(ax)
|
||||
return (uint64(dx)<<32 | uint64(ax)) ^ XCR0AMXMask
|
||||
}
|
||||
|
||||
// UseXsave returns the choice of fp state saving instruction.
|
||||
|
||||
@@ -215,6 +215,9 @@ func readMaxCPUFreq() {
|
||||
|
||||
}
|
||||
|
||||
// xgetbv reads an extended control register.
|
||||
func xgetbv(reg uintptr) uint64
|
||||
|
||||
// archInitialize initializes hostFeatureSet.
|
||||
func archInitialize() {
|
||||
hostFeatureSet = FeatureSet{
|
||||
|
||||
@@ -23,3 +23,16 @@ TEXT ·native(SB),NOSPLIT|NOFRAME,$0-24
|
||||
MOVL CX, ret_Ecx+16(FP)
|
||||
MOVL DX, ret_Edx+20(FP)
|
||||
RET
|
||||
|
||||
// xgetbv reads an extended control register.
|
||||
//
|
||||
// The code corresponds to:
|
||||
//
|
||||
// xgetbv
|
||||
//
|
||||
TEXT ·xgetbv(SB),NOSPLIT|NOFRAME,$0-16
|
||||
MOVQ reg+0(FP), CX
|
||||
BYTE $0x0f; BYTE $0x01; BYTE $0xd0;
|
||||
MOVL AX, ret+8(FP)
|
||||
MOVL DX, ret+12(FP)
|
||||
RET
|
||||
|
||||
+15
-8
@@ -88,6 +88,13 @@
|
||||
#define PTRACE_FS_BASE 168 // +checkoffset linux PtraceRegs.Fs_base
|
||||
#define PTRACE_GS_BASE 176 // +checkoffset linux PtraceRegs.Gs_base
|
||||
|
||||
// The value for XCR0 is defined to xsave/xrstor everything except for AMX
|
||||
// regions.
|
||||
// TODO(gvisor.dev/issues/9896): Implement AMX Support.
|
||||
#define XCR0_AMX_MASK ((1 << 17) | (1 << 18))
|
||||
#define XCR0_EAX (0xffffffff ^ XCR0_AMX_MASK)
|
||||
#define XCR0_EDX 0xffffffff
|
||||
|
||||
// Saves a register set.
|
||||
//
|
||||
// This is a macro because it may need to executed in contents where a stack is
|
||||
@@ -229,8 +236,8 @@ TEXT ·doSwitchToUser(SB),NOSPLIT,$16-48
|
||||
// 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
|
||||
MOVL $XCR0_EAX, AX
|
||||
MOVL $XCR0_EDX, DX
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x2f // XRSTOR64 0(DI)
|
||||
JMP fprestore_done
|
||||
no_xrstor:
|
||||
@@ -275,8 +282,8 @@ done_sysret_or_iret:
|
||||
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
|
||||
MOVL $XCR0_EAX, AX
|
||||
MOVL $XCR0_EDX, DX
|
||||
TESTB CX, CX
|
||||
JZ no_xsaveopt
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x37; // XSAVEOPT64 0(DI)
|
||||
@@ -513,8 +520,8 @@ kernel:
|
||||
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
|
||||
MOVL $XCR0_EAX, AX
|
||||
MOVL $XCR0_EDX, DX
|
||||
TESTB CX, CX
|
||||
JZ no_xsaveopt
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x37; // XSAVEOPT64 0(DI)
|
||||
@@ -645,8 +652,8 @@ kernel:
|
||||
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
|
||||
MOVL $XCR0_EAX, AX
|
||||
MOVL $XCR0_EDX, DX
|
||||
TESTB CX, CX
|
||||
JZ no_xsaveopt
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x37; // XSAVEOPT64 0(DI)
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
// FXSAVE/XSAVE area. (Intel SDM Vol. 1, Table 10-2 "Format of an FXSAVE Area")
|
||||
#define MXCSR_OFFSET 24
|
||||
|
||||
// The value for XCR0 is defined to xsave/xrstor everything except for AMX
|
||||
// regions.
|
||||
// TODO(gvisor.dev/issues/9896): Implement AMX Support.
|
||||
#define XCR0_AMX_MASK ((1 << 17) | (1 << 18))
|
||||
#define XCR0_EAX (0xffffffff ^ XCR0_AMX_MASK)
|
||||
#define XCR0_EDX 0xffffffff
|
||||
|
||||
// initX86FPState initializes floating point state.
|
||||
//
|
||||
// func initX86FPState(data *FloatingPointData, useXsave bool)
|
||||
@@ -66,8 +73,8 @@ TEXT ·initX86FPState(SB), $24-9
|
||||
MOVL $MXCSR_DEFAULT, MXCSR_OFFSET(DI)
|
||||
|
||||
// Initialize registers with XRSTOR.
|
||||
MOVL $0xffffffff, AX
|
||||
MOVL $0xffffffff, DX
|
||||
MOVL $XCR0_EAX, AX
|
||||
MOVL $XCR0_EDX, DX
|
||||
BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x2f // XRSTOR64 0(DI)
|
||||
|
||||
// Now that all the state has been reset, write it back out to the
|
||||
|
||||
@@ -480,7 +480,7 @@ static void prep_fpstate_for_sigframe(void *buf, uint32_t user_size,
|
||||
|
||||
sw_bytes->magic1 = FP_XSTATE_MAGIC1;
|
||||
sw_bytes->extended_size = user_size + FP_XSTATE_MAGIC2_SIZE;
|
||||
sw_bytes->xfeatures = ~(0ULL);
|
||||
sw_bytes->xfeatures = ~(0ULL) ^ (XCR0_AMX_MASK);
|
||||
sw_bytes->xstate_size = user_size;
|
||||
*(uint32_t *)(buf + user_size) = use_xsave ? FP_XSTATE_MAGIC2 : 0;
|
||||
}
|
||||
|
||||
@@ -122,8 +122,8 @@ restored_gs:
|
||||
// - the memory address of the thread_context is loaded in %rcx.
|
||||
.macro save_fpstate
|
||||
lea offsetof_thread_context_fpstate(%rcx), %rdi
|
||||
movl $0xffffffff, %eax
|
||||
movl $0xffffffff, %edx
|
||||
movl $XCR0_EAX, %eax
|
||||
movl $XCR0_EDX, %edx
|
||||
movl __export_arch_state+offsetof_arch_state_xsave_mode(%rip), %esi
|
||||
cmpl $XSAVE_MODE_XSAVEOPT, %esi
|
||||
jl use_xsave
|
||||
@@ -153,8 +153,8 @@ fpu_saved:
|
||||
cmpl $XSAVE_MODE_FXSAVE, %eax
|
||||
jz use_fxrstor
|
||||
use_xrstor:
|
||||
movl $0xffffffff, %eax
|
||||
movl $0xffffffff, %edx
|
||||
movl $XCR0_EAX, %eax
|
||||
movl $XCR0_EDX, %edx
|
||||
xrstor (%rdi)
|
||||
jmp fpu_restored
|
||||
use_fxrstor:
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
// for the pkg/sentry/platform/systrap/usertrap package.
|
||||
#define FAULT_OPCODE 0x06
|
||||
|
||||
// The value for XCR0 is defined to xsave/xrstor everything except for AMX
|
||||
// regions.
|
||||
// TODO(gvisor.dev/issues/9896): Implement AMX Support.
|
||||
#define XCR0_AMX_MASK ((1 << 17) | (1 << 18))
|
||||
#define XCR0_EAX (0xffffffff ^ XCR0_AMX_MASK)
|
||||
#define XCR0_EDX 0xffffffff
|
||||
|
||||
// LINT.IfChange
|
||||
#define MAX_FPSTATE_LEN 3584
|
||||
// Note: To be explicit, 2^12 = 4096; if ALLOCATED_SIZEOF_THREAD_CONTEXT_STRUCT
|
||||
|
||||
Reference in New Issue
Block a user