mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2026-08-04 10:23:17 -05:00
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:
+17
-4
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -187,6 +187,8 @@ void cpuid_init(void)
|
||||
cpuid(0x7, 0, ®[0], ®[1], ®[2], ®[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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user