Bochs/bochs/cpu/cpudb/athlon64_venice.cc
Stanislav Shwartsman 9f57e70d5f Rewritten handling of supported CPUID features to be able to handle large amount of CPU extensions
Now enable support for up to 128 CPU extensions and could easily extend it more
Also reduce memory footprint for bx_ia_opcodes.h arrays
2014-08-31 18:39:18 +00:00

460 lines
14 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2011-2014 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 "athlon64_venice.h"
#define LOG_THIS cpu->
#if BX_SUPPORT_X86_64
athlon64_venice_t::athlon64_venice_t(BX_CPU_C *cpu): bx_cpuid_t(cpu)
{
if (! BX_SUPPORT_X86_64)
BX_PANIC(("You must enable x86-64 for Athlon64 configuration"));
BX_INFO(("WARNING: 3DNow! is not implemented yet !"));
static Bit8u supported_extensions[] = {
BX_ISA_X87,
BX_ISA_486,
BX_ISA_PENTIUM,
BX_ISA_MMX,
BX_ISA_3DNOW,
BX_ISA_SYSCALL_SYSRET_LEGACY,
BX_ISA_SYSENTER_SYSEXIT,
BX_ISA_P6,
BX_ISA_SSE,
BX_ISA_SSE2,
BX_ISA_SSE3,
BX_ISA_CLFLUSH,
BX_ISA_DEBUG_EXTENSIONS,
BX_ISA_VME,
BX_ISA_PSE,
BX_ISA_PAE,
BX_ISA_PGE,
#if BX_PHY_ADDRESS_LONG
BX_ISA_PSE36,
#endif
BX_ISA_MTRR,
BX_ISA_PAT,
BX_ISA_XAPIC,
BX_ISA_LONG_MODE,
BX_ISA_LM_LAHF_SAHF,
BX_ISA_NX,
BX_ISA_FFXSR,
BX_ISA_EXTENSION_LAST
};
register_cpu_extensions(supported_extensions);
}
void athlon64_venice_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const
{
static const char* brand_string = "AMD Athlon(tm) 64 Processor 3000+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
switch(function) {
case 0x8FFFFFFF:
get_cpuid_hidden_level(leaf);
return;
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(brand_string, function, leaf);
return;
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;
case 0x00000000:
get_std_cpuid_leaf_0(leaf);
return;
case 0x00000001:
get_std_cpuid_leaf_1(leaf);
return;
default:
get_reserved_leaf(leaf);
return;
}
}
// leaf 0x00000000 //
void athlon64_venice_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const
{
static const char* vendor_string = "AuthenticAMD";
// EAX: highest std function understood by CPUID
// EBX: vendor ID string
// EDX: vendor ID string
// ECX: vendor ID string
leaf->eax = 0x1;
// 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 athlon64_venice_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const
{
// 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 = 0x00020FF2;
// 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 = ((CACHE_LINE_SIZE / 8) << 8);
#if BX_SUPPORT_APIC
leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24);
#endif
// ECX: Extended Feature Flags
// * [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
leaf->ecx = BX_CPUID_EXT_SSE3;
// EDX: Standard Feature Flags
// * [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
leaf->edx = BX_CPUID_STD_X87 |
BX_CPUID_STD_VME |
BX_CPUID_STD_DEBUG_EXTENSIONS |
BX_CPUID_STD_PSE |
BX_CPUID_STD_TSC |
BX_CPUID_STD_MSR |
BX_CPUID_STD_PAE |
BX_CPUID_STD_MCE |
BX_CPUID_STD_CMPXCHG8B |
BX_CPUID_STD_SYSENTER_SYSEXIT |
BX_CPUID_STD_MTRR |
BX_CPUID_STD_GLOBAL_PAGES |
BX_CPUID_STD_MCA |
BX_CPUID_STD_CMOV |
BX_CPUID_STD_PAT |
BX_CPUID_STD_PSE36 |
BX_CPUID_STD_CLFLUSH |
BX_CPUID_STD_MMX |
BX_CPUID_STD_FXSAVE_FXRSTOR |
BX_CPUID_STD_SSE |
BX_CPUID_STD_SSE2;
#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)
leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip
#endif
}
// leaf 0x80000000 //
void athlon64_venice_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const
{
static const char* vendor_string = "AuthenticAMD";
// EAX: highest extended function understood by CPUID
// EBX: reserved
// EDX: reserved
// ECX: reserved
leaf->eax = 0x80000018;
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 0x80000001 //
void athlon64_venice_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const
{
// EAX: CPU Version Information (same as 0x00000001.EAX)
leaf->eax = 0x00020FF2;
// EBX: Brand ID
leaf->ebx = 0x00000108;
// 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
// [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
leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF;
// EDX:
// Many of the bits in EDX are the same as FN 0x00000001 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:18] Reserved
// [19: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 = BX_CPUID_STD_X87 |
BX_CPUID_STD_VME |
BX_CPUID_STD_DEBUG_EXTENSIONS |
BX_CPUID_STD_PSE |
BX_CPUID_STD_TSC |
BX_CPUID_STD_MSR |
BX_CPUID_STD_PAE |
BX_CPUID_STD_MCE |
BX_CPUID_STD_CMPXCHG8B |
BX_CPUID_STD2_SYSCALL_SYSRET |
BX_CPUID_STD_MTRR |
BX_CPUID_STD_GLOBAL_PAGES |
BX_CPUID_STD_MCA |
BX_CPUID_STD_CMOV |
BX_CPUID_STD_PAT |
BX_CPUID_STD_PSE36 |
BX_CPUID_STD2_NX |
BX_CPUID_STD2_AMD_MMX_EXT |
BX_CPUID_STD_MMX |
BX_CPUID_STD_FXSAVE_FXRSTOR |
BX_CPUID_STD2_FFXSR |
BX_CPUID_STD2_LONG_MODE |
BX_CPUID_STD2_3DNOW_EXT |
BX_CPUID_STD2_3DNOW;
#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)
leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip
#endif
}
// leaf 0x80000002 //
// leaf 0x80000003 //
// leaf 0x80000004 //
// leaf 0x80000005 //
void athlon64_venice_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const
{
// CPUID function 0x800000005 - L1 Cache and TLB Identifiers
leaf->eax = 0xFF08FF08;
leaf->ebx = 0xFF20FF20;
leaf->ecx = 0x40020140;
leaf->edx = 0x40020140;
}
// leaf 0x80000006 //
void athlon64_venice_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const
{
// CPUID function 0x800000006 - L2 Cache and TLB Identifiers
leaf->eax = 0x00000000;
leaf->ebx = 0x42004200;
leaf->ecx = 0x02008140;
leaf->edx = 0x00000000;
}
// leaf 0x80000007 //
void athlon64_venice_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const
{
// CPUID function 0x800000007 - Advanced Power Management
leaf->eax = 0;
leaf->ebx = 0;
leaf->ecx = 0;
leaf->edx = 0x0000003F;
}
// leaf 0x80000008 //
void athlon64_venice_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const
{
// 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;
}
// leaf 0x80000009 : Reserved //
// leaf 0x8000000A : SVM //
// leaf 0x8000000B - 0x80000018: Reserved //
// leaf 0x8FFFFFFF //
void athlon64_venice_t::get_cpuid_hidden_level(cpuid_function_t *leaf) const
{
static const char* magic_string = "IT'S HAMMER TIME";
memcpy(&(leaf->eax), magic_string , 4);
memcpy(&(leaf->ebx), magic_string + 4, 4);
memcpy(&(leaf->ecx), magic_string + 8, 4);
memcpy(&(leaf->edx), magic_string + 12, 4);
#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
}
void athlon64_venice_t::dump_cpuid(void) const
{
struct cpuid_function_t leaf;
unsigned n;
for (n=0; n<=1; n++) {
get_cpuid_leaf(n, 0x00000000, &leaf);
BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx));
}
for (n=0x80000000; n<=0x80000018; n++) {
get_cpuid_leaf(n, 0x00000000, &leaf);
BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx));
}
get_cpuid_leaf(0x8fffffff, 0x00000000, &leaf);
BX_INFO(("CPUID[0x8fffffff]: %08x %08x %08x %08x", leaf.eax, leaf.ebx, leaf.ecx, leaf.edx));
}
bx_cpuid_t *create_athlon64_venice_cpuid(BX_CPU_C *cpu) { return new athlon64_venice_t(cpu); }
#endif