-
Notifications
You must be signed in to change notification settings - Fork 874
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
If the CPU cores implement FEAT_IDST, emulate access to the CPU ID
registers from userland and set HWCAP_CPUID. This will allow detection of features to be introduced into the architecture in the future without allocating new HWCAP_xxx or HWCAP2_xxx bits. We provide the same sanitized view of the CPU ID registers as is currently available through sysctl(2). Note that this introduces an unconditional read of ID_AA64MMFR2_EL1. This is known to cause problems on older versions of QEMU. If this turns out to be a problem in cases where updating QEMU is not an option, we'll have to implement a workaround. Also note that since we don't emulate the CPU ID registers on older core, this means that microarchitectural optimizations keyed of reads of MIDR_EL1 are not possible on OpenBSD. I don't think that is a real problem. ok jca@
- Loading branch information
Showing
5 changed files
with
176 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: cpu.c,v 1.129 2024/07/21 18:57:31 kettenis Exp $ */ | ||
/* $OpenBSD: cpu.c,v 1.130 2024/07/24 21:24:18 kettenis Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2016 Dale Rahn <[email protected]> | ||
|
@@ -242,6 +242,9 @@ int cpu_node; | |
uint64_t cpu_id_aa64isar0; | ||
uint64_t cpu_id_aa64isar1; | ||
uint64_t cpu_id_aa64isar2; | ||
uint64_t cpu_id_aa64mmfr0; | ||
uint64_t cpu_id_aa64mmfr1; | ||
uint64_t cpu_id_aa64mmfr2; | ||
uint64_t cpu_id_aa64pfr0; | ||
uint64_t cpu_id_aa64pfr1; | ||
|
||
|
@@ -487,6 +490,7 @@ cpu_identify(struct cpu_info *ci) | |
static uint64_t prev_id_aa64isar2; | ||
static uint64_t prev_id_aa64mmfr0; | ||
static uint64_t prev_id_aa64mmfr1; | ||
static uint64_t prev_id_aa64mmfr2; | ||
static uint64_t prev_id_aa64pfr0; | ||
static uint64_t prev_id_aa64pfr1; | ||
uint64_t midr, impl, part; | ||
|
@@ -642,6 +646,7 @@ cpu_identify(struct cpu_info *ci) | |
READ_SPECIALREG(id_aa64isar2_el1) == prev_id_aa64isar2 && | ||
READ_SPECIALREG(id_aa64mmfr0_el1) == prev_id_aa64mmfr0 && | ||
READ_SPECIALREG(id_aa64mmfr1_el1) == prev_id_aa64mmfr1 && | ||
READ_SPECIALREG(id_aa64mmfr2_el1) == prev_id_aa64mmfr2 && | ||
READ_SPECIALREG(id_aa64pfr0_el1) == prev_id_aa64pfr0 && | ||
READ_SPECIALREG(id_aa64pfr1_el1) == prev_id_aa64pfr1) | ||
return; | ||
|
@@ -662,6 +667,18 @@ cpu_identify(struct cpu_info *ci) | |
printf("\n%s: mismatched ID_AA64ISAR2_EL1", | ||
ci->ci_dev->dv_xname); | ||
} | ||
if (READ_SPECIALREG(id_aa64mmfr0_el1) != cpu_id_aa64mmfr0) { | ||
printf("\n%s: mismatched ID_AA64MMFR0_EL1", | ||
ci->ci_dev->dv_xname); | ||
} | ||
if (READ_SPECIALREG(id_aa64mmfr1_el1) != cpu_id_aa64mmfr1) { | ||
printf("\n%s: mismatched ID_AA64MMFR1_EL1", | ||
ci->ci_dev->dv_xname); | ||
} | ||
if (READ_SPECIALREG(id_aa64mmfr2_el1) != cpu_id_aa64mmfr2) { | ||
printf("\n%s: mismatched ID_AA64MMFR2_EL1", | ||
ci->ci_dev->dv_xname); | ||
} | ||
id = READ_SPECIALREG(id_aa64pfr0_el1); | ||
/* Allow CSV2/CVS3 to be different. */ | ||
id &= ~ID_AA64PFR0_CSV2_MASK; | ||
|
@@ -938,6 +955,16 @@ cpu_identify(struct cpu_info *ci) | |
sep = ","; | ||
} | ||
|
||
/* | ||
* ID_AA64MMFR2 | ||
*/ | ||
id = READ_SPECIALREG(id_aa64mmfr2_el1); | ||
|
||
if (ID_AA64MMFR2_IDS(id) >= ID_AA64MMFR2_IDS_IMPL) { | ||
printf("%sIDS", sep); | ||
sep = ","; | ||
} | ||
|
||
/* | ||
* ID_AA64PFR0 | ||
*/ | ||
|
@@ -989,6 +1016,7 @@ cpu_identify(struct cpu_info *ci) | |
prev_id_aa64isar2 = READ_SPECIALREG(id_aa64isar2_el1); | ||
prev_id_aa64mmfr0 = READ_SPECIALREG(id_aa64mmfr0_el1); | ||
prev_id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1); | ||
prev_id_aa64mmfr2 = READ_SPECIALREG(id_aa64mmfr2_el1); | ||
prev_id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1); | ||
prev_id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1); | ||
|
||
|
@@ -1023,6 +1051,7 @@ cpu_identify(struct cpu_info *ci) | |
void | ||
cpu_identify_cleanup(void) | ||
{ | ||
uint64_t id_aa64mmfr2; | ||
uint64_t value; | ||
|
||
/* ID_AA64ISAR0_EL1 */ | ||
|
@@ -1040,6 +1069,15 @@ cpu_identify_cleanup(void) | |
value &= ~ID_AA64ISAR2_CLRBHB_MASK; | ||
cpu_id_aa64isar2 = value; | ||
|
||
/* ID_AA64MMFR0_EL1 */ | ||
cpu_id_aa64mmfr0 = 0; | ||
|
||
/* ID_AA64MMFR1_EL1 */ | ||
cpu_id_aa64mmfr1 = 0; | ||
|
||
/* ID_AA64MMFR2_EL1 */ | ||
cpu_id_aa64mmfr2 = 0; | ||
|
||
/* ID_AA64PFR0_EL1 */ | ||
value = 0; | ||
value |= cpu_id_aa64pfr0 & ID_AA64PFR0_FP_MASK; | ||
|
@@ -1071,7 +1109,9 @@ cpu_identify_cleanup(void) | |
hwcap |= HWCAP_ATOMICS; | ||
/* HWCAP_FPHP */ | ||
/* HWCAP_ASIMDHP */ | ||
/* HWCAP_CPUID */ | ||
id_aa64mmfr2 = READ_SPECIALREG(id_aa64mmfr2_el1); | ||
if (ID_AA64MMFR2_IDS(id_aa64mmfr2) >= ID_AA64MMFR2_IDS_IMPL) | ||
hwcap |= HWCAP_CPUID; | ||
if (ID_AA64ISAR0_RDM(cpu_id_aa64isar0) >= ID_AA64ISAR0_RDM_IMPL) | ||
hwcap |= HWCAP_ASIMDRDM; | ||
if (ID_AA64ISAR1_JSCVT(cpu_id_aa64isar1) >= ID_AA64ISAR1_JSCVT_IMPL) | ||
|
@@ -1271,6 +1311,9 @@ cpu_attach(struct device *parent, struct device *dev, void *aux) | |
cpu_id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1); | ||
cpu_id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1); | ||
cpu_id_aa64isar2 = READ_SPECIALREG(id_aa64isar2_el1); | ||
cpu_id_aa64mmfr0 = READ_SPECIALREG(id_aa64mmfr0_el1); | ||
cpu_id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1); | ||
cpu_id_aa64mmfr2 = READ_SPECIALREG(id_aa64mmfr2_el1); | ||
cpu_id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1); | ||
cpu_id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: machdep.c,v 1.91 2024/07/17 15:21:59 kettenis Exp $ */ | ||
/* $OpenBSD: machdep.c,v 1.92 2024/07/24 21:24:18 kettenis Exp $ */ | ||
/* | ||
* Copyright (c) 2014 Patrick Wildt <[email protected]> | ||
* Copyright (c) 2021 Mark Kettenis <[email protected]> | ||
|
@@ -360,8 +360,11 @@ cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, | |
case CPU_ID_AA64PFR1: | ||
return sysctl_rdquad(oldp, oldlenp, newp, cpu_id_aa64pfr1); | ||
case CPU_ID_AA64MMFR0: | ||
return sysctl_rdquad(oldp, oldlenp, newp, cpu_id_aa64mmfr0); | ||
case CPU_ID_AA64MMFR1: | ||
return sysctl_rdquad(oldp, oldlenp, newp, cpu_id_aa64mmfr1); | ||
case CPU_ID_AA64MMFR2: | ||
return sysctl_rdquad(oldp, oldlenp, newp, cpu_id_aa64mmfr2); | ||
case CPU_ID_AA64SMFR0: | ||
case CPU_ID_AA64ZFR0: | ||
return sysctl_rdquad(oldp, oldlenp, newp, 0); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: cpu.h,v 1.49 2024/07/17 15:21:59 kettenis Exp $ */ | ||
/* $OpenBSD: cpu.h,v 1.50 2024/07/24 21:24:18 kettenis Exp $ */ | ||
/* | ||
* Copyright (c) 2016 Dale Rahn <[email protected]> | ||
* | ||
|
@@ -64,6 +64,9 @@ | |
extern uint64_t cpu_id_aa64isar0; | ||
extern uint64_t cpu_id_aa64isar1; | ||
extern uint64_t cpu_id_aa64isar2; | ||
extern uint64_t cpu_id_aa64mmfr0; | ||
extern uint64_t cpu_id_aa64mmfr1; | ||
extern uint64_t cpu_id_aa64mmfr2; | ||
extern uint64_t cpu_id_aa64pfr0; | ||
extern uint64_t cpu_id_aa64pfr1; | ||
|
||
|