blob: 92401a578d581d928483a42f45d5a71742ed1a2e [file]
/*
* Copyright © 2018, VideoLAN and dav1d authors
* Copyright © 2018, Two Orioles, LLC
* All rights reserved.
*
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 "checkasm_config.h"
#if HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO
#include <sys/auxv.h>
#endif
#ifdef __APPLE__
#include <sys/sysctl.h>
#endif
#include <inttypes.h>
#include "cpu.h"
#include "internal.h"
COLD void checkasm_init_cpu(void)
{
#if ARCH_X86
checkasm_init_x86();
#elif ARCH_ARM
checkasm_init_arm();
#endif
}
COLD unsigned long checkasm_getauxval(unsigned long type)
{
#if HAVE_GETAUXVAL
return getauxval(type);
#elif HAVE_ELF_AUX_INFO
unsigned long aux = 0;
elf_aux_info(type, &aux, sizeof(aux));
return aux;
#else
(void) type;
return 0;
#endif
}
static COLD const char *get_brand_string(char *buf, size_t buflen, int affinity)
{
#if ARCH_X86
return checkasm_get_x86_cpuid(buf, buflen);
#elif defined(__APPLE__)
if (sysctlbyname("machdep.cpu.brand_string", buf, &buflen, NULL, 0) != 0) {
return NULL;
}
return buf;
#elif (ARCH_ARM || ARCH_AARCH64) && defined(__linux__)
return checkasm_get_arm_cpuinfo(buf, buflen, affinity);
#elif (ARCH_ARM || ARCH_AARCH64) && defined(_WIN32)
return checkasm_get_arm_win32_reg(buf, buflen, affinity);
#else
return NULL;
#endif
}
COLD void checkasm_cpu_info(void (*info_cb)(void *priv, const char *fmt, ...), void *priv,
const CheckasmConfig *config)
{
char buf[128];
const int affinity = config->cpu_affinity_set ? (int) config->cpu_affinity : -1;
const char *name = get_brand_string(buf, sizeof(buf), affinity);
if (name)
info_cb(priv, "%s", name);
#if ARCH_RISCV
uint32_t vendorid;
uintptr_t archid, impid;
if (checkasm_get_cpuids(&vendorid, &archid, &impid) == 0) {
const char *vendor = checkasm_get_riscv_vendor_name(vendorid);
const char *arch
= checkasm_get_riscv_arch_name(buf, sizeof(buf), vendorid, archid);
info_cb(priv, "%s, %s, imp 0x%" PRIXPTR, vendor, arch, impid);
}
if (checkasm_has_vector()) {
const unsigned long vlen = checkasm_get_vlen();
info_cb(priv, "VLEN = %lu bits", vlen);
}
#endif
#if ARCH_AARCH64
#if HAVE_SVE
if (checkasm_has_sve()) {
const unsigned sve_len = checkasm_sve_length();
info_cb(priv, "SVE = %d bits", sve_len);
}
#endif
#if HAVE_SME
if (checkasm_has_sme()) {
const unsigned sme_len = checkasm_sme_length();
info_cb(priv, "SME = %d bits", sme_len);
}
#endif
#endif
}
struct jedec_vendor {
unsigned char bank;
unsigned char offset;
char name[14];
};
static const struct jedec_vendor vendors[] = {
/* From JEDEC JEP106 (see OpenOCD's `jep106.inc` for a free equivalent). */
/* /!\ Must be sorted by bank then offset /!\ */
{ 0, 0x01, "AMD" },
{ 0, 0x09, "Intel" },
{ 0, 0x29, "Microchip" },
{ 0, 0x48, "Apple" },
{ 2, 0x27, "MIPS" },
{ 3, 0x6B, "NVIDIA" },
{ 4, 0x3B, "ARM" },
{ 6, 0x1E, "Andes Tech" },
{ 9, 0x09, "SiFive Inc" },
{ 10, 0x03, "Codasip GmbH" },
{ 11, 0x37, "T-Head" }, // formerly C-Sky
{ 14, 0x10, "SpacemiT" },
{ 15, 0x21, "Tenstorrent" },
};
static COLD int jvcmp(const void *pa, const void *pb)
{
const struct jedec_vendor *va = pa, *vb = pb;
int a = (va->bank << 7) | va->offset;
int b = (vb->bank << 7) | vb->offset;
return a - b;
}
COLD const char *checkasm_get_jedec_vendor_name(unsigned bank, unsigned offset)
{
const struct jedec_vendor key = { bank, offset, "" };
const struct jedec_vendor *v = bsearch(&key, vendors, ARRAY_SIZE(vendors),
sizeof (*v), jvcmp);
return (v != NULL) ? v->name : "unknown";
}