Rework Line #7 left block. Add preliminary CPUID function to detect CPU Topology

This commit is contained in:
Sam Demeulemeester 2022-04-11 19:37:52 +02:00 committed by Sam Demeulemeester
parent fac6e2a973
commit 979b85548d
7 changed files with 172 additions and 48 deletions

View File

@ -66,16 +66,12 @@
#define SEL_AREA (SEL_W * SEL_H)
static const char *cpu_mode_str[] = { "PAR", "SEQ", "RR " };
//------------------------------------------------------------------------------
// Private Variables
//------------------------------------------------------------------------------
static uint16_t popup_save_buffer[POP_W * POP_H];
static bool smp_enabled = true;
//------------------------------------------------------------------------------
// Public Variables
//------------------------------------------------------------------------------
@ -91,6 +87,8 @@ error_mode_t error_mode = ERROR_MODE_NONE;
cpu_state_t cpu_state[MAX_CPUS];
bool smp_enabled = true;
bool enable_temperature = true;
bool enable_trace = false;
@ -867,7 +865,7 @@ void config_menu(bool initial)
}
if (cpu_mode != old_cpu_mode) {
display_cpu_mode(cpu_mode_str[cpu_mode]);
display_cpu_topology();
restart = true;
}

View File

@ -45,6 +45,8 @@ extern error_mode_t error_mode;
extern cpu_state_t cpu_state[MAX_CPUS];
extern bool smp_enabled;
extern bool enable_temperature;
extern bool enable_trace;

View File

