Add AP Enumeration to distinguish P-Core from E-Core on Hybrid CPUs (#62)

Add AP Enumeration to distinguish E-Core from P-Core on Intel Hybrid CPUs, and exclude them from the selected cores by default.  Including E-Cores slows down some tests and takes longer to catch memory errors.

A new exclude_ecores flag has been added in config.c to include E-Cores if needed.
This commit is contained in:
Sam Demeulemeester
2022-07-16 13:28:53 +02:00
committed by GitHub
parent c2e94527e1
commit 89e2643de4
7 changed files with 106 additions and 12 deletions
+17 -4
View File
@@ -1,11 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020-2022 Martin Whitaker.
// Copyright (C) 2004-2022 Sam Demeulemeester.
//
// Derived from memtest86+ config.c:
//
// MemTest86+ V5.00 Specific code (GPL V2.0)
// By Samuel DEMEULEMEESTER, sdemeule@memtest.org
// http://www.x86-secret.com - http://www.memtest.org
// ----------------------------------------------------
// config.c - MemTest-86 Version 3.4
//
@@ -19,6 +17,7 @@
#include "bootparams.h"
#include "cpuinfo.h"
#include "cpuid.h"
#include "hwctrl.h"
#include "keyboard.h"
#include "memsize.h"
@@ -87,6 +86,9 @@ error_mode_t error_mode = ERROR_MODE_NONE;
cpu_state_t cpu_state[MAX_CPUS];
core_type_t hybrid_core_type[MAX_CPUS];
bool exclude_ecores = true;
bool smp_enabled = true;
bool enable_temperature = true;
@@ -699,7 +701,14 @@ static void cpu_selection_menu(void)
prints(POP_R+5, POP_LI, "<F3> Add one CPU");
prints(POP_R+6, POP_LI, "<F4> Add CPU range");
prints(POP_R+7, POP_LI, "<F5> Add all CPUs");
prints(POP_R+8, POP_LI, "<F10> Exit menu");
if (cpuid_info.topology.is_hybrid) {
if (exclude_ecores) {
prints(POP_R+8, POP_LI, "<F6> Include E-Cores");
} else {
prints(POP_R+8, POP_LI, "<F6> Exclude E-Cores");
}
}
prints(POP_R+9, POP_LI, "<F10> Exit menu");
display_cpu_selection(display_offset);
@@ -722,6 +731,10 @@ static void cpu_selection_menu(void)
case '5':
changed = set_all_cpus(true, display_offset);
break;
case '6':
exclude_ecores = !exclude_ecores;
prints(POP_R+8, POP_LI+6, exclude_ecores ? "Exclude" : "Include");
break;
case 'u':
if (display_offset >= SEL_W) {
display_offset -= SEL_W;
+4
View File
@@ -14,6 +14,7 @@
#include <stdint.h>
#include "smp.h"
#include "cpuid.h"
typedef enum {
PAR,
@@ -45,6 +46,9 @@ extern error_mode_t error_mode;
extern cpu_state_t cpu_state[MAX_CPUS];
extern core_type_t hybrid_core_type[MAX_CPUS];
extern bool exclude_ecores;
extern bool smp_enabled;
extern bool enable_temperature;
+21 -7
View File
@@ -179,8 +179,13 @@ void display_cpu_topology(void)
extern int num_enabled_cpus;
int num_cpu_sockets = 1;
// Display Thread Count and Thread Dispatch Mode
if (smp_enabled) {
display_threading(num_enabled_cpus, cpu_mode_str[cpu_mode]);
if (cpuid_info.topology.is_hybrid && cpuid_info.topology.ecore_count > 0 && exclude_ecores) {
display_threading(num_enabled_cpus - cpuid_info.topology.ecore_count, cpu_mode_str[cpu_mode]);
} else {
display_threading(num_enabled_cpus, cpu_mode_str[cpu_mode]);
}
} else {
display_threading_disabled();
}
@@ -198,16 +203,25 @@ void display_cpu_topology(void)
// 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_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
// Display P/E-Core count for Hybrid CPUs.
if (cpuid_info.topology.is_hybrid) {
display_cpu_topo_hybrid(cpuid_info.topology.thread_count);
if (cpuid_info.topology.pcore_count > 1) {
if (cpuid_info.flags.htt &&
(cpuid_info.topology.thread_count - cpuid_info.topology.ecore_count) == cpuid_info.topology.pcore_count) {
cpuid_info.topology.pcore_count /= 2;
}
display_cpu_topo_hybrid(cpuid_info.topology.pcore_count,
cpuid_info.topology.ecore_count,
cpuid_info.topology.thread_count);
} else {
display_cpu_topo_hybrid_short(cpuid_info.topology.thread_count);
}
return;
}
+7 -1
View File
@@ -81,7 +81,13 @@ typedef enum {
#define display_threading_disabled() \
prints(7,31, "Disabled")
#define display_cpu_topo_hybrid(num_threads) \
#define display_cpu_topo_hybrid(num_pcores, num_ecores, num_threads) \
{ \
clear_screen_region(7, 5, 7, 25); \
printf(7, 5, "%uP+%uE-Cores (%uT)", num_pcores, num_ecores, num_threads); \
}
#define display_cpu_topo_hybrid_short(num_threads) \
printf(7, 5, "%u Threads (Hybrid)", num_threads)
#define display_cpu_topo_multi_socket(num_sockets, num_cores, num_threads) \
+25
View File
@@ -304,6 +304,30 @@ static void global_init(void)
restart = false;
}
static void ap_enumerate(int my_cpu)
{
if (!cpuid_info.topology.is_hybrid) {
return;
}
hybrid_core_type[my_cpu] = get_ap_hybrid_type();
if (hybrid_core_type[my_cpu] == CORE_PCORE) {
cpuid_info.topology.pcore_count++;
} else if (hybrid_core_type[my_cpu] == CORE_ECORE) {
cpuid_info.topology.ecore_count++;
}
if (hybrid_core_type[my_cpu] == CORE_ECORE && exclude_ecores) {
cpu_state[my_cpu] = CPU_STATE_DISABLED;
//TODO : hlt AP?
}
if (my_cpu == num_enabled_cpus - 1) {
display_cpu_topology();
}
}
static void setup_vm_map(uintptr_t win_start, uintptr_t win_end)
{
vm_map_size = 0;
@@ -503,6 +527,7 @@ void main(void)
} else {
trace(my_cpu, "AP started");
cpu_state[my_cpu] = CPU_STATE_RUNNING;
ap_enumerate(my_cpu);
while (init_state < 2) {
usleep(100);
}
+18
View File
@@ -187,6 +187,8 @@ void cpuid_init(void)
cpuid(0x7, 0, &reg[0], &reg[1], &reg[2], &reg[3]);
if (reg[3] & (1 << 15)) {
cpuid_info.topology.is_hybrid = 1;
cpuid_info.topology.pcore_count = 1; // We have at least 1 P-Core as BSP
cpuid_info.topology.ecore_count = 0;
}
for (int i=0; i < 4; i++) {
@@ -226,3 +228,19 @@ void cpuid_init(void)
break;
}
}
core_type_t get_ap_hybrid_type(void)
{
uint32_t eax, ebx, ecx, edx;
cpuid(0x1A, 0, &eax, &ebx, &ecx, &edx);
switch ((eax >> 24) & 0xFF) {
case CPU_PCORE_ID:
return CORE_PCORE;
case CPU_ECORE_ID:
return CORE_ECORE;
default:
return CORE_UNKNOWN;
}
}
+14
View File
@@ -15,6 +15,15 @@
#include <stdint.h>
#define CPU_ECORE_ID 0x20
#define CPU_PCORE_ID 0x40
typedef enum {
CORE_UNKNOWN,
CORE_PCORE,
CORE_ECORE
} core_type_t;
/**
* Structures that hold the collected CPUID information.
*/
@@ -194,6 +203,11 @@ extern cpuid_info_t cpuid_info;
*/
void cpuid_init(void);
/**
* Return the Core Type (for Hybrid CPUs)
*/
core_type_t get_ap_hybrid_type(void);
/**
* Executes the cpuid instruction.
*/