Skip to content

Commit deeaac5

Browse files
kristina-martsenkoctmarinas
authored andcommitted
arm64: cpufeature: handle conflicts based on capability
Each system capability can be of either boot, local, or system scope, depending on when the state of the capability is finalized. When we detect a conflict on a late CPU, we either offline the CPU or panic the system. We currently always panic if the conflict is caused by a boot scope capability, and offline the CPU if the conflict is caused by a local or system scope capability. We're going to want to add a new capability (for pointer authentication) which needs to be boot scope but doesn't need to panic the system when a conflict is detected. So add a new flag to specify whether the capability requires the system to panic or not. Current boot scope capabilities are updated to set the flag, so there should be no functional change as a result of this patch. Signed-off-by: Amit Daniel Kachhap <[email protected]> Signed-off-by: Kristina Martsenko <[email protected]> Reviewed-by: Vincenzo Frascino <[email protected]> Reviewed-by: Suzuki K Poulose <[email protected]> Reviewed-by: Kees Cook <[email protected]> Signed-off-by: Catalin Marinas <[email protected]>
1 parent 8c176e1 commit deeaac5

File tree

2 files changed

+25
-16
lines changed

2 files changed

+25
-16
lines changed

arch/arm64/include/asm/cpufeature.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
208208
* In some non-typical cases either both (a) and (b), or neither,
209209
* should be permitted. This can be described by including neither
210210
* or both flags in the capability's type field.
211+
*
212+
* In case of a conflict, the CPU is prevented from booting. If the
213+
* ARM64_CPUCAP_PANIC_ON_CONFLICT flag is specified for the capability,
214+
* then a kernel panic is triggered.
211215
*/
212216

213217

@@ -240,6 +244,8 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
240244
#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU ((u16)BIT(4))
241245
/* Is it safe for a late CPU to miss this capability when system has it */
242246
#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU ((u16)BIT(5))
247+
/* Panic when a conflict is detected */
248+
#define ARM64_CPUCAP_PANIC_ON_CONFLICT ((u16)BIT(6))
243249

244250
/*
245251
* CPU errata workarounds that need to be enabled at boot time if one or
@@ -279,9 +285,11 @@ extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
279285

280286
/*
281287
* CPU feature used early in the boot based on the boot CPU. All secondary
282-
* CPUs must match the state of the capability as detected by the boot CPU.
288+
* CPUs must match the state of the capability as detected by the boot CPU. In
289+
* case of a conflict, a kernel panic is triggered.
283290
*/
284-
#define ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE ARM64_CPUCAP_SCOPE_BOOT_CPU
291+
#define ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE \
292+
(ARM64_CPUCAP_SCOPE_BOOT_CPU | ARM64_CPUCAP_PANIC_ON_CONFLICT)
285293

286294
struct arm64_cpu_capabilities {
287295
const char *desc;

arch/arm64/kernel/cpufeature.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,12 @@ cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
13761376
return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
13771377
}
13781378

1379+
static bool
1380+
cpucap_panic_on_conflict(const struct arm64_cpu_capabilities *cap)
1381+
{
1382+
return !!(cap->type & ARM64_CPUCAP_PANIC_ON_CONFLICT);
1383+
}
1384+
13791385
static const struct arm64_cpu_capabilities arm64_features[] = {
13801386
{
13811387
.desc = "GIC system register CPU interface",
@@ -2018,10 +2024,8 @@ static void __init enable_cpu_capabilities(u16 scope_mask)
20182024
* Run through the list of capabilities to check for conflicts.
20192025
* If the system has already detected a capability, take necessary
20202026
* action on this CPU.
2021-
*
2022-
* Returns "false" on conflicts.
20232027
*/
2024-
static bool verify_local_cpu_caps(u16 scope_mask)
2028+
static void verify_local_cpu_caps(u16 scope_mask)
20252029
{
20262030
int i;
20272031
bool cpu_has_cap, system_has_cap;
@@ -2066,10 +2070,12 @@ static bool verify_local_cpu_caps(u16 scope_mask)
20662070
pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
20672071
smp_processor_id(), caps->capability,
20682072
caps->desc, system_has_cap, cpu_has_cap);
2069-
return false;
2070-
}
20712073

2072-
return true;
2074+
if (cpucap_panic_on_conflict(caps))
2075+
cpu_panic_kernel();
2076+
else
2077+
cpu_die_early();
2078+
}
20732079
}
20742080

20752081
/*
@@ -2079,12 +2085,8 @@ static bool verify_local_cpu_caps(u16 scope_mask)
20792085
static void check_early_cpu_features(void)
20802086
{
20812087
verify_cpu_asid_bits();
2082-
/*
2083-
* Early features are used by the kernel already. If there
2084-
* is a conflict, we cannot proceed further.
2085-
*/
2086-
if (!verify_local_cpu_caps(SCOPE_BOOT_CPU))
2087-
cpu_panic_kernel();
2088+
2089+
verify_local_cpu_caps(SCOPE_BOOT_CPU);
20882090
}
20892091

20902092
static void
@@ -2132,8 +2134,7 @@ static void verify_local_cpu_capabilities(void)
21322134
* check_early_cpu_features(), as they need to be verified
21332135
* on all secondary CPUs.
21342136
*/
2135-
if (!verify_local_cpu_caps(SCOPE_ALL & ~SCOPE_BOOT_CPU))
2136-
cpu_die_early();
2137+
verify_local_cpu_caps(SCOPE_ALL & ~SCOPE_BOOT_CPU);
21372138

21382139
verify_local_elf_hwcaps(arm64_elf_hwcaps);
21392140

0 commit comments

Comments
 (0)