Debugger: add AVX support

- Unify storage of "FPU" registers between debugger and signal handler
  to use xsave format on both sides
- Handle YMM registers in Debugger (they are the same as XMM, but wider)

Tested:
- The system still boots with and without AVX
- The hello_avx test program can be debugged and the full value of YMM is visible

This changes the API of vregs in signal.h but not the ABI (structure are
declared differently but memory layout is the same). This changes the
API and ABI of arch_debugger.h for x86_64, but I don't think anything
outside Haiku uses it (did we ever have a 64bit compatible gdb?)

Change-Id: If93680ffa0339c19bab517876b4e029f5d66b240
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3038
Reviewed-by: Rene Gollent <rene@gollent.com>
This commit is contained in:
Adrien Destugues 2020-07-16 20:53:50 +02:00 committed by Adrien Destugues
parent 094b8dcf70
commit 6f3a5c9ab0
7 changed files with 201 additions and 165 deletions

View File

@ -6,38 +6,14 @@
#define _ARCH_X86_64_DEBUGGER_H
typedef struct x86_64_fp_register {
uint8 value[10];
uint8 reserved[6];
} x86_64_fp_register;
#if __x86_64__
typedef struct x86_64_xmm_register {
uint8 value[16];
} x86_64_xmm_register;
typedef struct x86_64_extended_registers {
uint16 control;
uint16 status;
uint8 tag;
uint8 reserved1;
uint16 opcode;
uint64 instruction_pointer;
uint64 data_pointer;
uint32 mxcsr;
uint32 mxcsr_mask;
union {
x86_64_fp_register fp_registers[8]; // st0-st7
x86_64_fp_register mmx_registers[8]; // mm0-mm7
};
x86_64_xmm_register xmm_registers[16]; // xmm0-xmm15
uint8 reserved2[96]; // 416 - 512
} x86_64_extended_registers;
#include <posix/arch/x86_64/signal.h>
struct x86_64_debug_cpu_state {
x86_64_extended_registers extended_registers;
struct savefpu extended_registers;
uint64 gs;
uint64 fs;
@ -68,4 +44,7 @@ struct x86_64_debug_cpu_state {
} __attribute__((aligned(16)));
#endif
#endif // _ARCH_X86_64_DEBUGGER_H

View File

@ -12,64 +12,18 @@
#if __x86_64__
struct fp_stack {
unsigned char st0[10];
unsigned char _reserved_42_47[6];
unsigned char st1[10];
unsigned char _reserved_58_63[6];
unsigned char st2[10];
unsigned char _reserved_74_79[6];
unsigned char st3[10];
unsigned char _reserved_90_95[6];
unsigned char st4[10];
unsigned char _reserved_106_111[6];
unsigned char st5[10];
unsigned char _reserved_122_127[6];
unsigned char st6[10];
unsigned char _reserved_138_143[6];
unsigned char st7[10];
unsigned char _reserved_154_159[6];
struct x86_64_fp_register {
unsigned char value[10];
unsigned char reserved[6];
};
struct mmx_regs {
unsigned char mm0[10];
unsigned char _reserved_42_47[6];
unsigned char mm1[10];
unsigned char _reserved_58_63[6];
unsigned char mm2[10];
unsigned char _reserved_74_79[6];
unsigned char mm3[10];
unsigned char _reserved_90_95[6];
unsigned char mm4[10];
unsigned char _reserved_106_111[6];
unsigned char mm5[10];
unsigned char _reserved_122_127[6];
unsigned char mm6[10];
unsigned char _reserved_138_143[6];
unsigned char mm7[10];
unsigned char _reserved_154_159[6];
struct x86_64_xmm_register {
unsigned char value[16];
};
struct xmm_regs {
unsigned char xmm0[16];
unsigned char xmm1[16];
unsigned char xmm2[16];
unsigned char xmm3[16];
unsigned char xmm4[16];
unsigned char xmm5[16];
unsigned char xmm6[16];
unsigned char xmm7[16];
unsigned char xmm8[16];
unsigned char xmm9[16];
unsigned char xmm10[16];
unsigned char xmm11[16];
unsigned char xmm12[16];
unsigned char xmm13[16];
unsigned char xmm14[16];
unsigned char xmm15[16];
};
// The layout of this struct matches the one used by the FXSAVE instruction
struct fpu_state {
unsigned short control;
unsigned short status;
@ -81,26 +35,33 @@ struct fpu_state {
unsigned int mscsr_mask;
union {
struct fp_stack fp;
struct mmx_regs mmx;
struct x86_64_fp_register fp[8];
struct x86_64_fp_register mmx[8];
};
struct xmm_regs xmm;
struct x86_64_xmm_register xmm[16];
unsigned char _reserved_416_511[96];
};
struct xstate_hdr {
unsigned long bv;
unsigned long xcomp_bv;
unsigned char _reserved[48];
};
// The layout of this struct matches the one used by the FXSAVE instruction on
// an AVX CPU
struct savefpu {
struct fpu_state fp_fxsave;
struct xstate_hdr fp_xstate;
unsigned long fp_ymm[16][2];
struct fpu_state fp_fxsave;
struct xstate_hdr fp_xstate;
struct x86_64_xmm_register fp_ymm[16];
// The high half of the YMM registers, to combine with the low half
// found in fp_fxsave.xmm
};
struct vregs {
unsigned long rax;
unsigned long rbx;

View File

@ -29,6 +29,7 @@
#include "disasm/DisassemblerX8664.h"
#define X86_64_EXTENDED_FEATURE_AVX (1 << 28)
static const int32 kFromDwarfRegisters[] = {
X86_64_REGISTER_RAX,
@ -170,6 +171,20 @@ ArchitectureX8664::Init()
if (fAssemblyLanguage == NULL)
return B_NO_MEMORY;
int featureFlags = 0;
#ifdef __x86_64__
// TODO: this needs to be determined/retrieved indirectly from the
// target host interface, as in the remote case the CPU features may
// differ from those of the local CPU.
cpuid_info info;
status_t error = get_cpuid(&info, 1, 0);
if (error != B_OK)
return error;
if ((info.eax_1.extended_features & X86_64_EXTENDED_FEATURE_AVX) != 0)
featureFlags |= X86_64_CPU_FEATURE_FLAG_AVX;
#endif
try {
_AddIntegerRegister(X86_64_REGISTER_RIP, "rip", B_UINT64_TYPE,
REGISTER_TYPE_INSTRUCTION_POINTER, false);
@ -240,38 +255,73 @@ ArchitectureX8664::Init()
_AddSIMDRegister(X86_64_REGISTER_MM6, "mm6", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM7, "mm7", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_XMM0, "xmm0",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM1, "xmm1",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM2, "xmm2",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM3, "xmm3",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM4, "xmm4",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM5, "xmm5",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM6, "xmm6",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM7, "xmm7",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM8, "xmm8",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM9, "xmm9",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM10, "xmm10",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM11, "xmm11",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM12, "xmm12",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM13, "xmm13",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM14, "xmm14",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM15, "xmm15",
sizeof(x86_64_xmm_register));
if ((featureFlags & X86_64_CPU_FEATURE_FLAG_AVX) != 0) {
_AddSIMDRegister(X86_64_REGISTER_XMM0, "ymm0",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM1, "ymm1",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM2, "ymm2",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM3, "ymm3",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM4, "ymm4",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM5, "ymm5",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM6, "ymm6",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM7, "ymm7",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM8, "ymm8",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM9, "ymm9",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM10, "ymm10",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM11, "ymm11",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM12, "ymm12",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM13, "ymm13",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM14, "ymm14",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM15, "ymm15",
sizeof(x86_64_xmm_register) * 2);
} else {
_AddSIMDRegister(X86_64_REGISTER_XMM0, "xmm0",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM1, "xmm1",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM2, "xmm2",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM3, "xmm3",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM4, "xmm4",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM5, "xmm5",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM6, "xmm6",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM7, "xmm7",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM8, "xmm8",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM9, "xmm9",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM10, "xmm10",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM11, "xmm11",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM12, "xmm12",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM13, "xmm13",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM14, "xmm14",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM15, "xmm15",
sizeof(x86_64_xmm_register));
}
} catch (std::bad_alloc&) {
return B_NO_MEMORY;

View File

@ -14,6 +14,13 @@
#include "Register.h"
enum {
X86_64_CPU_FEATURE_FLAG_NONE = 0,
X86_64_CPU_FEATURE_FLAG_AVX = 1,
X86_64_CPU_FEATURE_FLAG_AVX512 = 2
};
class SourceLanguage;

View File

@ -50,50 +50,70 @@ CpuStateX8664::CpuStateX8664(const x86_64_debug_cpu_state& state)
SetIntRegister(X86_64_REGISTER_GS, state.gs);
SetIntRegister(X86_64_REGISTER_SS, state.ss);
const x86_64_extended_registers& extended = state.extended_registers;
const struct savefpu& extended = state.extended_registers;
SetFloatRegister(X86_64_REGISTER_ST0,
(double)(*(long double*)(extended.fp_registers[0].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[0].value)));
SetFloatRegister(X86_64_REGISTER_ST1,
(double)(*(long double*)(extended.fp_registers[1].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[1].value)));
SetFloatRegister(X86_64_REGISTER_ST2,
(double)(*(long double*)(extended.fp_registers[2].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[2].value)));
SetFloatRegister(X86_64_REGISTER_ST3,
(double)(*(long double*)(extended.fp_registers[3].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[3].value)));
SetFloatRegister(X86_64_REGISTER_ST4,
(double)(*(long double*)(extended.fp_registers[4].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[4].value)));
SetFloatRegister(X86_64_REGISTER_ST5,
(double)(*(long double*)(extended.fp_registers[5].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[5].value)));
SetFloatRegister(X86_64_REGISTER_ST6,
(double)(*(long double*)(extended.fp_registers[6].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[6].value)));
SetFloatRegister(X86_64_REGISTER_ST7,
(double)(*(long double*)(extended.fp_registers[7].value)));
(double)(*(long double*)(extended.fp_fxsave.fp[7].value)));
SetMMXRegister(X86_64_REGISTER_MM0, extended.mmx_registers[0].value);
SetMMXRegister(X86_64_REGISTER_MM1, extended.mmx_registers[1].value);
SetMMXRegister(X86_64_REGISTER_MM2, extended.mmx_registers[2].value);
SetMMXRegister(X86_64_REGISTER_MM3, extended.mmx_registers[3].value);
SetMMXRegister(X86_64_REGISTER_MM4, extended.mmx_registers[4].value);
SetMMXRegister(X86_64_REGISTER_MM5, extended.mmx_registers[5].value);
SetMMXRegister(X86_64_REGISTER_MM6, extended.mmx_registers[6].value);
SetMMXRegister(X86_64_REGISTER_MM7, extended.mmx_registers[7].value);
SetMMXRegister(X86_64_REGISTER_MM0, extended.fp_fxsave.mmx[0].value);
SetMMXRegister(X86_64_REGISTER_MM1, extended.fp_fxsave.mmx[1].value);
SetMMXRegister(X86_64_REGISTER_MM2, extended.fp_fxsave.mmx[2].value);
SetMMXRegister(X86_64_REGISTER_MM3, extended.fp_fxsave.mmx[3].value);
SetMMXRegister(X86_64_REGISTER_MM4, extended.fp_fxsave.mmx[4].value);
SetMMXRegister(X86_64_REGISTER_MM5, extended.fp_fxsave.mmx[5].value);
SetMMXRegister(X86_64_REGISTER_MM6, extended.fp_fxsave.mmx[6].value);
SetMMXRegister(X86_64_REGISTER_MM7, extended.fp_fxsave.mmx[7].value);
SetXMMRegister(X86_64_REGISTER_XMM0, extended.xmm_registers[0].value);
SetXMMRegister(X86_64_REGISTER_XMM1, extended.xmm_registers[1].value);
SetXMMRegister(X86_64_REGISTER_XMM2, extended.xmm_registers[2].value);
SetXMMRegister(X86_64_REGISTER_XMM3, extended.xmm_registers[3].value);
SetXMMRegister(X86_64_REGISTER_XMM4, extended.xmm_registers[4].value);
SetXMMRegister(X86_64_REGISTER_XMM5, extended.xmm_registers[5].value);
SetXMMRegister(X86_64_REGISTER_XMM6, extended.xmm_registers[6].value);
SetXMMRegister(X86_64_REGISTER_XMM7, extended.xmm_registers[7].value);
SetXMMRegister(X86_64_REGISTER_XMM8, extended.xmm_registers[8].value);
SetXMMRegister(X86_64_REGISTER_XMM9, extended.xmm_registers[9].value);
SetXMMRegister(X86_64_REGISTER_XMM10, extended.xmm_registers[10].value);
SetXMMRegister(X86_64_REGISTER_XMM11, extended.xmm_registers[11].value);
SetXMMRegister(X86_64_REGISTER_XMM12, extended.xmm_registers[12].value);
SetXMMRegister(X86_64_REGISTER_XMM13, extended.xmm_registers[13].value);
SetXMMRegister(X86_64_REGISTER_XMM14, extended.xmm_registers[14].value);
SetXMMRegister(X86_64_REGISTER_XMM15, extended.xmm_registers[15].value);
// The YMM register value is split in two halves in the saved CPU context,
// so we have to reassemble it here.
// TODO check extended.xstate_hdr to see if the YMM values are present at
// all.
SetXMMRegister(X86_64_REGISTER_XMM0, extended.fp_ymm[0].value,
extended.fp_fxsave.xmm[0].value);
SetXMMRegister(X86_64_REGISTER_XMM1, extended.fp_ymm[1].value,
extended.fp_fxsave.xmm[1].value);
SetXMMRegister(X86_64_REGISTER_XMM2, extended.fp_ymm[2].value,
extended.fp_fxsave.xmm[2].value);
SetXMMRegister(X86_64_REGISTER_XMM3, extended.fp_ymm[3].value,
extended.fp_fxsave.xmm[3].value);
SetXMMRegister(X86_64_REGISTER_XMM4, extended.fp_ymm[4].value,
extended.fp_fxsave.xmm[4].value);
SetXMMRegister(X86_64_REGISTER_XMM5, extended.fp_ymm[5].value,
extended.fp_fxsave.xmm[5].value);
SetXMMRegister(X86_64_REGISTER_XMM6, extended.fp_ymm[6].value,
extended.fp_fxsave.xmm[6].value);
SetXMMRegister(X86_64_REGISTER_XMM7, extended.fp_ymm[7].value,
extended.fp_fxsave.xmm[7].value);
SetXMMRegister(X86_64_REGISTER_XMM8, extended.fp_ymm[8].value,
extended.fp_fxsave.xmm[8].value);
SetXMMRegister(X86_64_REGISTER_XMM9, extended.fp_ymm[9].value,
extended.fp_fxsave.xmm[9].value);
SetXMMRegister(X86_64_REGISTER_XMM10, extended.fp_ymm[10].value,
extended.fp_fxsave.xmm[10].value);
SetXMMRegister(X86_64_REGISTER_XMM11, extended.fp_ymm[11].value,
extended.fp_fxsave.xmm[11].value);
SetXMMRegister(X86_64_REGISTER_XMM12, extended.fp_ymm[12].value,
extended.fp_fxsave.xmm[12].value);
SetXMMRegister(X86_64_REGISTER_XMM13, extended.fp_ymm[13].value,
extended.fp_fxsave.xmm[13].value);
SetXMMRegister(X86_64_REGISTER_XMM14, extended.fp_ymm[14].value,
extended.fp_fxsave.xmm[14].value);
SetXMMRegister(X86_64_REGISTER_XMM15, extended.fp_ymm[15].value,
extended.fp_fxsave.xmm[15].value);
fInterruptVector = state.vector;
}
@ -160,21 +180,21 @@ CpuStateX8664::UpdateDebugState(void* state, size_t size) const
x64State->ss = IntRegisterValue(X86_64_REGISTER_SS);
for (int32 i = 0; i < 8; i++) {
*(long double*)(x64State->extended_registers.fp_registers[i].value)
*(long double*)(x64State->extended_registers.fp_fxsave.fp[i].value)
= (long double)FloatRegisterValue(X86_64_REGISTER_ST0 + i);
if (IsRegisterSet(X86_64_REGISTER_MM0 + i)) {
memcpy(&x64State->extended_registers.mmx_registers[i],
memcpy(&x64State->extended_registers.fp_fxsave.mmx[i],
&fMMXRegisters[i], sizeof(x86_64_fp_register));
}
}
for (int32 i = 0; i < 16; i++) {
if (IsRegisterSet(X86_64_REGISTER_XMM0 + i)) {
memcpy(&x64State->extended_registers.xmm_registers[i],
memcpy(&x64State->extended_registers.fp_fxsave.xmm[i],
&fXMMRegisters[i], sizeof(x86_64_xmm_register));
} else {
memset(&x64State->extended_registers.xmm_registers[i],
memset(&x64State->extended_registers.fp_fxsave.xmm[i],
0, sizeof(x86_64_xmm_register));
}
}
@ -372,12 +392,14 @@ CpuStateX8664::XMMRegisterValue(int32 index) const
void
CpuStateX8664::SetXMMRegister(int32 index, const uint8* value)
CpuStateX8664::SetXMMRegister(int32 index, const uint8* highValue, const uint8* lowValue)
{
if (index < X86_64_REGISTER_XMM0 || index >= X86_64_XMM_REGISTER_END)
return;
memcpy(fXMMRegisters[index - X86_64_REGISTER_XMM0].value, value,
memcpy(&fXMMRegisters[index - X86_64_REGISTER_XMM0].value[0], lowValue,
sizeof(x86_64_xmm_register));
memcpy(&fXMMRegisters[index - X86_64_REGISTER_XMM0].value[2], highValue,
sizeof(x86_64_xmm_register));
fSetRegisters[index] = 1;
}

View File

@ -99,6 +99,11 @@ enum {
- X86_64_MMX_REGISTER_END)
struct x86_64_ymm_register {
unsigned long value[4];
};
class CpuStateX8664 : public CpuState {
public:
CpuStateX8664();
@ -128,6 +133,7 @@ public:
uint64 IntRegisterValue(int32 index) const;
void SetIntRegister(int32 index, uint64 value);
private:
double FloatRegisterValue(int32 index) const;
void SetFloatRegister(int32 index, double value);
@ -137,7 +143,7 @@ public:
const void* XMMRegisterValue(int32 index) const;
void SetXMMRegister(int32 index,
const uint8* value);
const uint8* highValue, const uint8* lowValue);
void UnsetRegister(int32 index);
@ -148,7 +154,7 @@ private:
uint64 fIntRegisters[X86_64_INT_REGISTER_COUNT];
double fFloatRegisters[X86_64_FP_REGISTER_COUNT];
x86_64_fp_register fMMXRegisters[X86_64_MMX_REGISTER_COUNT];
x86_64_xmm_register fXMMRegisters[X86_64_XMM_REGISTER_COUNT];
x86_64_ymm_register fXMMRegisters[X86_64_XMM_REGISTER_COUNT];
RegisterBitSet fSetRegisters;
uint64 fInterruptVector;
};

View File

@ -33,7 +33,9 @@
// TODO: Make those real error codes.
#ifndef __x86_64__
#ifdef __x86_64__
extern bool gHasXsave;
#else
extern bool gHasSSE;
#endif
@ -202,12 +204,21 @@ get_cpu_state(Thread* thread, iframe* frame, debug_cpu_state* cpuState)
// For the floating point state to be correct the calling function must
// not use these registers (not even indirectly).
#ifdef __x86_64__
memset(&cpuState->extended_registers, 0,
sizeof(cpuState->extended_registers));
if (frame->fpu != nullptr) {
memcpy(&cpuState->extended_registers, frame->fpu,
sizeof(cpuState->extended_registers));
} else {
memset(&cpuState->extended_registers, 0,
sizeof(cpuState->extended_registers));
if (gHasXsave) {
// TODO check the xsave header to know the actual size of the
// register context depending on what is saved. For now we assume
// there is only the YMM AVX registers
memcpy(&cpuState->extended_registers, frame->fpu,
sizeof(cpuState->extended_registers));
} else {
// Only the "legacy area" saved by fxsave is available
memcpy(&cpuState->extended_registers, frame->fpu,
sizeof(cpuState->extended_registers.fp_fxsave));
}
}
#else
Thread* thisThread = thread_get_current_thread();