From 2b9d558ceff0e183c7bf6eae7399fd57e3438757 Mon Sep 17 00:00:00 2001 From: Nicholas Mosier Date: Sun, 10 Sep 2023 15:16:50 +0000 Subject: [PATCH] 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 --- src/arch/x86/kvm/x86_cpu.cc | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/arch/x86/kvm/x86_cpu.cc b/src/arch/x86/kvm/x86_cpu.cc index b88a96a2b9..da6e1bb9e1 100644 --- a/src/arch/x86/kvm/x86_cpu.cc +++ b/src/arch/x86/kvm/x86_cpu.cc @@ -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");