Skip to content

Commit 5f02442

Browse files
marcanherrnst
authored andcommitted
arm64: Implement PR_{GET,SET}_MEM_MODEL for always-TSO CPUs
Some ARM64 implementations are known to always use the TSO memory model. Add trivial support for the PR_{GET,SET}_MEM_MODEL prctl, which allows userspace to learn this fact. Known TSO implementations: - Nvidia Denver - Nvidia Carmel - Fujitsu A64FX Signed-off-by: Hector Martin <[email protected]>
1 parent 67ef149 commit 5f02442

File tree

6 files changed

+78
-3
lines changed

6 files changed

+78
-3
lines changed

arch/arm64/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,15 @@ config ARM64_DEBUG_PRIORITY_MASKING
21762176
If unsure, say N
21772177
endif # ARM64_PSEUDO_NMI
21782178

2179+
config ARM64_MEMORY_MODEL_CONTROL
2180+
bool "Runtime memory model control"
2181+
help
2182+
Some ARM64 CPUs support runtime switching of the CPU memory
2183+
model, which can be useful to emulate other CPU architectures
2184+
which have different memory models. Say Y to enable support
2185+
for the PR_SET_MEM_MODEL/PR_GET_MEM_MODEL prctl() calls on
2186+
CPUs with this feature.
2187+
21792188
config RELOCATABLE
21802189
bool "Build a relocatable kernel image" if EXPERT
21812190
select ARCH_HAS_RELR

arch/arm64/kernel/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
3434
cpufeature.o alternative.o cacheinfo.o \
3535
smp.o smp_spin_table.o topology.o smccc-call.o \
3636
syscall.o proton-pack.o idreg-override.o idle.o \
37-
patching.o
37+
patching.o cpufeature_impdef.o
3838

3939
obj-$(CONFIG_COMPAT) += sys32.o signal32.o \
4040
sys_compat.o

arch/arm64/kernel/cpufeature.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ DEFINE_STATIC_KEY_FALSE(arm64_mismatched_32bit_el0);
134134
*/
135135
static cpumask_var_t cpu_32bit_el0_mask __cpumask_var_read_mostly;
136136

137+
void __init init_cpu_hwcaps_indirect_list_impdef(void);
138+
137139
void dump_cpu_features(void)
138140
{
139141
/* file-wide pr_fmt adds "CPU features: " prefix */
@@ -953,7 +955,7 @@ static void init_cpu_ftr_reg(u32 sys_reg, u64 new)
953955
extern const struct arm64_cpu_capabilities arm64_errata[];
954956
static const struct arm64_cpu_capabilities arm64_features[];
955957

956-
static void __init
958+
void __init
957959
init_cpu_hwcaps_indirect_list_from_array(const struct arm64_cpu_capabilities *caps)
958960
{
959961
for (; caps->matches; caps++) {
@@ -1053,6 +1055,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
10531055
* before we handle the boot CPU below.
10541056
*/
10551057
init_cpu_hwcaps_indirect_list();
1058+
init_cpu_hwcaps_indirect_list_impdef();
10561059

10571060
/*
10581061
* Detect and enable early CPU capabilities based on the boot CPU,
@@ -1421,7 +1424,7 @@ has_always(const struct arm64_cpu_capabilities *entry, int scope)
14211424
return true;
14221425
}
14231426

1424-
static bool
1427+
bool
14251428
feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry)
14261429
{
14271430
int val = cpuid_feature_extract_field_width(reg, entry->field_pos,

arch/arm64/kernel/cpufeature_impdef.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Contains implementation-defined CPU feature definitions.
4+
*/
5+
6+
#include <asm/cpufeature.h>
7+
8+
void __init init_cpu_hwcaps_indirect_list_from_array(const struct arm64_cpu_capabilities *caps);
9+
bool feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry);
10+
11+
bool has_tso_fixed(const struct arm64_cpu_capabilities *entry, int scope)
12+
{
13+
/* List of CPUs that always use the TSO memory model */
14+
static const struct midr_range fixed_tso_list[] = {
15+
MIDR_ALL_VERSIONS(MIDR_NVIDIA_DENVER),
16+
MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
17+
MIDR_ALL_VERSIONS(MIDR_FUJITSU_A64FX),
18+
{ /* sentinel */ }
19+
};
20+
21+
return is_midr_in_range_list(read_cpuid_id(), fixed_tso_list);
22+
}
23+
24+
static const struct arm64_cpu_capabilities arm64_impdef_features[] = {
25+
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
26+
{
27+
.desc = "TSO memory model (Fixed)",
28+
.capability = ARM64_HAS_TSO_FIXED,
29+
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
30+
.matches = has_tso_fixed,
31+
},
32+
#endif
33+
{},
34+
};
35+
36+
void __init init_cpu_hwcaps_indirect_list_impdef(void)
37+
{
38+
init_cpu_hwcaps_indirect_list_from_array(arm64_impdef_features);
39+
}

arch/arm64/kernel/process.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,25 @@ static inline void actlr_thread_switch(struct task_struct *next)
540540
}
541541
#endif
542542

543+
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
544+
int arch_prctl_mem_model_get(struct task_struct *t)
545+
{
546+
return PR_SET_MEM_MODEL_DEFAULT;
547+
}
548+
549+
int arch_prctl_mem_model_set(struct task_struct *t, unsigned long val)
550+
{
551+
if (cpus_have_const_cap(ARM64_HAS_TSO_FIXED) &&
552+
val == PR_SET_MEM_MODEL_TSO)
553+
return 0;
554+
555+
if (val == PR_SET_MEM_MODEL_DEFAULT)
556+
return 0;
557+
558+
return -EINVAL;
559+
}
560+
#endif
561+
543562
/*
544563
* Thread switching.
545564
*/
@@ -679,6 +698,10 @@ void arch_setup_new_exec(void)
679698
arch_prctl_spec_ctrl_set(current, PR_SPEC_STORE_BYPASS,
680699
PR_SPEC_ENABLE);
681700
}
701+
702+
#ifdef CONFIG_ARM64_MEMORY_MODEL_CONTROL
703+
arch_prctl_mem_model_set(current, PR_SET_MEM_MODEL_DEFAULT);
704+
#endif
682705
}
683706

684707
#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI

arch/arm64/tools/cpucaps

Lines changed: 1 addition & 0 deletions
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_FIXED
4748
HAS_VIRT_HOST_EXTN
4849
HAS_WFXT
4950
HW_DBM

0 commit comments

Comments
 (0)