diff mbox series

[v3,12/13] arm64: Implement branch predictor hardening for Falkor

Message ID 1515432758-26440-13-git-send-email-will.deacon@arm.com
State New
Headers show
Series arm64 kpti hardening and variant 2 workarounds | expand

Commit Message

Will Deacon Jan. 8, 2018, 5:32 p.m. UTC
From: Shanker Donthineni <shankerd@codeaurora.org>


Falkor is susceptible to branch predictor aliasing and can
theoretically be attacked by malicious code. This patch
implements a mitigation for these attacks, preventing any
malicious entries from affecting other victim contexts.

Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>

[will: fix label name when !CONFIG_KVM]
Signed-off-by: Will Deacon <will.deacon@arm.com>

---
 arch/arm64/include/asm/cpucaps.h |  3 ++-
 arch/arm64/include/asm/kvm_asm.h |  2 ++
 arch/arm64/kernel/bpi.S          |  8 +++++++
 arch/arm64/kernel/cpu_errata.c   | 49 ++++++++++++++++++++++++++++++++++++++--
 arch/arm64/kvm/hyp/entry.S       | 12 ++++++++++
 arch/arm64/kvm/hyp/switch.c      | 10 ++++++++
 6 files changed, 81 insertions(+), 3 deletions(-)

-- 
2.1.4

Comments

Shanker Donthineni Jan. 12, 2018, 5:58 p.m. UTC | #1
Hi Will,
 

This patch is the right one for variant2, checks QDF2400 part numbers QCOM_FALKOR and FALKOR_V1
but unfortunately it got modified and merged to linux-next branch causing confusion.Please revert
and merge [V2] patch to fix the problem.
 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/arch/arm64?h=next-20180112&id=ec82b567a74fbdffdf418d4bb381d55f6a9096af

[v2] https://www.spinics.net/lists/arm-kernel/msg627364.html


Thanks,
Shanker

On 01/08/2018 11:32 AM, Will Deacon wrote:
> From: Shanker Donthineni <shankerd@codeaurora.org>

> 

> Falkor is susceptible to branch predictor aliasing and can

> theoretically be attacked by malicious code. This patch

> implements a mitigation for these attacks, preventing any

> malicious entries from affecting other victim contexts.

> 

> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>

> [will: fix label name when !CONFIG_KVM]

> Signed-off-by: Will Deacon <will.deacon@arm.com>

> ---

>  arch/arm64/include/asm/cpucaps.h |  3 ++-

>  arch/arm64/include/asm/kvm_asm.h |  2 ++

>  arch/arm64/kernel/bpi.S          |  8 +++++++

>  arch/arm64/kernel/cpu_errata.c   | 49 ++++++++++++++++++++++++++++++++++++++--

>  arch/arm64/kvm/hyp/entry.S       | 12 ++++++++++

>  arch/arm64/kvm/hyp/switch.c      | 10 ++++++++

>  6 files changed, 81 insertions(+), 3 deletions(-)

> 

> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h

> index 51616e77fe6b..7049b4802587 100644

> --- a/arch/arm64/include/asm/cpucaps.h

> +++ b/arch/arm64/include/asm/cpucaps.h

> @@ -43,7 +43,8 @@

>  #define ARM64_SVE				22

>  #define ARM64_UNMAP_KERNEL_AT_EL0		23

>  #define ARM64_HARDEN_BRANCH_PREDICTOR		24

> +#define ARM64_HARDEN_BP_POST_GUEST_EXIT		25

>  

> -#define ARM64_NCAPS				25

> +#define ARM64_NCAPS				26

>  

>  #endif /* __ASM_CPUCAPS_H */

> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h

> index ab4d0a926043..24961b732e65 100644

> --- a/arch/arm64/include/asm/kvm_asm.h

> +++ b/arch/arm64/include/asm/kvm_asm.h

> @@ -68,6 +68,8 @@ extern u32 __kvm_get_mdcr_el2(void);

>  

>  extern u32 __init_stage2_translation(void);

>  

> +extern void __qcom_hyp_sanitize_btac_predictors(void);

> +

>  #endif

>  

>  #endif /* __ARM_KVM_ASM_H__ */

> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S

> index dec95bd82e31..76225c2611ea 100644

> --- a/arch/arm64/kernel/bpi.S

> +++ b/arch/arm64/kernel/bpi.S

> @@ -77,3 +77,11 @@ ENTRY(__psci_hyp_bp_inval_start)

