Skip to content

Commit b092201

Browse files
Marc Zyngierctmarinas
authored andcommitted
arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1. It is lovely. Really. Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent f2d3b2e commit b092201

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

arch/arm64/kernel/bpi.S

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include <linux/linkage.h>
20+
#include <linux/arm-smccc.h>
2021

2122
.macro ventry target
2223
.rept 31
@@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
8586
.endr
8687
ldp x29, x30, [sp], #16
8788
ENTRY(__qcom_hyp_sanitize_link_stack_end)
89+
90+
.macro smccc_workaround_1 inst
91+
sub sp, sp, #(8 * 4)
92+
stp x2, x3, [sp, #(8 * 0)]
93+
stp x0, x1, [sp, #(8 * 2)]
94+
mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1
95+
\inst #0
96+
ldp x2, x3, [sp, #(8 * 0)]
97+
ldp x0, x1, [sp, #(8 * 2)]
98+
add sp, sp, #(8 * 4)
99+
.endm
100+
101+
ENTRY(__smccc_workaround_1_smc_start)
102+
smccc_workaround_1 smc
103+
ENTRY(__smccc_workaround_1_smc_end)
104+
105+
ENTRY(__smccc_workaround_1_hvc_start)
106+
smccc_workaround_1 hvc
107+
ENTRY(__smccc_workaround_1_hvc_end)

arch/arm64/kernel/cpu_errata.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
7070
extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
7171
extern char __qcom_hyp_sanitize_link_stack_start[];
7272
extern char __qcom_hyp_sanitize_link_stack_end[];
73+
extern char __smccc_workaround_1_smc_start[];
74+
extern char __smccc_workaround_1_smc_end[];
75+
extern char __smccc_workaround_1_hvc_start[];
76+
extern char __smccc_workaround_1_hvc_end[];
7377

7478
static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
7579
const char *hyp_vecs_end)
@@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
116120
#define __psci_hyp_bp_inval_end NULL
117121
#define __qcom_hyp_sanitize_link_stack_start NULL
118122
#define __qcom_hyp_sanitize_link_stack_end NULL
123+
#define __smccc_workaround_1_smc_start NULL
124+
#define __smccc_workaround_1_smc_end NULL
125+
#define __smccc_workaround_1_hvc_start NULL
126+
#define __smccc_workaround_1_hvc_end NULL
119127

120128
static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
121129
const char *hyp_vecs_start,
@@ -142,17 +150,75 @@ static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
142150
__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
143151
}
144152

153+
#include <uapi/linux/psci.h>
154+
#include <linux/arm-smccc.h>
145155
#include <linux/psci.h>
146156

157+
static void call_smc_arch_workaround_1(void)
158+
{
159+
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
160+
}
161+
162+
static void call_hvc_arch_workaround_1(void)
163+
{
164+
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
165+
}
166+
167+
static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
168+
{
169+
bp_hardening_cb_t cb;
170+
void *smccc_start, *smccc_end;
171+
struct arm_smccc_res res;
172+
173+
if (!entry->matches(entry, SCOPE_LOCAL_CPU))
174+
return false;
175+
176+
if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
177+
return false;
178+
179+
switch (psci_ops.conduit) {
180+
case PSCI_CONDUIT_HVC:
181+
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
182+
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
183+
if (res.a0)
184+
return false;
185+
cb = call_hvc_arch_workaround_1;
186+
smccc_start = __smccc_workaround_1_hvc_start;
187+
smccc_end = __smccc_workaround_1_hvc_end;
188+
break;
189+
190+
case PSCI_CONDUIT_SMC:
191+
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
192+
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
193+
if (res.a0)
194+
return false;
195+
cb = call_smc_arch_workaround_1;
196+
smccc_start = __smccc_workaround_1_smc_start;
197+
smccc_end = __smccc_workaround_1_smc_end;
198+
break;
199+
200+
default:
201+
return false;
202+
}
203+
204+
install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
205+
206+
return true;
207+
}
208+
147209
static int enable_psci_bp_hardening(void *data)
148210
{
149211
const struct arm64_cpu_capabilities *entry = data;
150212

151-
if (psci_ops.get_version)
213+
if (psci_ops.get_version) {
214+
if (check_smccc_arch_workaround_1(entry))
215+
return 0;
216+
152217
install_bp_hardening_cb(entry,
153218
(bp_hardening_cb_t)psci_ops.get_version,
154219
__psci_hyp_bp_inval_start,
155220
__psci_hyp_bp_inval_end);
221+
}
156222

157223
return 0;
158224
}

0 commit comments

Comments
 (0)