cpuid/x86: use leaf 80000008 for AMD physical core counts
This commit is contained in:
parent
471c81c43a
commit
0df4fd4bfa
@ -42,17 +42,48 @@ cpuid_t cpuid (u32 query, u32 param = 0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
namespace {
|
||||||
|
enum vendor_t {
|
||||||
|
INTEL,
|
||||||
|
AMD,
|
||||||
|
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static constexpr
|
||||||
|
vendor_t
|
||||||
|
find_vendor (cpuid_t const &leaf0)
|
||||||
|
{
|
||||||
|
constexpr struct {
|
||||||
|
u32 b, c, d;
|
||||||
|
vendor_t vendor;
|
||||||
|
} VALUES[] = {
|
||||||
|
{ 0x68747541, 0x444d4163, 0x69746e65, AMD },
|
||||||
|
{ 0x756e6547, 0x6c65746e, 0x49656e69, INTEL },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto const &v: VALUES) {
|
||||||
|
if (v.b == leaf0.b && v.c == leaf0.c && v.d == leaf0.d)
|
||||||
|
return v.vendor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
x86::x86 ()
|
x86::x86 ()
|
||||||
{
|
{
|
||||||
const auto &[largest_function, vendor0, vendor2, vendor1] = cpuid (0);
|
auto const leaf0 = cpuid (0);
|
||||||
(void)largest_function;
|
memcpy (vendor_name.data () + 0, &leaf0.b, sizeof (leaf0.b));
|
||||||
|
memcpy (vendor_name.data () + 4, &leaf0.d, sizeof (leaf0.d));
|
||||||
|
memcpy (vendor_name.data () + 8, &leaf0.c, sizeof (leaf0.c));
|
||||||
|
|
||||||
memcpy (vendor_name.data () + 0, &vendor0, sizeof (vendor0));
|
auto const vendor = find_vendor (leaf0);
|
||||||
memcpy (vendor_name.data () + 4, &vendor1, sizeof (vendor1));
|
|
||||||
memcpy (vendor_name.data () + 8, &vendor2, sizeof (vendor2));
|
|
||||||
|
|
||||||
const bool is_amd = vendor0 == 0x68747541 && vendor1 == 0x69746e65 && vendor2 == 0x444d4163;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto features = cpuid (1);
|
auto features = cpuid (1);
|
||||||
@ -66,7 +97,10 @@ x86::x86 ()
|
|||||||
simd.sse2 = features.d & (1u << 26);
|
simd.sse2 = features.d & (1u << 26);
|
||||||
|
|
||||||
cores.hyper_threading = features.d & (1u << 28);
|
cores.hyper_threading = features.d & (1u << 28);
|
||||||
|
if (cores.hyper_threading)
|
||||||
cores.logical = from_bits (features.b, 23, 16);
|
cores.logical = from_bits (features.b, 23, 16);
|
||||||
|
else
|
||||||
|
cores.logical = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -79,16 +113,36 @@ x86::x86 ()
|
|||||||
memcpy (&product_name[0x20], &product2, sizeof (product2));
|
memcpy (&product_name[0x20], &product2, sizeof (product2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function 4 isn't implemented by AMD. Intel uses it for cache
|
if (vendor == INTEL) {
|
||||||
// descriptors. It has some useful information (like procesor counts) but
|
cores.logical = cores.physical = 0;
|
||||||
// it's ugly as sin; try to avoid using it.
|
|
||||||
// { (void)cpuid (0x0b, 4); }
|
|
||||||
|
|
||||||
if (is_amd) {
|
for (int level = 0; true; ++level) {
|
||||||
auto long_mode = cpuid (0x8000'0008);
|
auto const param = cpuid (0x4, level);
|
||||||
auto apic_id_size = from_bits (long_mode.c, 15, 12);
|
|
||||||
(void)apic_id_size;
|
// The final level will set the 'cache type' bits to zero to
|
||||||
cores.physical = 0; //from_bits (long_mode.c, 7, 0) + 1;
|
// indicate there are no more caches.
|
||||||
|
if ((param.a & 0b1111) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
cores.physical = max (
|
||||||
|
cores.physical,
|
||||||
|
cruft::cast::lossless<int> (from_bits (param.a, 31, 26)) + 1
|
||||||
|
);
|
||||||
|
cores.logical = max (
|
||||||
|
cores.physical,
|
||||||
|
cruft::cast::lossless<int> (from_bits (param.a, 25, 14)) + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (vendor == AMD) {
|
||||||
|
auto const size_identifiers = cpuid (0x8000'0008);
|
||||||
|
|
||||||
|
if (auto const apic_id_size = from_bits (size_identifiers.c, 15, 12); apic_id_size) {
|
||||||
|
cores.physical = 1 << (apic_id_size - 1);
|
||||||
|
} else {
|
||||||
|
cores.physical = (size_identifiers.c & 0xff) + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cores.physical = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user