x86emu: Add an RDTSC implementation to the x86 emulator

This instruction is being used in some debug VBIOSes.  This implementation
doesn't even try to be accurate.  Instead, it just increments the counter by a
fixed amount every time an rdtsc instruction in encountered, to avoid divides
by zero.

Imported from:
http://cgit.freedesktop.org/xorg/xserver/commit/?id=c4b7e9d1c16797c3e4b1200b40aceab5696a7fb8

Change-Id: I8fba1a060c57ccb7bbd44aa321dd349bc56bf574
Signed-off-by: Stefan Reinauer <reinauer@google.com>
Reviewed-on: http://review.coreboot.org/1362
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
Stefan Reinauer 2012-07-26 15:15:38 -07:00 committed by Patrick Georgi
parent 08ef498d0b
commit 911f446d32
1 changed files with 35 additions and 1 deletions

View File

@ -155,6 +155,40 @@ static void x86emuOp2_wrmsr(u8 op2)
END_OF_INSTR(); END_OF_INSTR();
} }
/****************************************************************************
REMARKS:
Handles opcode 0x0f,0x31
****************************************************************************/
static void x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2))
{
#ifdef __HAS_LONG_LONG__
static u64 counter = 0;
#else
static u32 counter = 0;
#endif
counter += 0x10000;
/* read timestamp counter */
/*
* Note that instead of actually trying to accurately measure this, we just
* increase the counter by a fixed amount every time we hit one of these
* instructions. Feel free to come up with a better method.
*/
START_OF_INSTR();
DECODE_PRINTF("RDTSC\n");
TRACE_AND_STEP();
#ifdef __HAS_LONG_LONG__
M.x86.R_EAX = counter & 0xffffffff;
M.x86.R_EDX = counter >> 32;
#else
M.x86.R_EAX = counter;
M.x86.R_EDX = 0;
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
/**************************************************************************** /****************************************************************************
* REMARKS: * REMARKS:
* Handles opcode 0x0f,0x32 * Handles opcode 0x0f,0x32
@ -1728,7 +1762,7 @@ void (*x86emu_optab2[256])(u8) =
/* 0x2f */ x86emuOp2_illegal_op, /* 0x2f */ x86emuOp2_illegal_op,
/* 0x30 */ x86emuOp2_wrmsr, /* 0x30 */ x86emuOp2_wrmsr,
/* 0x31 */ x86emuOp2_illegal_op, /* 0x31 */ x86emuOp2_rdtsc,
/* 0x32 */ x86emuOp2_rdmsr, /* 0x32 */ x86emuOp2_rdmsr,
/* 0x33 */ x86emuOp2_illegal_op, /* 0x33 */ x86emuOp2_illegal_op,
/* 0x34 */ x86emuOp2_illegal_op, /* 0x34 */ x86emuOp2_illegal_op,