@ -37,6 +37,8 @@
static const char spin_state[NUM_SPIN_STATES] = { '|', '/', '-', '\\' };
static const char *cpu_mode_str[] = { "PAR", "SEQ", "RR " };
//------------------------------------------------------------------------------
// Private Variables
//------------------------------------------------------------------------------
@ -91,8 +93,8 @@ void display_init(void)
prints(4, 0, "L3 Cache: N/A | Testing: ");
prints(5, 0, "Memory : N/A | Pattern: ");
prints(6, 0, "-------------------------------------------------------------------------------");
prints(7, 0, "CPU cores: available, enabled | Time: Status: Init. ");
prints(8, 0, "Run mode : PAR Using: | Pass: Errors: ");
prints(7, 0, "CPU: SMP: N/A | Time: Status: Init. ");
prints(8, 0, "Using: | Pass: Errors: ");
prints(9, 0, "-------------------------------------------------------------------------------");
// Redraw lines using box drawing characters.
@ -133,11 +135,6 @@ void display_init(void)
if (clks_per_msec) {
display_cpu_clk((int)(clks_per_msec / 1000));
}
if (cpuid_info.flags.lm) {
display_cpu_addr_mode("(x64)");
} else if (cpuid_info.flags.pae) {
display_cpu_addr_mode("(PAE)");
}
if (l1_cache) {
display_l1_cache_size(l1_cache);
}
@ -167,6 +164,55 @@ void display_init(void)
scroll_message_row = ROW_SCROLL_T;
}
void display_cpu_topology(void)
{
extern int num_enabled_cpus;
int num_cpu_sockets = 1;
if(smp_enabled) {
printf(7,30, "%uT (%s)", num_enabled_cpus, cpu_mode_str[cpu_mode]);
} else {
prints(7,30, "Disabled");
}
// If topology failed, assume topology according to APIC
if(cpuid_info.topology.core_count <= 0) {
cpuid_info.topology.core_count = num_enabled_cpus;
cpuid_info.topology.thread_count = num_enabled_cpus;
if(cpuid_info.flags.htt && num_enabled_cpus >= 2 && num_enabled_cpus % 2 == 0) {
cpuid_info.topology.core_count /= 2;
}
}
// Compute number of sockets according to individual CPU core count
if(num_enabled_cpus > cpuid_info.topology.thread_count &&
num_enabled_cpus % cpuid_info.topology.thread_count == 0) {
num_cpu_sockets = num_enabled_cpus / cpuid_info.topology.thread_count;
}
// Temporary workaround for Hybrid CPUs.
// TODO: run cpuid on each core to get correct P+E topology
if(cpuid_info.topology.is_hybrid) {
printf(7, 5, "%u Threads (%s)", cpuid_info.topology.thread_count,
cpuid_info.flags.lm ? "X64" : "PAE");
return;
}
if(num_cpu_sockets < 2) {
printf(7, 5, "%uC/%uT (%s)", cpuid_info.topology.core_count,
cpuid_info.topology.thread_count,
cpuid_info.flags.lm ? "X64" : "PAE");
} else {
printf(7, 5, "%uS/%uC/%uT (%s)", num_cpu_sockets,
num_cpu_sockets * cpuid_info.topology.core_count,
num_cpu_sockets * cpuid_info.topology.thread_count,
cpuid_info.flags.lm ? "X64" : "PAE");
}
}
void post_display_init(void)
{
print_smbios_startup_info();

View File

@ -38,9 +38,6 @@
#define display_cpu_clk(freq) \
printf(1, 10, "%i MHz", freq)
#define display_cpu_addr_mode(str) \
prints(1, 20, str)
#define display_l1_cache_size(size) \
printf(2, 9, "%6kB", (uintptr_t)(size));
@ -72,21 +69,12 @@
dmicol = prints(23, dmicol, sys_man); \
prints(23, dmicol + 1, sys_sku);
#define display_available_cpus(count) \
printi(7, 10, count, 4, false, false)
#define display_enabled_cpus(count) \
printi(7, 25, count, 4, false, false)
#define display_cpu_mode(str) \
prints(8, 11, str)
#define display_active_cpu(cpu_num) \
prints(8, 25, "core #"); \
printi(8, 31, cpu_num, 3, false, true)
prints(8, 7, "Core #"); \
printi(8, 13, cpu_num, 3, false, true)
#define display_all_active \
prints(8, 25, "all cores")
prints(8, 7, "All Cores")
#define display_spinner(spin_state) \
printc(7, 76, spin_state)
@ -196,6 +184,8 @@ extern int scroll_message_row;
void display_init(void);
void display_cpu_topology(void);
void post_display_init(void);
void display_start_run(void);

View File

@ -67,8 +67,6 @@
static volatile int init_state = 0;
static int num_enabled_cpus = 1;
static uintptr_t low_load_addr;
static uintptr_t high_load_addr;
@ -100,6 +98,7 @@ efi_info_t saved_efi_info;
uint8_t chunk_index[MAX_CPUS];
int num_active_cpus = 0;
int num_enabled_cpus = 1;
int master_cpu = 0;
@ -230,8 +229,6 @@ static void global_init(void)
clear_message_area();
display_available_cpus(num_available_cpus);
num_enabled_cpus = 0;
for (int i = 0; i < num_available_cpus; i++) {
if (cpu_state[i] == CPU_STATE_ENABLED) {
@ -239,7 +236,7 @@ static void global_init(void)
num_enabled_cpus++;
}
}
display_enabled_cpus(num_enabled_cpus);
display_cpu_topology();
master_cpu = 0;

View File

@ -1,12 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020-2022 Martin Whitaker.
// Copyright (C) 2004-2022 Sam Demeulemeester.
//
// Derived from memtest86+ cpuid.h
// (original contained no copyright statement)
#include <stdint.h>
#include "cpuid.h"
#include "display.h"
//------------------------------------------------------------------------------
// Public Variables
@ -20,7 +22,7 @@ cpuid_info_t cpuid_info;
void cpuid_init(void)
{
uint32_t dummy[3];
uint32_t reg[4];
char *p, *q;
// Get the max standard cpuid & vendor ID.
@ -46,26 +48,26 @@ void cpuid_init(void)
if (cpuid_info.max_cpuid >= 6) {
cpuid(0x6, 0,
&cpuid_info.dts_pmp,
&dummy[0],
&dummy[1],
&dummy[2]
&reg[0],
&reg[1],
&reg[2]
);
}
// Get the max extended cpuid.
cpuid(0x80000000, 0,
&cpuid_info.max_xcpuid,
&dummy[0],
&dummy[1],
&dummy[2]
&reg[0],
&reg[1],
&reg[2]
);
// Get extended feature flags, only save EDX.
if (cpuid_info.max_xcpuid >= 0x80000001) {
cpuid(0x80000001, 0,
&dummy[0],
&dummy[1],
&dummy[2],
&reg[0],
&reg[1],
&reg[2],
&cpuid_info.flags.raw[2]
);
}
@ -112,16 +114,16 @@ void cpuid_init(void)
// AMD Processors
if (cpuid_info.max_xcpuid >= 0x80000005) {
cpuid(0x80000005, 0,
&dummy[0],
&dummy[1],
&reg[0],
&reg[1],
&cpuid_info.cache_info.raw[0],
&cpuid_info.cache_info.raw[1]
);
}
if (cpuid_info.max_xcpuid >= 0x80000006) {
cpuid(0x80000006, 0,
&dummy[0],
&dummy[1],
&reg[0],
&reg[1],
&cpuid_info.cache_info.raw[2],
&cpuid_info.cache_info.raw[3]
);
@ -132,4 +134,84 @@ void cpuid_init(void)
// No cpuid info to read.
break;
}
// Detect CPU Topology (Core/Thread) infos
cpuid_info.topology.core_count = -1;
cpuid_info.topology.thread_count = -1;
cpuid_info.topology.is_hybrid = 0;
cpuid_info.topology.ecore_count = -1;
cpuid_info.topology.pcore_count = -1;
int thread_per_core = 1;
switch (cpuid_info.vendor_id.str[0]) {
case 'A':
// AMD Processors
if (cpuid_info.max_xcpuid >= 0x80000008) {
cpuid(0x80000008, 0, &reg[0], &reg[1], &reg[2], &reg[3]);
cpuid_info.topology.thread_count = (reg[2] & 0xFF) + 1;
if (cpuid_info.max_xcpuid >= 0x8000001E) {
cpuid(0x8000001E, 0, &reg[0], &reg[1], &reg[2], &reg[3]);
if (((reg[1] >> 8) & 0x3) > 0) {
thread_per_core = 2;
}
} else if (cpuid_info.flags.htt) {
thread_per_core = 2;
}
cpuid_info.topology.core_count = cpuid_info.topology.thread_count / thread_per_core;
}
break;
case 'C':
// VIA / CentaurHauls
break;
case 'G':
if (cpuid_info.vendor_id.str[7] == 'T') break; // Transmeta
// Intel
if (cpuid_info.max_cpuid >= 0xB) {
// Populate Hybrid Status (CPUID 7.EDX[15]) for Alder Lake+
cpuid(0x7, 0, &reg[0], &reg[1], &reg[2], &reg[3]);
if (reg[3] & (1 << 15)) {
cpuid_info.topology.is_hybrid = 1;
}
for (int i=0; i < 4; i++) {
cpuid(0xB, i, &reg[0], &reg[1], &reg[2], &reg[3]);
switch((reg[2] >> 8) & 0xFF) {
case 1: // SMT
thread_per_core = reg[1] & 0xFF;
break;
case 2: // Cores
cpuid_info.topology.thread_count = reg[1] & 0xFFFF;
break;
default:
continue;
}
}
cpuid_info.topology.core_count = cpuid_info.topology.thread_count / thread_per_core;
} else if (cpuid_info.max_cpuid >= 0x4) {
cpuid(4, 0, &reg[0], &reg[1], &reg[2], &reg[3]);
cpuid_info.topology.core_count = (reg[0] >> 26) + 1;
cpuid_info.topology.thread_count = cpuid_info.topology.core_count;
if (cpuid_info.flags.htt){
cpuid_info.topology.thread_count *= 2;
}
} else if (cpuid_info.max_cpuid >= 0x2) {
if(cpuid_info.flags.htt){
cpuid_info.topology.core_count = 1;
cpuid_info.topology.thread_count = 2;
}
}
break;
default:
break;
}
}

View File

@ -8,9 +8,9 @@
*
*//*
* Copyright (C) 2020-2022 Martin Whitaker.
* Copyright (C) 2004-2022 Sam Demeulemeester.
*
* Derived from memtest86+ cpuid.h
* (original contained no copyright statement)
*/
#include <stdint.h>
@ -133,6 +133,14 @@ typedef union {
};
} cpuid_custom_features;
typedef struct {
int core_count;
int thread_count;
int is_hybrid;
int ecore_count;
int pcore_count;
} topology_t;
typedef struct {
uint32_t max_cpuid;
uint32_t max_xcpuid;
@ -144,6 +152,7 @@ typedef struct {
cpuid_brand_string_t brand_id;
cpuid_cache_info_t cache_info;
cpuid_custom_features custom;
topology_t topology;
} cpuid_info_t;
typedef union {