diff options
author | Mark Rutland <mark.rutland@arm.com> | 2013-07-18 12:20:33 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-07-26 07:01:17 -0400 |
commit | 8fbac214e5c594a0c2fe78c14adf2cdbb1febc92 (patch) | |
tree | 0f331dcd30fb4110f10afe7cde11bc40b8f83ada /arch | |
parent | ab8d46c0609843a83aef3f486365ca5e7c21d537 (diff) |
ARM: 7787/1: virt: ensure visibility of __boot_cpu_mode
Secondary CPUs write to __boot_cpu_mode with caches disabled, and thus a
cached value of __boot_cpu_mode may be incoherent with that in memory.
This could lead to a failure to detect mismatched boot modes.
This patch adds flushing to ensure that writes by secondaries to
__boot_cpu_mode are made visible before we test against it.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Dave Martin <Dave.Martin@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Christoffer Dall <cdall@cs.columbia.edu>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/include/asm/virt.h | 12 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 2 |
2 files changed, 14 insertions, 0 deletions
diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h index 50af92bac737..4371f45c5784 100644 --- a/arch/arm/include/asm/virt.h +++ b/arch/arm/include/asm/virt.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define BOOT_CPU_MODE_MISMATCH PSR_N_BIT | 29 | #define BOOT_CPU_MODE_MISMATCH PSR_N_BIT |
30 | 30 | ||
31 | #ifndef __ASSEMBLY__ | 31 | #ifndef __ASSEMBLY__ |
32 | #include <asm/cacheflush.h> | ||
32 | 33 | ||
33 | #ifdef CONFIG_ARM_VIRT_EXT | 34 | #ifdef CONFIG_ARM_VIRT_EXT |
34 | /* | 35 | /* |
@@ -41,10 +42,21 @@ | |||
41 | */ | 42 | */ |
42 | extern int __boot_cpu_mode; | 43 | extern int __boot_cpu_mode; |
43 | 44 | ||
45 | static inline void sync_boot_mode(void) | ||
46 | { | ||
47 | /* | ||
48 | * As secondaries write to __boot_cpu_mode with caches disabled, we | ||
49 | * must flush the corresponding cache entries to ensure the visibility | ||
50 | * of their writes. | ||
51 | */ | ||
52 | sync_cache_r(&__boot_cpu_mode); | ||
53 | } | ||
54 | |||
44 | void __hyp_set_vectors(unsigned long phys_vector_base); | 55 | void __hyp_set_vectors(unsigned long phys_vector_base); |
45 | unsigned long __hyp_get_vectors(void); | 56 | unsigned long __hyp_get_vectors(void); |
46 | #else | 57 | #else |
47 | #define __boot_cpu_mode (SVC_MODE) | 58 | #define __boot_cpu_mode (SVC_MODE) |
59 | #define sync_boot_mode() | ||
48 | #endif | 60 | #endif |
49 | 61 | ||
50 | #ifndef ZIMAGE | 62 | #ifndef ZIMAGE |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 96286cb383bd..afc2489ee13b 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -836,6 +836,8 @@ static int __init meminfo_cmp(const void *_a, const void *_b) | |||
836 | void __init hyp_mode_check(void) | 836 | void __init hyp_mode_check(void) |
837 | { | 837 | { |
838 | #ifdef CONFIG_ARM_VIRT_EXT | 838 | #ifdef CONFIG_ARM_VIRT_EXT |
839 | sync_boot_mode(); | ||
840 | |||
839 | if (is_hyp_mode_available()) { | 841 | if (is_hyp_mode_available()) { |
840 | pr_info("CPU: All CPU(s) started in HYP mode.\n"); | 842 | pr_info("CPU: All CPU(s) started in HYP mode.\n"); |
841 | pr_info("CPU: Virtualization extensions available.\n"); | 843 | pr_info("CPU: Virtualization extensions available.\n"); |