Skip to content

Commit d7eebbb

Browse files
marcanjannau
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 <marcan@marcan.st> Reviewed-by: Neal Gompa <neal@gompa.dev>
1 parent 10fb7b6 commit d7eebbb

6 files changed

Lines changed: 95 additions & 1 deletion

File tree

arch/arm64/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,6 +2308,8 @@ endif # ARM64_PSEUDO_NMI
23082308

23092309
config ARM64_MEMORY_MODEL_CONTROL
23102310
bool "Runtime memory model control"
2311+
default ARCH_APPLE
2312+
select ARM64_ACTLR_STATE
23112313
help
23122314
Some ARM64 CPUs support runtime switching of the CPU memory
23132315
model, which can be useful to emulate other CPU architectures
Lines changed: 15 additions & 0 deletions
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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,8 @@ static inline unsigned int get_vmid_bits(u64 mmfr1)
945945

946946
static __always_inline bool system_has_actlr_state(void)
947947
{
948-
return false;
948+
return IS_ENABLED(CONFIG_ARM64_ACTLR_STATE) &&
949+
alternative_has_cap_unlikely(ARM64_HAS_TSO_APPLE);
949950
}
950951

951952
s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new, s64 cur);

arch/arm64/kernel/cpufeature_impdef.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,51 @@
33
* Contains implementation-defined CPU feature definitions.
44
*/
55

6+
#define pr_fmt(fmt) "CPU features: " fmt
7+
68
#include <asm/cpufeature.h>
9+
#include <asm/apple_cpufeature.h>
10+
#include <linux/irqflags.h>
11+
#include <linux/preempt.h>
12+
#include <linux/printk.h>
713

814
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
15+
static bool has_apple_feature(const struct arm64_cpu_capabilities *entry, int scope)
16+
{
17+
u64 val;
18+
WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible());
19+
20+
if (read_cpuid_implementor() != ARM_CPU_IMP_APPLE)
21+
return false;
22+
23+
val = read_sysreg(aidr_el1);
24+
return cpufeature_matches(val, entry);
25+
}
26+
27+
static bool has_apple_tso(const struct arm64_cpu_capabilities *entry, int scope)
28+
{
29+
u64 val;
30+
31+
if (!has_apple_feature(entry, scope))
32+
return false;
33+
34+
/*
35+
* KVM and old versions of the macOS hypervisor will advertise TSO in
36+
* AIDR_EL1, but then ignore writes to ACTLR_EL1. Test that the bit is
37+
* actually writable before enabling TSO.
38+
*/
39+
40+
val = read_sysreg(actlr_el1);
41+
write_sysreg(val ^ ACTLR_APPLE_TSO, actlr_el1);
42+
if (!((val ^ read_sysreg(actlr_el1)) & ACTLR_APPLE_TSO)) {
43+
pr_info_once("CPU advertises Apple TSO but it is broken, ignoring\n");
44+
return false;
45+
}
46+
47+
write_sysreg(val, actlr_el1);
48+
return true;
49+
}
50+
951
static bool has_tso_fixed(const struct arm64_cpu_capabilities *entry, int scope)
1052
{
1153
/* List of CPUs that always use the TSO memory model */
@@ -22,6 +64,17 @@ static bool has_tso_fixed(const struct arm64_cpu_capabilities *entry, int scope)
2264

2365
static const struct arm64_cpu_capabilities arm64_impdef_features[] = {
2466
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
67+
{
68+
.desc = "TSO memory model (Apple)",
69+
.capability = ARM64_HAS_TSO_APPLE,
70+
.type = SCOPE_LOCAL_CPU | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU,
71+
.matches = has_apple_tso,
72+
.field_pos = AIDR_APPLE_TSO_SHIFT,
73+
.field_width = 1,
74+
.sign = FTR_UNSIGNED,
75+
.min_field_value = 1,
76+
.max_field_value = 1,
77+
},
2578
{
2679
.desc = "TSO memory model (Fixed)",
2780
.capability = ARM64_HAS_TSO_FIXED,

arch/arm64/kernel/process.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <linux/memory_ordering_model.h>
4545

4646
#include <asm/alternative.h>
47+
#include <asm/apple_cpufeature.h>
4748
#include <asm/arch_timer.h>
4849
#include <asm/compat.h>
4950
#include <asm/cpufeature.h>
@@ -668,6 +669,10 @@ void update_sctlr_el1(u64 sctlr)
668669
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
669670
int arch_prctl_mem_model_get(struct task_struct *t)
670671
{
672+
if (alternative_has_cap_unlikely(ARM64_HAS_TSO_APPLE) &&
673+
t->thread.actlr & ACTLR_APPLE_TSO)
674+
return PR_SET_MEM_MODEL_TSO;
675+
671676
return PR_SET_MEM_MODEL_DEFAULT;
672677
}
673678

@@ -677,6 +682,23 @@ int arch_prctl_mem_model_set(struct task_struct *t, unsigned long val)
677682
val == PR_SET_MEM_MODEL_TSO)
678683
return 0;
679684

685+
if (alternative_has_cap_unlikely(ARM64_HAS_TSO_APPLE)) {
686+
WARN_ON(!system_has_actlr_state());
687+
688+
switch (val) {
689+
case PR_SET_MEM_MODEL_TSO:
690+
t->thread.actlr |= ACTLR_APPLE_TSO;
691+
break;
692+
case PR_SET_MEM_MODEL_DEFAULT:
693+
t->thread.actlr &= ~ACTLR_APPLE_TSO;
694+
break;
695+
default:
696+
return -EINVAL;
697+
}
698+
write_sysreg(t->thread.actlr, actlr_el1);
699+
return 0;
700+
}
701+
680702
if (val == PR_SET_MEM_MODEL_DEFAULT)
681703
return 0;
682704

arch/arm64/tools/cpucaps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ HAS_STAGE2_FWB
5454
HAS_TCR2
5555
HAS_TIDCP1
5656
HAS_TLB_RANGE
57+
HAS_TSO_APPLE
5758
HAS_TSO_FIXED
5859
HAS_VA52
5960
HAS_VIRT_HOST_EXTN

0 commit comments

Comments
 (0)