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. // Copyright (C) 2001 MandrakeSoft S.A.
@ -172,6 +172,7 @@
#define MSR_CSTAR (BX_CPU_THIS_PTR msr.cstar) #define MSR_CSTAR (BX_CPU_THIS_PTR msr.cstar)
#define MSR_FMASK (BX_CPU_THIS_PTR msr.fmask) #define MSR_FMASK (BX_CPU_THIS_PTR msr.fmask)
#define MSR_KERNELGSBASE (BX_CPU_THIS_PTR msr.kernelgsbase) #define MSR_KERNELGSBASE (BX_CPU_THIS_PTR msr.kernelgsbase)
#define MSR_TSC_AUX (BX_CPU_THIS_PTR msr.tsc_aux)
#endif #endif
@ -326,6 +327,7 @@
#define BX_MSR_FSBASE 0xc0000100 #define BX_MSR_FSBASE 0xc0000100
#define BX_MSR_GSBASE 0xc0000101 #define BX_MSR_GSBASE 0xc0000101
#define BX_MSR_KERNELGSBASE 0xc0000102 #define BX_MSR_KERNELGSBASE 0xc0000102
#define BX_MSR_TSC_AUX 0xc0000103
#endif #endif
#define BX_MODE_IA32_REAL 0x0 // CR0.PE=0 | #define BX_MODE_IA32_REAL 0x0 // CR0.PE=0 |
@ -645,6 +647,8 @@ typedef struct {
Bit64u cstar; Bit64u cstar;
Bit64u fmask; Bit64u fmask;
Bit64u kernelgsbase; Bit64u kernelgsbase;
Bit32u tsc_aux;
#endif #endif
/* TODO finish of the others */ /* TODO finish of the others */
@ -2458,6 +2462,7 @@ public: // for now...
BX_SMF void LOOP64_Jb(bxInstruction_c *); BX_SMF void LOOP64_Jb(bxInstruction_c *);
BX_SMF void JCXZ64_Jb(bxInstruction_c *); BX_SMF void JCXZ64_Jb(bxInstruction_c *);
BX_SMF void RDTSCP(bxInstruction_c *);
BX_SMF void CMPXCHG16B(bxInstruction_c *); BX_SMF void CMPXCHG16B(bxInstruction_c *);
#endif // #if BX_SUPPORT_X86_64 #endif // #if BX_SUPPORT_X86_64

View File

@ -325,12 +325,16 @@ void BX_CPU_C::CPUID(bxInstruction_c *i)
// [21:21] Reserved // [21:21] Reserved
// [22:22] AMD MMX Extensions // [22:22] AMD MMX Extensions
// [25:25] Fast FXSAVE/FXRSTOR mode support // [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 // [29:29] Long Mode
// [30:30] AMD 3DNow! Extensions // [30:30] AMD 3DNow! Extensions
// [31:31] AMD 3DNow! Instructions // [31:31] AMD 3DNow! Instructions
features = features & 0x00003F3FF; 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; RBX = 0;
RCX = 0; RCX = 0;
break; 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. // 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 02 */ { BxAnother, &BX_CPU_C::LAR_GvEw },
/* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw }, /* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw },
/* 0F 04 */ { 0, &BX_CPU_C::BxError }, /* 0F 04 */ { 0, &BX_CPU_C::BxError },
#if BX_SUPPORT_X86_64 #if BX_CPU_LEVEL == 2
/* 0F 05 */ { 0, &BX_CPU_C::SYSCALL },
#elif BX_CPU_LEVEL == 2
/* 0F 05 */ { 0, &BX_CPU_C::LOADALL }, /* 0F 05 */ { 0, &BX_CPU_C::LOADALL },
#else #else
/* 0F 05 */ { 0, &BX_CPU_C::BxError }, /* 0F 05 */ { 0, &BX_CPU_C::BxError }, // SYSCALL is invalid in legacy mode
#endif #endif
/* 0F 06 */ { 0, &BX_CPU_C::CLTS }, /* 0F 06 */ { 0, &BX_CPU_C::CLTS },
#if BX_SUPPORT_X86_64 /* 0F 07 */ { 0, &BX_CPU_C::BxError }, // SYSRET is invalid in legacy mode
/* 0F 07 */ { 0, &BX_CPU_C::SYSRET },
#else
/* 0F 07 */ { 0, &BX_CPU_C::BxError },
#endif
/* 0F 08 */ { 0, &BX_CPU_C::INVD }, /* 0F 08 */ { 0, &BX_CPU_C::INVD },
/* 0F 09 */ { 0, &BX_CPU_C::WBINVD }, /* 0F 09 */ { 0, &BX_CPU_C::WBINVD },
/* 0F 0A */ { 0, &BX_CPU_C::BxError }, /* 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. // 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 --- | INVLPG | INVLPG
// MOD == 11 7 0 | #UD | SWAPGS // 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 (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
if ((i->rm() == 0) && (i->nnn() == 7)) { if (i->nnn() == 7) {
BX_CPU_THIS_PTR SWAPGS(i); switch(i->rm()) {
return; 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 // Protected instruction: CPL0 only
if (BX_CPU_THIS_PTR cr0.pe) { if (BX_CPU_THIS_PTR cr0.pe) {
if (CPL!=0) { if (CPL!=0) {
BX_INFO(("INVLPG: CPL!=0"));
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);
} }
} }
@ -620,6 +629,7 @@ void BX_CPU_C::INVLPG(bxInstruction_c* i)
#else #else
// not supported on < 486 // not supported on < 486
BX_INFO(("INVLPG: required i486, use --enable-cpu=4 option"));
UndefinedOpcode(i); UndefinedOpcode(i);
#endif #endif
} }
@ -703,8 +713,8 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
} }
// Get PDP entry // Get PDP entry
pdp_addr = (pml4 & 0xfffff000) | pdp_addr = (pml4 & 0xfffff000) |
((laddr & BX_CONST64(0x0000007fc0000000)) >> 27); ((laddr & BX_CONST64(0x0000007fc0000000)) >> 27);
} }
else else
#endif #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); BX_CPU_THIS_PTR address_xlation.len2, data);
} }
#endif #endif
return; 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. // 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 (); Bit64u ticks = bx_pc_system.time_ticks ();
RAX = (Bit32u) (ticks & 0xffffffff); RAX = (Bit32u) (ticks & 0xffffffff);
RDX = (Bit32u) ((ticks >> 32) & 0xffffffff); RDX = (Bit32u) ((ticks >> 32) & 0xffffffff);
//BX_INFO(("RDTSC: returning EDX:EAX = %08x:%08x", EDX, EAX));
} else { } else {
// not allowed to use RDTSC! // not allowed to use RDTSC!
BX_ERROR(("RDTSC: incorrect usage of RDTSC instruction !"));
exception (BX_GP_EXCEPTION, 0, 0); exception (BX_GP_EXCEPTION, 0, 0);
} }
#else #else
BX_INFO(("RDTSC: Pentium CPU required")); BX_INFO(("RDTSC: Pentium CPU required, use --enable-cpu=5"));
UndefinedOpcode(i); UndefinedOpcode(i);
#endif #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) void BX_CPU_C::RDMSR(bxInstruction_c *i)
{ {
#if BX_CPU_LEVEL >= 5 #if BX_CPU_LEVEL >= 5
@ -1524,21 +1532,32 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
if (v8086_mode()) { if (v8086_mode()) {
BX_INFO(("RDMSR: Invalid in virtual 8086 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")); BX_INFO(("RDMSR: CPL != 0"));
goto do_exception; exception(BX_GP_EXCEPTION, 0, 0);
} }
/* We have the requested MSR register in ECX */ /* We have the requested MSR register in ECX */
switch(ECX) { switch(ECX) {
#if BX_SUPPORT_SEP #if BX_SUPPORT_SEP
case BX_MSR_SYSENTER_CS: { EAX = BX_CPU_THIS_PTR sysenter_cs_msr; EDX = 0; return; } case BX_MSR_SYSENTER_CS:
case BX_MSR_SYSENTER_ESP: { EAX = BX_CPU_THIS_PTR sysenter_esp_msr; EDX = 0; return; } RAX = BX_CPU_THIS_PTR sysenter_cs_msr;
case BX_MSR_SYSENTER_EIP: { EAX = BX_CPU_THIS_PTR sysenter_eip_msr; EDX = 0; return; } 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 #endif
#if BX_CPU_LEVEL == 5 #if BX_CPU_LEVEL == 5
@ -1565,8 +1584,11 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
goto do_exception; goto do_exception;
#endif /* BX_CPU_LEVEL == 5 */ #endif /* BX_CPU_LEVEL == 5 */
case BX_MSR_TSC: case BX_MSR_TSC: {
RDTSC(i); Bit64u ticks = bx_pc_system.time_ticks ();
RAX = (Bit32u) (ticks & 0xffffffff);
RDX = (Bit32u) ((ticks >> 32) & 0xffffffff);
}
return; return;
/* MSR_APICBASE /* MSR_APICBASE
@ -1585,47 +1607,54 @@ void BX_CPU_C::RDMSR(bxInstruction_c *i)
return; return;
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
case BX_MSR_EFER: case BX_MSR_EFER:
RAX = (BX_CPU_THIS_PTR msr.sce << 0) RAX = (BX_CPU_THIS_PTR msr.sce << 0)
| (BX_CPU_THIS_PTR msr.lme << 8) | (BX_CPU_THIS_PTR msr.lme << 8)
| (BX_CPU_THIS_PTR msr.lma << 10); | (BX_CPU_THIS_PTR msr.lma << 10)
RDX = 0; | (BX_CPU_THIS_PTR msr.nxe << 11)
return; | (BX_CPU_THIS_PTR msr.ffxsr << 14);
RDX = 0;
return;
case BX_MSR_STAR: case BX_MSR_STAR:
RAX = MSR_STAR; RAX = MSR_STAR & 0xffffffff;
RDX = MSR_STAR >> 32; RDX = MSR_STAR >> 32;
return; return;
case BX_MSR_LSTAR: case BX_MSR_LSTAR:
RAX = MSR_LSTAR; RAX = MSR_LSTAR & 0xffffffff;
RDX = MSR_LSTAR >> 32; RDX = MSR_LSTAR >> 32;
return; return;
case BX_MSR_CSTAR: case BX_MSR_CSTAR:
RAX = MSR_CSTAR; RAX = MSR_CSTAR & 0xffffffff;
RDX = MSR_CSTAR >> 32; RDX = MSR_CSTAR >> 32;
return; return;
case BX_MSR_FMASK: case BX_MSR_FMASK:
RAX = MSR_FMASK; RAX = MSR_FMASK & 0xffffffff;
RDX = MSR_FMASK >> 32; RDX = MSR_FMASK >> 32;
return; return;
case BX_MSR_FSBASE: case BX_MSR_FSBASE:
RAX = MSR_FSBASE; RAX = MSR_FSBASE & 0xffffffff;
RDX = MSR_FSBASE >> 32; RDX = MSR_FSBASE >> 32;
return; return;
case BX_MSR_GSBASE: case BX_MSR_GSBASE:
RAX = MSR_GSBASE; RAX = MSR_GSBASE & 0xffffffff;
RDX = MSR_GSBASE >> 32; RDX = MSR_GSBASE >> 32;
return; return;
case BX_MSR_KERNELGSBASE: case BX_MSR_KERNELGSBASE:
RAX = MSR_KERNELGSBASE; RAX = MSR_KERNELGSBASE & 0xffffffff;
RDX = MSR_KERNELGSBASE >> 32; RDX = MSR_KERNELGSBASE >> 32;
return; return;
case BX_MSR_TSC_AUX:
RAX = MSR_TSC_AUX; // 32 bit MSR
RDX = 0;
return;
#endif // #if BX_SUPPORT_X86_64 #endif // #if BX_SUPPORT_X86_64
default: default:
@ -1653,12 +1682,12 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
if (v8086_mode()) { if (v8086_mode()) {
BX_INFO(("WRMSR: Invalid in virtual 8086 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")); 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); 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) { switch(ECX) {
#if BX_SUPPORT_SEP #if BX_SUPPORT_SEP
case BX_MSR_SYSENTER_CS: { 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 // not a bug according to book ... but very stOOpid
BX_CPU_THIS_PTR sysenter_cs_msr = EAX; // ... 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; 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 #endif
#if BX_CPU_LEVEL == 5 #if BX_CPU_LEVEL == 5
@ -1724,38 +1760,51 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i)
#endif #endif
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
case BX_MSR_EFER: case BX_MSR_EFER:
// GPF #0 if lme 0->1 and cr0.pg = 1 // GPF #0 if lme 0->1 and cr0.pg = 1
// GPF #0 if lme 1->0 and cr0.pg = 1 // GPF #0 if lme 1->0 and cr0.pg = 1
if ((BX_CPU_THIS_PTR msr.lme != ((EAX >> 8) & 1)) && if ((BX_CPU_THIS_PTR msr.lme != ((EAX >> 8) & 1)) &&
(BX_CPU_THIS_PTR cr0.pg == 1)) (BX_CPU_THIS_PTR cr0.pg == 1))
{ {
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);
} }
BX_CPU_THIS_PTR msr.sce = (EAX >> 0) & 1; BX_CPU_THIS_PTR msr.sce = (EAX >> 0) & 1;
BX_CPU_THIS_PTR msr.lme = (EAX >> 8) & 1; BX_CPU_THIS_PTR msr.lme = (EAX >> 8) & 1;
return; BX_CPU_THIS_PTR msr.nxe = (EAX >> 11) & 1;
case BX_MSR_STAR: BX_CPU_THIS_PTR msr.ffxsr = (EAX >> 14) & 1;
MSR_STAR = ((Bit64u) EDX << 32) + EAX; return;
return;
case BX_MSR_LSTAR: case BX_MSR_STAR:
MSR_LSTAR = ((Bit64u) EDX << 32) + EAX; MSR_STAR = ((Bit64u) EDX << 32) + EAX;
return; return;
case BX_MSR_CSTAR:
MSR_CSTAR = ((Bit64u) EDX << 32) + EAX; case BX_MSR_LSTAR:
return; MSR_LSTAR = ((Bit64u) EDX << 32) + EAX;
case BX_MSR_FMASK: return;
MSR_FMASK = ((Bit64u) EDX << 32) + EAX;
return; case BX_MSR_CSTAR:
case BX_MSR_FSBASE: MSR_CSTAR = ((Bit64u) EDX << 32) + EAX;
MSR_FSBASE = ((Bit64u) EDX << 32) + EAX; return;
return;
case BX_MSR_GSBASE: case BX_MSR_FMASK:
MSR_GSBASE = ((Bit64u) EDX << 32) + EAX; MSR_FMASK = ((Bit64u) EDX << 32) + EAX;
return; return;
case BX_MSR_KERNELGSBASE:
MSR_KERNELGSBASE = ((Bit64u) EDX << 32) + EAX; case BX_MSR_FSBASE:
return; 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 #endif // #if BX_SUPPORT_X86_64
default: default: