Skip to content

Commit

Permalink
eal: introduce x86 processor identification
Browse files Browse the repository at this point in the history
Signed-off-by: David Marchand <[email protected]>
  • Loading branch information
david-marchand committed Sep 21, 2023
1 parent aaee22f commit 37bd396
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 60 deletions.
81 changes: 21 additions & 60 deletions drivers/common/mlx5/mlx5_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <string.h>
#include <stdio.h>

#include <eal_cpu.h>
#include <rte_errno.h>
#include <rte_mempool.h>
#include <rte_class.h>
Expand Down Expand Up @@ -52,29 +53,6 @@ uint8_t haswell_broadwell_cpu;
*/
#define MLX5_SQ_DB_NC "sq_db_nc"

/* In case this is an x86_64 intel processor to check if
* we should use relaxed ordering.
*/
#ifdef RTE_ARCH_X86_64
/**
* This function returns processor identification and feature information
* into the registers.
*
* @param eax, ebx, ecx, edx
* Pointers to the registers that will hold cpu information.
* @param level
* The main category of information returned.
*/
static inline void mlx5_cpu_id(unsigned int level,
unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
__asm__("cpuid\n\t"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
: "0" (level));
}
#endif

RTE_LOG_REGISTER_DEFAULT(mlx5_common_logtype, NOTICE)

