Skip to content

Commit 3229369

Browse files
marcanherrnst
authored andcommitted
arm64: Implement Apple IMPDEF TSO memory model control
Apple CPUs may implement the TSO memory model as an optional configurable mode. This allows x86 emulators to simplify their load/store handling, greatly increasing performance. Expose this via the prctl PR_SET_MEM_MODEL_TSO mechanism. We use the Apple IMPDEF AIDR_EL1 register to check for the availability of TSO mode, and enable this codepath on all CPUs with an Apple implementer. This relies on the ACTLR_EL1 thread state scaffolding introduced earlier. Signed-off-by: Hector Martin <[email protected]>
1 parent 5f02442 commit 3229369

File tree

6 files changed

+66
-3
lines changed

6 files changed

+66
-3
lines changed

arch/arm64/Kconfig

+2
Original file line numberDiff line numberDiff line change
@@ -2178,6 +2178,8 @@ endif # ARM64_PSEUDO_NMI
21782178

21792179
config ARM64_MEMORY_MODEL_CONTROL
21802180
bool "Runtime memory model control"
2181+
default ARCH_APPLE
2182+
select ARM64_ACTLR_STATE
21812183
help
21822184
Some ARM64 CPUs support runtime switching of the CPU memory
21832185
model, which can be useful to emulate other CPU architectures
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#ifndef __ASM_APPLE_CPUFEATURES_H
4+
#define __ASM_APPLE_CPUFEATURES_H
5+
6+
#include <linux/bits.h>
7+
#include <asm/sysreg.h>
8+
9+
#define AIDR_APPLE_TSO_SHIFT 9
10+
#define AIDR_APPLE_TSO BIT(9)
11+
12+
#define ACTLR_APPLE_TSO_SHIFT 1
13+
#define ACTLR_APPLE_TSO BIT(1)
14+
15+
#endif

arch/arm64/include/asm/cpufeature.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,8 @@ static inline unsigned int get_vmid_bits(u64 mmfr1)
917917

918918
static __always_inline bool system_has_actlr_state(void)
919919
{
920-
return false;
920+
return IS_ENABLED(CONFIG_ARM64_ACTLR_STATE) &&
921+
cpus_have_const_cap(ARM64_HAS_TSO_APPLE);
921922
}
922923

923924
struct arm64_ftr_reg *get_arm64_ftr_reg(u32 sys_id);

arch/arm64/kernel/cpufeature_impdef.c

+23
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,23 @@
44
*/
55

66
#include <asm/cpufeature.h>
7+
#include <asm/apple_cpufeature.h>
78

89
void __init init_cpu_hwcaps_indirect_list_from_array(const struct arm64_cpu_capabilities *caps);
910
bool feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry);
1011

12+
bool has_apple_feature(const struct arm64_cpu_capabilities *entry, int scope)
13+
{
14+
u64 val;
15+
WARN_ON(scope != SCOPE_SYSTEM);
16+
17+
if (read_cpuid_implementor() != ARM_CPU_IMP_APPLE)
18+
return false;
19+
20+
val = read_sysreg(aidr_el1);
21+
return feature_matches(val, entry);
22+
}
23+
1124
bool has_tso_fixed(const struct arm64_cpu_capabilities *entry, int scope)
1225
{
1326
/* List of CPUs that always use the TSO memory model */
@@ -23,6 +36,16 @@ bool has_tso_fixed(const struct arm64_cpu_capabilities *entry, int scope)
2336

2437
static const struct arm64_cpu_capabilities arm64_impdef_features[] = {
2538
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
39+
{
40+
.desc = "TSO memory model (Apple)",
41+
.capability = ARM64_HAS_TSO_APPLE,
42+
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
43+
.matches = has_apple_feature,
44+
.field_pos = AIDR_APPLE_TSO_SHIFT,
45+
.field_width = 1,
46+
.sign = FTR_UNSIGNED,
47+
.min_field_value = 1,
48+
},
2649
{
2750
.desc = "TSO memory model (Fixed)",
2851
.capability = ARM64_HAS_TSO_FIXED,

arch/arm64/kernel/process.c

+23-2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <linux/stacktrace.h>
4444

4545
#include <asm/alternative.h>
46+
#include <asm/apple_cpufeature.h>
4647
#include <asm/compat.h>
4748
#include <asm/cpufeature.h>
4849
#include <asm/cacheflush.h>
@@ -543,15 +544,35 @@ static inline void actlr_thread_switch(struct task_struct *next)
543544
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
544545
int arch_prctl_mem_model_get(struct task_struct *t)
545546
{
547+
if (cpus_have_const_cap(ARM64_HAS_TSO_APPLE) &&
548+
t->thread.actlr & ACTLR_APPLE_TSO)
549+
return PR_SET_MEM_MODEL_TSO;
550+
546551
return PR_SET_MEM_MODEL_DEFAULT;
547552
}
548553

549554
int arch_prctl_mem_model_set(struct task_struct *t, unsigned long val)
550555
{
551-
if (cpus_have_const_cap(ARM64_HAS_TSO_FIXED) &&
552-
val == PR_SET_MEM_MODEL_TSO)
556+
if (cpus_have_const_cap(ARM64_HAS_TSO_FIXED) && val == PR_SET_MEM_MODEL_TSO)
553557
return 0;
554558

559+
if (cpus_have_const_cap(ARM64_HAS_TSO_APPLE)) {
560+
WARN_ON(!system_has_actlr_state());
561+
562+
switch (val) {
563+
case PR_SET_MEM_MODEL_TSO:
564+
t->thread.actlr |= ACTLR_APPLE_TSO;
565+
break;
566+
case PR_SET_MEM_MODEL_DEFAULT:
567+
t->thread.actlr &= ~ACTLR_APPLE_TSO;
568+
break;
569+
default:
570+
return -EINVAL;
571+
}
572+
write_sysreg(t->thread.actlr, actlr_el1);
573+
return 0;
574+
}
575+
555576
if (val == PR_SET_MEM_MODEL_DEFAULT)
556577
return 0;
557578

arch/arm64/tools/cpucaps

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ HAS_SB
4444
HAS_STAGE2_FWB
4545
HAS_TIDCP1
4646
HAS_TLB_RANGE
47+
HAS_TSO_APPLE
4748
HAS_TSO_FIXED
4849
HAS_VIRT_HOST_EXTN
4950
HAS_WFXT

0 commit comments

Comments
 (0)