diff options
author | Mark Rutland <mark.rutland@arm.com> | 2013-07-09 10:16:06 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2013-07-23 06:00:24 -0400 |
commit | 82b2f495fba338d1e3098dde1df54944a9c19751 (patch) | |
tree | 866012a9d6b7bb010d8ea6fcde80da1954549f52 /arch | |
parent | 3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b (diff) |
arm64: 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>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Christoffer Dall <cdall@cs.columbia.edu>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm64/include/asm/virt.h | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h index 439827271e3d..26e310c54344 100644 --- a/arch/arm64/include/asm/virt.h +++ b/arch/arm64/include/asm/virt.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define BOOT_CPU_MODE_EL2 (0x0e12b007) | 21 | #define BOOT_CPU_MODE_EL2 (0x0e12b007) |
22 | 22 | ||
23 | #ifndef __ASSEMBLY__ | 23 | #ifndef __ASSEMBLY__ |
24 | #include <asm/cacheflush.h> | ||
24 | 25 | ||
25 | /* | 26 | /* |
26 | * __boot_cpu_mode records what mode CPUs were booted in. | 27 | * __boot_cpu_mode records what mode CPUs were booted in. |
@@ -36,9 +37,20 @@ extern u32 __boot_cpu_mode[2]; | |||
36 | void __hyp_set_vectors(phys_addr_t phys_vector_base); | 37 | void __hyp_set_vectors(phys_addr_t phys_vector_base); |
37 | phys_addr_t __hyp_get_vectors(void); | 38 | phys_addr_t __hyp_get_vectors(void); |
38 | 39 | ||
40 | static inline void sync_boot_mode(void) | ||
41 | { | ||
42 | /* | ||
43 | * As secondaries write to __boot_cpu_mode with caches disabled, we | ||
44 | * must flush the corresponding cache entries to ensure the visibility | ||
45 | * of their writes. | ||
46 | */ | ||
47 | __flush_dcache_area(__boot_cpu_mode, sizeof(__boot_cpu_mode)); | ||
48 | } | ||
49 | |||
39 | /* Reports the availability of HYP mode */ | 50 | /* Reports the availability of HYP mode */ |
40 | static inline bool is_hyp_mode_available(void) | 51 | static inline bool is_hyp_mode_available(void) |
41 | { | 52 | { |
53 | sync_boot_mode(); | ||
42 | return (__boot_cpu_mode[0] == BOOT_CPU_MODE_EL2 && | 54 | return (__boot_cpu_mode[0] == BOOT_CPU_MODE_EL2 && |
43 | __boot_cpu_mode[1] == BOOT_CPU_MODE_EL2); | 55 | __boot_cpu_mode[1] == BOOT_CPU_MODE_EL2); |
44 | } | 56 | } |
@@ -46,6 +58,7 @@ static inline bool is_hyp_mode_available(void) | |||
46 | /* Check if the bootloader has booted CPUs in different modes */ | 58 | /* Check if the bootloader has booted CPUs in different modes */ |
47 | static inline bool is_hyp_mode_mismatched(void) | 59 | static inline bool is_hyp_mode_mismatched(void) |
48 | { | 60 | { |
61 | sync_boot_mode(); | ||
49 | return __boot_cpu_mode[0] != __boot_cpu_mode[1]; | 62 | return __boot_cpu_mode[0] != __boot_cpu_mode[1]; |
50 | } | 63 | } |
51 | 64 | ||