Skip to content

Commit

Permalink
Get CPU brand string
Browse files Browse the repository at this point in the history
  • Loading branch information
phaubertin committed Jan 11, 2025
1 parent 08ab789 commit 6e188e6
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 4 deletions.
1 change: 1 addition & 0 deletions include/kernel/infrastructure/i686/cpuinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions include/kernel/infrastructure/i686/isa/instrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
86 changes: 82 additions & 4 deletions kernel/infrastructure/i686/cpuinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,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) {
Expand Down Expand Up @@ -176,6 +187,68 @@ static void identify_model(cpuinfo_t *cpuinfo, const x86_cpuid_leafs *leafs) {
}
}

/**
* Coalesce spaces in a string
*
* @param cpuinfo structure in which to set the brand string (OUT)
* @param leafs CPUID leafs structure filled by a call_cpuid()
*/
static void coalesce_spaces(char *buffer) {
for(int idx = 0; buffer[idx] != '\0'; ++idx) {
if(buffer[idx] != ' ' || buffer[idx + 1] != ' ') {
continue;
}

int src = idx + 2;

while(buffer[src] == ' ') {
++src;
}

/* Warning: the strings overlap, so we are relying here on behaviour of
* our strcpy() implementation that is undefined behaviour according to
* the standard. */
strcpy(&buffer[idx + 1], &buffer[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
);

/* The brand string in CPUID leafs 0x80000002-0x80000004 sometimes contains
* sequences of multiple spaces. */
coalesce_spaces(cpuinfo->brand_string);
}

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

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

/**
Expand All @@ -368,8 +441,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,
Expand All @@ -378,8 +453,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);
}

/**
Expand All @@ -395,6 +471,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);
Expand Down

0 comments on commit 6e188e6

Please sign in to comment.