/* Head of list of drivers. */
Expand Down Expand Up @@ -1246,46 +1224,29 @@ mlx5_common_init(void)
RTE_INIT_PRIO(mlx5_is_haswell_broadwell_cpu, LOG)
{
#ifdef RTE_ARCH_X86_64
unsigned int broadwell_models[4] = {0x3d, 0x47, 0x4F, 0x56};
unsigned int haswell_models[4] = {0x3c, 0x3f, 0x45, 0x46};
unsigned int i, model, family, brand_id, vendor;
unsigned int signature_intel_ebx = 0x756e6547;
unsigned int extended_model;
unsigned int eax = 0;
unsigned int ebx = 0;
unsigned int ecx = 0;
unsigned int edx = 0;
int max_level;

mlx5_cpu_id(0, &eax, &ebx, &ecx, &edx);
vendor = ebx;
max_level = eax;
if (max_level < 1) {
haswell_broadwell_cpu = 0;
uint8_t broadwell_models[] = {0x3d, 0x47, 0x4F, 0x56};
uint8_t haswell_models[] = {0x3c, 0x3f, 0x45, 0x46};
unsigned int i;
uint8_t model;

if (!rte_cpu_is_x86() || !rte_cpu_x86_is_intel() || rte_cpu_x86_brand() != 0x0 ||
rte_cpu_x86_family() != 0x6)
goto out;

model = rte_cpu_x86_model();
for (i = 0; i < RTE_DIM(broadwell_models); i++) {
if (model != broadwell_models[i])
continue;
haswell_broadwell_cpu = 1;
return;
}
mlx5_cpu_id(1, &eax, &ebx, &ecx, &edx);
model = (eax >> 4) & 0x0f;
family = (eax >> 8) & 0x0f;
brand_id = ebx & 0xff;
extended_model = (eax >> 12) & 0xf0;
/* Check if the processor is Haswell or Broadwell */
if (vendor == signature_intel_ebx) {
if (family == 0x06)
model += extended_model;
if (brand_id == 0 && family == 0x6) {
for (i = 0; i < RTE_DIM(broadwell_models); i++)
if (model == broadwell_models[i]) {
haswell_broadwell_cpu = 1;
return;
}
for (i = 0; i < RTE_DIM(haswell_models); i++)
if (model == haswell_models[i]) {
haswell_broadwell_cpu = 1;
return;
}
}
for (i = 0; i < RTE_DIM(haswell_models); i++) {
if (model != haswell_models[i])
continue;
haswell_broadwell_cpu = 1;
return;
}
out:
#endif
haswell_broadwell_cpu = 0;
}
Expand Down
137 changes: 137 additions & 0 deletions lib/eal/common/eal_common_cpu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2023 Red Hat, Inc.
*/

#include "eal_cpu.h"

#if defined(RTE_ARCH_X86) && !defined RTE_TOOLCHAIN_MSVC
#include <cpuid.h>

static void
x86_cpuid(uint32_t leaf, uint32_t subleaf, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
uint32_t regs[4];

#ifdef RTE_TOOLCHAIN_MSVC
__cpuidex(regs, leaf, subleaf);
#else
__cpuid_count(leaf, subleaf, regs[0], regs[1], regs[2], regs[3]);
#endif

*eax = regs[0];
*ebx = regs[1];
*ecx = regs[2];
*edx = regs[3];
}
#endif

bool
rte_cpu_is_x86(void)
{
#ifndef RTE_ARCH_X86
return false;
#else
return true;
#endif
}

bool
rte_cpu_x86_is_amd(void)
{
#ifndef RTE_ARCH_X86
rte_panic("Calling %s does not make sense on %s architecture.\n",
__func__, RTE_ARCH);
#else
uint32_t eax, ebx, ecx, edx;

x86_cpuid(0x0, 0x0, &eax, &ebx, &ecx, &edx);
/* htonl("Auth enti cAMD") */
return ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65;
#endif
}

bool
rte_cpu_x86_is_intel(void)
{
#ifndef RTE_ARCH_X86
rte_panic("Calling %s does not make sense on %s architecture.\n",
__func__, RTE_ARCH);
#else
uint32_t eax, ebx, ecx, edx;

x86_cpuid(0x0, 0x0, &eax, &ebx, &ecx, &edx);
/* htonl("Genu ineI ntel") */
return ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69;
#endif
}

uint8_t
rte_cpu_x86_brand(void)
{
#ifndef RTE_ARCH_X86
rte_panic("Calling %s does not make sense on %s architecture.\n",
__func__, RTE_ARCH);
#else
uint32_t eax, ebx, ecx, edx;
uint8_t brand = 0;

x86_cpuid(0x0, 0x0, &eax, &ebx, &ecx, &edx);
if (eax >= 1) {
x86_cpuid(0x1, 0x0, &eax, &ebx, &ecx, &edx);
brand = ebx & 0xff;
}

return brand;
#endif
}

uint8_t
rte_cpu_x86_family(void)
{
#ifndef RTE_ARCH_X86
rte_panic("Calling %s does not make sense on %s architecture.\n",
__func__, RTE_ARCH);
#else
uint32_t eax, ebx, ecx, edx;
uint8_t family = 0;

x86_cpuid(0x0, 0x0, &eax, &ebx, &ecx, &edx);
if (eax >= 1) {
uint8_t family_id;

x86_cpuid(0x1, 0x0, &eax, &ebx, &ecx, &edx);
family_id = (eax >> 8) & 0x0f;
family = family_id;
if (family_id == 0xf)
family += (eax >> 20) & 0xff;
}

return family;
#endif
}

uint8_t
rte_cpu_x86_model(void)
{
#ifndef RTE_ARCH_X86
rte_panic("Calling %s does not make sense on %s architecture.\n",
__func__, RTE_ARCH);
#else
uint32_t eax, ebx, ecx, edx;
uint8_t model = 0;

x86_cpuid(0x0, 0x0, &eax, &ebx, &ecx, &edx);
if (eax >= 1) {
uint8_t family_id;

x86_cpuid(0x1, 0x0, &eax, &ebx, &ecx, &edx);
family_id = (eax >> 8) & 0x0f;
model = (eax >> 4) & 0x0f;
if (family_id == 0x6 || family_id == 0xf)
model += (eax >> 16) & 0x0f;
}

return model;
#endif
}
28 changes: 28 additions & 0 deletions lib/eal/common/eal_cpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2023 Red Hat, Inc.
*/

#ifndef EAL_CPU_H
#define EAL_CPU_H

#include <stdbool.h>
#include <stdint.h>

#include <rte_compat.h>

__rte_internal
bool rte_cpu_is_x86(void);

__rte_internal
bool rte_cpu_x86_is_amd(void);
__rte_internal
bool rte_cpu_x86_is_intel(void);

__rte_internal
uint8_t rte_cpu_x86_brand(void);
__rte_internal
uint8_t rte_cpu_x86_family(void);
__rte_internal
uint8_t rte_cpu_x86_model(void);

#endif /* EAL_CPU_H */
1 change: 1 addition & 0 deletions lib/eal/common/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sources += files(
'eal_common_bus.c',
'eal_common_class.c',
'eal_common_config.c',
'eal_common_cpu.c',
'eal_common_debug.c',
'eal_common_dev.c',
'eal_common_devargs.c',
Expand Down
6 changes: 6 additions & 0 deletions lib/eal/version.map
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,12 @@ INTERNAL {

rte_bus_register;
rte_bus_unregister;
rte_cpu_is_x86;
rte_cpu_x86_brand;
rte_cpu_x86_family;
rte_cpu_x86_is_amd;
rte_cpu_x86_is_intel;
rte_cpu_x86_model;
rte_eal_get_baseaddr;
rte_eal_parse_coremask;
rte_firmware_read;
Expand Down

0 comments on commit 37bd396

Please sign in to comment.