>  	ldp	x0, x1, [sp, #(16 * 8)]

>  	add	sp, sp, #(8 * 18)

>  ENTRY(__psci_hyp_bp_inval_end)

> +

> +ENTRY(__qcom_hyp_sanitize_link_stack_start)

> +	stp     x29, x30, [sp, #-16]!

> +	.rept	16

> +	bl	. + 4

> +	.endr

> +	ldp	x29, x30, [sp], #16

> +ENTRY(__qcom_hyp_sanitize_link_stack_end)

> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c

> index cb0fb3796bb8..7b4efde087fc 100644

> --- a/arch/arm64/kernel/cpu_errata.c

> +++ b/arch/arm64/kernel/cpu_errata.c

> @@ -54,6 +54,8 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);

>  

>  #ifdef CONFIG_KVM

>  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_end[];

>  

>  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,

>  				const char *hyp_vecs_end)

> @@ -96,8 +98,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,

>  	spin_unlock(&bp_lock);

>  }

>  #else

> -#define __psci_hyp_bp_inval_start	NULL

> -#define __psci_hyp_bp_inval_end		NULL

> +#define __psci_hyp_bp_inval_start		NULL

> +#define __psci_hyp_bp_inval_end			NULL

> +#define __qcom_hyp_sanitize_link_stack_start	NULL

> +#define __qcom_hyp_sanitize_link_stack_end	NULL

>  

>  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,

>  				      const char *hyp_vecs_start,

> @@ -138,6 +142,29 @@ static int enable_psci_bp_hardening(void *data)

>  

>  	return 0;

>  }

> +

> +static void qcom_link_stack_sanitization(void)

> +{

> +	u64 tmp;

> +

> +	asm volatile("mov	%0, x30		\n"

> +		     ".rept	16		\n"

> +		     "bl	. + 4		\n"

> +		     ".endr			\n"

> +		     "mov	x30, %0		\n"

> +		     : "=&r" (tmp));

> +}

> +

> +static int qcom_enable_link_stack_sanitization(void *data)

> +{

> +	const struct arm64_cpu_capabilities *entry = data;

> +

> +	install_bp_hardening_cb(entry, qcom_link_stack_sanitization,

> +				__qcom_hyp_sanitize_link_stack_start,

> +				__qcom_hyp_sanitize_link_stack_end);

> +

> +	return 0;

> +}

>  #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */

>  

>  #define MIDR_RANGE(model, min, max) \

> @@ -302,6 +329,24 @@ const struct arm64_cpu_capabilities arm64_errata[] = {

>  		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),

>  		.enable = enable_psci_bp_hardening,

>  	},

> +	{

> +		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,

> +		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),

> +		.enable = qcom_enable_link_stack_sanitization,

> +	},

> +	{

> +		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,

> +		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),

> +		.enable = qcom_enable_link_stack_sanitization,

> +	},

> +	{

> +		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,

> +		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),

> +	},

> +	{

> +		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,

> +		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),

> +	},

>  #endif

>  	{

>  	}

> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S

> index 12ee62d6d410..9c45c6af1f58 100644

> --- a/arch/arm64/kvm/hyp/entry.S

> +++ b/arch/arm64/kvm/hyp/entry.S

> @@ -196,3 +196,15 @@ alternative_endif

>  

>  	eret

>  ENDPROC(__fpsimd_guest_restore)

> +

> +ENTRY(__qcom_hyp_sanitize_btac_predictors)

> +	/**

> +	 * Call SMC64 with Silicon provider serviceID 23<<8 (0xc2001700)

> +	 * 0xC2000000-0xC200FFFF: assigned to SiP Service Calls

> +	 * b15-b0: contains SiP functionID

> +	 */

> +	movz    x0, #0x1700

> +	movk    x0, #0xc200, lsl #16

> +	smc     #0

> +	ret

> +ENDPROC(__qcom_hyp_sanitize_btac_predictors)

> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c

> index 4d273f6d0e69..7e373791fad1 100644

> --- a/arch/arm64/kvm/hyp/switch.c

> +++ b/arch/arm64/kvm/hyp/switch.c

> @@ -406,6 +406,16 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)

>  		/* 0 falls through to be handled out of EL2 */

>  	}

>  

> +	if (cpus_have_const_cap(ARM64_HARDEN_BP_POST_GUEST_EXIT)) {

> +		u32 midr = read_cpuid_id();

> +

> +		/* Apply BTAC predictors mitigation to all Falkor chips */

> +		if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) ||

> +		    ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1)) {

> +			__qcom_hyp_sanitize_btac_predictors();

> +		}

> +	}

> +

>  	fp_enabled = __fpsimd_enabled();

>  

>  	__sysreg_save_guest_state(guest_ctxt);

> 


-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 51616e77fe6b..7049b4802587 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -43,7 +43,8 @@ 
 #define ARM64_SVE				22
 #define ARM64_UNMAP_KERNEL_AT_EL0		23
 #define ARM64_HARDEN_BRANCH_PREDICTOR		24
+#define ARM64_HARDEN_BP_POST_GUEST_EXIT		25
 
-#define ARM64_NCAPS				25
+#define ARM64_NCAPS				26
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index ab4d0a926043..24961b732e65 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -68,6 +68,8 @@  extern u32 __kvm_get_mdcr_el2(void);
 
 extern u32 __init_stage2_translation(void);
 
+extern void __qcom_hyp_sanitize_btac_predictors(void);
+
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
index dec95bd82e31..76225c2611ea 100644
--- a/arch/arm64/kernel/bpi.S
+++ b/arch/arm64/kernel/bpi.S
@@ -77,3 +77,11 @@  ENTRY(__psci_hyp_bp_inval_start)
 	ldp	x0, x1, [sp, #(16 * 8)]
 	add	sp, sp, #(8 * 18)
 ENTRY(__psci_hyp_bp_inval_end)
+
+ENTRY(__qcom_hyp_sanitize_link_stack_start)
+	stp     x29, x30, [sp, #-16]!
+	.rept	16
+	bl	. + 4
+	.endr
+	ldp	x29, x30, [sp], #16
+ENTRY(__qcom_hyp_sanitize_link_stack_end)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index cb0fb3796bb8..7b4efde087fc 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -54,6 +54,8 @@  DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
 
 #ifdef CONFIG_KVM
 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_end[];
 
 static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
 				const char *hyp_vecs_end)
@@ -96,8 +98,10 @@  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 	spin_unlock(&bp_lock);
 }
 #else
-#define __psci_hyp_bp_inval_start	NULL
-#define __psci_hyp_bp_inval_end		NULL
+#define __psci_hyp_bp_inval_start		NULL
+#define __psci_hyp_bp_inval_end			NULL
+#define __qcom_hyp_sanitize_link_stack_start	NULL
+#define __qcom_hyp_sanitize_link_stack_end	NULL
 
 static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 				      const char *hyp_vecs_start,
@@ -138,6 +142,29 @@  static int enable_psci_bp_hardening(void *data)
 
 	return 0;
 }
+
+static void qcom_link_stack_sanitization(void)
+{
+	u64 tmp;
+
+	asm volatile("mov	%0, x30		\n"
+		     ".rept	16		\n"
+		     "bl	. + 4		\n"
+		     ".endr			\n"
+		     "mov	x30, %0		\n"
+		     : "=&r" (tmp));
+}
+
+static int qcom_enable_link_stack_sanitization(void *data)
+{
+	const struct arm64_cpu_capabilities *entry = data;
+
+	install_bp_hardening_cb(entry, qcom_link_stack_sanitization,
+				__qcom_hyp_sanitize_link_stack_start,
+				__qcom_hyp_sanitize_link_stack_end);
+
+	return 0;
+}
 #endif	/* CONFIG_HARDEN_BRANCH_PREDICTOR */
 
 #define MIDR_RANGE(model, min, max) \
@@ -302,6 +329,24 @@  const struct arm64_cpu_capabilities arm64_errata[] = {
 		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
 		.enable = enable_psci_bp_hardening,
 	},
+	{
+		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
+		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+		.enable = qcom_enable_link_stack_sanitization,
+	},
+	{
+		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
+		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
+		.enable = qcom_enable_link_stack_sanitization,
+	},
+	{
+		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
+		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+	},
+	{
+		.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
+		MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
+	},
 #endif
 	{
 	}
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 12ee62d6d410..9c45c6af1f58 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -196,3 +196,15 @@  alternative_endif
 
 	eret
 ENDPROC(__fpsimd_guest_restore)
+
+ENTRY(__qcom_hyp_sanitize_btac_predictors)
+	/**
+	 * Call SMC64 with Silicon provider serviceID 23<<8 (0xc2001700)
+	 * 0xC2000000-0xC200FFFF: assigned to SiP Service Calls
+	 * b15-b0: contains SiP functionID
+	 */
+	movz    x0, #0x1700
+	movk    x0, #0xc200, lsl #16
+	smc     #0
+	ret
+ENDPROC(__qcom_hyp_sanitize_btac_predictors)
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 4d273f6d0e69..7e373791fad1 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -406,6 +406,16 @@  int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
 		/* 0 falls through to be handled out of EL2 */
 	}
 
+	if (cpus_have_const_cap(ARM64_HARDEN_BP_POST_GUEST_EXIT)) {
+		u32 midr = read_cpuid_id();
+
+		/* Apply BTAC predictors mitigation to all Falkor chips */
+		if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) ||
+		    ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1)) {
+			__qcom_hyp_sanitize_btac_predictors();
+		}
+	}
+
 	fp_enabled = __fpsimd_enabled();
 
 	__sysreg_save_guest_state(guest_ctxt);