Skip to content

Commit

Permalink
Get CPU brand string (#106)
Browse files Browse the repository at this point in the history
Get and log the CPU brand string from CPUID leafs 0x80000002-0x80000004.
  • Loading branch information
phaubertin authored Jan 11, 2025
1 parent b92e88d commit 1cd5b71
Showing 5 changed files with 141 additions and 13 deletions.
12 changes: 12 additions & 0 deletions include/ctype.h
Original file line number Diff line number Diff line change
@@ -40,4 +40,16 @@ static inline int isxdigit(int c) {
return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}

static inline int isblank(int c) {
return c == ' ' || c == '\t';
}

static inline int isspace(int c) {
return isblank(c) || c == '\n' || c == '\r' || c == '\v';
}

static inline int isprint(int c) {
return c >= ' ' && c <= '~';
}

#endif
23 changes: 14 additions & 9 deletions include/kernel/infrastructure/i686/asm/cpuid.h
Original file line number Diff line number Diff line change
@@ -32,6 +32,18 @@
#ifndef JINUE_KERNEL_INFRASTRUCTURE_I686_ASM_CPUID_H
#define JINUE_KERNEL_INFRASTRUCTURE_I686_ASM_CPUID_H

/* Basic leaf 0 (0x00000001) ebx, ecx, edx */

#define CPUID_VENDOR_AMD_DW0 0x68747541 /* Auth */
#define CPUID_VENDOR_AMD_DW1 0x69746e65 /* enti */
#define CPUID_VENDOR_AMD_DW2 0x444d4163 /* cAMD */

#define CPUID_VENDOR_INTEL_DW0 0x756e6547 /* Genu */
#define CPUID_VENDOR_INTEL_DW1 0x49656e69 /* ineI */
#define CPUID_VENDOR_INTEL_DW2 0x6c65746e /* ntel */

/* Basic leaf 1 (0x00000001) edx */

#define CPUID_FEATURE_FPU (1<<0)

#define CPUID_FEATURE_PSE (1<<3)
@@ -46,19 +58,12 @@

#define CPUID_FEATURE_CLFLUSH (1<<19)

#define CPUID_FEATURE_NXE (1<<20)

#define CPUID_FEATURE_HTT (1<<28)

/* Extended leaf 1 (0x8000001) edx */

#define CPUID_EXT_FEATURE_SYSCALL (1<<11)

#define CPUID_VENDOR_AMD_DW0 0x68747541 /* Auth */
#define CPUID_VENDOR_AMD_DW1 0x69746e65 /* enti */
#define CPUID_VENDOR_AMD_DW2 0x444d4163 /* cAMD */

#define CPUID_VENDOR_INTEL_DW0 0x756e6547 /* Genu */
#define CPUID_VENDOR_INTEL_DW1 0x49656e69 /* ineI */
#define CPUID_VENDOR_INTEL_DW2 0x6c65746e /* ntel */
#define CPUID_FEATURE_NXE (1<<20)

#endif
1 change: 1 addition & 0 deletions include/kernel/infrastructure/i686/cpuinfo.h
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@ typedef struct {
unsigned int family;
unsigned int model;
unsigned int stepping;
char brand_string[49];
} cpuinfo_t;

extern cpuinfo_t bsp_cpuinfo;
4 changes: 4 additions & 0 deletions include/kernel/infrastructure/i686/isa/instrs.h
Original file line number Diff line number Diff line change
@@ -46,7 +46,11 @@ typedef struct {
x86_cpuid_regs_t basic1;
x86_cpuid_regs_t ext0;
x86_cpuid_regs_t ext1;
x86_cpuid_regs_t ext2;
x86_cpuid_regs_t ext3;
x86_cpuid_regs_t ext4;
x86_cpuid_regs_t ext8;
bool ext4_valid;
bool ext8_valid;
} x86_cpuid_leafs;

114 changes: 110 additions & 4 deletions kernel/infrastructure/i686/cpuinfo.c
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@
#include <kernel/infrastructure/i686/isa/regs.h>
#include <kernel/infrastructure/i686/cpuinfo.h>
#include <kernel/machine/cpuinfo.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

@@ -96,6 +97,17 @@ static void call_cpuid(x86_cpuid_leafs *leafs) {
(void)cpuid(&leafs->ext1);
}

leafs->ext4_valid = ext_max >= ext_base + 4;

if(leafs->ext4_valid) {
leafs->ext2.eax = ext_base + 2;
leafs->ext3.eax = ext_base + 3;
leafs->ext4.eax = ext_base + 4;
(void)cpuid(&leafs->ext2);
(void)cpuid(&leafs->ext3);
(void)cpuid(&leafs->ext4);
}

leafs->ext8_valid = ext_max >= ext_base + 8;

if(leafs->ext8_valid) {
@@ -176,6 +188,95 @@ static void identify_model(cpuinfo_t *cpuinfo, const x86_cpuid_leafs *leafs) {
}
}

typedef enum {
CLEAN_STATE_START,
CLEAN_STATE_IDLE,
CLEAN_STATE_SPACE,
} clean_state_t;

/**
* Clean the CPU brand string
*
* Remove leading and trailing whitespace characters, coalesce sequences of
* whitespace charaters and remove non-printable characters.
*
* @param buffer string buffer containing brand string
*/
static void clean_brand_string(char *buffer) {
clean_state_t state = CLEAN_STATE_START;

int dest = 0;
int src = 0;

/* Invariant: dest is always at or before src, so what happens at dest
* never affects the condition of this loop. */
while(true) {
int c = buffer[src];

if(c == '\0') {
/* Add a single space character if there is a pending space. This
* ensure space/tab sequences are coalesced into a single space
* charater and leading spaces are trimmed. */
if(state == CLEAN_STATE_SPACE) {
buffer[dest++] = ' ';
}

buffer[dest++] = '\0';
break;
} else if(isblank(c)) {
/* Transition to the space state only if at least one printable
* character was encountered since the start of the string. */
if(state == CLEAN_STATE_IDLE) {
state = CLEAN_STATE_SPACE;
}
} else if(isprint(c) && !isspace(c)) {
if(state == CLEAN_STATE_SPACE) {
buffer[dest++] = ' ';
}

buffer[dest++] = c;
state = CLEAN_STATE_IDLE;
}

++src;
}
}

/**
* Get the CPU brand string
*
* Sets an empty string if the brand string cannot be retrieved.
*
* @param cpuinfo structure in which to set the brand string (OUT)
* @param leafs CPUID leafs structure filled by a call_cpuid()
*/
static void get_brand_string(cpuinfo_t *cpuinfo, const x86_cpuid_leafs *leafs) {
if(! leafs->ext4_valid) {
cpuinfo->brand_string[0] = '\0';
return;
}

snprintf(
cpuinfo->brand_string,
sizeof(cpuinfo->brand_string),
"%.4s%.4s%.4s%.4s%.4s%.4s%.4s%.4s%.4s%.4s%.4s%.4s",
(const char *)&leafs->ext2.eax,
(const char *)&leafs->ext2.ebx,
(const char *)&leafs->ext2.ecx,
(const char *)&leafs->ext2.edx,
(const char *)&leafs->ext3.eax,
(const char *)&leafs->ext3.ebx,
(const char *)&leafs->ext3.ecx,
(const char *)&leafs->ext3.edx,
(const char *)&leafs->ext4.eax,
(const char *)&leafs->ext4.ebx,
(const char *)&leafs->ext4.ecx,
(const char *)&leafs->ext4.edx
);

clean_brand_string(cpuinfo->brand_string);
}

/**
* Identify the data cache alignment
*
@@ -342,7 +443,7 @@ static void dump_features(const cpuinfo_t *cpuinfo) {
(cpuinfo->features & CPUINFO_FEATURE_SYSENTER) ? " sysenter" : ""
);

info("CPU features:%s", buffer);
info(" Features:%s", buffer);
}

/**
@@ -368,8 +469,10 @@ static const char *get_vendor_string(const cpuinfo_t *cpuinfo) {
* @param cpuinfo CPU information structure
*/
static void dump_cpu_features(const cpuinfo_t *cpuinfo) {
info("CPU information:");

info(
"CPU vendor: %s family: %u model: %u stepping: %u",
" Vendor: %s family: %u model: %u stepping: %u",
get_vendor_string(cpuinfo),
cpuinfo->family,
cpuinfo->model,
@@ -378,8 +481,9 @@ static void dump_cpu_features(const cpuinfo_t *cpuinfo) {

dump_features(cpuinfo);

info("CPU data cache alignment: %u bytes", cpuinfo->dcache_alignment);
info("CPU physical address size: %u bits", cpuinfo->maxphyaddr);
info(" Brand string: %s", cpuinfo->brand_string);
info(" Data cache alignment: %u bytes", cpuinfo->dcache_alignment);
info(" Physical address size: %u bits", cpuinfo->maxphyaddr);
}

/**
@@ -395,6 +499,8 @@ void detect_cpu_features(void) {

identify_model(&bsp_cpuinfo, &cpuid_leafs);

get_brand_string(&bsp_cpuinfo, &cpuid_leafs);

identify_dcache_alignment(&bsp_cpuinfo, &cpuid_leafs);

enumerate_features(&bsp_cpuinfo, &cpuid_leafs);

0 comments on commit 1cd5b71

Please sign in to comment.