From 8be190d84884bf7d4768fe56a9f4fa9d67dbb560 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Fri, 5 Aug 2005 12:47:33 +0000 Subject: [PATCH] Implemented RDTSCP instruction --- bochs/cpu/cpu.h | 7 +- bochs/cpu/cpuid.cc | 8 +- bochs/cpu/fetchdecode.cc | 14 +-- bochs/cpu/paging.cc | 27 +++-- bochs/cpu/proc_ctrl.cc | 219 ++++++++++++++++++++++++--------------- 5 files changed, 168 insertions(+), 107 deletions(-) diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index cf2b9b0ff..41fc7eb08 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -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 diff --git a/bochs/cpu/cpuid.cc b/bochs/cpu/cpuid.cc index 8dd6f6f5b..79c715e6b 100755 --- a/bochs/cpu/cpuid.cc +++ b/bochs/cpu/cpuid.cc @@ -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; diff --git a/bochs/cpu/fetchdecode.cc b/bochs/cpu/fetchdecode.cc index 189e4dbe7..e16f4ade1 100644 --- a/bochs/cpu/fetchdecode.cc +++ b/bochs/cpu/fetchdecode.cc @@ -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 }, diff --git a/bochs/cpu/paging.cc b/bochs/cpu/paging.cc index de2b04396..eb81008e0 100644 --- a/bochs/cpu/paging.cc +++ b/bochs/cpu/paging.cc @@ -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; } } diff --git a/bochs/cpu/proc_ctrl.cc b/bochs/cpu/proc_ctrl.cc index a10bebf27..e31db09a9 100644 --- a/bochs/cpu/proc_ctrl.cc +++ b/bochs/cpu/proc_ctrl.cc @@ -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: