cpuid: add initial trivial CPUID queries
This commit is contained in:
parent
b307ab935d
commit
68faa8838e
@ -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)
|
||||
|
36
cpuid.hpp
Normal file
36
cpuid.hpp
Normal 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
119
cpuid_x86.cpp
Normal 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
56
cpuid_x86.hpp
Normal 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
26
tools/cpuid.cpp
Normal 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';
|
||||
};
|
Loading…
Reference in New Issue
Block a user