Skip to content

Commit 22e2c69

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 <[email protected]> Reviewed-by: Neal Gompa <[email protected]>
1 parent cc10554 commit 22e2c69

File tree

6 files changed

+65
-1
lines changed

6 files changed

+65
-1
lines changed

arch/arm64/Kconfig

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

22132213
config ARM64_MEMORY_MODEL_CONTROL
22142214
bool "Runtime memory model control"
2215+
default ARCH_APPLE
2216+
select ARM64_ACTLR_STATE
22152217
help
22162218
Some ARM64 CPUs support runtime switching of the CPU memory
22172219
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
@@ -911,7 +911,8 @@ static inline unsigned int get_vmid_bits(u64 mmfr1)
911911

912912
static __always_inline bool system_has_actlr_state(void)
913913
{
914-
return false;
914+
return IS_ENABLED(CONFIG_ARM64_ACTLR_STATE) &&
915+
alternative_has_cap_unlikely(ARM64_HAS_TSO_APPLE);
915916
}
916917

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

arch/arm64/kernel/cpufeature_impdef.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,21 @@
44
*/
55

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

89
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
10+
static bool has_apple_feature(const struct arm64_cpu_capabilities *entry, int scope)
11+
{
12+
u64 val;
13+
WARN_ON(scope != SCOPE_SYSTEM);
14+
15+
if (read_cpuid_implementor() != ARM_CPU_IMP_APPLE)
16+
return false;
17+
18+
val = read_sysreg(aidr_el1);
19+
return cpufeature_matches(val, entry);
20+
}
21+
922
static bool has_tso_fixed(const struct arm64_cpu_capabilities *entry, int scope)
1023
{
1124
/* List of CPUs that always use the TSO memory model */
@@ -22,6 +35,16 @@ static bool has_tso_fixed(const struct arm64_cpu_capabilities *entry, int scope)
2235

2336
static const struct arm64_cpu_capabilities arm64_impdef_features[] = {
2437
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
38+
{
39+
.desc = "TSO memory model (Apple)",
40+
.capability = ARM64_HAS_TSO_APPLE,
41+
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
42+
.matches = has_apple_feature,
43+
.field_pos = AIDR_APPLE_TSO_SHIFT,
44+
.field_width = 1,
45+
.sign = FTR_UNSIGNED,
46+
.min_field_value = 1,
47+
},
2548
{
2649
.desc = "TSO memory model (Fixed)",
2750
.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/compat.h>
4849
#include <asm/cpufeature.h>
4950
#include <asm/cacheflush.h>
@@ -522,6 +523,10 @@ void update_sctlr_el1(u64 sctlr)
522523
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
523524
int arch_prctl_mem_model_get(struct task_struct *t)
524525
{
526+
if (alternative_has_cap_unlikely(ARM64_HAS_TSO_APPLE) &&
527+
t->thread.actlr & ACTLR_APPLE_TSO)
528+
return PR_SET_MEM_MODEL_TSO;
529+
525530
return PR_SET_MEM_MODEL_DEFAULT;
526531
}
527532

@@ -531,6 +536,23 @@ int arch_prctl_mem_model_set(struct task_struct *t, unsigned long val)
531536
val == PR_SET_MEM_MODEL_TSO)
532537
return 0;
533538

539+
if (alternative_has_cap_unlikely(ARM64_HAS_TSO_APPLE)) {
540+
WARN_ON(!system_has_actlr_state());
541+
542+
switch (val) {
543+
case PR_SET_MEM_MODEL_TSO:
544+
t->thread.actlr |= ACTLR_APPLE_TSO;
545+
break;
546+
case PR_SET_MEM_MODEL_DEFAULT:
547+
t->thread.actlr &= ~ACTLR_APPLE_TSO;
548+
break;
549+
default:
550+
return -EINVAL;
551+
}
552+
write_sysreg(t->thread.actlr, actlr_el1);
553+
return 0;
554+
}
555+
534556
if (val == PR_SET_MEM_MODEL_DEFAULT)
535557
return 0;
536558

arch/arm64/tools/cpucaps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ HAS_STAGE2_FWB
5252
HAS_TCR2
5353
HAS_TIDCP1
5454
HAS_TLB_RANGE
55+
HAS_TSO_APPLE
5556
HAS_TSO_FIXED
5657
HAS_VA52
5758
HAS_VIRT_HOST_EXTN

0 commit comments

Comments
 (0)