cpuid: add initial trivial CPUID queries

This commit is contained in:
Danny Robson 2018-03-18 17:29:44 +11:00
parent b307ab935d
commit 68faa8838e
6 changed files with 243 additions and 1 deletions

View File

@ -195,8 +195,13 @@ list (
coord/ops.hpp
coord/simd.hpp
coord/simd_sse.hpp
coord/simd_neon.hpp
coord/store.hpp
coord/traits.hpp
cpuid.cpp
cpuid.hpp
cpuid_x86.cpp
cpuid_x86.hpp
debug.cpp
debug.hpp
encode/base.cpp
@ -434,7 +439,7 @@ target_link_libraries(cruft-util dl)
###############################################################################
foreach (tool json-clean json-schema json-validate macro scratch)
foreach (tool cpuid json-clean json-schema json-validate macro scratch)
add_executable (util_${tool} tools/${tool}.cpp)
set_target_properties (util_${tool} PROPERTIES OUTPUT_NAME ${tool})
target_link_libraries (util_${tool} cruft-util)

0
cpuid.cpp Normal file
View File

36
cpuid.hpp Normal file
View File

@ -0,0 +1,36 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
*/
#ifndef CRUFT_UTIL_CPUID_HPP
#define CRUFT_UTIL_CPUID_HPP
#include <ostream>
namespace util::cpu {
struct base {
struct {
int logical;
int physical;
} cores;
};
std::ostream&
operator<< (std::ostream&, const util::cpu::base&);
};
#endif

119
cpuid_x86.cpp Normal file
View File

@ -0,0 +1,119 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
*/
#include "cpuid_x86.hpp"
#include "endian.hpp"
#include "view.hpp"
#include "format.hpp"
#include "bitwise.hpp"
#include <cstdint>
#include <iostream>
using util::cpu::x86;
///////////////////////////////////////////////////////////////////////////////
auto cpuid (int query, int param = 0)
{
struct {
uint32_t a, b, c, d;
} res;
asm (
"cpuid"
: "=a" (res.a), "=b" (res.b), "=c" (res.c), "=d" (res.d)
: "a" (query), "c" (param)
);
return res;
}
///////////////////////////////////////////////////////////////////////////////
x86::x86 ()
{
const auto &[largest_function, vendor0, vendor2, vendor1] = cpuid (0);
(void)largest_function;
memcpy (vendor_name.data () + 0, &vendor0, sizeof (vendor0));
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);
simd.sse3 = features.c & (1u << 0);
simd.ssse3 = features.c & (1u << 9);
simd.sse41 = features.c & (1u << 19);
simd.sse42 = features.c & (1u << 20);
simd.avx = features.c & (1u << 28);
simd.sse = features.d & (1u << 25);
simd.sse2 = features.d & (1u << 26);
cores.hyper_threading = features.d & (1u << 28);
cores.logical = from_bits (features.b, 23, 16);
}
{
const auto product0 = cpuid (0x8000'0002);
const auto product1 = cpuid (0x8000'0003);
const auto product2 = cpuid (0x8000'0004);
memcpy (&product_name[0x00], &product0, sizeof (product0));
memcpy (&product_name[0x10], &product1, sizeof (product1));
memcpy (&product_name[0x20], &product2, sizeof (product2));
}
// Function 4 isn't implemented by AMD. Intel uses it for cache
// descriptors. It has some useful information (like procesor counts) but
// it's ugly as sin; try to avoid using it.
// { (void)cpuid (0x0b, 4); }
if (is_amd) {
auto long_mode = cpuid (0x8000'0008);
auto apic_id_size = from_bits (long_mode.c, 15, 12);
(void)apic_id_size;
cores.physical = 0; //from_bits (long_mode.c, 7, 0) + 1;
}
}
///////////////////////////////////////////////////////////////////////////////
std::ostream&
util::cpu::operator<< (std::ostream &os, const x86 &val)
{
return os << util::format::printf (
"{ name: { vendor: '%!', product: '%!' }"
", cores: { logical: %!, physical: %!, hyper_threading: %! }"
", simd { sse: %!, sse2: %!, sse3: %!, ssse3: %!, sse41: %!, sse42: %! }"
" }",
util::view {val.vendor_name},
util::view {val.product_name},
val.cores.logical,
val.cores.physical,
val.cores.hyper_threading,
val.simd.sse,
val.simd.sse2,
val.simd.sse3,
val.simd.ssse3,
val.simd.sse41,
val.simd.sse42
);
}

56
cpuid_x86.hpp Normal file
View File

@ -0,0 +1,56 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
*/
#ifndef CRUFT_UTIL_CPUID_X86_HPP
#define CRUFT_UTIL_CPUID_X86_HPP
#include "cpuid.hpp"
#include <array>
namespace util::cpu {
struct x86 {
x86 ();
struct {
int logical;
// currently unused because we lack APIC enumeration code
// required for physical:logical mappings.
int physical = 0;
bool hyper_threading;
} cores;
struct {
bool sse;
bool sse2;
bool sse3;
bool ssse3;
bool sse41;
bool sse42;
bool avx;
} simd;
std::array<char,12> vendor_name;
std::array<char,48> product_name;
};
std::ostream&
operator<< (std::ostream&, const util::cpu::x86&);
};
#endif

26
tools/cpuid.cpp Normal file
View File

@ -0,0 +1,26 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
*/
#include "cpuid_x86.hpp"
#include <iostream>
///////////////////////////////////////////////////////////////////////////////
int
main ()
{
std::cout << util::cpu::x86 {} << '\n';
};