summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2014-03-26 18:25:55 (GMT)
committerChanho Park <chanho61.park@samsung.com>2014-04-16 12:36:51 (GMT)
commit613666cd77fd957ed9a18e139981e552d0994ebd (patch)
treeea071531e2d0e8045dea6212f6082922492fcb2c
parent0c5d0b51439430eaa9981a5e56a09107479b620f (diff)
downloadlinux-3.10-613666cd77fd957ed9a18e139981e552d0994ebd.zip
linux-3.10-613666cd77fd957ed9a18e139981e552d0994ebd.tar.gz
linux-3.10-613666cd77fd957ed9a18e139981e552d0994ebd.tar.bz2
arm64: Relax the kernel cache requirements for boot
With system caches for the host OS or architected caches for guest OS we cannot easily guarantee that there are no dirty or stale cache lines for the areas of memory written by the kernel during boot with the MMU off (therefore non-cacheable accesses). This patch adds the necessary cache maintenance during boot and relaxes the booting requirements. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--Documentation/arm64/booting.txt10
-rw-r--r--arch/arm64/kernel/head.S30
-rw-r--r--arch/arm64/mm/cache.S9
3 files changed, 45 insertions, 4 deletions
diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 5122f37..9324018 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -111,8 +111,14 @@ Before jumping into the kernel, the following conditions must be met:
- Caches, MMUs
The MMU must be off.
Instruction cache may be on or off.
- Data cache must be off and invalidated.
- External caches (if present) must be configured and disabled.
+ The address range corresponding to the loaded kernel image must be
+ cleaned to the PoC. In the presence of a system cache or other
+ coherent masters with caches enabled, this will typically require
+ cache maintenance by VA rather than set/way operations.
+ System caches which respect the architected cache maintenance by VA
+ operations must be configured and may be enabled.
+ System caches which do not respect architected cache maintenance by VA
+ operations (not recommended) must be configured and disabled.
- Architected timers
CNTFRQ must be programmed with the timer frequency and CNTVOFF must
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 61035d6..2610968 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -26,6 +26,7 @@
#include <asm/assembler.h>
#include <asm/ptrace.h>
#include <asm/asm-offsets.h>
+#include <asm/cache.h>
#include <asm/cputype.h>
#include <asm/memory.h>
#include <asm/thread_info.h>
@@ -229,7 +230,11 @@ ENTRY(set_cpu_boot_mode_flag)
cmp w20, #BOOT_CPU_MODE_EL2
b.ne 1f
add x1, x1, #4
-1: str w20, [x1] // This CPU has booted in EL1
+1: dc cvac, x1 // Clean potentially dirty cache line
+ dsb sy
+ str w20, [x1] // This CPU has booted in EL1
+ dc civac, x1 // Clean&invalidate potentially stale cache line
+ dsb sy
ret
ENDPROC(set_cpu_boot_mode_flag)
@@ -240,8 +245,9 @@ ENDPROC(set_cpu_boot_mode_flag)
* This is not in .bss, because we set it sufficiently early that the boot-time
* zeroing of .bss would clobber it.
*/
- .pushsection .data
+ .pushsection .data..cacheline_aligned
ENTRY(__boot_cpu_mode)
+ .align L1_CACHE_SHIFT
.long BOOT_CPU_MODE_EL2
.long 0
.popsection
@@ -408,6 +414,15 @@ ENDPROC(__calc_phys_offset)
*/
__create_page_tables:
pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses
+ mov x27, lr
+
+ /*
+ * Invalidate the idmap and swapper page tables to avoid potential
+ * dirty cache lines being evicted.
+ */
+ mov x0, x25
+ add x1, x26, #SWAPPER_DIR_SIZE
+ bl __inval_cache_range
/*
* Clear the idmap and swapper page tables.
@@ -470,6 +485,17 @@ __create_page_tables:
add x0, x26, #2 * PAGE_SIZE // section table address
create_pgd_entry x26, x0, x5, x6, x7
#endif
+
+ /*
+ * Since the page tables have been populated with non-cacheable
+ * accesses (MMU disabled), invalidate the idmap and swapper page
+ * tables again to remove any speculatively loaded cache lines.
+ */
+ mov x0, x25
+ add x1, x26, #SWAPPER_DIR_SIZE
+ bl __inval_cache_range
+
+ mov lr, x27
ret
ENDPROC(__create_page_tables)
.ltorg
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index c46f48b..e803a62 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -168,6 +168,14 @@ ENTRY(__flush_dcache_area)
ENDPROC(__flush_dcache_area)
/*
+ * __inval_cache_range(start, end)
+ * - start - start address of region
+ * - end - end address of region
+ */
+ENTRY(__inval_cache_range)
+ /* FALLTHROUGH */
+
+/*
* __dma_inv_range(start, end)
* - start - virtual start address of region
* - end - virtual end address of region
@@ -183,6 +191,7 @@ __dma_inv_range:
b.lo 1b
dsb sy
ret
+ENDPROC(__inval_cache_range)
ENDPROC(__dma_inv_range)
/*