|
@@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
|
|
extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
|
|
extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
|
|
extern char __qcom_hyp_sanitize_link_stack_start[];
|
|
extern char __qcom_hyp_sanitize_link_stack_start[];
|
|
extern char __qcom_hyp_sanitize_link_stack_end[];
|
|
extern char __qcom_hyp_sanitize_link_stack_end[];
|
|
|
|
+extern char __smccc_workaround_1_smc_start[];
|
|
|
|
+extern char __smccc_workaround_1_smc_end[];
|
|
|
|
+extern char __smccc_workaround_1_hvc_start[];
|
|
|
|
+extern char __smccc_workaround_1_hvc_end[];
|
|
|
|
|
|
static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
|
|
static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
|
|
const char *hyp_vecs_end)
|
|
const char *hyp_vecs_end)
|
|
@@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
|
|
#define __psci_hyp_bp_inval_end NULL
|
|
#define __psci_hyp_bp_inval_end NULL
|
|
#define __qcom_hyp_sanitize_link_stack_start NULL
|
|
#define __qcom_hyp_sanitize_link_stack_start NULL
|
|
#define __qcom_hyp_sanitize_link_stack_end NULL
|
|
#define __qcom_hyp_sanitize_link_stack_end NULL
|
|
|
|
+#define __smccc_workaround_1_smc_start NULL
|
|
|
|
+#define __smccc_workaround_1_smc_end NULL
|
|
|
|
+#define __smccc_workaround_1_hvc_start NULL
|
|
|
|
+#define __smccc_workaround_1_hvc_end NULL
|
|
|
|
|
|
static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
|
|
static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
|
|
const char *hyp_vecs_start,
|
|
const char *hyp_vecs_start,
|
|
@@ -142,17 +150,75 @@ static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
|
|
__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
|
|
__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#include <uapi/linux/psci.h>
|
|
|
|
+#include <linux/arm-smccc.h>
|
|
#include <linux/psci.h>
|
|
#include <linux/psci.h>
|
|
|
|
|
|
|
|
+static void call_smc_arch_workaround_1(void)
|
|
|
|
+{
|
|
|
|
+ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void call_hvc_arch_workaround_1(void)
|
|
|
|
+{
|
|
|
|
+ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
|
|
|
|
+{
|
|
|
|
+ bp_hardening_cb_t cb;
|
|
|
|
+ void *smccc_start, *smccc_end;
|
|
|
|
+ struct arm_smccc_res res;
|
|
|
|
+
|
|
|
|
+ if (!entry->matches(entry, SCOPE_LOCAL_CPU))
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ switch (psci_ops.conduit) {
|
|
|
|
+ case PSCI_CONDUIT_HVC:
|
|
|
|
+ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
|
|
|
|
+ ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
|
|
|
+ if (res.a0)
|
|
|
|
+ return false;
|
|
|
|
+ cb = call_hvc_arch_workaround_1;
|
|
|
|
+ smccc_start = __smccc_workaround_1_hvc_start;
|
|
|
|
+ smccc_end = __smccc_workaround_1_hvc_end;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case PSCI_CONDUIT_SMC:
|
|
|
|
+ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
|
|
|
|
+ ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
|
|
|
+ if (res.a0)
|
|
|
|
+ return false;
|
|
|
|
+ cb = call_smc_arch_workaround_1;
|
|
|
|
+ smccc_start = __smccc_workaround_1_smc_start;
|
|
|
|
+ smccc_end = __smccc_workaround_1_smc_end;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
static int enable_psci_bp_hardening(void *data)
|
|
static int enable_psci_bp_hardening(void *data)
|
|
{
|
|
{
|
|
const struct arm64_cpu_capabilities *entry = data;
|
|
const struct arm64_cpu_capabilities *entry = data;
|
|
|
|
|
|
- if (psci_ops.get_version)
|
|
|
|
|
|
+ if (psci_ops.get_version) {
|
|
|
|
+ if (check_smccc_arch_workaround_1(entry))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
install_bp_hardening_cb(entry,
|
|
install_bp_hardening_cb(entry,
|
|
(bp_hardening_cb_t)psci_ops.get_version,
|
|
(bp_hardening_cb_t)psci_ops.get_version,
|
|
__psci_hyp_bp_inval_start,
|
|
__psci_hyp_bp_inval_start,
|
|
__psci_hyp_bp_inval_end);
|
|
__psci_hyp_bp_inval_end);
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|