Rework CPU identification on ARM64
This commit reworks the code responsible for identification of the CPUs during runtime. It is necessary to provide a way for workarounds and erratums to be applied only for certain HW versions. The copy of MIDR is now stored in pcpu to provide a fast and convenient way for assambly code to read it (pcpu is used quite often so there is a chance it's inside the cache). The MIDR is also better way of identification than using user-friendly cpu_desc structure, because it can be compiled into comparision of single u32 with only one access to the memory - this is crucial for some erratums which are called from performance-critical places. Changes in cpu_identify makes this function safe to be called on non-boot CPUs. New function CPU_MATCH was implemented which returns boolean value based on mathing masked MIDR with chip identification. Example of usage: printf("is thunder: %d\n", CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK, CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0)); printf("is generic: %d\n", CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK, CPU_IMPL_ARM, CPU_PART_FOUNDATION, 0, 0)); Reviewed by: andrew Obtained from: Semihalf Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D3030
This commit is contained in:
parent
fcb5b3a419
commit
6c03ba71f8
@ -48,7 +48,7 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
|
||||
/*
|
||||
* Per-CPU affinity as provided in MPIDR_EL1
|
||||
* Indexed by CPU number in logical order selected by the system.
|
||||
* Relevant fields can be extracetd using CPU_AFFn macros,
|
||||
* Relevant fields can be extracted using CPU_AFFn macros,
|
||||
* Aff3.Aff2.Aff1.Aff0 construct a unique CPU address in the system.
|
||||
*
|
||||
* Fields used by us:
|
||||
@ -57,28 +57,6 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
|
||||
*/
|
||||
uint64_t __cpu_affinity[MAXCPU];
|
||||
|
||||
#define CPU_IMPL_ARM 0x41
|
||||
#define CPU_IMPL_BROADCOM 0x42
|
||||
#define CPU_IMPL_CAVIUM 0x43
|
||||
#define CPU_IMPL_DEC 0x44
|
||||
#define CPU_IMPL_INFINEON 0x49
|
||||
#define CPU_IMPL_FREESCALE 0x4D
|
||||
#define CPU_IMPL_NVIDIA 0x4E
|
||||
#define CPU_IMPL_APM 0x50
|
||||
#define CPU_IMPL_QUALCOMM 0x51
|
||||
#define CPU_IMPL_MARVELL 0x56
|
||||
#define CPU_IMPL_INTEL 0x69
|
||||
|
||||
#define CPU_PART_THUNDER 0x0A1
|
||||
#define CPU_PART_FOUNDATION 0xD00
|
||||
#define CPU_PART_CORTEX_A53 0xD03
|
||||
#define CPU_PART_CORTEX_A57 0xD07
|
||||
|
||||
#define CPU_IMPL(midr) (((midr) >> 24) & 0xff)
|
||||
#define CPU_PART(midr) (((midr) >> 4) & 0xfff)
|
||||
#define CPU_VAR(midr) (((midr) >> 20) & 0xf)
|
||||
#define CPU_REV(midr) (((midr) >> 0) & 0xf)
|
||||
|
||||
struct cpu_desc {
|
||||
u_int cpu_impl;
|
||||
u_int cpu_part_num;
|
||||
@ -112,14 +90,14 @@ struct cpu_implementers {
|
||||
*/
|
||||
/* ARM Ltd. */
|
||||
static const struct cpu_parts cpu_parts_arm[] = {
|
||||
{ 0xD00, "Foundation-Model" },
|
||||
{ 0xD03, "Cortex-A53" },
|
||||
{ 0xD07, "Cortex-A57" },
|
||||
{ CPU_PART_FOUNDATION, "Foundation-Model" },
|
||||
{ CPU_PART_CORTEX_A53, "Cortex-A53" },
|
||||
{ CPU_PART_CORTEX_A57, "Cortex-A57" },
|
||||
CPU_PART_NONE,
|
||||
};
|
||||
/* Cavium */
|
||||
static const struct cpu_parts cpu_parts_cavium[] = {
|
||||
{ 0x0A1, "Thunder" },
|
||||
{ CPU_PART_THUNDER, "Thunder" },
|
||||
CPU_PART_NONE,
|
||||
};
|
||||
|
||||
@ -162,6 +140,12 @@ identify_cpu(void)
|
||||
cpu = PCPU_GET(cpuid);
|
||||
midr = get_midr();
|
||||
|
||||
/*
|
||||
* Store midr to pcpu to allow fast reading
|
||||
* from EL0, EL1 and assembly code.
|
||||
*/
|
||||
PCPU_SET(midr, midr);
|
||||
|
||||
impl_id = CPU_IMPL(midr);
|
||||
for (i = 0; i < nitems(cpu_implementers); i++) {
|
||||
if (impl_id == cpu_implementers[i].impl_id ||
|
||||
@ -183,15 +167,21 @@ identify_cpu(void)
|
||||
}
|
||||
}
|
||||
|
||||
printf("CPU: %s %s r%dp%d\n", cpu_desc[cpu].cpu_impl_name,
|
||||
cpu_desc[cpu].cpu_part_name, CPU_VAR(midr), CPU_REV(midr));
|
||||
cpu_desc[cpu].cpu_revision = CPU_REV(midr);
|
||||
cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
|
||||
|
||||
/*
|
||||
* Save affinity for the boot CPU.
|
||||
* (CPU0 in the internal system enumeration.
|
||||
*/
|
||||
/* Save affinity for current CPU */
|
||||
mpidr = get_mpidr();
|
||||
CPU_AFFINITY(0) = mpidr & CPU_AFF_MASK;
|
||||
CPU_AFFINITY(cpu) = mpidr & CPU_AFF_MASK;
|
||||
|
||||
/* Print details for boot CPU or if we want verbose output */
|
||||
if (cpu == 0 || bootverbose) {
|
||||
printf("CPU(%d): %s %s r%dp%d\n", cpu,
|
||||
cpu_desc[cpu].cpu_impl_name,
|
||||
cpu_desc[cpu].cpu_part_name,
|
||||
cpu_desc[cpu].cpu_variant,
|
||||
cpu_desc[cpu].cpu_revision);
|
||||
}
|
||||
|
||||
if (bootverbose)
|
||||
printf("CPU%u affinity: %u.%u.%u.%u\n", 0, CPU_AFF0(mpidr),
|
||||
|
@ -60,6 +60,43 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define CPU_IMPL_ARM 0x41
|
||||
#define CPU_IMPL_BROADCOM 0x42
|
||||
#define CPU_IMPL_CAVIUM 0x43
|
||||
#define CPU_IMPL_DEC 0x44
|
||||
#define CPU_IMPL_INFINEON 0x49
|
||||
#define CPU_IMPL_FREESCALE 0x4D
|
||||
#define CPU_IMPL_NVIDIA 0x4E
|
||||
#define CPU_IMPL_APM 0x50
|
||||
#define CPU_IMPL_QUALCOMM 0x51
|
||||
#define CPU_IMPL_MARVELL 0x56
|
||||
#define CPU_IMPL_INTEL 0x69
|
||||
|
||||
#define CPU_PART_THUNDER 0x0A1
|
||||
#define CPU_PART_FOUNDATION 0xD00
|
||||
#define CPU_PART_CORTEX_A53 0xD03
|
||||
#define CPU_PART_CORTEX_A57 0xD07
|
||||
|
||||
#define CPU_IMPL(midr) (((midr) >> 24) & 0xff)
|
||||
#define CPU_PART(midr) (((midr) >> 4) & 0xfff)
|
||||
#define CPU_VAR(midr) (((midr) >> 20) & 0xf)
|
||||
#define CPU_REV(midr) (((midr) >> 0) & 0xf)
|
||||
|
||||
#define CPU_IMPL_TO_MIDR(val) (((val) & 0xff) << 24)
|
||||
#define CPU_PART_TO_MIDR(val) (((val) & 0xfff) << 4)
|
||||
#define CPU_VAR_TO_MIDR(val) (((val) & 0xf) << 20)
|
||||
#define CPU_REV_TO_MIDR(val) (((val) & 0xf) << 0)
|
||||
|
||||
#define CPU_IMPL_MASK (0xff << 24)
|
||||
#define CPU_PART_MASK (0xfff << 4)
|
||||
#define CPU_VAR_MASK (0xf << 20)
|
||||
#define CPU_REV_MASK (0xf << 0)
|
||||
|
||||
#define CPU_MATCH(mask, impl, part, var, rev) \
|
||||
(((mask) & PCPU_GET(midr)) == (CPU_IMPL_TO_MIDR((impl)) | \
|
||||
CPU_PART_TO_MIDR((part)) | CPU_VAR_TO_MIDR((var)) | \
|
||||
CPU_REV_TO_MIDR((rev))))
|
||||
|
||||
extern char btext[];
|
||||
extern char etext[];
|
||||
|
||||
|
@ -36,8 +36,9 @@
|
||||
#define ALT_STACK_SIZE 128
|
||||
|
||||
#define PCPU_MD_FIELDS \
|
||||
u_int pc_acpi_id; /* ACPI CPU id */ \
|
||||
char __pad[125]
|
||||
u_int pc_acpi_id; /* ACPI CPU id */ \
|
||||
u_int pc_midr; /* stored MIDR value */ \
|
||||
char __pad[121]
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user