Implemented RDTSCP instruction

This commit is contained in:
Stanislav Shwartsman 2005-08-05 12:47:33 +00:00
parent 3e310fea90
commit 8be190d848
5 changed files with 168 additions and 107 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.233 2005-08-04 19:38:49 sshwarts Exp $
// $Id: cpu.h,v 1.234 2005-08-05 12:47:28 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -172,6 +172,7 @@
#define MSR_CSTAR (BX_CPU_THIS_PTR msr.cstar)
#define MSR_FMASK (BX_CPU_THIS_PTR msr.fmask)
#define MSR_KERNELGSBASE (BX_CPU_THIS_PTR msr.kernelgsbase)
#define MSR_TSC_AUX (BX_CPU_THIS_PTR msr.tsc_aux)
#endif
@ -326,6 +327,7 @@
#define BX_MSR_FSBASE 0xc0000100
#define BX_MSR_GSBASE 0xc0000101
#define BX_MSR_KERNELGSBASE 0xc0000102
#define BX_MSR_TSC_AUX 0xc0000103
#endif
#define BX_MODE_IA32_REAL 0x0 // CR0.PE=0 |
@ -645,6 +647,8 @@ typedef struct {
Bit64u cstar;
Bit64u fmask;
Bit64u kernelgsbase;
Bit32u tsc_aux;
#endif
/* TODO finish of the others */
@ -2458,6 +2462,7 @@ public: // for now...
BX_SMF void LOOP64_Jb(bxInstruction_c *);
BX_SMF void JCXZ64_Jb(bxInstruction_c *);
BX_SMF void RDTSCP(bxInstruction_c *);
BX_SMF void CMPXCHG16B(bxInstruction_c *);
#endif // #if BX_SUPPORT_X86_64

View File

@ -325,12 +325,16 @@ void BX_CPU_C::CPUID(bxInstruction_c *i)
// [21:21] Reserved
// [22:22] AMD MMX Extensions
// [25:25] Fast FXSAVE/FXRSTOR mode support
// [25:28] Reserved
// [26:26] Reserved
// [27:27] Support RDTSCP Instruction
// [28:28] Reserved
// [29:29] Long Mode
// [30:30] AMD 3DNow! Extensions
// [31:31] AMD 3DNow! Instructions
features = features & 0x00003F3FF;
RDX = features | (1 << 29) | (1 << 25) | (1 << 22) | (1 << 20) | (1 << 11);
RDX = features | (1 << 29) | (1 << 27) | (1 << 25) |
(1 << 22) | (1 << 20) | (1 << 11);
RBX = 0;
RCX = 0;
break;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode.cc,v 1.82 2005-07-31 17:57:25 sshwarts Exp $
// $Id: fetchdecode.cc,v 1.83 2005-08-05 12:47:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -1218,19 +1218,13 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
/* 0F 02 */ { BxAnother, &BX_CPU_C::LAR_GvEw },
/* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw },
/* 0F 04 */ { 0, &BX_CPU_C::BxError },
#if BX_SUPPORT_X86_64
/* 0F 05 */ { 0, &BX_CPU_C::SYSCALL },
#elif BX_CPU_LEVEL == 2
#if BX_CPU_LEVEL == 2
/* 0F 05 */ { 0, &BX_CPU_C::LOADALL },
#else
/* 0F 05 */ { 0, &BX_CPU_C::BxError },
/* 0F 05 */ { 0, &BX_CPU_C::BxError }, // SYSCALL is invalid in legacy mode
#endif
/* 0F 06 */ { 0, &BX_CPU_C::CLTS },
#if BX_SUPPORT_X86_64
/* 0F 07 */ { 0, &BX_CPU_C::SYSRET },
#else
/* 0F 07 */ { 0, &BX_CPU_C::BxError },
#endif
/* 0F 07 */ { 0, &BX_CPU_C::BxError }, // SYSRET is invalid in legacy mode
/* 0F 08 */ { 0, &BX_CPU_C::INVD },
/* 0F 09 */ { 0, &BX_CPU_C::WBINVD },
/* 0F 0A */ { 0, &BX_CPU_C::BxError },

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.60 2005-06-14 20:55:57 sshwarts Exp $
// $Id: paging.cc,v 1.61 2005-08-05 12:47:31 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -582,12 +582,22 @@ void BX_CPU_C::INVLPG(bxInstruction_c* i)
// ----------------------------------------------------
// MOD <> 11 7 --- | INVLPG | INVLPG
// MOD == 11 7 0 | #UD | SWAPGS
// MOD == 11 7 1-7 | #UD | #UD
// MOD == 11 7 1 | #UD | RDTSCP
// MOD == 11 7 2-7 | #UD | #UD
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
if ((i->rm() == 0) && (i->nnn() == 7)) {
BX_CPU_THIS_PTR SWAPGS(i);
return;
if (i->nnn() == 7) {
switch(i->rm()) {
case 0:
BX_CPU_THIS_PTR SWAPGS(i);
return;
case 1:
BX_CPU_THIS_PTR RDTSCP(i);
return;
default:
BX_INFO(("INVLPG: 0F 01 /7 RM=%d opcode is undefined !", i->rm()));
UndefinedOpcode(i);
}
}
}
@ -604,7 +614,6 @@ void BX_CPU_C::INVLPG(bxInstruction_c* i)
// Protected instruction: CPL0 only
if (BX_CPU_THIS_PTR cr0.pe) {
if (CPL!=0) {
BX_INFO(("INVLPG: CPL!=0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
@ -620,6 +629,7 @@ void BX_CPU_C::INVLPG(bxInstruction_c* i)
#else
// not supported on < 486
BX_INFO(("INVLPG: required i486, use --enable-cpu=4 option"));
UndefinedOpcode(i);
#endif
}
@ -703,8 +713,8 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
}
// Get PDP entry
pdp_addr = (pml4 & 0xfffff000) |
((laddr & BX_CONST64(0x0000007fc0000000)) >> 27);
pdp_addr = (pml4 & 0xfffff000) |
((laddr & BX_CONST64(0x0000007fc0000000)) >> 27);
}
else
#endif
@ -1284,7 +1294,6 @@ BX_CPU_C::access_linear(bx_address laddr, unsigned length, unsigned pl,
BX_CPU_THIS_PTR address_xlation.len2, data);
}
#endif
return;
}
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.111 2005-07-31 17:57:27 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.112 2005-08-05 12:47:33 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -1506,17 +1506,25 @@ void BX_CPU_C::RDTSC(bxInstruction_c *i)
Bit64u ticks = bx_pc_system.time_ticks ();
RAX = (Bit32u) (ticks & 0xffffffff);
RDX = (Bit32u) ((ticks >> 32) & 0xffffffff);
//BX_INFO(("RDTSC: returning EDX:EAX = %08x:%08x", EDX, EAX));
} else {
// not allowed to use RDTSC!
BX_ERROR(("RDTSC: incorrect usage of RDTSC instruction !"));
exception (BX_GP_EXCEPTION, 0, 0);
}
#else
BX_INFO(("RDTSC: Pentium CPU required"));
BX_INFO(("RDTSC: Pentium CPU required, use --enable-cpu=5"));
UndefinedOpcode(i);
#endif
}
#if BX_SUPPORT_X86_64
void BX_CPU_C::RDTSCP(bxInstruction_c *i)
{
RDTSC(i);
RCX = MSR_TSC_AUX;
}
#endif
void BX_CPU_C::RDMSR(bxInstruction_c *i)
{
#if BX_CPU_LEVEL >= 5
@ -1524,21 +1532,32 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
if (v8086_mode()) {
BX_INFO(("RDMSR: Invalid in virtual 8086 mode"));
goto do_exception;
exception(BX_GP_EXCEPTION, 0, 0);
}
if (CPL!= 0) {
if (protected_mode() && CPL != 0) {
BX_INFO(("RDMSR: CPL != 0"));
goto do_exception;
exception(BX_GP_EXCEPTION, 0, 0);
}
/* We have the requested MSR register in ECX */
switch(ECX) {
#if BX_SUPPORT_SEP
case BX_MSR_SYSENTER_CS: { EAX = BX_CPU_THIS_PTR sysenter_cs_msr; EDX = 0; return; }
case BX_MSR_SYSENTER_ESP: { EAX = BX_CPU_THIS_PTR sysenter_esp_msr; EDX = 0; return; }
case BX_MSR_SYSENTER_EIP: { EAX = BX_CPU_THIS_PTR sysenter_eip_msr; EDX = 0; return; }
case BX_MSR_SYSENTER_CS:
RAX = BX_CPU_THIS_PTR sysenter_cs_msr;
RDX = 0;
return;
case BX_MSR_SYSENTER_ESP:
RAX = BX_CPU_THIS_PTR sysenter_esp_msr;
RDX = 0;
return;
case BX_MSR_SYSENTER_EIP:
RAX = BX_CPU_THIS_PTR sysenter_eip_msr;
RDX = 0;
return;
#endif
#if BX_CPU_LEVEL == 5
@ -1565,8 +1584,11 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
goto do_exception;
#endif /* BX_CPU_LEVEL == 5 */
case BX_MSR_TSC:
RDTSC(i);
case BX_MSR_TSC: {
Bit64u ticks = bx_pc_system.time_ticks ();
RAX = (Bit32u) (ticks & 0xffffffff);
RDX = (Bit32u) ((ticks >> 32) & 0xffffffff);
}
return;
/* MSR_APICBASE
@ -1585,47 +1607,54 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
return;
#if BX_SUPPORT_X86_64
case BX_MSR_EFER:
RAX = (BX_CPU_THIS_PTR msr.sce << 0)
| (BX_CPU_THIS_PTR msr.lme << 8)
| (BX_CPU_THIS_PTR msr.lma << 10);
RDX = 0;
return;
case BX_MSR_EFER:
RAX = (BX_CPU_THIS_PTR msr.sce << 0)
| (BX_CPU_THIS_PTR msr.lme << 8)
| (BX_CPU_THIS_PTR msr.lma << 10)
| (BX_CPU_THIS_PTR msr.nxe << 11)
| (BX_CPU_THIS_PTR msr.ffxsr << 14);
RDX = 0;
return;
case BX_MSR_STAR:
RAX = MSR_STAR;
RDX = MSR_STAR >> 32;
return;
case BX_MSR_STAR:
RAX = MSR_STAR & 0xffffffff;
RDX = MSR_STAR >> 32;
return;
case BX_MSR_LSTAR:
RAX = MSR_LSTAR;
RDX = MSR_LSTAR >> 32;
return;
case BX_MSR_LSTAR:
RAX = MSR_LSTAR & 0xffffffff;
RDX = MSR_LSTAR >> 32;
return;
case BX_MSR_CSTAR:
RAX = MSR_CSTAR;
RDX = MSR_CSTAR >> 32;
return;
case BX_MSR_CSTAR:
RAX = MSR_CSTAR & 0xffffffff;
RDX = MSR_CSTAR >> 32;
return;
case BX_MSR_FMASK:
RAX = MSR_FMASK;
RDX = MSR_FMASK >> 32;
return;
case BX_MSR_FMASK:
RAX = MSR_FMASK & 0xffffffff;
RDX = MSR_FMASK >> 32;
return;
case BX_MSR_FSBASE:
RAX = MSR_FSBASE;
RDX = MSR_FSBASE >> 32;
return;
case BX_MSR_FSBASE:
RAX = MSR_FSBASE & 0xffffffff;
RDX = MSR_FSBASE >> 32;
return;
case BX_MSR_GSBASE:
RAX = MSR_GSBASE;
RDX = MSR_GSBASE >> 32;
return;
case BX_MSR_GSBASE:
RAX = MSR_GSBASE & 0xffffffff;
RDX = MSR_GSBASE >> 32;
return;
case BX_MSR_KERNELGSBASE:
RAX = MSR_KERNELGSBASE;
RDX = MSR_KERNELGSBASE >> 32;
return;
case BX_MSR_KERNELGSBASE:
RAX = MSR_KERNELGSBASE & 0xffffffff;
RDX = MSR_KERNELGSBASE >> 32;
return;
case BX_MSR_TSC_AUX:
RAX = MSR_TSC_AUX; // 32 bit MSR
RDX = 0;
return;
#endif // #if BX_SUPPORT_X86_64
default:
@ -1653,12 +1682,12 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
if (v8086_mode()) {
BX_INFO(("WRMSR: Invalid in virtual 8086 mode"));
goto do_exception;
exception(BX_GP_EXCEPTION, 0, 0);
}
if (CPL!= 0) {
if (protected_mode() && CPL != 0) {
BX_INFO(("WDMSR: CPL != 0"));
goto do_exception;
exception(BX_GP_EXCEPTION, 0, 0);
}
BX_INSTR_WRMSR(BX_CPU_ID, ECX, ((Bit64u) EDX << 32) + EAX);
@ -1667,13 +1696,20 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
switch(ECX) {
#if BX_SUPPORT_SEP
case BX_MSR_SYSENTER_CS: {
if (EAX & 3) BX_PANIC (("writing sysenter_cs_msr with non-kernel mode selector %X", EAX)); // not a bug according to book
BX_CPU_THIS_PTR sysenter_cs_msr = EAX; // ... but very stOOpid
case BX_MSR_SYSENTER_CS: {
// not a bug according to book ... but very stOOpid
if (EAX & 3) BX_PANIC(("writing sysenter_cs_msr with non-kernel mode selector %X", EAX));
BX_CPU_THIS_PTR sysenter_cs_msr = EAX;
return;
}
case BX_MSR_SYSENTER_ESP: { BX_CPU_THIS_PTR sysenter_esp_msr = EAX; return; }
case BX_MSR_SYSENTER_EIP: { BX_CPU_THIS_PTR sysenter_eip_msr = EAX; return; }
case BX_MSR_SYSENTER_ESP:
BX_CPU_THIS_PTR sysenter_esp_msr = EAX;
return;
case BX_MSR_SYSENTER_EIP:
BX_CPU_THIS_PTR sysenter_eip_msr = EAX;
return;
#endif
#if BX_CPU_LEVEL == 5
@ -1724,38 +1760,51 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
#endif
#if BX_SUPPORT_X86_64
case BX_MSR_EFER:
// GPF #0 if lme 0->1 and cr0.pg = 1
// GPF #0 if lme 1->0 and cr0.pg = 1
if ((BX_CPU_THIS_PTR msr.lme != ((EAX >> 8) & 1)) &&
(BX_CPU_THIS_PTR cr0.pg == 1))
{
exception(BX_GP_EXCEPTION, 0, 0);
}
BX_CPU_THIS_PTR msr.sce = (EAX >> 0) & 1;
BX_CPU_THIS_PTR msr.lme = (EAX >> 8) & 1;
return;
case BX_MSR_STAR:
MSR_STAR = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_LSTAR:
MSR_LSTAR = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_CSTAR:
MSR_CSTAR = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_FMASK:
MSR_FMASK = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_FSBASE:
MSR_FSBASE = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_GSBASE:
MSR_GSBASE = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_KERNELGSBASE:
MSR_KERNELGSBASE = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_EFER:
// GPF #0 if lme 0->1 and cr0.pg = 1
// GPF #0 if lme 1->0 and cr0.pg = 1
if ((BX_CPU_THIS_PTR msr.lme != ((EAX >> 8) & 1)) &&
(BX_CPU_THIS_PTR cr0.pg == 1))
{
exception(BX_GP_EXCEPTION, 0, 0);
}
BX_CPU_THIS_PTR msr.sce = (EAX >> 0) & 1;
BX_CPU_THIS_PTR msr.lme = (EAX >> 8) & 1;
BX_CPU_THIS_PTR msr.nxe = (EAX >> 11) & 1;
BX_CPU_THIS_PTR msr.ffxsr = (EAX >> 14) & 1;
return;
case BX_MSR_STAR:
MSR_STAR = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_LSTAR:
MSR_LSTAR = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_CSTAR:
MSR_CSTAR = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_FMASK:
MSR_FMASK = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_FSBASE:
MSR_FSBASE = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_GSBASE:
MSR_GSBASE = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_KERNELGSBASE:
MSR_KERNELGSBASE = ((Bit64u) EDX << 32) + EAX;
return;
case BX_MSR_TSC_AUX:
MSR_TSC_AUX = EAX;
return;
#endif // #if BX_SUPPORT_X86_64
default: