mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 01:22:04 +00:00
470 lines
26 KiB
C
470 lines
26 KiB
C
|
/*
|
||
|
* Copyright 2008 Veselin Georgiev,
|
||
|
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
*
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
#include "libcpuid.h"
|
||
|
#include "recog_amd.h"
|
||
|
#include "libcpuid_util.h"
|
||
|
|
||
|
enum _amd_code_t {
|
||
|
NA,
|
||
|
NO_CODE,
|
||
|
OPTERON_GENERIC,
|
||
|
OPTERON_800,
|
||
|
ATHLON_XP,
|
||
|
ATHLON_XP_M,
|
||
|
ATHLON_XP_M_LV,
|
||
|
ATHLON,
|
||
|
ATHLON_MP,
|
||
|
MOBILE_ATHLON64,
|
||
|
ATHLON_FX,
|
||
|
DURON,
|
||
|
DURON_MP,
|
||
|
MOBILE_DURON,
|
||
|
MOBILE_SEMPRON,
|
||
|
OPTERON_SINGLE,
|
||
|
OPTERON_DUALCORE,
|
||
|
OPTERON_800_DUALCORE,
|
||
|
MOBILE_TURION,
|
||
|
ATHLON_64,
|
||
|
ATHLON_64_FX,
|
||
|
TURION_64,
|
||
|
TURION_X2,
|
||
|
SEMPRON,
|
||
|
M_SEMPRON,
|
||
|
SEMPRON_DUALCORE,
|
||
|
PHENOM,
|
||
|
PHENOM2,
|
||
|
ATHLON_64_X2,
|
||
|
ATHLON_64_X3,
|
||
|
ATHLON_64_X4,
|
||
|
FUSION_C,
|
||
|
FUSION_E,
|
||
|
FUSION_EA,
|
||
|
FUSION_Z,
|
||
|
};
|
||
|
typedef enum _amd_code_t amd_code_t;
|
||
|
|
||
|
const struct match_entry_t cpudb_amd[] = {
|
||
|
{ -1, -1, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown AMD CPU" },
|
||
|
|
||
|
/* 486 and the likes */
|
||
|
{ 4, -1, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown AMD 486" },
|
||
|
{ 4, 3, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "AMD 486DX2" },
|
||
|
{ 4, 7, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "AMD 486DX2WB" },
|
||
|
{ 4, 8, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "AMD 486DX4" },
|
||
|
{ 4, 9, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "AMD 486DX4WB" },
|
||
|
|
||
|
/* Pentia clones */
|
||
|
{ 5, -1, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown AMD 586" },
|
||
|
{ 5, 0, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K5" },
|
||
|
{ 5, 1, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K5" },
|
||
|
{ 5, 2, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K5" },
|
||
|
{ 5, 3, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K5" },
|
||
|
|
||
|
/* The K6 */
|
||
|
{ 5, 6, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K6" },
|
||
|
{ 5, 7, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K6" },
|
||
|
|
||
|
{ 5, 8, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K6-2" },
|
||
|
{ 5, 9, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K6-III" },
|
||
|
{ 5, 10, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown K6" },
|
||
|
{ 5, 11, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown K6" },
|
||
|
{ 5, 12, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown K6" },
|
||
|
{ 5, 13, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "K6-2+" },
|
||
|
|
||
|
/* Athlon et al. */
|
||
|
{ 6, 1, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Athlon (Slot-A)" },
|
||
|
{ 6, 2, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Athlon (Slot-A)" },
|
||
|
{ 6, 3, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Duron (Spitfire)" },
|
||
|
{ 6, 4, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Athlon (ThunderBird)" },
|
||
|
|
||
|
{ 6, 6, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown Athlon" },
|
||
|
{ 6, 6, -1, -1, -1, 1, -1, -1, ATHLON , 0, "Athlon (Palomino)" },
|
||
|
{ 6, 6, -1, -1, -1, 1, -1, -1, ATHLON_MP , 0, "Athlon MP (Palomino)" },
|
||
|
{ 6, 6, -1, -1, -1, 1, -1, -1, DURON , 0, "Duron (Palomino)" },
|
||
|
{ 6, 6, -1, -1, -1, 1, -1, -1, ATHLON_XP , 0, "Athlon XP" },
|
||
|
|
||
|
{ 6, 7, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Unknown Athlon XP" },
|
||
|
{ 6, 7, -1, -1, -1, 1, -1, -1, DURON , 0, "Duron (Morgan)" },
|
||
|
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Athlon XP" },
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, ATHLON , 0, "Athlon XP (Thoroughbred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, ATHLON_XP , 0, "Athlon XP (Thoroughbred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, DURON , 0, "Duron (Applebred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, SEMPRON , 0, "Sempron (Thoroughbred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, 128, -1, SEMPRON , 0, "Sempron (Thoroughbred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, 256, -1, SEMPRON , 0, "Sempron (Thoroughbred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, ATHLON_MP , 0, "Athlon MP (Thoroughbred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, ATHLON_XP_M , 0, "Mobile Athlon (T-Bred)" },
|
||
|
{ 6, 8, -1, -1, -1, 1, -1, -1, ATHLON_XP_M_LV , 0, "Mobile Athlon (T-Bred)" },
|
||
|
|
||
|
{ 6, 10, -1, -1, -1, 1, -1, -1, NO_CODE , 0, "Athlon XP (Barton)" },
|
||
|
{ 6, 10, -1, -1, -1, 1, 512, -1, ATHLON_XP , 0, "Athlon XP (Barton)" },
|
||
|
{ 6, 10, -1, -1, -1, 1, 512, -1, SEMPRON , 0, "Sempron (Barton)" },
|
||
|
{ 6, 10, -1, -1, -1, 1, 256, -1, SEMPRON , 0, "Sempron (Thorton)" },
|
||
|
{ 6, 10, -1, -1, -1, 1, 256, -1, ATHLON_XP , 0, "Athlon XP (Thorton)" },
|
||
|
{ 6, 10, -1, -1, -1, 1, -1, -1, ATHLON_MP , 0, "Athlon MP (Barton)" },
|
||
|
{ 6, 10, -1, -1, -1, 1, -1, -1, ATHLON_XP_M , 0, "Mobile Athlon (Barton)" },
|
||
|
{ 6, 10, -1, -1, -1, 1, -1, -1, ATHLON_XP_M_LV , 0, "Mobile Athlon (Barton)" },
|
||
|
|
||
|
/* K8 Architecture */
|
||
|
{ 15, -1, -1, 15, -1, 1, -1, -1, NO_CODE , 0, "Unknown K8" },
|
||
|
{ 15, -1, -1, 16, -1, 1, -1, -1, NO_CODE , 0, "Unknown K9" },
|
||
|
|
||
|
{ 15, -1, -1, 15, -1, 1, -1, -1, NO_CODE , 0, "Unknown A64" },
|
||
|
{ 15, -1, -1, 15, -1, 1, -1, -1, OPTERON_SINGLE , 0, "Opteron" },
|
||
|
{ 15, -1, -1, 15, -1, 2, -1, -1, OPTERON_DUALCORE , 0, "Opteron (Dual Core)" },
|
||
|
{ 15, 3, -1, 15, -1, 1, -1, -1, OPTERON_SINGLE , 0, "Opteron" },
|
||
|
{ 15, 3, -1, 15, -1, 2, -1, -1, OPTERON_DUALCORE , 0, "Opteron (Dual Core)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (512K)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, 1024, -1, ATHLON_64 , 0, "Athlon 64 (1024K)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, -1, -1, ATHLON_FX , 0, "Athlon FX" },
|
||
|
{ 15, -1, -1, 15, -1, 1, -1, -1, ATHLON_64_FX , 0, "Athlon 64 FX" },
|
||
|
{ 15, -1, -1, 15, -1, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (512K)" },
|
||
|
{ 15, -1, -1, 15, -1, 2, 1024, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (1024K)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, 512, -1, TURION_64 , 0, "Turion 64 (512K)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, 1024, -1, TURION_64 , 0, "Turion 64 (1024K)" },
|
||
|
{ 15, -1, -1, 15, -1, 2, 512, -1, TURION_X2 , 0, "Turion 64 X2 (512K)" },
|
||
|
{ 15, -1, -1, 15, -1, 2, 1024, -1, TURION_X2 , 0, "Turion 64 X2 (1024K)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, 128, -1, SEMPRON , 0, "A64 Sempron (128K)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, 256, -1, SEMPRON , 0, "A64 Sempron (256K)" },
|
||
|
{ 15, -1, -1, 15, -1, 1, 512, -1, SEMPRON , 0, "A64 Sempron (512K)" },
|
||
|
{ 15, -1, -1, 15, 0x4f, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (Orleans/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x5f, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (Orleans/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x2f, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (Venice/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x2c, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (Venice/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x1f, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (Winchester/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x0c, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (Newcastle/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x27, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (San Diego/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x37, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (San Diego/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x04, 1, 512, -1, ATHLON_64 , 0, "Athlon 64 (ClawHammer/512K)" },
|
||
|
|
||
|
{ 15, -1, -1, 15, 0x5f, 1, 1024, -1, ATHLON_64 , 0, "Athlon 64 (Orleans/1024K)" },
|
||
|
{ 15, -1, -1, 15, 0x27, 1, 1024, -1, ATHLON_64 , 0, "Athlon 64 (San Diego/1024K)" },
|
||
|
{ 15, -1, -1, 15, 0x04, 1, 1024, -1, ATHLON_64 , 0, "Athlon 64 (ClawHammer/1024K)" },
|
||
|
|
||
|
{ 15, -1, -1, 15, 0x4b, 2, 256, -1, SEMPRON_DUALCORE , 0, "Athlon 64 X2 (Windsor/256K)" },
|
||
|
|
||
|
{ 15, -1, -1, 15, 0x23, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (Toledo/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x4b, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (Windsor/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x43, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (Windsor/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x6b, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (Brisbane/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x2b, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (Manchester/512K)"},
|
||
|
|
||
|
{ 15, -1, -1, 15, 0x23, 2, 1024, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (Toledo/1024K)" },
|
||
|
{ 15, -1, -1, 15, 0x43, 2, 1024, -1, ATHLON_64_X2 , 0, "Athlon 64 X2 (Windsor/1024K)" },
|
||
|
|
||
|
{ 15, -1, -1, 15, 0x08, 1, 128, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Dublin/128K)"},
|
||
|
{ 15, -1, -1, 15, 0x08, 1, 256, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Dublin/256K)"},
|
||
|
{ 15, -1, -1, 15, 0x0c, 1, 256, -1, SEMPRON , 0, "Sempron 64 (Paris)" },
|
||
|
{ 15, -1, -1, 15, 0x1c, 1, 128, -1, SEMPRON , 0, "Sempron 64 (Palermo/128K)" },
|
||
|
{ 15, -1, -1, 15, 0x1c, 1, 256, -1, SEMPRON , 0, "Sempron 64 (Palermo/256K)" },
|
||
|
{ 15, -1, -1, 15, 0x1c, 1, 128, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Sonora/128K)"},
|
||
|
{ 15, -1, -1, 15, 0x1c, 1, 256, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Sonora/256K)"},
|
||
|
{ 15, -1, -1, 15, 0x2c, 1, 128, -1, SEMPRON , 0, "Sempron 64 (Palermo/128K)" },
|
||
|
{ 15, -1, -1, 15, 0x2c, 1, 256, -1, SEMPRON , 0, "Sempron 64 (Palermo/256K)" },
|
||
|
{ 15, -1, -1, 15, 0x2c, 1, 128, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Albany/128K)"},
|
||
|
{ 15, -1, -1, 15, 0x2c, 1, 256, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Albany/256K)"},
|
||
|
{ 15, -1, -1, 15, 0x2f, 1, 128, -1, SEMPRON , 0, "Sempron 64 (Palermo/128K)" },
|
||
|
{ 15, -1, -1, 15, 0x2f, 1, 256, -1, SEMPRON , 0, "Sempron 64 (Palermo/256K)" },
|
||
|
{ 15, -1, -1, 15, 0x4f, 1, 128, -1, SEMPRON , 0, "Sempron 64 (Manila/128K)" },
|
||
|
{ 15, -1, -1, 15, 0x4f, 1, 256, -1, SEMPRON , 0, "Sempron 64 (Manila/256K)" },
|
||
|
{ 15, -1, -1, 15, 0x5f, 1, 128, -1, SEMPRON , 0, "Sempron 64 (Manila/128K)" },
|
||
|
{ 15, -1, -1, 15, 0x5f, 1, 256, -1, SEMPRON , 0, "Sempron 64 (Manila/256K)" },
|
||
|
{ 15, -1, -1, 15, 0x6b, 2, 256, -1, SEMPRON , 0, "Sempron 64 Dual (Sherman/256K)"},
|
||
|
{ 15, -1, -1, 15, 0x6b, 2, 512, -1, SEMPRON , 0, "Sempron 64 Dual (Sherman/512K)"},
|
||
|
{ 15, -1, -1, 15, 0x7f, 1, 256, -1, SEMPRON , 0, "Sempron 64 (Sparta/256K)" },
|
||
|
{ 15, -1, -1, 15, 0x7f, 1, 512, -1, SEMPRON , 0, "Sempron 64 (Sparta/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x4c, 1, 256, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Keene/256K)"},
|
||
|
{ 15, -1, -1, 15, 0x4c, 1, 512, -1, M_SEMPRON , 0, "Mobile Sempron 64 (Keene/512K)"},
|
||
|
{ 15, -1, -1, 15, -1, 2, -1, -1, SEMPRON_DUALCORE , 0, "Sempron Dual Core" },
|
||
|
|
||
|
{ 15, -1, -1, 15, 0x24, 1, 512, -1, TURION_64 , 0, "Turion 64 (Lancaster/512K)" },
|
||
|
{ 15, -1, -1, 15, 0x24, 1, 1024, -1, TURION_64 , 0, "Turion 64 (Lancaster/1024K)" },
|
||
|
{ 15, -1, -1, 15, 0x48, 2, 256, -1, TURION_X2 , 0, "Turion X2 (Taylor)" },
|
||
|
{ 15, -1, -1, 15, 0x48, 2, 512, -1, TURION_X2 , 0, "Turion X2 (Trinidad)" },
|
||
|
{ 15, -1, -1, 15, 0x4c, 1, 512, -1, TURION_64 , 0, "Turion 64 (Richmond)" },
|
||
|
{ 15, -1, -1, 15, 0x68, 2, 256, -1, TURION_X2 , 0, "Turion X2 (Tyler/256K)" },
|
||
|
{ 15, -1, -1, 15, 0x68, 2, 512, -1, TURION_X2 , 0, "Turion X2 (Tyler/512K)" },
|
||
|
{ 15, -1, -1, 17, 3, 2, 512, -1, TURION_X2 , 0, "Turion X2 (Griffin/512K)" },
|
||
|
{ 15, -1, -1, 17, 3, 2, 1024, -1, TURION_X2 , 0, "Turion X2 (Griffin/1024K)" },
|
||
|
|
||
|
/* K9 Architecture */
|
||
|
{ 15, -1, -1, 16, -1, 1, -1, -1, PHENOM , 0, "Unknown AMD Phenom" },
|
||
|
{ 15, 2, -1, 16, -1, 1, -1, -1, PHENOM , 0, "Phenom" },
|
||
|
{ 15, 2, -1, 16, -1, 3, -1, -1, PHENOM , 0, "Phenom X3 (Toliman)" },
|
||
|
{ 15, 2, -1, 16, -1, 4, -1, -1, PHENOM , 0, "Phenom X4 (Agena)" },
|
||
|
{ 15, 2, -1, 16, -1, 3, 512, -1, PHENOM , 0, "Phenom X3 (Toliman/256K)" },
|
||
|
{ 15, 2, -1, 16, -1, 3, 512, -1, PHENOM , 0, "Phenom X3 (Toliman/512K)" },
|
||
|
{ 15, 2, -1, 16, -1, 4, 128, -1, PHENOM , 0, "Phenom X4 (Agena/128K)" },
|
||
|
{ 15, 2, -1, 16, -1, 4, 256, -1, PHENOM , 0, "Phenom X4 (Agena/256K)" },
|
||
|
{ 15, 2, -1, 16, -1, 4, 512, -1, PHENOM , 0, "Phenom X4 (Agena/512K)" },
|
||
|
{ 15, 2, -1, 16, -1, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon X2 (Kuma)" },
|
||
|
/* Phenom II derivates: */
|
||
|
{ 15, 4, -1, 16, -1, 4, -1, -1, NO_CODE , 0, "Phenom (Deneb-based)" },
|
||
|
{ 15, 4, -1, 16, -1, 1, 1024, -1, SEMPRON , 0, "Sempron (Sargas)" },
|
||
|
{ 15, 4, -1, 16, -1, 2, 512, -1, PHENOM2 , 0, "Phenom II X2 (Callisto)" },
|
||
|
{ 15, 4, -1, 16, -1, 3, 512, -1, PHENOM2 , 0, "Phenom II X3 (Heka)" },
|
||
|
{ 15, 4, -1, 16, -1, 4, 512, -1, PHENOM2 , 0, "Phenom II X4" },
|
||
|
{ 15, 4, -1, 16, 4, 4, 512, -1, PHENOM2 , 0, "Phenom II X4 (Deneb)" },
|
||
|
{ 15, 5, -1, 16, 5, 4, 512, -1, PHENOM2 , 0, "Phenom II X4 (Deneb)" },
|
||
|
{ 15, 4, -1, 16, 10, 4, 512, -1, PHENOM2 , 0, "Phenom II X4 (Zosma)" },
|
||
|
{ 15, 4, -1, 16, 10, 6, 512, -1, PHENOM2 , 0, "Phenom II X6 (Thuban)" },
|
||
|
|
||
|
{ 15, 4, -1, 16, -1, 2, 1024, -1, ATHLON_64_X2 , 0, "Athlon II X2 (Regor)" },
|
||
|
{ 15, 4, -1, 16, -1, 2, 512, -1, ATHLON_64_X2 , 0, "Athlon II X2 (Regor)" },
|
||
|
{ 15, 5, -1, 16, 5, 3, 512, -1, ATHLON_64_X3 , 0, "Athlon II X3 (Rana)" },
|
||
|
{ 15, 5, -1, 16, 5, 4, 512, -1, ATHLON_64_X4 , 0, "Athlon II X4 (Propus)" },
|
||
|
/* 2011 CPUs with AMD fusion: */
|
||
|
{ 15, -1, -1, 20, 1, 1, 512, -1, FUSION_C , 0, "Brazos Ontario" },
|
||
|
{ 15, -1, -1, 20, 1, 2, 512, -1, FUSION_C , 0, "Brazos Ontario (Dual-core)" },
|
||
|
{ 15, -1, -1, 20, 1, 1, 512, -1, FUSION_E , 0, "Brazos Zacate" },
|
||
|
{ 15, -1, -1, 20, 1, 2, 512, -1, FUSION_E , 0, "Brazos Zacate (Dual-core)" },
|
||
|
{ 15, -1, -1, 20, 1, 1, 512, -1, FUSION_Z , 0, "Brazos Desna" },
|
||
|
{ 15, -1, -1, 18, 1, 2, 512, -1, FUSION_EA , 0, "Llano X2" },
|
||
|
{ 15, -1, -1, 18, 1, 2, 1024, -1, FUSION_EA , 0, "Llano X2" },
|
||
|
{ 15, -1, -1, 18, 1, 3, 1024, -1, FUSION_EA , 0, "Llano X3" },
|
||
|
{ 15, -1, -1, 18, 1, 4, 1024, -1, FUSION_EA , 0, "Llano X4" },
|
||
|
|
||
|
/* Newer Opterons: */
|
||
|
{ 15, 9, -1, 16, 9, 8, -1, -1, OPTERON_GENERIC , 0, "Magny-Cours Opteron" },
|
||
|
|
||
|
/* Bulldozer CPUs: */
|
||
|
{ 15, -1, -1, 21, 1, 4, 2048, -1, NO_CODE , 0, "Bulldozer X2" },
|
||
|
{ 15, -1, -1, 21, 1, 6, 2048, -1, NO_CODE , 0, "Bulldozer X3" },
|
||
|
{ 15, -1, -1, 21, 1, 8, 2048, -1, NO_CODE , 0, "Bulldozer X4" },
|
||
|
{ 15, -1, -1, 21, 2, 4, 2048, -1, NO_CODE , 0, "Vishera X2" },
|
||
|
{ 15, -1, -1, 21, 2, 6, 2048, -1, NO_CODE , 0, "Vishera X3" },
|
||
|
{ 15, -1, -1, 21, 2, 8, 2048, -1, NO_CODE , 0, "Vishera X4" },
|
||
|
};
|
||
|
|
||
|
|
||
|
static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||
|
{
|
||
|
const struct feature_map_t matchtable_edx81[] = {
|
||
|
{ 20, CPU_FEATURE_NX },
|
||
|
{ 22, CPU_FEATURE_MMXEXT },
|
||
|
{ 25, CPU_FEATURE_FXSR_OPT },
|
||
|
{ 30, CPU_FEATURE_3DNOWEXT },
|
||
|
{ 31, CPU_FEATURE_3DNOW },
|
||
|
};
|
||
|
const struct feature_map_t matchtable_ecx81[] = {
|
||
|
{ 1, CPU_FEATURE_CMP_LEGACY },
|
||
|
{ 2, CPU_FEATURE_SVM },
|
||
|
{ 5, CPU_FEATURE_ABM },
|
||
|
{ 6, CPU_FEATURE_SSE4A },
|
||
|
{ 7, CPU_FEATURE_MISALIGNSSE },
|
||
|
{ 8, CPU_FEATURE_3DNOWPREFETCH },
|
||
|
{ 9, CPU_FEATURE_OSVW },
|
||
|
{ 10, CPU_FEATURE_IBS },
|
||
|
{ 11, CPU_FEATURE_XOP },
|
||
|
{ 12, CPU_FEATURE_SKINIT },
|
||
|
{ 13, CPU_FEATURE_WDT },
|
||
|
{ 16, CPU_FEATURE_FMA4 },
|
||
|
};
|
||
|
const struct feature_map_t matchtable_edx87[] = {
|
||
|
{ 0, CPU_FEATURE_TS },
|
||
|
{ 1, CPU_FEATURE_FID },
|
||
|
{ 2, CPU_FEATURE_VID },
|
||
|
{ 3, CPU_FEATURE_TTP },
|
||
|
{ 4, CPU_FEATURE_TM_AMD },
|
||
|
{ 5, CPU_FEATURE_STC },
|
||
|
{ 6, CPU_FEATURE_100MHZSTEPS },
|
||
|
{ 7, CPU_FEATURE_HWPSTATE },
|
||
|
/* id 8 is handled in common */
|
||
|
{ 9, CPU_FEATURE_CPB },
|
||
|
{ 10, CPU_FEATURE_APERFMPERF },
|
||
|
{ 11, CPU_FEATURE_PFI },
|
||
|
{ 12, CPU_FEATURE_PA },
|
||
|
};
|
||
|
if (raw->ext_cpuid[0][0] >= 0x80000001) {
|
||
|
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||
|
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
|
||
|
}
|
||
|
if (raw->ext_cpuid[0][0] >= 0x80000001)
|
||
|
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
|
||
|
if (raw->ext_cpuid[0][0] >= 0x8000001a) {
|
||
|
/* We have the extended info about SSE unit size */
|
||
|
data->detection_hints[CPU_HINT_SSE_SIZE_AUTH] = 1;
|
||
|
data->sse_size = (raw->ext_cpuid[0x1a][0] & 1) ? 128 : 64;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||
|
{
|
||
|
int l3_result;
|
||
|
const int assoc_table[16] = {
|
||
|
0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 92, 128, 255
|
||
|
};
|
||
|
unsigned n = raw->ext_cpuid[0][0];
|
||
|
|
||
|
if (n >= 0x80000005) {
|
||
|
data->l1_data_cache = (raw->ext_cpuid[5][2] >> 24) & 0xff;
|
||
|
data->l1_assoc = (raw->ext_cpuid[5][2] >> 16) & 0xff;
|
||
|
data->l1_cacheline = (raw->ext_cpuid[5][2]) & 0xff;
|
||
|
data->l1_instruction_cache = (raw->ext_cpuid[5][3] >> 24) & 0xff;
|
||
|
}
|
||
|
if (n >= 0x80000006) {
|
||
|
data->l2_cache = (raw->ext_cpuid[6][2] >> 16) & 0xffff;
|
||
|
data->l2_assoc = assoc_table[(raw->ext_cpuid[6][2] >> 12) & 0xf];
|
||
|
data->l2_cacheline = (raw->ext_cpuid[6][2]) & 0xff;
|
||
|
|
||
|
l3_result = (raw->ext_cpuid[6][3] >> 18);
|
||
|
if (l3_result > 0) {
|
||
|
l3_result = 512 * l3_result; /* AMD spec says it's a range,
|
||
|
but we take the lower bound */
|
||
|
data->l3_cache = l3_result;
|
||
|
data->l3_assoc = assoc_table[(raw->ext_cpuid[6][3] >> 12) & 0xf];
|
||
|
data->l3_cacheline = (raw->ext_cpuid[6][3]) & 0xff;
|
||
|
} else {
|
||
|
data->l3_cache = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void decode_amd_number_of_cores(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||
|
{
|
||
|
int logical_cpus = -1, num_cores = -1;
|
||
|
|
||
|
if (raw->basic_cpuid[0][0] >= 1) {
|
||
|
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
|
||
|
if (raw->ext_cpuid[0][0] >= 8) {
|
||
|
num_cores = 1 + (raw->ext_cpuid[8][2] & 0xff);
|
||
|
}
|
||
|
}
|
||
|
if (data->flags[CPU_FEATURE_HT]) {
|
||
|
if (num_cores > 1) {
|
||
|
data->num_cores = num_cores;
|
||
|
data->num_logical_cpus = logical_cpus;
|
||
|
} else {
|
||
|
data->num_cores = 1;
|
||
|
data->num_logical_cpus = (logical_cpus >= 2 ? logical_cpus : 2);
|
||
|
}
|
||
|
} else {
|
||
|
data->num_cores = data->num_logical_cpus = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int amd_has_turion_modelname(const char *bs)
|
||
|
{
|
||
|
/* We search for something like TL-60. Ahh, I miss regexes...*/
|
||
|
int i, l, k;
|
||
|
char code[3] = {0};
|
||
|
const char* codes[] = { "ML", "MT", "MK", "TK", "TL", "RM", "ZM", "" };
|
||
|
l = (int) strlen(bs);
|
||
|
for (i = 3; i < l - 2; i++) {
|
||
|
if (bs[i] == '-' &&
|
||
|
isupper(bs[i-1]) && isupper(bs[i-2]) && !isupper(bs[i-3]) &&
|
||
|
isdigit(bs[i+1]) && isdigit(bs[i+2]) && !isdigit(bs[i+3]))
|
||
|
{
|
||
|
code[0] = bs[i-2];
|
||
|
code[1] = bs[i-1];
|
||
|
for (k = 0; codes[k][0]; k++)
|
||
|
if (!strcmp(codes[k], code)) return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static amd_code_t decode_amd_codename_part1(const char *bs)
|
||
|
{
|
||
|
int is_dual = 0, is_quad = 0, is_tri = 0;
|
||
|
if (strstr(bs, "Dual Core") ||
|
||
|
strstr(bs, "Dual-Core") ||
|
||
|
strstr(bs, " X2 "))
|
||
|
is_dual = 1;
|
||
|
if (strstr(bs, " X4 ")) is_quad = 1;
|
||
|
if (strstr(bs, " X3 ")) is_tri = 1;
|
||
|
if (strstr(bs, "Opteron")) {
|
||
|
return is_dual ? OPTERON_DUALCORE : OPTERON_SINGLE;
|
||
|
}
|
||
|
if (strstr(bs, "Phenom")) {
|
||
|
if (strstr(bs, "II")) return PHENOM2;
|
||
|
else return PHENOM;
|
||
|
}
|
||
|
if (amd_has_turion_modelname(bs)) {
|
||
|
return is_dual ? TURION_X2 : TURION_64;
|
||
|
}
|
||
|
if (strstr(bs, "Athlon(tm) 64 FX")) return ATHLON_64_FX;
|
||
|
if (strstr(bs, "Athlon(tm) FX")) return ATHLON_FX;
|
||
|
if (strstr(bs, "Athlon(tm) 64") || strstr(bs, "Athlon(tm) II X") || match_pattern(bs, "Athlon(tm) X#")) {
|
||
|
if (is_quad) return ATHLON_64_X4;
|
||
|
if (is_dual) return ATHLON_64_X2;
|
||
|
if (is_tri) return ATHLON_64_X3;
|
||
|
return ATHLON_64;
|
||
|
}
|
||
|
if (strstr(bs, "Turion")) {
|
||
|
return is_dual ? TURION_X2 : TURION_64;
|
||
|
}
|
||
|
|
||
|
if (strstr(bs, "mobile") || strstr(bs, "Mobile")) {
|
||
|
if (strstr(bs, "Athlon(tm) XP-M (LV)")) return ATHLON_XP_M_LV;
|
||
|
if (strstr(bs, "Athlon(tm) XP")) return ATHLON_XP_M;
|
||
|
if (strstr(bs, "Sempron(tm)")) return M_SEMPRON;
|
||
|
if (strstr(bs, "Athlon")) return MOBILE_ATHLON64;
|
||
|
if (strstr(bs, "Duron")) return MOBILE_DURON;
|
||
|
|
||
|
} else {
|
||
|
if (strstr(bs, "Athlon(tm) XP")) return ATHLON_XP;
|
||
|
if (strstr(bs, "Athlon(tm) MP")) return ATHLON_MP;
|
||
|
if (strstr(bs, "Sempron(tm)")) return SEMPRON;
|
||
|
if (strstr(bs, "Duron")) return DURON;
|
||
|
if (strstr(bs, "Athlon")) return ATHLON;
|
||
|
}
|
||
|
if (match_pattern(bs, "C-##")) return FUSION_C;
|
||
|
if (match_pattern(bs, "E-###")) return FUSION_E;
|
||
|
if (match_pattern(bs, "Z-##")) return FUSION_Z;
|
||
|
if (match_pattern(bs, "E#-####") || match_pattern(bs, "A#-####")) return FUSION_EA;
|
||
|
|
||
|
return NO_CODE;
|
||
|
}
|
||
|
|
||
|
static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||
|
{
|
||
|
amd_code_t code = decode_amd_codename_part1(data->brand_str);
|
||
|
|
||
|
if (code == ATHLON_64_X2 && data->l2_cache < 512)
|
||
|
code = SEMPRON_DUALCORE;
|
||
|
match_cpu_codename(cpudb_amd, COUNT_OF(cpudb_amd), data, code, 0);
|
||
|
}
|
||
|
|
||
|
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||
|
{
|
||
|
load_amd_features(raw, data);
|
||
|
decode_amd_cache_info(raw, data);
|
||
|
decode_amd_number_of_cores(raw, data);
|
||
|
decode_amd_codename(raw, data);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void cpuid_get_list_amd(struct cpu_list_t* list)
|
||
|
{
|
||
|
generic_get_cpu_list(cpudb_amd, COUNT_OF(cpudb_amd), list);
|
||
|
}
|