Skip to content

Commit f612026

Browse files
committed
Change XGETBV architecture modeling to hypercall
1 parent 56eee94 commit f612026

5 files changed

Lines changed: 15 additions & 77 deletions

File tree

include/remill/Arch/Runtime/HyperCall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class SyncHyperCall {
6262
kX86SysCall,
6363
kX86SysEnter,
6464
kX86SysExit,
65+
kX86XGetBV,
6566

6667
// TODO(pag): How to distinguish little- and big-endian?
6768
kAArch64EmulateInstruction = 0x200U,

include/remill/Arch/X86/Runtime/State.h

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -445,34 +445,6 @@ struct alignas(8) ArithFlags final {
445445

446446
static_assert(16 == sizeof(ArithFlags), "Invalid packing of `ArithFlags`.");
447447

448-
union XCR0 {
449-
uint64_t flat;
450-
451-
struct {
452-
uint32_t eax;
453-
uint32_t edx;
454-
} __attribute__((packed));
455-
456-
// Bits specify what process states should be saved.
457-
struct {
458-
uint64_t x87_fpu_mmx : 1; // Must be 1; bit 0.
459-
uint64_t xmm : 1; // SSE.
460-
uint64_t ymm : 1; // AVX and AVX2.
461-
uint64_t bndreg : 1; // Part of MPX.
462-
uint64_t bndcsr : 1; // Part of MPX.
463-
uint64_t opmask : 1; // Registers k0 through k7, AVX512-only.
464-
uint64_t
465-
zmm_hi256 : 1; // High 256 bits of ZMM0 through ZMM15, AVX512-only.
466-
uint64_t hi16_zmm : 1; // ZMM16 through ZMM31, AVX512-only.
467-
uint64_t pkru : 1; // Protected key stuff.
468-
uint64_t _reserved0 : 53;
469-
uint64_t lwp : 1; // AMD lightweight profiling.
470-
uint64_t _reserved1 : 1;
471-
} __attribute__((packed));
472-
} __attribute__((packed));
473-
474-
static_assert(8 == sizeof(XCR0), "Invalid packing of `XCR0`.");
475-
476448
struct alignas(8) Segments final {
477449
volatile uint16_t _0;
478450
SegmentSelector ss;
@@ -794,7 +766,7 @@ struct alignas(16) X86State : public ArchState {
794766
X87Stack st; // 128 bytes.
795767
MMX mmx; // 128 bytes.
796768
FPUStatusFlags sw; // 24 bytes
797-
XCR0 xcr0; // 8 bytes.
769+
uint8_t _padding[8]; // 8 bytes
798770
FPU x87; // 512 bytes
799771
SegmentCaches seg_caches; // 96 bytes
800772
K_REG k_reg; // 128 bytes.

lib/Arch/Runtime/HyperCall.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ Memory *__remill_sync_hyper_call(State &state, Memory *mem,
8989
"d"(state.gpr.rdx.aword));
9090
break;
9191

92+
case SyncHyperCall::kX86XGetBV: {
93+
uint32_t eax = 0;
94+
uint32_t edx = 0;
95+
const auto selector = static_cast<uint32_t>(state.addr_to_load);
96+
asm volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(selector));
97+
state.gpr.rax.aword = eax;
98+
state.gpr.rdx.aword = edx;
99+
break;
100+
}
101+
92102
case SyncHyperCall::kX86LoadGlobalDescriptorTable: {
93103
const auto read =
94104
__remill_read_memory_64(mem, static_cast<addr_t>(state.addr_to_load));

lib/Arch/X86/Semantics/XSAVE.cpp

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,9 @@
1616

1717
namespace {
1818

19-
DEF_SEM(DoXGETBV, PC next_pc) {
20-
switch (Read(REG_ECX)) {
21-
22-
// Current state of the `xcr0` register.
23-
case 0:
24-
WriteZExt(IF_64BIT_ELSE(REG_RAX, REG_EAX), state.xcr0.eax);
25-
WriteZExt(IF_64BIT_ELSE(REG_RDX, REG_EDX), state.xcr0.edx);
26-
break;
27-
28-
// Current state of the `xcr0` register, anded with the `xinuse` register.
29-
// We fake this as saying: this is what
30-
case 1: {
31-
XCR0 xcr0 = {};
32-
xcr0.x87_fpu_mmx = 1;
33-
xcr0.xmm = 1;
34-
IF_AVX(xcr0.ymm = 1;)
35-
IF_AVX512(xcr0.opmask = 1;)
36-
IF_AVX512(xcr0.zmm_hi256 = 1;)
37-
IF_AVX512(xcr0.hi16_zmm = 1;)
38-
WriteZExt(IF_64BIT_ELSE(REG_RAX, REG_EAX), xcr0.eax);
39-
WriteZExt(IF_64BIT_ELSE(REG_RDX, REG_EDX), xcr0.edx);
40-
break;
41-
}
42-
43-
default: WriteZExt(REG_PC, Read(next_pc)); StopFailure();
44-
}
45-
return memory;
19+
DEF_SEM(DoXGETBV, PC) {
20+
state.addr_to_load = ZExtTo<uint64_t>(Read(REG_ECX));
21+
return __remill_sync_hyper_call(state, memory, SyncHyperCall::kX86XGetBV);
4622
}
4723

4824
} // namespace

tests/X86/Run.cpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -914,26 +914,6 @@ static void RunWithFlags(const test::TestInfo *info, Flags flags,
914914
ImportX87State(native_state);
915915
ResetFlags();
916916

917-
#if defined(__x86_64__) || defined(__i386__)
918-
{
919-
uint32_t eax = 1;
920-
uint32_t ebx = 0;
921-
uint32_t ecx = 0;
922-
uint32_t edx = 0;
923-
asm volatile("cpuid"
924-
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
925-
: "a"(eax), "b"(ebx), "c"(ecx), "d"(edx));
926-
if (ecx & (1U << 26U)) {
927-
uint32_t xcr0_lo = 0;
928-
uint32_t xcr0_hi = 0;
929-
asm volatile("xgetbv" : "=a"(xcr0_lo), "=d"(xcr0_hi) : "c"(0));
930-
native_state->xcr0.eax = xcr0_lo;
931-
native_state->xcr0.edx = xcr0_hi;
932-
lifted_state->xcr0 = native_state->xcr0;
933-
}
934-
}
935-
#endif
936-
937917
// Set up the RIP correctly.
938918
lifted_state->gpr.rip.aword = static_cast<addr_t>(info->test_begin);
939919
native_state->gpr.rip.aword = static_cast<addr_t>(info->test_end);
@@ -1206,7 +1186,6 @@ static void RunWithFlags(const test::TestInfo *info, Flags flags,
12061186
<< "st:" << offsetof(State, st) << "\n"
12071187
<< "mmx:" << offsetof(State, mmx) << "\n"
12081188
<< "sw:" << offsetof(State, sw) << "\n"
1209-
<< "xcr0:" << offsetof(State, xcr0) << "\n"
12101189
<< "x87:" << offsetof(State, x87) << "\n"
12111190
<< "seg_caches:" << offsetof(State, seg_caches) << "\n";
12121191
}

0 commit comments

Comments
 (0)