cpu-kvm: properly set x86 xsave header on gem5->KVM transition

If the XSAVE KVM capability is available (KVM_CAP_XSAVE), the X86KvmCPU
will try to set the x87 FPU + SSE state using KVM_SET_XSAVE, which
expects a buffer (struct kvm_xsave) in XSAVE area format (Vol. 1,
Sec. 13.4 of Intel x86 SDM). The original implementation of
`X86KvmCPU::updateKvmStateFPUXSave()`, however, improperly sets the
xsave header, which contains a bitmap of state components present
in the xsave area.

This patch defines `XSaveHeader` structure to model the xsave header,
which is expected directly following the legacy FPU region (defined in
the `FXSave` structure) in the xsave area. It then sets two bist in
the xsave header to indicate the presence of x86 FPU and SSE state
components.

GitHub issue: https://github.com/gem5/gem5/issues/296

Change-Id: I5c5c7925fa7f78a7b5e2adc209187deff53ac039
This commit is contained in:
Nicholas Mosier
2023-09-10 15:16:50 +00:00
parent ebde1133c0
commit 2b9d558cef

View File

@@ -42,6 +42,7 @@
#include "arch/x86/regs/int.hh"
#include "arch/x86/regs/msr.hh"
#include "arch/x86/utility.hh"
#include "base/bitunion.hh"
#include "base/compiler.hh"
#include "cpu/kvm/base.hh"
#include "debug/Drain.hh"
@@ -117,6 +118,32 @@ struct GEM5_PACKED FXSave
static_assert(sizeof(FXSave) == 512, "Unexpected size of FXSave");
BitUnion64(XStateBV)
Bitfield<0> fpu;
Bitfield<1> sse;
Bitfield<2> avx;
Bitfield<4, 3> mpx;
Bitfield<7, 5> avx512;
Bitfield<8> pt;
Bitfield<9> pkru;
Bitfield<10> pasid;
Bitfield<12, 11> cet;
Bitfield<13> hdc;
Bitfield<14> uintr;
Bitfield<15> lbr;
Bitfield<16> hwp;
Bitfield<18, 17> amx;
Bitfield<63, 19> reserved;
EndBitUnion(XStateBV)
struct XSaveHeader
{
XStateBV xstate_bv;
uint64_t reserved[7];
};
static_assert(sizeof(XSaveHeader) == 64, "Unexpected size of XSaveHeader");
#define FOREACH_IREG() \
do { \
APPLY_IREG(rax, int_reg::Rax); \
@@ -912,6 +939,19 @@ X86KvmCPU::updateKvmStateFPUXSave()
updateKvmStateFPUCommon(tc, xsave);
/**
* The xsave header (Vol. 1, Section 13.4.2 of the Intel Software
* Development Manual) directly follows the legacy xsave region
* (i.e., the FPU/SSE state). The first 8 bytes of the xsave header
* hold a state-component bitmap called xstate_bv. We need to set
* the state component bits corresponding to the FPU and SSE
* states.
*/
XSaveHeader& xsave_hdr =
* (XSaveHeader *) ((char *) &kxsave + sizeof(FXSave));
xsave_hdr.xstate_bv.fpu = 1;
xsave_hdr.xstate_bv.sse = 1;
if (tc->readMiscRegNoEffect(misc_reg::Fiseg))
warn_once("misc_reg::Fiseg is non-zero.\n");