[prev in list] [next in list] [prev in thread] [next in thread]
List: bochs-cvs
Subject: [Bochs-cvs] SF.net SVN: bochs:[10498] trunk/bochs/cpu
From: sshwarts () users ! sourceforge ! net
Date: 2011-07-28 16:17:42
Message-ID: E1QmTHK-0000z3-IG () sfp-svn-5 ! v30 ! ch3 ! sourceforge ! com
[Download RAW message or body]
Revision: 10498
http://bochs.svn.sourceforge.net/bochs/?rev=10498&view=rev
Author: sshwarts
Date: 2011-07-28 16:17:42 +0000 (Thu, 28 Jul 2011)
Log Message:
-----------
First step toward completely configurable CPU.
Change CPUID to generic interface which could be chosen from .bochsrc.
Bochs CPU emulation will enable/disable features (like instruction sets) according to \
CPUID that is selected.
TODO: Add database of CPUID from real hardware CPUs
Modified Paths:
--------------
trunk/bochs/cpu/Makefile.in
trunk/bochs/cpu/cpu.h
trunk/bochs/cpu/cpuid.h
trunk/bochs/cpu/init.cc
trunk/bochs/cpu/msr.cc
trunk/bochs/cpu/proc_ctrl.cc
Added Paths:
-----------
trunk/bochs/cpu/generic_cpuid.cc
Removed Paths:
-------------
trunk/bochs/cpu/cpuid.cc
Modified: trunk/bochs/cpu/Makefile.in
===================================================================
--- trunk/bochs/cpu/Makefile.in 2011-07-27 14:16:51 UTC (rev 10497)
+++ trunk/bochs/cpu/Makefile.in 2011-07-28 16:17:42 UTC (rev 10498)
@@ -89,7 +89,7 @@
data_xfer16.o \
data_xfer32.o \
exception.o \
- cpuid.o \
+ generic_cpuid.o \
proc_ctrl.o \
crregs.o \
msr.o \
@@ -284,7 +284,7 @@
icache.h apic.h ../cpu/i387.h ../fpu/softfloat.h ../fpu/tag_w.h \
../fpu/status_w.h ../fpu/control_w.h ../cpu/xmm.h vmx.h stack.h \
../iodev/iodev.h ../param_names.h
-cpuid.o: cpuid.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
+generic_cpuid.o: generic_cpuid.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
../bx_debug/debug.h \
../config.h ../osdep.h ../bxversion.h ../gui/siminterface.h \
../gui/paramtree.h ../memory/memory.h ../pc_system.h ../plugin.h \
../extplugin.h ../gui/gui.h ../instrument/stubs/instrument.h cpu.h \
Modified: trunk/bochs/cpu/cpu.h
===================================================================
--- trunk/bochs/cpu/cpu.h 2011-07-27 14:16:51 UTC (rev 10497)
+++ trunk/bochs/cpu/cpu.h 2011-07-28 16:17:42 UTC (rev 10498)
@@ -814,9 +814,9 @@
unsigned bx_cpuid;
- // cpuid
- cpuid_function_t cpuid_std_function[MAX_STD_CPUID_FUNCTION];
- cpuid_function_t cpuid_ext_function[MAX_EXT_CPUID_FUNCTION];
+#if BX_CPU_LEVEL >= 4
+ bx_cpuid_t *cpuid;
+#endif
Bit32u isa_extensions_bitmask;
Bit32u cpu_extensions_bitmask;
@@ -3449,28 +3449,14 @@
BX_SMF void iobreakpoint_match(unsigned port, unsigned len);
BX_SMF Bit32u code_breakpoint_match(bx_address laddr);
BX_SMF void hwbreakpoint_match(bx_address laddr, unsigned len, unsigned rw);
- BX_SMF Bit32u hwdebug_compare(bx_address laddr, unsigned len,
- unsigned opa, unsigned opb);
+ BX_SMF Bit32u hwdebug_compare(bx_address laddr, unsigned len, unsigned opa, \
unsigned opb); #endif
- BX_SMF Bit32u get_cpu_version_information(void);
- BX_SMF Bit32u get_extended_cpuid_features(void);
- BX_SMF Bit32u get_std_cpuid_features(void);
- BX_SMF Bit32u get_std2_cpuid_features(void);
- BX_SMF Bit32u get_ext2_cpuid_features(void);
-
- BX_SMF void init_isa_features_bitmask(void);
- BX_SMF void init_cpu_features_bitmask(void);
BX_SMF void init_FetchDecodeTables(void);
-#if BX_CPU_LEVEL >= 4
- BX_SMF void set_cpuid_defaults(void);
+
+#if BX_SUPPORT_APIC
+ BX_SMF BX_CPP_INLINE Bit8u get_apic_id(void) { return BX_CPU_THIS_PTR bx_cpuid; }
#endif
-#if BX_CPU_LEVEL >= 6
- BX_SMF void bx_cpuid_extended_topology_leaf(Bit32u subfunction);
- BX_SMF void bx_cpuid_xsave_leaf(Bit32u subfunction);
- BX_SMF void bx_cpuid_extended_cpuid_leaf(Bit32u subfunction);
- BX_SMF Bit32u get_ext3_cpuid_features(void);
-#endif
BX_SMF BX_CPP_INLINE int bx_cpuid_support_debug_extensions(void);
BX_SMF BX_CPP_INLINE int bx_cpuid_support_1g_paging(void);
@@ -3916,18 +3902,18 @@
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_xsave(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].ecx & BX_CPUID_EXT_XSAVE);
+ return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_XSAVE);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_x2apic(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].ecx & BX_CPUID_EXT_X2APIC);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_X2APIC);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pcid(void)
{
#if BX_SUPPORT_X86_64
- return (BX_CPU_THIS_PTR cpuid_std_function[1].ecx & BX_CPUID_EXT_PCID);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PCID);
#else
return 0;
#endif
@@ -3936,7 +3922,7 @@
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_fsgsbase(void)
{
#if BX_SUPPORT_X86_64
- return BX_CPU_THIS_PTR cpuid_std_function[7].ebx & BX_CPUID_EXT3_FSGSBASE;
+ return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_FSGSBASE);
#else
return 0;
#endif
@@ -3944,63 +3930,63 @@
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_smep(void)
{
- return BX_CPU_THIS_PTR cpuid_std_function[7].ebx & BX_CPUID_EXT3_SMEP;
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_SMEP);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_vme(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_VME);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_VME);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_debug_extensions(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & \
BX_CPUID_STD_DEBUG_EXTENSIONS); + return (BX_CPU_THIS_PTR cpu_extensions_bitmask & \
BX_CPU_DEBUG_EXTENSIONS); }
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pse(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_PSE);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PSE);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pae(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_PAE);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PAE);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pge(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_GLOBAL_PAGES);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PGE);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pse36(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_PSE36);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PSE36);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_mmx(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_MMX);
+ return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_MMX);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_sse(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_SSE);
+ return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSE);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_sep(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & \
BX_CPUID_STD_SYSENTER_SYSEXIT); + return (BX_CPU_THIS_PTR isa_extensions_bitmask & \
BX_CPU_SYSENTER_SYSEXIT); }
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_fxsave_fxrstor(void)
{
- return (BX_CPU_THIS_PTR cpuid_std_function[1].edx & BX_CPUID_STD_FXSAVE_FXRSTOR);
+ return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_FXSAVE_FXRSTOR);
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_1g_paging(void)
{
#if BX_SUPPORT_X86_64
- return (BX_CPU_THIS_PTR cpuid_ext_function[1].edx & BX_CPUID_STD2_1G_PAGES);
+ return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_1G_PAGES);
#else
return 0;
#endif
Deleted: trunk/bochs/cpu/cpuid.cc
===================================================================
--- trunk/bochs/cpu/cpuid.cc 2011-07-27 14:16:51 UTC (rev 10497)
+++ trunk/bochs/cpu/cpuid.cc 2011-07-28 16:17:42 UTC (rev 10498)
@@ -1,1244 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// $Id$
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2007-2011 Stanislav Shwartsman
-// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
-//
-/////////////////////////////////////////////////////////////////////////
-
-#define NEED_CPU_REG_SHORTCUTS 1
-#include "bochs.h"
-#include "cpu.h"
-#define LOG_THIS BX_CPU_THIS_PTR
-
-#include "param_names.h"
-
-/*
- * Get CPU version information:
- *
- * [3:0] Stepping ID
- * [7:4] Model: starts at 1
- * [11:8] Family: 4=486, 5=Pentium, 6=PPro, ...
- * [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
- * [19:16] Extended Model
- * [27:29] Extended Family
- */
-
-Bit32u BX_CPU_C::get_cpu_version_information(void)
-{
-#if BX_CPU_LEVEL >= 4
- Bit32u stepping = SIM->get_param_num(BXPN_CPUID_STEPPING)->get();
- Bit32u model = SIM->get_param_num(BXPN_CPUID_MODEL)->get();
- Bit32u family = SIM->get_param_num(BXPN_CPUID_FAMILY)->get();
-
- if (family < 6 && family != BX_CPU_LEVEL)
- BX_PANIC(("PANIC: CPUID family %x not matching configured cpu level %d", family, \
BX_CPU_LEVEL));
-
- return ((family & 0xfff0) << 16) |
- ((model & 0xf0) << 12) |
- ((family & 0x0f) << 8) |
- ((model & 0x0f) << 4) | stepping;
-#else
- return 0; /* CPUID not supported */
-#endif
-}
-
-/* Get CPU extended feature flags. */
-Bit32u BX_CPU_C::get_extended_cpuid_features(void)
-{
- // [0:0] SSE3: SSE3 Instructions
- // [1:1] PCLMULQDQ Instruction support
- // [2:2] DTES64: 64-bit DS area
- // [3:3] MONITOR/MWAIT support
- // [4:4] DS-CPL: CPL qualified debug store
- // [5:5] VMX: Virtual Machine Technology
- // [6:6] SMX: Secure Virtual Machine Technology
- // [7:7] EST: Enhanced Intel SpeedStep Technology
- // [8:8] TM2: Thermal Monitor 2
- // [9:9] SSSE3: SSSE3 Instructions
- // [10:10] CNXT-ID: L1 context ID
- // [11:11] reserved
- // [12:12] FMA Instructions support
- // [13:13] CMPXCHG16B: CMPXCHG16B instruction support
- // [14:14] xTPR update control
- // [15:15] PDCM - Perfon and Debug Capability MSR
- // [16:16] reserved
- // [17:17] PCID: Process Context Identifiers
- // [18:18] DCA - Direct Cache Access
- // [19:19] SSE4.1 Instructions
- // [20:20] SSE4.2 Instructions
- // [21:21] X2APIC
- // [22:22] MOVBE instruction
- // [23:23] POPCNT instruction
- // [24:24] TSC Deadline
- // [25:25] AES Instructions
- // [26:26] XSAVE extensions support
- // [27:27] OSXSAVE support
- // [28:28] AVX extensions support
- // [29:29] AVX F16C - Float16 conversion support
- // [30:30] RDRAND instruction
- // [31:31] reserved
-
- Bit32u features = 0;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE3))
- features |= BX_CPUID_EXT_SSE3;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AES_PCLMULQDQ))
- features |= BX_CPUID_EXT_PCLMULQDQ;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MONITOR_MWAIT))
- features |= BX_CPUID_EXT_MONITOR_MWAIT;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_VMX))
- features |= BX_CPUID_EXT_VMX;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSSE3))
- features |= BX_CPUID_EXT_SSSE3;
-
-#if BX_SUPPORT_X86_64
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_X86_64))
- features |= BX_CPUID_EXT_CMPXCHG16B;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PCID))
- features |= BX_CPUID_EXT_PCID;
-#endif
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_1))
- features |= BX_CPUID_EXT_SSE4_1;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_2))
- features |= BX_CPUID_EXT_SSE4_2;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC))
- features |= BX_CPUID_EXT_X2APIC;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MOVBE))
- features |= BX_CPUID_EXT_MOVBE;
-
- // enable POPCNT if SSE4_2 is enabled
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_2))
- features |= BX_CPUID_EXT_POPCNT;
-
- // support for AES
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AES_PCLMULQDQ))
- features |= BX_CPUID_EXT_AES;
-
- // support XSAVE extensions
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
- features |= BX_CPUID_EXT_XSAVE | BX_CPUID_EXT_OSXSAVE;
-
-#if BX_SUPPORT_AVX
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AVX))
- features |= BX_CPUID_EXT_AVX;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AVX_F16C))
- features |= BX_CPUID_EXT_AVX_F16C;
-#endif
-
- return features;
-}
-
-#if BX_CPU_LEVEL >= 6
-Bit32u BX_CPU_C::get_ext3_cpuid_features(void)
-{
- Bit32u features = 0;
-
- // [0:0] FS/GS BASE access instructions
- // [2:1] reserved
- // [3:3] BMI1: Advanced Bit Manipulation Extensions
- // [4:4] reserved
- // [5:5] AVX2
- // [6:6] reserved
- // [7:7] SMEP: Supervisor Mode Execution Protection
- // [8:8] BMI2: Advanced Bit Manipulation Extensions
- // [9:9] Support for Enhanced REP MOVSB/STOSB
- // [10:10] Support for INVPCID instruction
- // [31:10] reserved
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_FSGSBASE))
- features |= BX_CPUID_EXT3_FSGSBASE;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_SMEP))
- features |= BX_CPUID_EXT3_SMEP;
-
- return features;
-}
-#endif
-
-/* Get CPU feature flags. Returned by CPUID functions 1 and 80000001. */
-Bit32u BX_CPU_C::get_std_cpuid_features(void)
-{
- // [0:0] FPU on chip
- // [1:1] VME: Virtual-8086 Mode enhancements
- // [2:2] DE: Debug Extensions (I/O breakpoints)
- // [3:3] PSE: Page Size Extensions
- // [4:4] TSC: Time Stamp Counter
- // [5:5] MSR: RDMSR and WRMSR support
- // [6:6] PAE: Physical Address Extensions
- // [7:7] MCE: Machine Check Exception
- // [8:8] CXS: CMPXCHG8B instruction
- // [9:9] APIC: APIC on Chip
- // [10:10] Reserved
- // [11:11] SYSENTER/SYSEXIT support
- // [12:12] MTRR: Memory Type Range Reg
- // [13:13] PGE/PTE Global Bit
- // [14:14] MCA: Machine Check Architecture
- // [15:15] CMOV: Cond Mov/Cmp Instructions
- // [16:16] PAT: Page Attribute Table
- // [17:17] PSE-36: Physical Address Extensions
- // [18:18] PSN: Processor Serial Number
- // [19:19] CLFLUSH: CLFLUSH Instruction support
- // [20:20] Reserved
- // [21:21] DS: Debug Store
- // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities
- // [23:23] MMX Technology
- // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
- // [25:25] SSE: SSE Extensions
- // [26:26] SSE2: SSE2 Extensions
- // [27:27] Self Snoop
- // [28:28] Hyper Threading Technology
- // [29:29] TM: Thermal Monitor
- // [30:30] Reserved
- // [31:31] PBE: Pending Break Enable
-
- Bit32u features = 0;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_X87))
- features |= BX_CPUID_STD_X87;
-
-#if BX_CPU_LEVEL >= 5
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_PENTIUM)) {
- // Pentium only features
- features |= BX_CPUID_STD_TSC;
- features |= BX_CPUID_STD_MSR;
- // support Machine Check
- features |= BX_CPUID_STD_MCE | BX_CPUID_STD_MCA;
- features |= BX_CPUID_STD_CMPXCHG8B;
- }
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_VME))
- features |= BX_CPUID_STD_VME;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_DEBUG_EXTENSIONS))
- features |= BX_CPUID_STD_DEBUG_EXTENSIONS;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE))
- features |= BX_CPUID_STD_PSE;
-#endif
-
-#if BX_SUPPORT_APIC
- // if MSR_APICBASE APIC Global Enable bit has been cleared,
- // the CPUID feature flag for the APIC is set to 0.
- if (BX_CPU_THIS_PTR msr.apicbase & 0x800)
- features |= BX_CPUID_STD_APIC; // APIC on chip
-#endif
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SYSENTER_SYSEXIT))
- features |= BX_CPUID_STD_SYSENTER_SYSEXIT;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_CLFLUSH))
- features |= BX_CPUID_STD_CLFLUSH;
-
-#if BX_CPU_LEVEL >= 5
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MMX))
- features |= BX_CPUID_STD_MMX;
-#endif
-
-#if BX_CPU_LEVEL >= 6
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_P6)) {
- features |= BX_CPUID_STD_CMOV;
- features |= BX_CPUID_STD_ACPI;
- }
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAT_MTRR))
- features |= BX_CPUID_STD_PAT | BX_CPUID_STD_MTRR;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAE))
- features |= BX_CPUID_STD_PAE;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PGE))
- features |= BX_CPUID_STD_GLOBAL_PAGES;
-
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE36))
- features |= BX_CPUID_STD_PSE36;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_FXSAVE_FXRSTOR))
- features |= BX_CPUID_STD_FXSAVE_FXRSTOR;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE))
- features |= BX_CPUID_STD_SSE;
-
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE2))
- features |= BX_CPUID_STD_SSE2;
-
- if (BX_CPU_VENDOR_INTEL)
- features |= BX_CPUID_STD_SELF_SNOOP;
-#endif
-
-#if BX_SUPPORT_SMP
- // Intel(R) HyperThreading Technology
- if (SIM->get_param_num(BXPN_CPU_NTHREADS)->get() > 1)
- features |= BX_CPUID_STD_HT;
-#endif
-
- return features;
-}
-
-/* Get CPU feature flags. Returned by CPUID function 80000001 in EDX register */
-Bit32u BX_CPU_C::get_std2_cpuid_features(void)
-{
- // Many of the bits in EDX are the same as EAX [*] for AMD
- // [*] [0:0] FPU on chip
- // [*] [1:1] VME: Virtual-8086 Mode enhancements
- // [*] [2:2] DE: Debug Extensions (I/O breakpoints)
- // [*] [3:3] PSE: Page Size Extensions
- // [*] [4:4] TSC: Time Stamp Counter
- // [*] [5:5] MSR: RDMSR and WRMSR support
- // [*] [6:6] PAE: Physical Address Extensions
- // [*] [7:7] MCE: Machine Check Exception
- // [*] [8:8] CXS: CMPXCHG8B instruction
- // [*] [9:9] APIC: APIC on Chip
- // [10:10] Reserved
- // [11:11] SYSCALL/SYSRET support
- // [*] [12:12] MTRR: Memory Type Range Reg
- // [*] [13:13] PGE/PTE Global Bit
- // [*] [14:14] MCA: Machine Check Architecture
- // [*] [15:15] CMOV: Cond Mov/Cmp Instructions
- // [*] [16:16] PAT: Page Attribute Table
- // [*] [17:17] PSE-36: Physical Address Extensions
- // [18:19] Reserved
- // [20:20] No-Execute page protection
- // [21:21] Reserved
- // [22:22] AMD MMX Extensions
- // [*] [23:23] MMX Technology
- // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
- // [25:25] Fast FXSAVE/FXRSTOR mode support
- // [26:26] 1G paging support
- // [27:27] Support RDTSCP Instruction
- // [28:28] Reserved
- // [29:29] Long Mode
- // [30:30] AMD 3DNow! Extensions
- // [31:31] AMD 3DNow! Instructions
- Bit32u features = BX_CPU_VENDOR_INTEL ? 0 : get_std_cpuid_features();
- features &= 0x0183F3FF;
-#if BX_SUPPORT_3DNOW
- // only AMD is interesting in AMD MMX extensions
- features |= BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD2_3DNOW_EXT | \
BX_CPUID_STD2_3DNOW;
-#endif
-#if BX_SUPPORT_X86_64
- features |= BX_CPUID_STD2_SYSCALL_SYSRET |
- BX_CPUID_STD2_NX |
- BX_CPUID_STD2_FFXSR |
- BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE;
- static bx_bool xlarge_pages = SIM->get_param_bool(BXPN_CPUID_1G_PAGES)->get();
- if (xlarge_pages)
- features |= BX_CPUID_STD2_1G_PAGES;
-#endif
-
- return features;
-}
-
-/* Get CPU feature flags. Returned by CPUID function 80000001 in ECX register */
-Bit32u BX_CPU_C::get_ext2_cpuid_features(void)
-{
- // ECX:
- // [0:0] LAHF/SAHF instructions support in 64-bit mode
- // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD)
- // [2:2] SVM: Secure Virtual Machine (AMD)
- // [3:3] Extended APIC Space
- // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8
- // [5:5] LZCNT: LZCNT instruction support
- // [6:6] SSE4A: SSE4A Instructions support (deprecated?)
- // [7:7] Misaligned SSE support
- // [8:8] PREFETCHW: PREFETCHW instruction support
- // [9:9] OSVW: OS visible workarounds (AMD)
- // [11:10] reserved
- // [12:12] SKINIT support
- // [13:13] WDT: Watchdog timer support
- // [31:14] reserved
- Bit32u features = 0;
-
-#if BX_SUPPORT_X86_64
- features |= BX_CPUID_EXT2_LAHF_SAHF;
-#endif
-#if BX_SUPPORT_MISALIGNED_SSE
- features |= BX_CPUID_EXT2_MISALIGNED_SSE;
-#endif
-
- return features;
-}
-
-BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CPUID(bxInstruction_c *i)
-{
-#if BX_CPU_LEVEL >= 4
- Bit32u function = EAX;
-
-#if BX_SUPPORT_VMX
- if (BX_CPU_THIS_PTR in_vmx_guest) {
- BX_ERROR(("VMEXIT: CPUID in VMX non-root operation"));
- VMexit(i, VMX_VMEXIT_CPUID, 0);
- }
-#endif
-
- unsigned max_std_function = BX_CPU_THIS_PTR cpuid_std_function[0].eax;
- unsigned max_ext_function = BX_CPU_THIS_PTR cpuid_ext_function[0].eax;
-
- if(function < 0x80000000) {
- if(function <= max_std_function) {
-#if BX_CPU_LEVEL >= 6
- Bit32u subfunction = ECX;
-
- if (function == 0xb) {
- bx_cpuid_extended_topology_leaf(subfunction);
- }
- else if (function == 0x7) {
- bx_cpuid_extended_cpuid_leaf(subfunction);
- }
- else if (function == 0xd) {
- bx_cpuid_xsave_leaf(subfunction);
- }
- else
-#endif
- {
- RAX = BX_CPU_THIS_PTR cpuid_std_function[function].eax;
- RBX = BX_CPU_THIS_PTR cpuid_std_function[function].ebx;
- RCX = BX_CPU_THIS_PTR cpuid_std_function[function].ecx;
- RDX = BX_CPU_THIS_PTR cpuid_std_function[function].edx;
- }
-
- BX_NEXT_INSTR(i);
- }
- }
- else {
- if(function <= max_ext_function) {
- function -= 0x80000000;
- RAX = BX_CPU_THIS_PTR cpuid_ext_function[function].eax;
- RBX = BX_CPU_THIS_PTR cpuid_ext_function[function].ebx;
- RCX = BX_CPU_THIS_PTR cpuid_ext_function[function].ecx;
- RDX = BX_CPU_THIS_PTR cpuid_ext_function[function].edx;
-
- BX_NEXT_INSTR(i);
- }
- }
-
- // unknown CPUID function - return maximum standard leaf
- RAX = BX_CPU_THIS_PTR cpuid_std_function[max_std_function].eax;
- RBX = BX_CPU_THIS_PTR cpuid_std_function[max_std_function].ebx;
- RCX = BX_CPU_THIS_PTR cpuid_std_function[max_std_function].ecx;
- RDX = BX_CPU_THIS_PTR cpuid_std_function[max_std_function].edx;
-#endif
-
- BX_NEXT_INSTR(i);
-}
-
-#if BX_CPU_LEVEL >= 4
-void BX_CPU_C::set_cpuid_defaults(void)
-{
- Bit8u *vendor_string = (Bit8u \
*)SIM->get_param_string(BXPN_VENDOR_STRING)->getptr();
- Bit8u *brand_string = (Bit8u *)SIM->get_param_string(BXPN_BRAND_STRING)->getptr();
- bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get();
-
- cpuid_function_t *cpuid;
- int i;
-
- for (i=0;i<MAX_STD_CPUID_FUNCTION;i++) {
- BX_CPU_THIS_PTR cpuid_std_function[i].eax = 0;
- BX_CPU_THIS_PTR cpuid_std_function[i].ebx = 0;
- BX_CPU_THIS_PTR cpuid_std_function[i].ecx = 0;
- BX_CPU_THIS_PTR cpuid_std_function[i].edx = 0;
- }
-
- for (i=0;i<MAX_EXT_CPUID_FUNCTION;i++) {
- BX_CPU_THIS_PTR cpuid_ext_function[i].eax = 0;
- BX_CPU_THIS_PTR cpuid_ext_function[i].ebx = 0;
- BX_CPU_THIS_PTR cpuid_ext_function[i].ecx = 0;
- BX_CPU_THIS_PTR cpuid_ext_function[i].edx = 0;
- }
-
- // ------------------------------------------------------
- // CPUID function 0x00000000
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[0]);
-
- // EAX: highest input value understood by CPUID
- // EBX: vendor ID string
- // EDX: vendor ID string
- // ECX: vendor ID string
-
-#if BX_CPU_LEVEL <= 5
- // 486 and Pentium processors
- cpuid->eax = 1;
-#else
- // for Pentium Pro, Pentium II, Pentium 4 processors
- cpuid->eax = 3;
-
- // do not report CPUID functions above 0x3 if cpuid_limit_winnt is set
- // to workaround WinNT issue.
- if (! cpuid_limit_winnt) {
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MONITOR_MWAIT))
- cpuid->eax = 0x5;
- if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC))
- cpuid->eax = 0xb;
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
- cpuid->eax = 0xd;
- }
-#endif
-
- // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...)
- memcpy(&(cpuid->ebx), vendor_string, 4);
- memcpy(&(cpuid->edx), vendor_string + 4, 4);
- memcpy(&(cpuid->ecx), vendor_string + 8, 4);
-#ifdef BX_BIG_ENDIAN
- cpuid->ebx = bx_bswap32(cpuid->ebx);
- cpuid->ecx = bx_bswap32(cpuid->ecx);
- cpuid->edx = bx_bswap32(cpuid->edx);
-#endif
-
- BX_INFO(("CPUID[0x00000000]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x00000001
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[1]);
-
- // EAX: CPU Version Information
- // [3:0] Stepping ID
- // [7:4] Model: starts at 1
- // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ...
- // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
- // [19:16] Extended Model
- // [27:20] Extended Family
- cpuid->eax = get_cpu_version_information();
-
- // EBX:
- // [7:0] Brand ID
- // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes)
- // [23:16] Number of logical processors in one physical processor
- // [31:24] Local Apic ID
-
- cpuid->ebx = 0;
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_CLFLUSH)) {
- cpuid->ebx |= (CACHE_LINE_SIZE / 8) << 8;
- }
- unsigned n_logical_processors = \
SIM->get_param_num(BXPN_CPU_NCORES)->get()*SIM->get_param_num(BXPN_CPU_NTHREADS)->get();
- if (n_logical_processors > 1)
- cpuid->ebx |= (n_logical_processors << 16);
-#if BX_SUPPORT_APIC
- cpuid->ebx |= ((BX_CPU_THIS_PTR lapic.get_id() & 0xff) << 24);
-#endif
-
- // ECX: Extended Feature Flags
- cpuid->ecx = get_extended_cpuid_features();
-
- // EDX: Standard Feature Flags
- cpuid->edx = get_std_cpuid_features();
-
- BX_INFO(("CPUID[0x00000001]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
-#if BX_CPU_LEVEL >= 6
- // ------------------------------------------------------
- // CPUID function 0x00000002 - Cache and TLB Descriptors
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[2]);
-
-#if BX_CPU_VENDOR_INTEL
- cpuid->eax = 0x00410601; // for Pentium Pro compatibility
- cpuid->ebx = 0;
- cpuid->ecx = 0;
- cpuid->edx = 0;
-#else
- cpuid->eax = 0; // ignore for AMD
- cpuid->ebx = 0;
- cpuid->ecx = 0;
- cpuid->edx = 0;
-#endif
-
- BX_INFO(("CPUID[0x00000002]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x00000003 - Processor Serial Number
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[3]);
-
- cpuid->eax = 0;
- cpuid->ebx = 0;
- cpuid->ecx = 0;
- cpuid->edx = 0;
-
- BX_INFO(("CPUID[0x00000003]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // do not report CPUID functions above 0x3 if cpuid_limit_winnt is set
- // to workaround WinNT issue.
- if (cpuid_limit_winnt) return;
-
- // ------------------------------------------------------
- // CPUID function 0x00000004 - Deterministic Cache Parameters
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[4]);
-
- cpuid->eax = 0;
- cpuid->ebx = 0;
- cpuid->ecx = 0;
- cpuid->edx = 0;
-
- BX_INFO(("CPUID[0x00000004]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
-#if BX_SUPPORT_MONITOR_MWAIT
- // ------------------------------------------------------
- // CPUID function 0x00000005
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MONITOR_MWAIT))
- {
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[5]);
-
- // EAX - Smallest monitor-line size in bytes
- // EBX - Largest monitor-line size in bytes
- // ECX -
- // [31:2] - reserved
- // [1:1] - exit MWAIT even with EFLAGS.IF = 0
- // [0:0] - MONITOR/MWAIT extensions are supported
- // EDX - Reserved
- cpuid->eax = CACHE_LINE_SIZE;
- cpuid->ebx = CACHE_LINE_SIZE;
- cpuid->ecx = 3;
- cpuid->edx = 0;
-
- BX_INFO(("CPUID[0x00000005]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
- }
-#endif
-
- // ------------------------------------------------------
- // CPUID function 0x00000007
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[7]);
-
- cpuid->ebx = get_ext3_cpuid_features();
- cpuid->ecx = 0;
- cpuid->edx = 0;
- if (cpuid->ebx)
- cpuid->eax = 1; /* report max sub-leaves that are supported in leaf 7 */
- else
- cpuid->eax = 0; /* leaf 7 not supported */
-
- BX_INFO(("CPUID[0x00000007]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x0000000d
- if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
- {
- cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[0xd]);
-
- // EAX - valid bits of XCR0 (lower part)
- // EBX - Maximum size (in bytes) required by enabled features
- // ECX - Maximum size (in bytes) required by CPU supported features
- // EDX - valid bits of XCR0 (upper part)
- cpuid->eax = BX_CPU_THIS_PTR xcr0_suppmask;
- cpuid->ebx = 512+64;
-#if BX_SUPPORT_AVX
- if (BX_CPU_THIS_PTR xcr0_suppmask & BX_XCR0_AVX_MASK)
- cpuid->ebx += 256;
-#endif
- cpuid->ecx = 512+64;
-#if BX_SUPPORT_AVX
- if (BX_CPU_THIS_PTR xcr0_suppmask & BX_XCR0_AVX_MASK)
- cpuid->ecx += 256;
-#endif
- cpuid->edx = 0;
-
- BX_INFO(("CPUID[0x0000000d]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
- }
-
- // do not report Pentium 4 extended functions if not needed
- if (! BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE2))
- return;
-
- // ------------------------------------------------------
- // CPUID function 0x80000000
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[0]);
-
- // EAX: highest input value understood by CPUID
- // EBX: vendor ID string
- // EDX: vendor ID string
- // ECX: vendor ID string
- cpuid->eax = BX_SUPPORT_X86_64 ? 0x80000008 : 0x80000004;
-#if BX_CPU_VENDOR_INTEL
- cpuid->ebx = 0;
- cpuid->edx = 0; // Reserved for Intel
- cpuid->ecx = 0;
-#else
- memcpy(&(cpuid->ebx), vendor_string, 4);
- memcpy(&(cpuid->edx), vendor_string + 4, 4);
- memcpy(&(cpuid->ecx), vendor_string + 8, 4);
-#endif
-
-#ifdef BX_BIG_ENDIAN
- cpuid->ebx = bx_bswap32(cpuid->ebx);
- cpuid->ecx = bx_bswap32(cpuid->ecx);
- cpuid->edx = bx_bswap32(cpuid->edx);
-#endif
-
- BX_INFO(("CPUID[0x80000000]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x80000001
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[1]);
-
- // EAX: CPU Version Information
- cpuid->eax = BX_CPU_VENDOR_INTEL ? 0 : get_cpu_version_information();
-
- // EBX: Brand ID
- cpuid->ebx = 0;
-
- // ECX:
- cpuid->ecx = get_ext2_cpuid_features();
-
- // EDX:
- // Many of the bits in EDX are the same as EAX [*] for AMD
- // [*] [0:0] FPU on chip
- // [*] [1:1] VME: Virtual-8086 Mode enhancements
- // [*] [2:2] DE: Debug Extensions (I/O breakpoints)
- // [*] [3:3] PSE: Page Size Extensions
- // [*] [4:4] TSC: Time Stamp Counter
- // [*] [5:5] MSR: RDMSR and WRMSR support
- // [*] [6:6] PAE: Physical Address Extensions
- // [*] [7:7] MCE: Machine Check Exception
- // [*] [8:8] CXS: CMPXCHG8B instruction
- // [*] [9:9] APIC: APIC on Chip
- // [10:10] Reserved
- // [11:11] SYSCALL/SYSRET support
- // [*] [12:12] MTRR: Memory Type Range Reg
- // [*] [13:13] PGE/PTE Global Bit
- // [*] [14:14] MCA: Machine Check Architecture
- // [*] [15:15] CMOV: Cond Mov/Cmp Instructions
- // [*] [16:16] PAT: Page Attribute Table
- // [*] [17:17] PSE-36: Physical Address Extensions
- // [18:19] Reserved
- // [20:20] No-Execute page protection
- // [21:21] Reserved
- // [22:22] AMD MMX Extensions
- // [*] [23:23] MMX Technology
- // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
- // [25:25] Fast FXSAVE/FXRSTOR mode support
- // [26:26] 1G paging support
- // [27:27] Support RDTSCP Instruction
- // [28:28] Reserved
- // [29:29] Long Mode
- // [30:30] AMD 3DNow! Extensions
- // [31:31] AMD 3DNow! Instructions
- cpuid->edx = get_std2_cpuid_features();
-
- BX_INFO(("CPUID[0x80000001]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // Processor Brand String, use the value that is returned
- // by the first processor in the Pentium 4 family
- // (according to Intel manual or the AMD manual)
-
- // ------------------------------------------------------
- // CPUID function 0x80000002
-
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[2]);
- memcpy(&(cpuid->eax), brand_string , 4);
- memcpy(&(cpuid->ebx), brand_string + 4, 4);
- memcpy(&(cpuid->ecx), brand_string + 8, 4);
- memcpy(&(cpuid->edx), brand_string + 12, 4);
-#ifdef BX_BIG_ENDIAN
- cpuid->eax = bx_bswap32(cpuid->eax);
- cpuid->ebx = bx_bswap32(cpuid->ebx);
- cpuid->ecx = bx_bswap32(cpuid->ecx);
- cpuid->edx = bx_bswap32(cpuid->edx);
-#endif
-
- BX_INFO(("CPUID[0x80000002]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x80000003
-
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[3]);
- memcpy(&(cpuid->eax), brand_string + 16, 4);
- memcpy(&(cpuid->ebx), brand_string + 20, 4);
- memcpy(&(cpuid->ecx), brand_string + 24, 4);
- memcpy(&(cpuid->edx), brand_string + 28, 4);
-#ifdef BX_BIG_ENDIAN
- cpuid->eax = bx_bswap32(cpuid->eax);
- cpuid->ebx = bx_bswap32(cpuid->ebx);
- cpuid->ecx = bx_bswap32(cpuid->ecx);
- cpuid->edx = bx_bswap32(cpuid->edx);
-#endif
-
- BX_INFO(("CPUID[0x80000003]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x80000004
-
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[4]);
- memcpy(&(cpuid->eax), brand_string + 32, 4);
- memcpy(&(cpuid->ebx), brand_string + 36, 4);
- memcpy(&(cpuid->ecx), brand_string + 40, 4);
- memcpy(&(cpuid->edx), brand_string + 44, 4);
-#ifdef BX_BIG_ENDIAN
- cpuid->eax = bx_bswap32(cpuid->eax);
- cpuid->ebx = bx_bswap32(cpuid->ebx);
- cpuid->ecx = bx_bswap32(cpuid->ecx);
- cpuid->edx = bx_bswap32(cpuid->edx);
-#endif
-
- BX_INFO(("CPUID[0x80000004]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
-#if BX_SUPPORT_X86_64
- // ------------------------------------------------------
- // CPUID function 0x80000005
-
-#if BX_CPU_VENDOR_INTEL == 0
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[5]);
-
- /* cache info (L1 cache) */
- cpuid->eax = 0x01ff01ff;
- cpuid->ebx = 0x01ff01ff;
- cpuid->ecx = 0x40020140;
- cpuid->edx = 0x40020140;
-
- BX_INFO(("CPUID[0x80000005]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-#endif
-
- // ------------------------------------------------------
- // CPUID function 0x80000006
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[6]);
-
- /* cache info (L2 cache) */
- cpuid->eax = 0;
- cpuid->ebx = 0x42004200;
- cpuid->ecx = 0x02008140;
- cpuid->edx = 0;
-
- BX_INFO(("CPUID[0x80000006]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x80000007
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[7]);
-
- cpuid->eax = 0;
- cpuid->ebx = 0;
- cpuid->ecx = 0;
- cpuid->edx = 0;
-
- BX_INFO(("CPUID[0x80000007]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
- // ------------------------------------------------------
- // CPUID function 0x80000008
- cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[8]);
-
- // virtual & phys address size in low 2 bytes.
- cpuid->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8);
- cpuid->ebx = 0;
- cpuid->ecx = 0; // Reserved, undefined
- cpuid->edx = 0;
-
- BX_INFO(("CPUID[0x80000008]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, \
cpuid->ecx, cpuid->edx));
-
-#endif // BX_SUPPORT_X86_64
-
-#endif // BX_CPU_LEVEL >= 6
-}
-
-#if BX_CPU_LEVEL >= 6
-
-BX_CPP_INLINE static Bit32u ilog2(Bit32u x)
-{
- Bit32u count = 0;
- while(x>>=1) count++;
- return count;
-}
-
-void BX_CPU_C::bx_cpuid_extended_topology_leaf(Bit32u subfunction)
-{
- if (! bx_cpuid_support_x2apic()) {
- RAX = 0;
- RBX = 0;
- RCX = 0;
- RDX = 0;
- return;
- }
-
- static int nthreads = SIM->get_param_num(BXPN_CPU_NTHREADS)->get();
- static int ncores = SIM->get_param_num(BXPN_CPU_NCORES)->get();
- static int nprocessors = SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get();
-
- RCX = subfunction;
- RDX = BX_CPU_THIS_PTR lapic.get_id(); // x2apic ID
-
- switch(subfunction) {
- case 0:
- if (nthreads > 1) {
- RAX = ilog2(nthreads-1)+1;
- RBX = nthreads;
- RCX |= (1<<8);
- }
- else if (ncores > 1) {
- RAX = ilog2(ncores-1)+1;
- RBX = ncores;
- RCX |= (2<<8);
- }
- else if (nprocessors > 1) {
- RAX = ilog2(nprocessors-1)+1;
- RBX = nprocessors;
- }
- else {
- RAX = 0;
- RBX = 0;
- }
- break;
-
- case 1:
- if (nthreads > 1) {
- if (ncores > 1) {
- RAX = ilog2(ncores-1)+1;
- RBX = ncores;
- RCX |= (2<<8);
- }
- else if (nprocessors > 1) {
- RAX = ilog2(nprocessors-1)+1;
- RBX = nprocessors;
- }
- else {
- RAX = 0;
- RBX = 0;
- }
- }
- else if (ncores > 1) {
- if (nprocessors > 1) {
- RAX = ilog2(nprocessors-1)+1;
- RBX = nprocessors;
- }
- else {
- RAX = 0;
- RBX = 0;
- }
- } else {
- RAX = 0;
- RBX = 0;
- }
- break;
-
- case 2:
- if (nthreads > 1) {
- if (nprocessors > 1) {
- RAX = ilog2(nprocessors-1)+1;
- RBX = nprocessors;
- }
- else {
- RAX = 0;
- RBX = 0;
- }
- }
- else {
- RAX = 0;
- RBX = 0;
- }
- break;
-
- default:
- RAX = 0;
- RBX = 0;
- break;
- }
-}
-
-void BX_CPU_C::bx_cpuid_extended_cpuid_leaf(Bit32u subfunction)
-{
- if (subfunction == 0) {
- RAX = BX_CPU_THIS_PTR cpuid_std_function[0x7].eax;
- RBX = BX_CPU_THIS_PTR cpuid_std_function[0x7].ebx;
- RCX = BX_CPU_THIS_PTR cpuid_std_function[0x7].ecx;
- RDX = BX_CPU_THIS_PTR cpuid_std_function[0x7].edx;
- }
- else {
- RAX = 0; // reserved
- RBX = 0; // reserved
- RCX = 0; // reserved
- RDX = 0; // reserved
- }
-}
-
-void BX_CPU_C::bx_cpuid_xsave_leaf(Bit32u subfunction)
-{
- BX_ASSERT(BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE));
-
- switch(subfunction) {
- case 0:
- RAX = BX_CPU_THIS_PTR cpuid_std_function[0xd].eax;
- RBX = BX_CPU_THIS_PTR cpuid_std_function[0xd].ebx;
- RCX = BX_CPU_THIS_PTR cpuid_std_function[0xd].ecx;
- RDX = BX_CPU_THIS_PTR cpuid_std_function[0xd].edx;
- break;
-
- case 1:
- RAX = BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVEOPT);
- RBX = 0;
- RCX = 0;
- RDX = 0;
- break;
-
-#if BX_SUPPORT_AVX
- case 2: // AVX leaf
- if (BX_CPU_THIS_PTR xcr0_suppmask & BX_XCR0_AVX_MASK) {
- RAX = 256;
- RBX = 576;
- RCX = 0;
- RDX = 0;
- break;
- }
- // else fall through
-#endif
-
- default:
- RAX = 0; // reserved
- RBX = 0; // reserved
- RCX = 0; // reserved
- RDX = 0; // reserved
- break;
- }
-}
-#endif
-
-#endif
-
-void BX_CPU_C::init_isa_features_bitmask(void)
-{
- Bit32u features_bitmask = 0;
-
-#if BX_SUPPORT_FPU
- features_bitmask |= BX_CPU_X87;
-#endif
-
-#if BX_CPU_LEVEL >= 4
- features_bitmask |= BX_CPU_486;
-
-#if BX_CPU_LEVEL >= 5
- features_bitmask |= BX_CPU_PENTIUM;
-
- static bx_bool mmx_enabled = SIM->get_param_bool(BXPN_CPUID_MMX)->get();
- if (mmx_enabled)
- features_bitmask |= BX_CPU_MMX;
-
-#if BX_SUPPORT_3DNOW
- features_bitmask |= BX_CPU_3DNOW;
-
- if (! mmx_enabled) {
- BX_PANIC(("PANIC: 3DNOW emulation requires MMX support !"));
- return;
- }
-#endif
-
-#if BX_CPU_LEVEL >= 6
- features_bitmask |= BX_CPU_P6;
-
-#if BX_SUPPORT_MONITOR_MWAIT
- static bx_bool mwait_enabled = SIM->get_param_bool(BXPN_CPUID_MWAIT)->get();
- if (mwait_enabled)
- features_bitmask |= BX_CPU_MONITOR_MWAIT;
-#endif
-
- // FXSAVE/FXRSTOR support come with Pentium II
- if (mmx_enabled)
- features_bitmask |= BX_CPU_FXSAVE_FXRSTOR;
-
- static unsigned sse_enabled = SIM->get_param_enum(BXPN_CPUID_SSE)->get();
- // determine SSE in runtime
- switch (sse_enabled) {
- case BX_CPUID_SUPPORT_SSE4_2:
- features_bitmask |= BX_CPU_SSE4_2;
- case BX_CPUID_SUPPORT_SSE4_1:
- features_bitmask |= BX_CPU_SSE4_1;
- case BX_CPUID_SUPPORT_SSSE3:
- features_bitmask |= BX_CPU_SSSE3;
- case BX_CPUID_SUPPORT_SSE3:
- features_bitmask |= BX_CPU_SSE3;
- case BX_CPUID_SUPPORT_SSE2:
- features_bitmask |= BX_CPU_SSE2;
- case BX_CPUID_SUPPORT_SSE:
- features_bitmask |= BX_CPU_SSE;
- case BX_CPUID_SUPPORT_NOSSE:
- default:
- break;
- };
-
- if (sse_enabled) {
- if (mmx_enabled == 0 || BX_CPU_LEVEL < 6) {
- BX_PANIC(("PANIC: SSE support requires P6 emulation with MMX enabled !"));
- return;
- }
- }
-
- // enabled CLFLUSH only when SSE2 or higher is enabled
- if (sse_enabled >= BX_CPUID_SUPPORT_SSE2)
- features_bitmask |= BX_CPU_CLFLUSH;
-
- static bx_bool sep_enabled = SIM->get_param_bool(BXPN_CPUID_SEP)->get();
- if (sep_enabled)
- features_bitmask |= BX_CPU_SYSENTER_SYSEXIT;
-
- static bx_bool xsave_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVE)->get();
- if (xsave_enabled) {
- features_bitmask |= BX_CPU_XSAVE;
-
- if (! sse_enabled) {
- BX_PANIC(("PANIC: XSAVE emulation requires SSE support !"));
- return;
- }
- }
-
- static bx_bool xsaveopt_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVEOPT)->get();
- if (xsaveopt_enabled) {
- features_bitmask |= BX_CPU_XSAVEOPT;
-
- if (! xsave_enabled) {
- BX_PANIC(("PANIC: XSAVEOPT emulation requires XSAVE !"));
- return;
- }
- }
-
- static bx_bool aes_enabled = SIM->get_param_bool(BXPN_CPUID_AES)->get();
- if (aes_enabled) {
- features_bitmask |= BX_CPU_AES_PCLMULQDQ;
-
- // AES required 3-byte opcode (SSS3E support or more)
- if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
- BX_PANIC(("PANIC: AES support requires SSSE3 or higher !"));
- return;
- }
- }
-
- static bx_bool movbe_enabled = SIM->get_param_bool(BXPN_CPUID_MOVBE)->get();
- if (movbe_enabled) {
- features_bitmask |= BX_CPU_MOVBE;
-
- // MOVBE required 3-byte opcode (SSS3E support or more)
- if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
- BX_PANIC(("PANIC: MOVBE support requires SSSE3 or higher !"));
- return;
- }
- }
-
-#if BX_SUPPORT_AVX
- static bx_bool avx_enabled = SIM->get_param_bool(BXPN_CPUID_AVX)->get();
- if (avx_enabled) {
- features_bitmask |= BX_CPU_AVX;
-
- if (! xsave_enabled) {
- BX_PANIC(("PANIC: AVX emulation requires XSAVE support !"));
- return;
- }
- }
-
- static bx_bool avx_f16c_enabled = \
SIM->get_param_bool(BXPN_CPUID_AVX_F16CVT)->get();
- if (avx_f16c_enabled) {
- if (! avx_enabled) {
- BX_PANIC(("PANIC: Float16 convert emulation requires AVX support !"));
- return;
- }
-
- features_bitmask |= BX_CPU_AVX_F16C;
- }
-#endif
-
-#if BX_SUPPORT_VMX
- features_bitmask |= BX_CPU_VMX;
-
- if (! sep_enabled) {
- BX_PANIC(("PANIC: VMX emulation requires SYSENTER/SYSEXIT support !"));
- return;
- }
-#endif
-
-#if BX_SUPPORT_X86_64
- features_bitmask |= BX_CPU_X86_64;
-
- if (sse_enabled < BX_CPUID_SUPPORT_SSE2) {
- BX_PANIC(("PANIC: x86-64 emulation requires SSE2 support !"));
- return;
- }
-
- if (! sep_enabled) {
- BX_PANIC(("PANIC: x86-64 emulation requires SYSENTER/SYSEXIT support !"));
- return;
- }
-
- static bx_bool fsgsbase_enabled = SIM->get_param_bool(BXPN_CPUID_FSGSBASE)->get();
- if (fsgsbase_enabled)
- features_bitmask |= BX_CPU_FSGSBASE;
-
- static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get();
- if (apic_enabled < BX_CPUID_SUPPORT_XAPIC) {
- BX_PANIC(("PANIC: x86-64 emulation requires XAPIC support !"));
- return;
- }
-#endif
-
-#endif // CPU_LEVEL >= 6
-
-#endif // CPU_LEVEL >= 5
-
-#endif // CPU_LEVEL >= 4
-
- BX_CPU_THIS_PTR isa_extensions_bitmask = features_bitmask;
-}
-
-void BX_CPU_C::init_cpu_features_bitmask(void)
-{
- Bit32u features_bitmask = 0;
-
-#if BX_SUPPORT_APIC
- static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get();
- // determine SSE in runtime
- switch (apic_enabled) {
- case BX_CPUID_SUPPORT_X2APIC:
- features_bitmask |= BX_CPU_X2APIC;
- case BX_CPUID_SUPPORT_XAPIC:
- features_bitmask |= BX_CPU_XAPIC;
- case BX_CPUID_SUPPORT_LEGACY_APIC:
- default:
- break;
- };
-
- // I would like to allow XAPIC configuration with i586 together
- if (apic_enabled >= BX_CPUID_SUPPORT_X2APIC && BX_CPU_LEVEL < 6) {
- BX_PANIC(("PANIC: X2APIC require CPU_LEVEL >= 6 !"));
- return;
- }
-#endif
-
-#if BX_CPU_LEVEL >= 5
- features_bitmask |= BX_CPU_VME;
- features_bitmask |= BX_CPU_DEBUG_EXTENSIONS;
- features_bitmask |= BX_CPU_PSE;
-
-#if BX_CPU_LEVEL >= 6
- features_bitmask |= BX_CPU_PAE;
- features_bitmask |= BX_CPU_PGE;
- features_bitmask |= BX_CPU_PSE36;
- features_bitmask |= BX_CPU_PAT_MTRR;
-
- static bx_bool smep_enabled = SIM->get_param_bool(BXPN_CPUID_SMEP)->get();
- if (smep_enabled)
- features_bitmask |= BX_CPU_SMEP;
-
-#if BX_SUPPORT_X86_64
- static bx_bool pcid_enabled = SIM->get_param_bool(BXPN_CPUID_PCID)->get();
- if (pcid_enabled)
- features_bitmask |= BX_CPU_PCID;
-#endif
-
-#endif // CPU_LEVEL >= 6
-
-#endif // CPU_LEVEL >= 5
-
- BX_CPU_THIS_PTR cpu_extensions_bitmask = features_bitmask;
-}
Modified: trunk/bochs/cpu/cpuid.h
===================================================================
--- trunk/bochs/cpu/cpuid.h 2011-07-27 14:16:51 UTC (rev 10497)
+++ trunk/bochs/cpu/cpuid.h 2011-07-28 16:17:42 UTC (rev 10498)
@@ -31,6 +31,25 @@
Bit32u edx;
};
+class bx_cpuid_t {
+public:
+ bx_cpuid_t(BX_CPU_C *_cpu): cpu(_cpu) {}
+ virtual ~bx_cpuid_t() {}
+
+ // return CPU name
+ virtual const char *get_name(void) const { return NULL; }
+
+ virtual Bit32u get_isa_extensions_bitmask(void) const = 0;
+ virtual Bit32u get_cpu_extensions_bitmask(void) const = 0;
+
+ virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t \
*leaf) {} +
+ virtual void dump_cpuid(void) = 0;
+
+protected:
+ BX_CPU_C *cpu;
+};
+
// cpuid ISA (duplicated in disasm.h)
#define BX_CPU_X87 (1 << 0) /* FPU (X87) instruction */
#define BX_CPU_486 (1 << 1) /* 486 new instruction */
Copied: trunk/bochs/cpu/generic_cpuid.cc (from rev 10497, trunk/bochs/cpu/cpuid.cc)
===================================================================
--- trunk/bochs/cpu/generic_cpuid.cc (rev 0)
+++ trunk/bochs/cpu/generic_cpuid.cc 2011-07-28 16:17:42 UTC (rev 10498)
@@ -0,0 +1,1224 @@
+/////////////////////////////////////////////////////////////////////////
+// $Id$
+/////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2011 Stanislav Shwartsman
+// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
+//
+/////////////////////////////////////////////////////////////////////////
+
+#include "bochs.h"
+#include "cpu.h"
+#include "param_names.h"
+#include "generic_cpuid.h"
+
+#define LOG_THIS cpu->
+
+bx_generic_cpuid_t::bx_generic_cpuid_t(BX_CPU_C *cpu): bx_cpuid_t(cpu)
+{
+#if BX_SUPPORT_SMP
+ nthreads = SIM->get_param_num(BXPN_CPU_NTHREADS)->get();
+ ncores = SIM->get_param_num(BXPN_CPU_NCORES)->get();
+ nprocessors = SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get();
+#endif
+
+ init_isa_extensions_bitmask();
+ init_cpu_extensions_bitmask();
+}
+
+void bx_generic_cpuid_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, \
cpuid_function_t *leaf) +{
+ static bx_bool cpuid_limit_winnt = \
SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); + if (function > 3 && \
cpuid_limit_winnt) + function = 3;
+
+ switch(function) {
+#if BX_CPU_LEVEL >= 6
+ case 0x80000000:
+ get_ext_cpuid_leaf_0(leaf);
+ return;
+ case 0x80000001:
+ get_ext_cpuid_leaf_1(leaf);
+ return;
+ case 0x80000002:
+ case 0x80000003:
+ case 0x80000004:
+ get_ext_cpuid_brand_string_leaf(function, leaf);
+ return;
+#if BX_SUPPORT_X86_64
+ case 0x80000005:
+ get_ext_cpuid_leaf_5(leaf);
+ return;
+ case 0x80000006:
+ get_ext_cpuid_leaf_6(leaf);
+ return;
+ case 0x80000007:
+ get_ext_cpuid_leaf_7(leaf);
+ return;
+ case 0x80000008:
+ get_ext_cpuid_leaf_8(leaf);
+ return;
+#endif
+#endif
+ case 0x00000000:
+ get_std_cpuid_leaf_0(leaf);
+ return;
+ case 0x00000001:
+ get_std_cpuid_leaf_1(leaf);
+ return;
+#if BX_CPU_LEVEL >= 6
+ case 0x00000002:
+ get_std_cpuid_leaf_2(leaf);
+ return;
+ case 0x00000003:
+ get_std_cpuid_leaf_3(leaf);
+ return;
+ case 0x00000004:
+ get_std_cpuid_leaf_4(subfunction, leaf);
+ return;
+ case 0x00000005:
+ get_std_cpuid_leaf_5(leaf);
+ return;
+ case 0x00000006:
+ get_std_cpuid_leaf_6(leaf);
+ return;
+ case 0x00000007:
+ get_std_cpuid_leaf_7(subfunction, leaf);
+ return;
+ case 0x00000008:
+ get_std_cpuid_leaf_8(leaf);
+ return;
+ case 0x00000009:
+ get_std_cpuid_leaf_9(leaf);
+ return;
+ case 0x0000000A:
+ get_std_cpuid_leaf_A(leaf);
+ return;
+ case 0x0000000B:
+ get_std_cpuid_extended_topology_leaf(subfunction, leaf);
+ return;
+ case 0x0000000C:
+ get_std_cpuid_leaf_C(leaf);
+ return;
+ case 0x0000000D:
+ default:
+ get_std_cpuid_xsave_leaf(subfunction, leaf);
+ return;
+#endif
+ }
+}
+
+// leaf 0x00000000 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf)
+{
+ static Bit8u *vendor_string = (Bit8u \
*)SIM->get_param_string(BXPN_VENDOR_STRING)->getptr(); +
+ // EAX: highest input value understood by CPUID
+ // EBX: vendor ID string
+ // EDX: vendor ID string
+ // ECX: vendor ID string
+
+#if BX_CPU_LEVEL <= 5
+ // 486 and Pentium processors
+ leaf->eax = 1;
+#else
+ // for Pentium Pro, Pentium II, Pentium 4 processors
+ leaf->eax = 3;
+
+ // do not report CPUID functions above 0x3 if cpuid_limit_winnt is set
+ // to workaround WinNT issue.
+ static bx_bool cpuid_limit_winnt = \
SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); + if (! cpuid_limit_winnt) {
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MONITOR_MWAIT))
+ leaf->eax = 0x5;
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC))
+ leaf->eax = 0xb;
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
+ leaf->eax = 0xd;
+ }
+#endif
+
+ // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...)
+ memcpy(&(leaf->ebx), vendor_string, 4);
+ memcpy(&(leaf->edx), vendor_string + 4, 4);
+ memcpy(&(leaf->ecx), vendor_string + 8, 4);
+#ifdef BX_BIG_ENDIAN
+ leaf->ebx = bx_bswap32(leaf->ebx);
+ leaf->ecx = bx_bswap32(leaf->ecx);
+ leaf->edx = bx_bswap32(leaf->edx);
+#endif
+}
+
+// leaf 0x00000001 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf)
+{
+ // EAX: CPU Version Information
+ // [3:0] Stepping ID
+ // [7:4] Model: starts at 1
+ // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ...
+ // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
+ // [19:16] Extended Model
+ // [27:20] Extended Family
+ leaf->eax = get_cpu_version_information();
+
+ // EBX:
+ // [7:0] Brand ID
+ // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes)
+ // [23:16] Number of logical processors in one physical processor
+ // [31:24] Local Apic ID
+ leaf->ebx = 0;
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_CLFLUSH)) {
+ leaf->ebx |= (CACHE_LINE_SIZE / 8) << 8;
+ }
+#if BX_SUPPORT_SMP
+ unsigned n_logical_processors = ncores*nthreads;
+ if (n_logical_processors > 1)
+ leaf->ebx |= (n_logical_processors << 16);
+#endif
+#if BX_SUPPORT_APIC
+ leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24);
+#endif
+
+ // ECX: Extended Feature Flags
+ leaf->ecx = get_extended_cpuid_features();
+
+ // EDX: Standard Feature Flags
+ leaf->edx = get_std_cpuid_features();
+}
+
+// leaf 0x00000002 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf)
+{
+ // CPUID function 0x00000002 - Cache and TLB Descriptors
+#if BX_CPU_VENDOR_INTEL
+ leaf->eax = 0x00410601; // for Pentium Pro compatibility
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+#else
+ leaf->eax = 0; // ignore for AMD
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+#endif
+}
+
+// leaf 0x00000003 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_3(cpuid_function_t *leaf)
+{
+ // CPUID function 0x00000003 - Processor Serial Number
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+// leaf 0x00000004 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t \
*leaf) +{
+ // CPUID function 0x00000004 - Deterministic Cache Parameters
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+// leaf 0x00000005 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf)
+{
+ // CPUID function 0x00000005 - MONITOR/MWAIT Leaf
+#if BX_SUPPORT_MONITOR_MWAIT
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MONITOR_MWAIT))
+ {
+ // EAX - Smallest monitor-line size in bytes
+ // EBX - Largest monitor-line size in bytes
+ // ECX -
+ // [31:2] - reserved
+ // [1:1] - exit MWAIT even with EFLAGS.IF = 0
+ // [0:0] - MONITOR/MWAIT extensions are supported
+ // EDX - Reserved
+ leaf->eax = CACHE_LINE_SIZE;
+ leaf->ebx = CACHE_LINE_SIZE;
+ leaf->ecx = 3;
+ leaf->edx = 0;
+ }
+ else
+#endif
+ {
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+ }
+}
+
+// leaf 0x00000006 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf)
+{
+ // CPUID function 0x00000006 - Thermal and Power Management Leaf
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+// leaf 0x00000007 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t \
*leaf) +{
+ leaf->ebx = get_ext3_cpuid_features();
+ leaf->ecx = 0;
+ leaf->edx = 0;
+ if (leaf->ebx)
+ leaf->eax = 1; /* report max sub-leaves that are supported in leaf 7 */
+ else
+ leaf->eax = 0; /* leaf 7 not supported */
+}
+
+// leaf 0x00000008 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_8(cpuid_function_t *leaf)
+{
+ // CPUID function 0x00000008 - reserved
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+// leaf 0x00000009 //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_9(cpuid_function_t *leaf)
+{
+ // CPUID function 0x00000009 - Direct Cache Access Information Leaf
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+// leaf 0x0000000A //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf)
+{
+ // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+BX_CPP_INLINE static Bit32u ilog2(Bit32u x)
+{
+ Bit32u count = 0;
+ while(x>>=1) count++;
+ return count;
+}
+
+// leaf 0x0000000B //
+void bx_generic_cpuid_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, \
cpuid_function_t *leaf) +{
+ // CPUID function 0x0000000B - Extended Topology Leaf
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = subfunction;
+ leaf->edx = cpu->get_apic_id();
+
+#if BX_SUPPORT_SMP
+ switch(subfunction) {
+ case 0:
+ if (nthreads > 1) {
+ leaf->eax = ilog2(nthreads-1)+1;
+ leaf->ebx = nthreads;
+ leaf->ecx |= (1<<8);
+ }
+ else if (ncores > 1) {
+ leaf->eax = ilog2(ncores-1)+1;
+ leaf->ebx = ncores;
+ leaf->ecx |= (2<<8);
+ }
+ else if (nprocessors > 1) {
+ leaf->eax = ilog2(nprocessors-1)+1;
+ leaf->ebx = nprocessors;
+ }
+ else {
+ leaf->eax = 1;
+ leaf->ebx = 1; // number of logical CPUs at this level
+ }
+ break;
+
+ case 1:
+ if (nthreads > 1) {
+ if (ncores > 1) {
+ leaf->eax = ilog2(ncores-1)+1;
+ leaf->ebx = ncores;
+ leaf->ecx |= (2<<8);
+ }
+ else if (nprocessors > 1) {
+ leaf->eax = ilog2(nprocessors-1)+1;
+ leaf->ebx = nprocessors;
+ }
+ }
+ else if (ncores > 1) {
+ if (nprocessors > 1) {
+ leaf->eax = ilog2(nprocessors-1)+1;
+ leaf->ebx = nprocessors;
+ }
+ }
+ break;
+
+ case 2:
+ if (nthreads > 1) {
+ if (nprocessors > 1) {
+ leaf->eax = ilog2(nprocessors-1)+1;
+ leaf->ebx = nprocessors;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+#endif
+}
+
+// leaf 0x0000000C //
+void bx_generic_cpuid_t::get_std_cpuid_leaf_C(cpuid_function_t *leaf)
+{
+ // CPUID function 0x0000000C - reserved
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+// leaf 0x0000000D //
+void bx_generic_cpuid_t::get_std_cpuid_xsave_leaf(Bit32u subfunction, \
cpuid_function_t *leaf) +{
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
+ {
+ switch(subfunction) {
+ case 0:
+ // EAX - valid bits of XCR0 (lower part)
+ // EBX - Maximum size (in bytes) required by enabled features
+ // ECX - Maximum size (in bytes) required by CPU supported features
+ // EDX - valid bits of XCR0 (upper part)
+ leaf->eax = cpu->xcr0_suppmask;
+ leaf->ebx = 512+64;
+#if BX_SUPPORT_AVX
+ if (cpu->xcr0_suppmask & BX_XCR0_AVX_MASK)
+ leaf->ebx += 256;
+#endif
+ leaf->ecx = 512+64;
+#if BX_SUPPORT_AVX
+ if (cpu->xcr0_suppmask & BX_XCR0_AVX_MASK)
+ leaf->ecx += 256;
+#endif
+ leaf->edx = 0;
+ return;
+
+ case 1:
+ leaf->eax = BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVEOPT);
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+ return;
+
+#if BX_SUPPORT_AVX
+ case 2: // AVX leaf
+ if (cpu->xcr0_suppmask & BX_XCR0_AVX_MASK) {
+ leaf->eax = 256;
+ leaf->ebx = 576;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+ break;
+ }
+ // else fall through
+#endif
+
+ default:
+ leaf->eax = 0; // reserved
+ leaf->ebx = 0; // reserved
+ leaf->ecx = 0; // reserved
+ leaf->edx = 0; // reserved
+ break;
+ }
+ }
+}
+
+// leaf 0x80000000 //
+void bx_generic_cpuid_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf)
+{
+ // EAX: highest extended function understood by CPUID
+ // EBX: vendor ID string
+ // EDX: vendor ID string
+ // ECX: vendor ID string
+ leaf->eax = BX_SUPPORT_X86_64 ? 0x80000008 : 0x80000004;
+#if BX_CPU_VENDOR_INTEL
+ leaf->ebx = 0;
+ leaf->edx = 0; // Reserved for Intel
+ leaf->ecx = 0;
+#else
+ static Bit8u *vendor_string = (Bit8u \
*)SIM->get_param_string(BXPN_VENDOR_STRING)->getptr(); +
+ memcpy(&(leaf->ebx), vendor_string, 4);
+ memcpy(&(leaf->edx), vendor_string + 4, 4);
+ memcpy(&(leaf->ecx), vendor_string + 8, 4);
+#endif
+
+#ifdef BX_BIG_ENDIAN
+ leaf->ebx = bx_bswap32(leaf->ebx);
+ leaf->ecx = bx_bswap32(leaf->ecx);
+ leaf->edx = bx_bswap32(leaf->edx);
+#endif
+}
+
+// leaf 0x80000001 //
+void bx_generic_cpuid_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf)
+{
+ // EAX: CPU Version Information
+ leaf->eax = BX_CPU_VENDOR_INTEL ? 0 : get_cpu_version_information();
+
+ // EBX: Brand ID
+ leaf->ebx = 0;
+
+ // ECX:
+ leaf->ecx = get_ext2_cpuid_features();
+
+ // EDX:
+ // Many of the bits in EDX are the same as EAX [*] for AMD
+ // [*] [0:0] FPU on chip
+ // [*] [1:1] VME: Virtual-8086 Mode enhancements
+ // [*] [2:2] DE: Debug Extensions (I/O breakpoints)
+ // [*] [3:3] PSE: Page Size Extensions
+ // [*] [4:4] TSC: Time Stamp Counter
+ // [*] [5:5] MSR: RDMSR and WRMSR support
+ // [*] [6:6] PAE: Physical Address Extensions
+ // [*] [7:7] MCE: Machine Check Exception
+ // [*] [8:8] CXS: CMPXCHG8B instruction
+ // [*] [9:9] APIC: APIC on Chip
+ // [10:10] Reserved
+ // [11:11] SYSCALL/SYSRET support
+ // [*] [12:12] MTRR: Memory Type Range Reg
+ // [*] [13:13] PGE/PTE Global Bit
+ // [*] [14:14] MCA: Machine Check Architecture
+ // [*] [15:15] CMOV: Cond Mov/Cmp Instructions
+ // [*] [16:16] PAT: Page Attribute Table
+ // [*] [17:17] PSE-36: Physical Address Extensions
+ // [18:19] Reserved
+ // [20:20] No-Execute page protection
+ // [21:21] Reserved
+ // [22:22] AMD MMX Extensions
+ // [*] [23:23] MMX Technology
+ // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
+ // [25:25] Fast FXSAVE/FXRSTOR mode support
+ // [26:26] 1G paging support
+ // [27:27] Support RDTSCP Instruction
+ // [28:28] Reserved
+ // [29:29] Long Mode
+ // [30:30] AMD 3DNow! Extensions
+ // [31:31] AMD 3DNow! Instructions
+ leaf->edx = get_std2_cpuid_features();
+}
+
+// leaf 0x80000002 //
+// leaf 0x80000003 //
+// leaf 0x80000004 //
+void bx_generic_cpuid_t::get_ext_cpuid_brand_string_leaf(Bit32u function, \
cpuid_function_t *leaf) +{
+ static Bit8u *brand_string = (Bit8u \
*)SIM->get_param_string(BXPN_BRAND_STRING)->getptr(); +
+ switch(function) {
+ case 0x80000002:
+ memcpy(&(leaf->eax), brand_string , 4);
+ memcpy(&(leaf->ebx), brand_string + 4, 4);
+ memcpy(&(leaf->ecx), brand_string + 8, 4);
+ memcpy(&(leaf->edx), brand_string + 12, 4);
+ break;
+ case 0x80000003:
+ memcpy(&(leaf->eax), brand_string + 16, 4);
+ memcpy(&(leaf->ebx), brand_string + 20, 4);
+ memcpy(&(leaf->ecx), brand_string + 24, 4);
+ memcpy(&(leaf->edx), brand_string + 28, 4);
+ break;
+ case 0x80000004:
+ memcpy(&(leaf->eax), brand_string + 32, 4);
+ memcpy(&(leaf->ebx), brand_string + 36, 4);
+ memcpy(&(leaf->ecx), brand_string + 40, 4);
+ memcpy(&(leaf->edx), brand_string + 44, 4);
+ break;
+ default:
+ break;
+ }
+
+#ifdef BX_BIG_ENDIAN
+ leaf->eax = bx_bswap32(leaf->eax);
+ leaf->ebx = bx_bswap32(leaf->ebx);
+ leaf->ecx = bx_bswap32(leaf->ecx);
+ leaf->edx = bx_bswap32(leaf->edx);
+#endif
+}
+
+// leaf 0x80000005 //
+void bx_generic_cpuid_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf)
+{
+ /* cache info (L1 cache) */
+ leaf->eax = 0x01ff01ff;
+ leaf->ebx = 0x01ff01ff;
+ leaf->ecx = 0x40020140;
+ leaf->edx = 0x40020140;
+}
+
+// leaf 0x80000006 //
+void bx_generic_cpuid_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf)
+{
+ /* cache info (L2 cache) */
+ leaf->eax = 0;
+ leaf->ebx = 0x42004200;
+ leaf->ecx = 0x02008140;
+ leaf->edx = 0;
+}
+
+// leaf 0x80000007 //
+void bx_generic_cpuid_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf)
+{
+ leaf->eax = 0;
+ leaf->ebx = 0;
+ leaf->ecx = 0;
+ leaf->edx = 0;
+}
+
+// leaf 0x80000008 //
+void bx_generic_cpuid_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf)
+{
+ // virtual & phys address size in low 2 bytes.
+ leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8);
+ leaf->ebx = 0;
+ leaf->ecx = 0; // Reserved, undefined
+ leaf->edx = 0;
+}
+
+void bx_generic_cpuid_t::init_isa_extensions_bitmask(void)
+{
+ Bit32u features_bitmask = 0;
+
+#if BX_SUPPORT_FPU
+ features_bitmask |= BX_CPU_X87;
+#endif
+
+#if BX_CPU_LEVEL >= 4
+ features_bitmask |= BX_CPU_486;
+
+#if BX_CPU_LEVEL >= 5
+ features_bitmask |= BX_CPU_PENTIUM;
+
+ static bx_bool mmx_enabled = SIM->get_param_bool(BXPN_CPUID_MMX)->get();
+ if (mmx_enabled)
+ features_bitmask |= BX_CPU_MMX;
+
+#if BX_SUPPORT_3DNOW
+ features_bitmask |= BX_CPU_3DNOW;
+
+ if (! mmx_enabled) {
+ BX_PANIC(("PANIC: 3DNOW emulation requires MMX support !"));
+ return;
+ }
+#endif
+
+#if BX_CPU_LEVEL >= 6
+ features_bitmask |= BX_CPU_P6;
+
+#if BX_SUPPORT_MONITOR_MWAIT
+ static bx_bool mwait_enabled = SIM->get_param_bool(BXPN_CPUID_MWAIT)->get();
+ if (mwait_enabled)
+ features_bitmask |= BX_CPU_MONITOR_MWAIT;
+#endif
+
+ // FXSAVE/FXRSTOR support come with Pentium II
+ if (mmx_enabled)
+ features_bitmask |= BX_CPU_FXSAVE_FXRSTOR;
+
+ static unsigned sse_enabled = SIM->get_param_enum(BXPN_CPUID_SSE)->get();
+ // determine SSE in runtime
+ switch (sse_enabled) {
+ case BX_CPUID_SUPPORT_SSE4_2:
+ features_bitmask |= BX_CPU_SSE4_2;
+ case BX_CPUID_SUPPORT_SSE4_1:
+ features_bitmask |= BX_CPU_SSE4_1;
+ case BX_CPUID_SUPPORT_SSSE3:
+ features_bitmask |= BX_CPU_SSSE3;
+ case BX_CPUID_SUPPORT_SSE3:
+ features_bitmask |= BX_CPU_SSE3;
+ case BX_CPUID_SUPPORT_SSE2:
+ features_bitmask |= BX_CPU_SSE2;
+ case BX_CPUID_SUPPORT_SSE:
+ features_bitmask |= BX_CPU_SSE;
+ case BX_CPUID_SUPPORT_NOSSE:
+ default:
+ break;
+ };
+
+ if (sse_enabled) {
+ if (mmx_enabled == 0 || BX_CPU_LEVEL < 6) {
+ BX_PANIC(("PANIC: SSE support requires P6 emulation with MMX enabled !"));
+ return;
+ }
+ }
+
+ // enabled CLFLUSH only when SSE2 or higher is enabled
+ if (sse_enabled >= BX_CPUID_SUPPORT_SSE2)
+ features_bitmask |= BX_CPU_CLFLUSH;
+
+ static bx_bool sep_enabled = SIM->get_param_bool(BXPN_CPUID_SEP)->get();
+ if (sep_enabled)
+ features_bitmask |= BX_CPU_SYSENTER_SYSEXIT;
+
+ static bx_bool xsave_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVE)->get();
+ if (xsave_enabled) {
+ features_bitmask |= BX_CPU_XSAVE;
+
+ if (! sse_enabled) {
+ BX_PANIC(("PANIC: XSAVE emulation requires SSE support !"));
+ return;
+ }
+ }
+
+ static bx_bool xsaveopt_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVEOPT)->get();
+ if (xsaveopt_enabled) {
+ features_bitmask |= BX_CPU_XSAVEOPT;
+
+ if (! xsave_enabled) {
+ BX_PANIC(("PANIC: XSAVEOPT emulation requires XSAVE !"));
+ return;
+ }
+ }
+
+ static bx_bool aes_enabled = SIM->get_param_bool(BXPN_CPUID_AES)->get();
+ if (aes_enabled) {
+ features_bitmask |= BX_CPU_AES_PCLMULQDQ;
+
+ // AES required 3-byte opcode (SSS3E support or more)
+ if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
+ BX_PANIC(("PANIC: AES support requires SSSE3 or higher !"));
+ return;
+ }
+ }
+
+ static bx_bool movbe_enabled = SIM->get_param_bool(BXPN_CPUID_MOVBE)->get();
+ if (movbe_enabled) {
+ features_bitmask |= BX_CPU_MOVBE;
+
+ // MOVBE required 3-byte opcode (SSS3E support or more)
+ if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) {
+ BX_PANIC(("PANIC: MOVBE support requires SSSE3 or higher !"));
+ return;
+ }
+ }
+
+#if BX_SUPPORT_AVX
+ static bx_bool avx_enabled = SIM->get_param_bool(BXPN_CPUID_AVX)->get();
+ if (avx_enabled) {
+ features_bitmask |= BX_CPU_AVX;
+
+ if (! xsave_enabled) {
+ BX_PANIC(("PANIC: AVX emulation requires XSAVE support !"));
+ return;
+ }
+ }
+
+ static bx_bool avx_f16c_enabled = \
SIM->get_param_bool(BXPN_CPUID_AVX_F16CVT)->get(); + if (avx_f16c_enabled) {
+ if (! avx_enabled) {
+ BX_PANIC(("PANIC: Float16 convert emulation requires AVX support !"));
+ return;
+ }
+
+ features_bitmask |= BX_CPU_AVX_F16C;
+ }
+#endif
+
+#if BX_SUPPORT_VMX
+ features_bitmask |= BX_CPU_VMX;
+
+ if (! sep_enabled) {
+ BX_PANIC(("PANIC: VMX emulation requires SYSENTER/SYSEXIT support !"));
+ return;
+ }
+#endif
+
+#if BX_SUPPORT_X86_64
+ features_bitmask |= BX_CPU_X86_64;
+
+ if (sse_enabled < BX_CPUID_SUPPORT_SSE2) {
+ BX_PANIC(("PANIC: x86-64 emulation requires SSE2 support !"));
+ return;
+ }
+
+ if (! sep_enabled) {
+ BX_PANIC(("PANIC: x86-64 emulation requires SYSENTER/SYSEXIT support !"));
+ return;
+ }
+
+ static bx_bool fsgsbase_enabled = SIM->get_param_bool(BXPN_CPUID_FSGSBASE)->get();
+ if (fsgsbase_enabled)
+ features_bitmask |= BX_CPU_FSGSBASE;
+
+ static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get();
+ if (apic_enabled < BX_CPUID_SUPPORT_XAPIC) {
+ BX_PANIC(("PANIC: x86-64 emulation requires XAPIC support !"));
+ return;
+ }
+#endif
+
+#endif // CPU_LEVEL >= 6
+
+#endif // CPU_LEVEL >= 5
+
+#endif // CPU_LEVEL >= 4
+
+ this->isa_extensions_bitmask = features_bitmask;
+}
+
+void bx_generic_cpuid_t::init_cpu_extensions_bitmask(void)
+{
+ Bit32u features_bitmask = 0;
+
+#if BX_SUPPORT_APIC
+ static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get();
+ // determine SSE in runtime
+ switch (apic_enabled) {
+ case BX_CPUID_SUPPORT_X2APIC:
+ features_bitmask |= BX_CPU_X2APIC;
+ case BX_CPUID_SUPPORT_XAPIC:
+ features_bitmask |= BX_CPU_XAPIC;
+ case BX_CPUID_SUPPORT_LEGACY_APIC:
+ default:
+ break;
+ };
+
+ // I would like to allow XAPIC configuration with i586 together
+ if (apic_enabled >= BX_CPUID_SUPPORT_X2APIC && BX_CPU_LEVEL < 6) {
+ BX_PANIC(("PANIC: X2APIC require CPU_LEVEL >= 6 !"));
+ return;
+ }
+#endif
+
+#if BX_CPU_LEVEL >= 5
+ features_bitmask |= BX_CPU_VME;
+ features_bitmask |= BX_CPU_DEBUG_EXTENSIONS;
+ features_bitmask |= BX_CPU_PSE;
+
+#if BX_CPU_LEVEL >= 6
+ features_bitmask |= BX_CPU_PAE;
+ features_bitmask |= BX_CPU_PGE;
+ features_bitmask |= BX_CPU_PSE36;
+ features_bitmask |= BX_CPU_PAT_MTRR;
+
+ static bx_bool smep_enabled = SIM->get_param_bool(BXPN_CPUID_SMEP)->get();
+ if (smep_enabled)
+ features_bitmask |= BX_CPU_SMEP;
+
+#if BX_SUPPORT_X86_64
+ static bx_bool pcid_enabled = SIM->get_param_bool(BXPN_CPUID_PCID)->get();
+ if (pcid_enabled)
+ features_bitmask |= BX_CPU_PCID;
+#endif
+
+#endif // CPU_LEVEL >= 6
+
+#endif // CPU_LEVEL >= 5
+
+ this->cpu_extensions_bitmask = features_bitmask;
+}
+
+/*
+ * Get CPU version information:
+ *
+ * [3:0] Stepping ID
+ * [7:4] Model: starts at 1
+ * [11:8] Family: 4=486, 5=Pentium, 6=PPro, ...
+ * [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
+ * [19:16] Extended Model
+ * [27:29] Extended Family
+ */
+
+Bit32u bx_generic_cpuid_t::get_cpu_version_information(void)
+{
+ static Bit32u stepping = SIM->get_param_num(BXPN_CPUID_STEPPING)->get();
+ static Bit32u model = SIM->get_param_num(BXPN_CPUID_MODEL)->get();
+ static Bit32u family = SIM->get_param_num(BXPN_CPUID_FAMILY)->get();
+
+ if (family < 6 && family != BX_CPU_LEVEL)
+ BX_PANIC(("PANIC: CPUID family %x not matching configured cpu level %d", family, \
BX_CPU_LEVEL)); +
+ return ((family & 0xfff0) << 16) |
+ ((model & 0xf0) << 12) |
+ ((family & 0x0f) << 8) |
+ ((model & 0x0f) << 4) | stepping;
+}
+
+/* Get CPU extended feature flags. */
+Bit32u bx_generic_cpuid_t::get_extended_cpuid_features(void)
+{
+ // [0:0] SSE3: SSE3 Instructions
+ // [1:1] PCLMULQDQ Instruction support
+ // [2:2] DTES64: 64-bit DS area
+ // [3:3] MONITOR/MWAIT support
+ // [4:4] DS-CPL: CPL qualified debug store
+ // [5:5] VMX: Virtual Machine Technology
+ // [6:6] SMX: Secure Virtual Machine Technology
+ // [7:7] EST: Enhanced Intel SpeedStep Technology
+ // [8:8] TM2: Thermal Monitor 2
+ // [9:9] SSSE3: SSSE3 Instructions
+ // [10:10] CNXT-ID: L1 context ID
+ // [11:11] reserved
+ // [12:12] FMA Instructions support
+ // [13:13] CMPXCHG16B: CMPXCHG16B instruction support
+ // [14:14] xTPR update control
+ // [15:15] PDCM - Perfon and Debug Capability MSR
+ // [16:16] reserved
+ // [17:17] PCID: Process Context Identifiers
+ // [18:18] DCA - Direct Cache Access
+ // [19:19] SSE4.1 Instructions
+ // [20:20] SSE4.2 Instructions
+ // [21:21] X2APIC
+ // [22:22] MOVBE instruction
+ // [23:23] POPCNT instruction
+ // [24:24] TSC Deadline
+ // [25:25] AES Instructions
+ // [26:26] XSAVE extensions support
+ // [27:27] OSXSAVE support
+ // [28:28] AVX extensions support
+ // [29:29] AVX F16C - Float16 conversion support
+ // [30:30] RDRAND instruction
+ // [31:31] reserved
+
+ Bit32u features = 0;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE3))
+ features |= BX_CPUID_EXT_SSE3;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AES_PCLMULQDQ))
+ features |= BX_CPUID_EXT_PCLMULQDQ;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MONITOR_MWAIT))
+ features |= BX_CPUID_EXT_MONITOR_MWAIT;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_VMX))
+ features |= BX_CPUID_EXT_VMX;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSSE3))
+ features |= BX_CPUID_EXT_SSSE3;
+
+#if BX_SUPPORT_X86_64
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_X86_64))
+ features |= BX_CPUID_EXT_CMPXCHG16B;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PCID))
+ features |= BX_CPUID_EXT_PCID;
+#endif
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_1))
+ features |= BX_CPUID_EXT_SSE4_1;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_2))
+ features |= BX_CPUID_EXT_SSE4_2;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC))
+ features |= BX_CPUID_EXT_X2APIC;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MOVBE))
+ features |= BX_CPUID_EXT_MOVBE;
+
+ // enable POPCNT if SSE4_2 is enabled
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_2))
+ features |= BX_CPUID_EXT_POPCNT;
+
+ // support for AES
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AES_PCLMULQDQ))
+ features |= BX_CPUID_EXT_AES;
+
+ // support XSAVE extensions
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
+ features |= BX_CPUID_EXT_XSAVE | BX_CPUID_EXT_OSXSAVE;
+
+#if BX_SUPPORT_AVX
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AVX))
+ features |= BX_CPUID_EXT_AVX;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_AVX_F16C))
+ features |= BX_CPUID_EXT_AVX_F16C;
+#endif
+
+ return features;
+}
+
+#if BX_CPU_LEVEL >= 6
+Bit32u bx_generic_cpuid_t::get_ext3_cpuid_features(void)
+{
+ Bit32u features = 0;
+
+ // [0:0] FS/GS BASE access instructions
+ // [2:1] reserved
+ // [3:3] BMI1: Advanced Bit Manipulation Extensions
+ // [4:4] reserved
+ // [5:5] AVX2
+ // [6:6] reserved
+ // [7:7] SMEP: Supervisor Mode Execution Protection
+ // [8:8] BMI2: Advanced Bit Manipulation Extensions
+ // [9:9] Support for Enhanced REP MOVSB/STOSB
+ // [10:10] Support for INVPCID instruction
+ // [31:10] reserved
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_FSGSBASE))
+ features |= BX_CPUID_EXT3_FSGSBASE;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_SMEP))
+ features |= BX_CPUID_EXT3_SMEP;
+
+ return features;
+}
+#endif
+
+/* Get CPU feature flags. Returned by CPUID functions 1 and 80000001. */
+Bit32u bx_generic_cpuid_t::get_std_cpuid_features(void)
+{
+ // [0:0] FPU on chip
+ // [1:1] VME: Virtual-8086 Mode enhancements
+ // [2:2] DE: Debug Extensions (I/O breakpoints)
+ // [3:3] PSE: Page Size Extensions
+ // [4:4] TSC: Time Stamp Counter
+ // [5:5] MSR: RDMSR and WRMSR support
+ // [6:6] PAE: Physical Address Extensions
+ // [7:7] MCE: Machine Check Exception
+ // [8:8] CXS: CMPXCHG8B instruction
+ // [9:9] APIC: APIC on Chip
+ // [10:10] Reserved
+ // [11:11] SYSENTER/SYSEXIT support
+ // [12:12] MTRR: Memory Type Range Reg
+ // [13:13] PGE/PTE Global Bit
+ // [14:14] MCA: Machine Check Architecture
+ // [15:15] CMOV: Cond Mov/Cmp Instructions
+ // [16:16] PAT: Page Attribute Table
+ // [17:17] PSE-36: Physical Address Extensions
+ // [18:18] PSN: Processor Serial Number
+ // [19:19] CLFLUSH: CLFLUSH Instruction support
+ // [20:20] Reserved
+ // [21:21] DS: Debug Store
+ // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities
+ // [23:23] MMX Technology
+ // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
+ // [25:25] SSE: SSE Extensions
+ // [26:26] SSE2: SSE2 Extensions
+ // [27:27] Self Snoop
+ // [28:28] Hyper Threading Technology
+ // [29:29] TM: Thermal Monitor
+ // [30:30] Reserved
+ // [31:31] PBE: Pending Break Enable
+
+ Bit32u features = 0;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_X87))
+ features |= BX_CPUID_STD_X87;
+
+#if BX_CPU_LEVEL >= 5
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_PENTIUM)) {
+ // Pentium only features
+ features |= BX_CPUID_STD_TSC;
+ features |= BX_CPUID_STD_MSR;
+ // support Machine Check
+ features |= BX_CPUID_STD_MCE | BX_CPUID_STD_MCA;
+ features |= BX_CPUID_STD_CMPXCHG8B;
+ }
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_VME))
+ features |= BX_CPUID_STD_VME;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_DEBUG_EXTENSIONS))
+ features |= BX_CPUID_STD_DEBUG_EXTENSIONS;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE))
+ features |= BX_CPUID_STD_PSE;
+#endif
+
+#if BX_SUPPORT_APIC
+ // if MSR_APICBASE APIC Global Enable bit has been cleared,
+ // the CPUID feature flag for the APIC is set to 0.
+ if (cpu->msr.apicbase & 0x800)
+ features |= BX_CPUID_STD_APIC; // APIC on chip
+#endif
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SYSENTER_SYSEXIT))
+ features |= BX_CPUID_STD_SYSENTER_SYSEXIT;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_CLFLUSH))
+ features |= BX_CPUID_STD_CLFLUSH;
+
+#if BX_CPU_LEVEL >= 5
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_MMX))
+ features |= BX_CPUID_STD_MMX;
+#endif
+
+#if BX_CPU_LEVEL >= 6
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_P6)) {
+ features |= BX_CPUID_STD_CMOV;
+ features |= BX_CPUID_STD_ACPI;
+ }
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAT_MTRR))
+ features |= BX_CPUID_STD_PAT | BX_CPUID_STD_MTRR;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAE))
+ features |= BX_CPUID_STD_PAE;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PGE))
+ features |= BX_CPUID_STD_GLOBAL_PAGES;
+
+ if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE36))
+ features |= BX_CPUID_STD_PSE36;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_FXSAVE_FXRSTOR))
+ features |= BX_CPUID_STD_FXSAVE_FXRSTOR;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE))
+ features |= BX_CPUID_STD_SSE;
+
+ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_CPU_SSE2))
+ features |= BX_CPUID_STD_SSE2;
+
+ if (BX_CPU_VENDOR_INTEL)
+ features |= BX_CPUID_STD_SELF_SNOOP;
+#endif
+
+#if BX_SUPPORT_SMP
+ // Intel(R) HyperThreading Technology
+ if (SIM->get_param_num(BXPN_CPU_NTHREADS)->get() > 1)
+ features |= BX_CPUID_STD_HT;
+#endif
+
+ return features;
+}
+
+/* Get CPU feature flags. Returned by CPUID function 80000001 in EDX register */
+Bit32u bx_generic_cpuid_t::get_std2_cpuid_features(void)
+{
+ // Many of the bits in EDX are the same as EAX [*] for AMD
+ // [*] [0:0] FPU on chip
+ // [*] [1:1] VME: Virtual-8086 Mode enhancements
+ // [*] [2:2] DE: Debug Extensions (I/O breakpoints)
+ // [*] [3:3] PSE: Page Size Extensions
+ // [*] [4:4] TSC: Time Stamp Counter
+ // [*] [5:5] MSR: RDMSR and WRMSR support
+ // [*] [6:6] PAE: Physical Address Extensions
+ // [*] [7:7] MCE: Machine Check Exception
+ // [*] [8:8] CXS: CMPXCHG8B instruction
+ // [*] [9:9] APIC: APIC on Chip
+ // [10:10] Reserved
+ // [11:11] SYSCALL/SYSRET support
+ // [*] [12:12] MTRR: Memory Type Range Reg
+ // [*] [13:13] PGE/PTE Global Bit
+ // [*] [14:14] MCA: Machine Check Architecture
+ // [*] [15:15] CMOV: Cond Mov/Cmp Instructions
+ // [*] [16:16] PAT: Page Attribute Table
+ // [*] [17:17] PSE-36: Physical Address Extensions
+ // [18:19] Reserved
+ // [20:20] No-Execute page protection
+ // [21:21] Reserved
+ // [22:22] AMD MMX Extensions
+ // [*] [23:23] MMX Technology
+ // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
+ // [25:25] Fast FXSAVE/FXRSTOR mode support
+ // [26:26] 1G paging support
+ // [27:27] Support RDTSCP Instruction
+ // [28:28] Reserved
+ // [29:29] Long Mode
+ // [30:30] AMD 3DNow! Extensions
+ // [31:31] AMD 3DNow! Instructions
+ Bit32u features = BX_CPU_VENDOR_INTEL ? 0 : get_std_cpuid_features();
+ features &= 0x0183F3FF;
+#if BX_SUPPORT_3DNOW
+ // only AMD is interesting in AMD MMX extensions
+ features |= BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD2_3DNOW_EXT | \
BX_CPUID_STD2_3DNOW; +#endif
+#if BX_SUPPORT_X86_64
+ features |= BX_CPUID_STD2_SYSCALL_SYSRET |
+ BX_CPUID_STD2_NX |
+ BX_CPUID_STD2_FFXSR |
+ BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE;
+ static bx_bool xlarge_pages = SIM->get_param_bool(BXPN_CPUID_1G_PAGES)->get();
+ if (xlarge_pages)
+ features |= BX_CPUID_STD2_1G_PAGES;
+#endif
+
+ return features;
+}
+
+/* Get CPU feature flags. Returned by CPUID function 80000001 in ECX register */
+Bit32u bx_generic_cpuid_t::get_ext2_cpuid_features(void)
+{
+ // ECX:
+ // [0:0] LAHF/SAHF instructions support in 64-bit mode
+ // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD)
+ // [2:2] SVM: Secure Virtual Machine (AMD)
+ // [3:3] Extended APIC Space
+ // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8
+ // [5:5] LZCNT: LZCNT instruction support
+ // [6:6] SSE4A: SSE4A Instructions support (deprecated?)
+ // [7:7] Misaligned SSE support
+ // [8:8] PREFETCHW: PREFETCHW instruction support
+ // [9:9] OSVW: OS visible workarounds (AMD)
+ // [11:10] reserved
+ // [12:12] SKINIT support
+ // [13:13] WDT: Watchdog timer support
+ // [31:14] reserved
+ Bit32u features = 0;
+
+#if BX_SUPPORT_X86_64
+ features |= BX_CPUID_EXT2_LAHF_SAHF;
+#endif
+#if BX_SUPPORT_MISALIGNED_SSE
+ features |= BX_CPUID_EXT2_MISALIGNED_SSE;
+#endif
+
+ return features;
+}
+
+void bx_generic_cpuid_t::dump_cpuid(void)
+{
+ struct cpuid_function_t leaf;
+
+ BX_CPU_THIS_PTR cpuid->get_cpuid_leaf(0x00000000, 0x00000000, &leaf);
+ BX_INFO(("CPUID[0x00000000]: %08x %08x %08x %08x", leaf.eax, leaf.ebx, leaf.ecx, \
leaf.edx)); + Bit32u max_std_function = leaf.eax, n;
+
+ if (max_std_function > 0) {
+ for (n=1; n<=max_std_function;n++) {
+ BX_CPU_THIS_PTR cpuid->get_cpuid_leaf(n, 0x00000000, &leaf);
+ BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, \
leaf.ecx, leaf.edx)); + }
+ }
+
+#if BX_CPU_LEVEL >= 6
+ BX_CPU_THIS_PTR cpuid->get_cpuid_leaf(0x80000000, 0x00000000, &leaf);
+ BX_INFO(("CPUID[0x80000000]: %08x %08x %08x %08x", leaf.eax, leaf.ebx, leaf.ecx, \
leaf.edx)); + Bit32u max_ext_function = leaf.eax;
+
+ if (max_ext_function > 0) {
+ for (n=0x80000001; n<=max_ext_function;n++) {
+ BX_CPU_THIS_PTR cpuid->get_cpuid_leaf(n, 0x00000000, &leaf);
+ BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, \
leaf.ecx, leaf.edx)); + }
+ }
+#endif
+}
+
+bx_cpuid_t *create_bx_generic_cpuid(BX_CPU_C *cpu) { return new \
bx_generic_cpuid_t(cpu); }
Modified: trunk/bochs/cpu/init.cc
===================================================================
--- trunk/bochs/cpu/init.cc 2011-07-27 14:16:51 UTC (rev 10497)
+++ trunk/bochs/cpu/init.cc 2011-07-28 16:17:42 UTC (rev 10498)
@@ -27,7 +27,7 @@
#include "param_names.h"
-BX_CPU_C::BX_CPU_C(unsigned id): bx_cpuid(id)
+BX_CPU_C::BX_CPU_C(unsigned id): bx_cpuid(id), cpuid(NULL)
#if BX_SUPPORT_APIC
,lapic (this, id)
#endif
@@ -38,6 +38,9 @@
char buffer[16];
sprintf(buffer, "CPU%x", bx_cpuid);
put(buffer);
+
+ isa_extensions_bitmask = BX_SUPPORT_FPU ? BX_CPU_X87 : 0;
+ cpu_extensions_bitmask = 0;
}
#if BX_WITH_WX
@@ -142,14 +145,18 @@
#endif
+#include "generic_cpuid.h"
+
// BX_CPU_C constructor
void BX_CPU_C::initialize(void)
{
BX_CPU_THIS_PTR set_INTR(0);
- init_cpu_features_bitmask();
- init_isa_features_bitmask();
+ BX_CPU_THIS_PTR cpuid = create_bx_generic_cpuid(this);
+ BX_CPU_THIS_PTR isa_extensions_bitmask = cpuid->get_isa_extensions_bitmask();
+ BX_CPU_THIS_PTR cpu_extensions_bitmask = cpuid->get_cpu_extensions_bitmask();
+
init_FetchDecodeTables(); // must be called after init_isa_features_bitmask()
#if BX_CONFIGURE_MSRS
@@ -698,6 +705,10 @@
BX_CPU_C::~BX_CPU_C()
{
+#if BX_CPU_LEVEL >= 4
+ delete cpuid;
+#endif
+
BX_INSTR_EXIT(BX_CPU_ID);
BX_DEBUG(("Exit."));
}
@@ -716,7 +727,7 @@
for (n=0;n<BX_GENERAL_REGISTERS;n++)
BX_WRITE_32BIT_REGZ(n, 0);
- BX_WRITE_32BIT_REGZ(BX_32BIT_REG_EDX, get_cpu_version_information());
+//BX_WRITE_32BIT_REGZ(BX_32BIT_REG_EDX, get_cpu_version_information());
// initialize NIL register
BX_WRITE_32BIT_REGZ(BX_NIL_REGISTER, 0);
@@ -1037,13 +1048,12 @@
}
#endif
- // initialize CPUID values - make sure apicbase already initialized
+ updateFetchModeMask();
+
#if BX_CPU_LEVEL >= 4
- set_cpuid_defaults();
+ BX_CPU_THIS_PTR cpuid->dump_cpuid();
#endif
- updateFetchModeMask();
-
BX_INSTR_RESET(BX_CPU_ID, source);
}
Modified: trunk/bochs/cpu/msr.cc
===================================================================
--- trunk/bochs/cpu/msr.cc 2011-07-27 14:16:51 UTC (rev 10497)
+++ trunk/bochs/cpu/msr.cc 2011-07-28 16:17:42 UTC (rev 10498)
@@ -703,12 +703,6 @@
BX_CPU_THIS_PTR lapic.set_base(BX_CPU_THIS_PTR msr.apicbase);
// TLB flush is required for emulation correctness
TLB_flush(); // don't care about performance of apic relocation
-
- if ((val32_lo & 0x800) == 0) {
- // APIC global enable bit cleared, clear APIC on chip CPUID feature flag
- BX_CPU_THIS_PTR cpuid_std_function[0x1].edx &= ~BX_CPUID_STD_APIC;
- BX_CPU_THIS_PTR cpuid_ext_function[0x1].edx &= ~BX_CPUID_STD_APIC;
- }
}
else {
BX_INFO(("WRMSR: MSR_APICBASE APIC global enable bit cleared !"));
Modified: trunk/bochs/cpu/proc_ctrl.cc
===================================================================
--- trunk/bochs/cpu/proc_ctrl.cc 2011-07-27 14:16:51 UTC (rev 10497)
+++ trunk/bochs/cpu/proc_ctrl.cc 2011-07-28 16:17:42 UTC (rev 10498)
@@ -60,6 +60,29 @@
BX_NEXT_INSTR(i);
}
+BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CPUID(bxInstruction_c *i)
+{
+#if BX_CPU_LEVEL >= 4
+
+#if BX_SUPPORT_VMX
+ if (BX_CPU_THIS_PTR in_vmx_guest) {
+ BX_ERROR(("VMEXIT: CPUID in VMX non-root operation"));
+ VMexit(i, VMX_VMEXIT_CPUID, 0);
+ }
+#endif
+
+ struct cpuid_function_t leaf;
+ BX_CPU_THIS_PTR cpuid->get_cpuid_leaf(EAX, ECX, &leaf);
+
+ RAX = leaf.eax;
+ RBX = leaf.ebx;
+ RCX = leaf.ecx;
+ RDX = leaf.edx;
+#endif
+
+ BX_NEXT_INSTR(i);
+}
+
//
// The shutdown state is very similar to the state following the exection
// if HLT instruction. In this mode the processor stops executing
This was sent by the SourceForge.net collaborative development platform, the world's \
largest Open Source development site.
------------------------------------------------------------------------------
Got Input? Slashdot Needs You.
Take our quick survey online. Come on, we don't ask for help often.
Plus, you'll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey
_______________________________________________
Bochs-cvs mailing list
Bochs-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bochs-cvs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic