arm64: head: fix cache flushing and barriers in set_cpu_boot_mode_flag
authorWill Deacon <will.deacon@arm.com>
Fri, 2 May 2014 15:24:13 +0000 (16:24 +0100)
committerMark Brown <broonie@kernel.org>
Thu, 23 Oct 2014 18:57:57 +0000 (19:57 +0100)
commit1c35c017ac61c43e75d49218f7a64d9455905b97
tree8ea8cda42f74dc728d0bda48130f7184f3372168
parentb817da4cf03a33c8c40e3bef04d3f3ed64277d47
arm64: head: fix cache flushing and barriers in set_cpu_boot_mode_flag

set_cpu_boot_mode_flag is used to identify which exception levels are
encountered across the system by CPUs trying to enter the kernel. The
basic algorithm is: if a CPU is booting at EL2, it will set a flag at
an offset of #4 from __boot_cpu_mode, a cacheline-aligned variable.
Otherwise, a flag is set at an offset of zero into the same cacheline.
This enables us to check that all CPUs booted at the same exception
level.

This cacheline is written with the stage-1 MMU off (that is, via a
strongly-ordered mapping) and will bypass any clean lines in the cache,
leading to potential coherence problems when the variable is later
checked via the normal, cacheable mapping of the kernel image.

This patch reworks the broken flushing code so that we:

  (1) Use a DMB to order the strongly-ordered write of the cacheline
      against the subsequent cache-maintenance operation (by-VA
      operations only hazard against normal, cacheable accesses).

  (2) Use a single dc ivac instruction to invalidate any clean lines
      containing a stale copy of the line after it has been updated.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
(cherry picked from commit d0488597a1b7105957b6d7d1bb0b6ee88aa51b37)
Signed-off-by: Mark Brown <broonie@kernel.org>
arch/arm64/kernel/head.S