diff options
41 files changed, 623 insertions, 23 deletions
diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting index a341d87d276e..0c1f475fdf36 100644 --- a/Documentation/arm/Booting +++ b/Documentation/arm/Booting | |||
| @@ -154,13 +154,33 @@ In either case, the following conditions must be met: | |||
| 154 | 154 | ||
| 155 | - CPU mode | 155 | - CPU mode |
| 156 | All forms of interrupts must be disabled (IRQs and FIQs) | 156 | All forms of interrupts must be disabled (IRQs and FIQs) |
| 157 | The CPU must be in SVC mode. (A special exception exists for Angel) | 157 | |
| 158 | For CPUs which do not include the ARM virtualization extensions, the | ||
| 159 | CPU must be in SVC mode. (A special exception exists for Angel) | ||
| 160 | |||
| 161 | CPUs which include support for the virtualization extensions can be | ||
| 162 | entered in HYP mode in order to enable the kernel to make full use of | ||
| 163 | these extensions. This is the recommended boot method for such CPUs, | ||
| 164 | unless the virtualisations are already in use by a pre-installed | ||
| 165 | hypervisor. | ||
| 166 | |||
| 167 | If the kernel is not entered in HYP mode for any reason, it must be | ||
| 168 | entered in SVC mode. | ||
| 158 | 169 | ||
| 159 | - Caches, MMUs | 170 | - Caches, MMUs |
| 160 | The MMU must be off. | 171 | The MMU must be off. |
| 161 | Instruction cache may be on or off. | 172 | Instruction cache may be on or off. |
| 162 | Data cache must be off. | 173 | Data cache must be off. |
| 163 | 174 | ||
| 175 | If the kernel is entered in HYP mode, the above requirements apply to | ||
| 176 | the HYP mode configuration in addition to the ordinary PL1 (privileged | ||
| 177 | kernel modes) configuration. In addition, all traps into the | ||
| 178 | hypervisor must be disabled, and PL1 access must be granted for all | ||
| 179 | peripherals and CPU resources for which this is architecturally | ||
| 180 | possible. Except for entering in HYP mode, the system configuration | ||
| 181 | should be such that a kernel which does not include support for the | ||
| 182 | virtualization extensions can boot correctly without extra help. | ||
| 183 | |||
| 164 | - The boot loader is expected to call the kernel image by jumping | 184 | - The boot loader is expected to call the kernel image by jumping |
| 165 | directly to the first instruction of the kernel image. | 185 | directly to the first instruction of the kernel image. |
| 166 | 186 | ||
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index d0d441c429ae..f79a08efe000 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | ashldi3.S | 1 | ashldi3.S |
| 2 | font.c | 2 | font.c |
| 3 | lib1funcs.S | 3 | lib1funcs.S |
| 4 | hyp-stub.S | ||
| 4 | piggy.gzip | 5 | piggy.gzip |
| 5 | piggy.lzo | 6 | piggy.lzo |
| 6 | piggy.lzma | 7 | piggy.lzma |
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index bb267562e7ed..a517153a13ea 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile | |||
| @@ -30,6 +30,10 @@ FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c | |||
| 30 | OBJS += string.o | 30 | OBJS += string.o |
| 31 | CFLAGS_string.o := -Os | 31 | CFLAGS_string.o := -Os |
| 32 | 32 | ||
| 33 | ifeq ($(CONFIG_ARM_VIRT_EXT),y) | ||
| 34 | OBJS += hyp-stub.o | ||
| 35 | endif | ||
| 36 | |||
| 33 | # | 37 | # |
| 34 | # Architecture dependencies | 38 | # Architecture dependencies |
| 35 | # | 39 | # |
| @@ -126,7 +130,7 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) | |||
| 126 | endif | 130 | endif |
| 127 | 131 | ||
| 128 | ccflags-y := -fpic -fno-builtin -I$(obj) | 132 | ccflags-y := -fpic -fno-builtin -I$(obj) |
| 129 | asflags-y := -Wa,-march=all | 133 | asflags-y := -Wa,-march=all -DZIMAGE |
| 130 | 134 | ||
| 131 | # Supply kernel BSS size to the decompressor via a linker symbol. | 135 | # Supply kernel BSS size to the decompressor via a linker symbol. |
| 132 | KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \ | 136 | KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \ |
| @@ -198,3 +202,6 @@ $(obj)/font.c: $(FONTC) | |||
| 198 | 202 | ||
| 199 | $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG) | 203 | $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG) |
| 200 | @sed "$(SEDFLAGS)" < $< > $@ | 204 | @sed "$(SEDFLAGS)" < $< > $@ |
| 205 | |||
| 206 | $(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S | ||
| 207 | $(call cmd,shipped) | ||
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index bc67cbff3944..90275f036cd1 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
| 10 | */ | 10 | */ |
| 11 | #include <linux/linkage.h> | 11 | #include <linux/linkage.h> |
| 12 | #include <asm/assembler.h> | ||
| 12 | 13 | ||
| 13 | /* | 14 | /* |
| 14 | * Debugging stuff | 15 | * Debugging stuff |
| @@ -132,7 +133,12 @@ start: | |||
| 132 | .word start @ absolute load/run zImage address | 133 | .word start @ absolute load/run zImage address |
| 133 | .word _edata @ zImage end address | 134 | .word _edata @ zImage end address |
| 134 | THUMB( .thumb ) | 135 | THUMB( .thumb ) |
| 135 | 1: mov r7, r1 @ save architecture ID | 136 | 1: |
| 137 | mrs r9, cpsr | ||
| 138 | #ifdef CONFIG_ARM_VIRT_EXT | ||
| 139 | bl __hyp_stub_install @ get into SVC mode, reversibly | ||
| 140 | #endif | ||
| 141 | mov r7, r1 @ save architecture ID | ||
| 136 | mov r8, r2 @ save atags pointer | 142 | mov r8, r2 @ save atags pointer |
| 137 | 143 | ||
| 138 | #ifndef __ARM_ARCH_2__ | 144 | #ifndef __ARM_ARCH_2__ |
| @@ -148,9 +154,9 @@ start: | |||
| 148 | ARM( swi 0x123456 ) @ angel_SWI_ARM | 154 | ARM( swi 0x123456 ) @ angel_SWI_ARM |
| 149 | THUMB( svc 0xab ) @ angel_SWI_THUMB | 155 | THUMB( svc 0xab ) @ angel_SWI_THUMB |
| 150 | not_angel: | 156 | not_angel: |
| 151 | mrs r2, cpsr @ turn off interrupts to | 157 | safe_svcmode_maskall r0 |
| 152 | orr r2, r2, #0xc0 @ prevent angel from running | 158 | msr spsr_cxsf, r9 @ Save the CPU boot mode in |
| 153 | msr cpsr_c, r2 | 159 | @ SPSR |
| 154 | #else | 160 | #else |
| 155 | teqp pc, #0x0c000003 @ turn off interrupts | 161 | teqp pc, #0x0c000003 @ turn off interrupts |
| 156 | #endif | 162 | #endif |
| @@ -350,6 +356,20 @@ dtb_check_done: | |||
| 350 | adr r5, restart | 356 | adr r5, restart |
| 351 | bic r5, r5, #31 | 357 | bic r5, r5, #31 |
| 352 | 358 | ||
| 359 | /* Relocate the hyp vector base if necessary */ | ||
| 360 | #ifdef CONFIG_ARM_VIRT_EXT | ||
| 361 | mrs r0, spsr | ||
| 362 | and r0, r0, #MODE_MASK | ||
| 363 | cmp r0, #HYP_MODE | ||
| 364 | bne 1f | ||
| 365 | |||
| 366 | bl __hyp_get_vectors | ||
| 367 | sub r0, r0, r5 | ||
| 368 | add r0, r0, r10 | ||
| 369 | bl __hyp_set_vectors | ||
| 370 | 1: | ||
| 371 | #endif | ||
| 372 | |||
| 353 | sub r9, r6, r5 @ size to copy | 373 | sub r9, r6, r5 @ size to copy |
| 354 | add r9, r9, #31 @ rounded up to a multiple | 374 | add r9, r9, #31 @ rounded up to a multiple |
| 355 | bic r9, r9, #31 @ ... of 32 bytes | 375 | bic r9, r9, #31 @ ... of 32 bytes |
| @@ -458,11 +478,29 @@ not_relocated: mov r0, #0 | |||
| 458 | bl decompress_kernel | 478 | bl decompress_kernel |
| 459 | bl cache_clean_flush | 479 | bl cache_clean_flush |
| 460 | bl cache_off | 480 | bl cache_off |
| 461 | mov r0, #0 @ must be zero | ||
| 462 | mov r1, r7 @ restore architecture number | 481 | mov r1, r7 @ restore architecture number |
| 463 | mov r2, r8 @ restore atags pointer | 482 | mov r2, r8 @ restore atags pointer |
| 464 | ARM( mov pc, r4 ) @ call kernel | 483 | |
| 465 | THUMB( bx r4 ) @ entry point is always ARM | 484 | #ifdef CONFIG_ARM_VIRT_EXT |
| 485 | mrs r0, spsr @ Get saved CPU boot mode | ||
| 486 | and r0, r0, #MODE_MASK | ||
| 487 | cmp r0, #HYP_MODE @ if not booted in HYP mode... | ||
| 488 | bne __enter_kernel @ boot kernel directly | ||
| 489 | |||
| 490 | adr r12, .L__hyp_reentry_vectors_offset | ||
| 491 | ldr r0, [r12] | ||
| 492 | add r0, r0, r12 | ||
| 493 | |||
| 494 | bl __hyp_set_vectors | ||
| 495 | __HVC(0) @ otherwise bounce to hyp mode | ||
| 496 | |||
| 497 | b . @ should never be reached | ||
| 498 | |||
| 499 | .align 2 | ||
| 500 | .L__hyp_reentry_vectors_offset: .long __hyp_reentry_vectors - . | ||
| 501 | #else | ||
| 502 | b __enter_kernel | ||
| 503 | #endif | ||
| 466 | 504 | ||
| 467 | .align 2 | 505 | .align 2 |
| 468 | .type LC0, #object | 506 | .type LC0, #object |
| @@ -1196,6 +1234,25 @@ memdump: mov r12, r0 | |||
| 1196 | #endif | 1234 | #endif |
| 1197 | 1235 | ||
| 1198 | .ltorg | 1236 | .ltorg |
| 1237 | |||
| 1238 | #ifdef CONFIG_ARM_VIRT_EXT | ||
| 1239 | .align 5 | ||
| 1240 | __hyp_reentry_vectors: | ||
| 1241 | W(b) . @ reset | ||
| 1242 | W(b) . @ undef | ||
| 1243 | W(b) . @ svc | ||
| 1244 | W(b) . @ pabort | ||
| 1245 | W(b) . @ dabort | ||
| 1246 | W(b) __enter_kernel @ hyp | ||
| 1247 | W(b) . @ irq | ||
| 1248 | W(b) . @ fiq | ||
| 1249 | #endif /* CONFIG_ARM_VIRT_EXT */ | ||
| 1250 | |||
| 1251 | __enter_kernel: | ||
| 1252 | mov r0, #0 @ must be 0 | ||
| 1253 | ARM( mov pc, r4 ) @ call kernel | ||
| 1254 | THUMB( bx r4 ) @ entry point is always ARM | ||
| 1255 | |||
| 1199 | reloc_code_end: | 1256 | reloc_code_end: |
| 1200 | 1257 | ||
| 1201 | .align | 1258 | .align |
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 5c8b3bf4d825..2ef95813fce0 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #include <asm/ptrace.h> | 23 | #include <asm/ptrace.h> |
| 24 | #include <asm/domain.h> | 24 | #include <asm/domain.h> |
| 25 | #include <asm/opcodes-virt.h> | ||
| 25 | 26 | ||
| 26 | #define IOMEM(x) (x) | 27 | #define IOMEM(x) (x) |
| 27 | 28 | ||
| @@ -240,6 +241,34 @@ | |||
| 240 | #endif | 241 | #endif |
| 241 | 242 | ||
| 242 | /* | 243 | /* |
| 244 | * Helper macro to enter SVC mode cleanly and mask interrupts. reg is | ||
| 245 | * a scratch register for the macro to overwrite. | ||
| 246 | * | ||
| 247 | * This macro is intended for forcing the CPU into SVC mode at boot time. | ||
| 248 | * you cannot return to the original mode. | ||
| 249 | * | ||
| 250 | * Beware, it also clobers LR. | ||
| 251 | */ | ||
| 252 | .macro safe_svcmode_maskall reg:req | ||
| 253 | mrs \reg , cpsr | ||
| 254 | mov lr , \reg | ||
| 255 | and lr , lr , #MODE_MASK | ||
| 256 | cmp lr , #HYP_MODE | ||
| 257 | orr \reg , \reg , #PSR_I_BIT | PSR_F_BIT | ||
| 258 | bic \reg , \reg , #MODE_MASK | ||
| 259 | orr \reg , \reg , #SVC_MODE | ||
| 260 | THUMB( orr \reg , \reg , #PSR_T_BIT ) | ||
| 261 | bne 1f | ||
| 262 | orr \reg, \reg, #PSR_A_BIT | ||
| 263 | adr lr, BSYM(2f) | ||
| 264 | msr spsr_cxsf, \reg | ||
| 265 | __MSR_ELR_HYP(14) | ||
| 266 | __ERET | ||
| 267 | 1: msr cpsr_c, \reg | ||
| 268 | 2: | ||
| 269 | .endm | ||
| 270 | |||
| 271 | /* | ||
| 243 | * STRT/LDRT access macros with ARM and Thumb-2 variants | 272 | * STRT/LDRT access macros with ARM and Thumb-2 variants |
| 244 | */ | 273 | */ |
| 245 | #ifdef CONFIG_THUMB2_KERNEL | 274 | #ifdef CONFIG_THUMB2_KERNEL |
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index e4448e16046d..e1489c54cd12 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
| @@ -49,6 +49,13 @@ | |||
| 49 | * | 49 | * |
| 50 | * Unconditionally clean and invalidate the entire cache. | 50 | * Unconditionally clean and invalidate the entire cache. |
| 51 | * | 51 | * |
| 52 | * flush_kern_louis() | ||
| 53 | * | ||
| 54 | * Flush data cache levels up to the level of unification | ||
| 55 | * inner shareable and invalidate the I-cache. | ||
| 56 | * Only needed from v7 onwards, falls back to flush_cache_all() | ||
| 57 | * for all other processor versions. | ||
| 58 | * | ||
| 52 | * flush_user_all() | 59 | * flush_user_all() |
| 53 | * | 60 | * |
| 54 | * Clean and invalidate all user space cache entries | 61 | * Clean and invalidate all user space cache entries |
| @@ -97,6 +104,7 @@ | |||
| 97 | struct cpu_cache_fns { | 104 | struct cpu_cache_fns { |
| 98 | void (*flush_icache_all)(void); | 105 | void (*flush_icache_all)(void); |
| 99 | void (*flush_kern_all)(void); | 106 | void (*flush_kern_all)(void); |
| 107 | void (*flush_kern_louis)(void); | ||
| 100 | void (*flush_user_all)(void); | 108 | void (*flush_user_all)(void); |
| 101 | void (*flush_user_range)(unsigned long, unsigned long, unsigned int); | 109 | void (*flush_user_range)(unsigned long, unsigned long, unsigned int); |
| 102 | 110 | ||
| @@ -119,6 +127,7 @@ extern struct cpu_cache_fns cpu_cache; | |||
| 119 | 127 | ||
| 120 | #define __cpuc_flush_icache_all cpu_cache.flush_icache_all | 128 | #define __cpuc_flush_icache_all cpu_cache.flush_icache_all |
| 121 | #define __cpuc_flush_kern_all cpu_cache.flush_kern_all | 129 | #define __cpuc_flush_kern_all cpu_cache.flush_kern_all |
| 130 | #define __cpuc_flush_kern_louis cpu_cache.flush_kern_louis | ||
| 122 | #define __cpuc_flush_user_all cpu_cache.flush_user_all | 131 | #define __cpuc_flush_user_all cpu_cache.flush_user_all |
| 123 | #define __cpuc_flush_user_range cpu_cache.flush_user_range | 132 | #define __cpuc_flush_user_range cpu_cache.flush_user_range |
| 124 | #define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range | 133 | #define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range |
| @@ -139,6 +148,7 @@ extern struct cpu_cache_fns cpu_cache; | |||
| 139 | 148 | ||
| 140 | extern void __cpuc_flush_icache_all(void); | 149 | extern void __cpuc_flush_icache_all(void); |
| 141 | extern void __cpuc_flush_kern_all(void); | 150 | extern void __cpuc_flush_kern_all(void); |
| 151 | extern void __cpuc_flush_kern_louis(void); | ||
| 142 | extern void __cpuc_flush_user_all(void); | 152 | extern void __cpuc_flush_user_all(void); |
| 143 | extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); | 153 | extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); |
| 144 | extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); | 154 | extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); |
| @@ -204,6 +214,11 @@ static inline void __flush_icache_all(void) | |||
| 204 | __flush_icache_preferred(); | 214 | __flush_icache_preferred(); |
| 205 | } | 215 | } |
| 206 | 216 | ||
| 217 | /* | ||
| 218 | * Flush caches up to Level of Unification Inner Shareable | ||
| 219 | */ | ||
| 220 | #define flush_cache_louis() __cpuc_flush_kern_louis() | ||
| 221 | |||
| 207 | #define flush_cache_all() __cpuc_flush_kern_all() | 222 | #define flush_cache_all() __cpuc_flush_kern_all() |
| 208 | 223 | ||
| 209 | static inline void vivt_flush_cache_mm(struct mm_struct *mm) | 224 | static inline void vivt_flush_cache_mm(struct mm_struct *mm) |
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index 4f8d2c0dc441..cca9f15704ed 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h | |||
| @@ -132,6 +132,7 @@ | |||
| 132 | #ifndef MULTI_CACHE | 132 | #ifndef MULTI_CACHE |
| 133 | #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) | 133 | #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) |
| 134 | #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) | 134 | #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) |
| 135 | #define __cpuc_flush_kern_louis __glue(_CACHE,_flush_kern_cache_louis) | ||
| 135 | #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) | 136 | #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) |
| 136 | #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) | 137 | #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) |
| 137 | #define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) | 138 | #define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) |
diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h index b85665a96f8e..efcfdf92d9d5 100644 --- a/arch/arm/include/asm/opcodes-virt.h +++ b/arch/arm/include/asm/opcodes-virt.h | |||
| @@ -26,4 +26,14 @@ | |||
| 26 | 0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \ | 26 | 0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \ |
| 27 | ) | 27 | ) |
| 28 | 28 | ||
| 29 | #define __ERET __inst_arm_thumb32( \ | ||
| 30 | 0xE160006E, \ | ||
| 31 | 0xF3DE8F00 \ | ||
| 32 | ) | ||
| 33 | |||
| 34 | #define __MSR_ELR_HYP(regnum) __inst_arm_thumb32( \ | ||
| 35 | 0xE12EF300 | regnum, \ | ||
| 36 | 0xF3808E30 | (regnum << 16) \ | ||
| 37 | ) | ||
| 38 | |||
| 29 | #endif /* ! __ASM_ARM_OPCODES_VIRT_H */ | 39 | #endif /* ! __ASM_ARM_OPCODES_VIRT_H */ |
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 44fe998269d9..142d6ae41231 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #define IRQ_MODE 0x00000012 | 44 | #define IRQ_MODE 0x00000012 |
| 45 | #define SVC_MODE 0x00000013 | 45 | #define SVC_MODE 0x00000013 |
| 46 | #define ABT_MODE 0x00000017 | 46 | #define ABT_MODE 0x00000017 |
| 47 | #define HYP_MODE 0x0000001a | ||
| 47 | #define UND_MODE 0x0000001b | 48 | #define UND_MODE 0x0000001b |
| 48 | #define SYSTEM_MODE 0x0000001f | 49 | #define SYSTEM_MODE 0x0000001f |
| 49 | #define MODE32_BIT 0x00000010 | 50 | #define MODE32_BIT 0x00000010 |
diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index a7aadbd9a6dd..6a6f1e485f41 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | ldr \tmp, =elf_hwcap @ may not have MVFR regs | 28 | ldr \tmp, =elf_hwcap @ may not have MVFR regs |
| 29 | ldr \tmp, [\tmp, #0] | 29 | ldr \tmp, [\tmp, #0] |
| 30 | tst \tmp, #HWCAP_VFPv3D16 | 30 | tst \tmp, #HWCAP_VFPv3D16 |
| 31 | ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} | 31 | ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} |
| 32 | addne \base, \base, #32*4 @ step over unused register space | 32 | addne \base, \base, #32*4 @ step over unused register space |
| 33 | #else | 33 | #else |
| 34 | VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 | 34 | VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 |
| @@ -52,7 +52,7 @@ | |||
| 52 | ldr \tmp, =elf_hwcap @ may not have MVFR regs | 52 | ldr \tmp, =elf_hwcap @ may not have MVFR regs |
| 53 | ldr \tmp, [\tmp, #0] | 53 | ldr \tmp, [\tmp, #0] |
| 54 | tst \tmp, #HWCAP_VFPv3D16 | 54 | tst \tmp, #HWCAP_VFPv3D16 |
| 55 | stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} | 55 | stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} |
| 56 | addne \base, \base, #32*4 @ step over unused register space | 56 | addne \base, \base, #32*4 @ step over unused register space |
| 57 | #else | 57 | #else |
| 58 | VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 | 58 | VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 |
diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h new file mode 100644 index 000000000000..86164df86cb4 --- /dev/null +++ b/arch/arm/include/asm/virt.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Linaro Limited. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along | ||
| 15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef VIRT_H | ||
| 20 | #define VIRT_H | ||
| 21 | |||
| 22 | #include <asm/ptrace.h> | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Flag indicating that the kernel was not entered in the same mode on every | ||
| 26 | * CPU. The zImage loader stashes this value in an SPSR, so we need an | ||
| 27 | * architecturally defined flag bit here (the N flag, as it happens) | ||
| 28 | */ | ||
| 29 | #define BOOT_CPU_MODE_MISMATCH (1<<31) | ||
| 30 | |||
| 31 | #ifndef __ASSEMBLY__ | ||
| 32 | |||
| 33 | #ifdef CONFIG_ARM_VIRT_EXT | ||
| 34 | /* | ||
| 35 | * __boot_cpu_mode records what mode the primary CPU was booted in. | ||
| 36 | * A correctly-implemented bootloader must start all CPUs in the same mode: | ||
| 37 | * if it fails to do this, the flag BOOT_CPU_MODE_MISMATCH is set to indicate | ||
| 38 | * that some CPU(s) were booted in a different mode. | ||
| 39 | * | ||
| 40 | * This allows the kernel to flag an error when the secondaries have come up. | ||
| 41 | */ | ||
| 42 | extern int __boot_cpu_mode; | ||
| 43 | |||
| 44 | void __hyp_set_vectors(unsigned long phys_vector_base); | ||
| 45 | unsigned long __hyp_get_vectors(void); | ||
| 46 | #else | ||
| 47 | #define __boot_cpu_mode (SVC_MODE) | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #ifndef ZIMAGE | ||
| 51 | void hyp_mode_check(void); | ||
| 52 | |||
| 53 | /* Reports the availability of HYP mode */ | ||
| 54 | static inline bool is_hyp_mode_available(void) | ||
| 55 | { | ||
| 56 | return ((__boot_cpu_mode & MODE_MASK) == HYP_MODE && | ||
| 57 | !(__boot_cpu_mode & BOOT_CPU_MODE_MISMATCH)); | ||
| 58 | } | ||
| 59 | |||
| 60 | /* Check if the bootloader has booted CPUs in different modes */ | ||
| 61 | static inline bool is_hyp_mode_mismatched(void) | ||
| 62 | { | ||
| 63 | return !!(__boot_cpu_mode & BOOT_CPU_MODE_MISMATCH); | ||
| 64 | } | ||
| 65 | #endif | ||
| 66 | |||
| 67 | #endif /* __ASSEMBLY__ */ | ||
| 68 | |||
| 69 | #endif /* ! VIRT_H */ | ||
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 5dfef9d97ed9..5bbec7b8183e 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
| @@ -81,4 +81,6 @@ head-y := head$(MMUEXT).o | |||
| 81 | obj-$(CONFIG_DEBUG_LL) += debug.o | 81 | obj-$(CONFIG_DEBUG_LL) += debug.o |
| 82 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 82 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
| 83 | 83 | ||
| 84 | obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o | ||
| 85 | |||
| 84 | extra-y := $(head-y) vmlinux.lds | 86 | extra-y := $(head-y) vmlinux.lds |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 9874d0741191..4eee351f4668 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
| @@ -83,8 +83,12 @@ ENTRY(stext) | |||
| 83 | THUMB( .thumb ) @ switch to Thumb now. | 83 | THUMB( .thumb ) @ switch to Thumb now. |
| 84 | THUMB(1: ) | 84 | THUMB(1: ) |
| 85 | 85 | ||
| 86 | setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode | 86 | #ifdef CONFIG_ARM_VIRT_EXT |
| 87 | @ and irqs disabled | 87 | bl __hyp_stub_install |
| 88 | #endif | ||
| 89 | @ ensure svc mode and all interrupts masked | ||
| 90 | safe_svcmode_maskall r9 | ||
| 91 | |||
| 88 | mrc p15, 0, r9, c0, c0 @ get processor id | 92 | mrc p15, 0, r9, c0, c0 @ get processor id |
| 89 | bl __lookup_processor_type @ r5=procinfo r9=cpuid | 93 | bl __lookup_processor_type @ r5=procinfo r9=cpuid |
| 90 | movs r10, r5 @ invalid processor (r5=0)? | 94 | movs r10, r5 @ invalid processor (r5=0)? |
| @@ -326,7 +330,11 @@ ENTRY(secondary_startup) | |||
| 326 | * the processor type - there is no need to check the machine type | 330 | * the processor type - there is no need to check the machine type |
| 327 | * as it has already been validated by the primary processor. | 331 | * as it has already been validated by the primary processor. |
| 328 | */ | 332 | */ |
| 329 | setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 | 333 | #ifdef CONFIG_ARM_VIRT_EXT |
| 334 | bl __hyp_stub_install | ||
| 335 | #endif | ||
| 336 | safe_svcmode_maskall r9 | ||
| 337 | |||
| 330 | mrc p15, 0, r9, c0, c0 @ get processor id | 338 | mrc p15, 0, r9, c0, c0 @ get processor id |
| 331 | bl __lookup_processor_type | 339 | bl __lookup_processor_type |
| 332 | movs r10, r5 @ invalid processor? | 340 | movs r10, r5 @ invalid processor? |
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S new file mode 100644 index 000000000000..65b2417aebce --- /dev/null +++ b/arch/arm/kernel/hyp-stub.S | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Linaro Limited. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along | ||
| 15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/linkage.h> | ||
| 21 | #include <asm/assembler.h> | ||
| 22 | #include <asm/virt.h> | ||
| 23 | |||
| 24 | #ifndef ZIMAGE | ||
| 25 | /* | ||
| 26 | * For the kernel proper, we need to find out the CPU boot mode long after | ||
| 27 | * boot, so we need to store it in a writable variable. | ||
| 28 | * | ||
| 29 | * This is not in .bss, because we set it sufficiently early that the boot-time | ||
| 30 | * zeroing of .bss would clobber it. | ||
| 31 | */ | ||
| 32 | .data | ||
| 33 | ENTRY(__boot_cpu_mode) | ||
| 34 | .long 0 | ||
| 35 | .text | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Save the primary CPU boot mode. Requires 3 scratch registers. | ||
| 39 | */ | ||
| 40 | .macro store_primary_cpu_mode reg1, reg2, reg3 | ||
| 41 | mrs \reg1, cpsr | ||
| 42 | and \reg1, \reg1, #MODE_MASK | ||
| 43 | adr \reg2, .L__boot_cpu_mode_offset | ||
| 44 | ldr \reg3, [\reg2] | ||
| 45 | str \reg1, [\reg2, \reg3] | ||
| 46 | .endm | ||
| 47 | |||
| 48 | /* | ||
| 49 | * Compare the current mode with the one saved on the primary CPU. | ||
| 50 | * If they don't match, record that fact. The Z bit indicates | ||
| 51 | * if there's a match or not. | ||
| 52 | * Requires 3 additionnal scratch registers. | ||
| 53 | */ | ||
| 54 | .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3 | ||
| 55 | adr \reg2, .L__boot_cpu_mode_offset | ||
| 56 | ldr \reg3, [\reg2] | ||
| 57 | ldr \reg1, [\reg2, \reg3] | ||
| 58 | cmp \mode, \reg1 @ matches primary CPU boot mode? | ||
| 59 | orrne r7, r7, #BOOT_CPU_MODE_MISMATCH | ||
| 60 | strne r7, [r5, r6] @ record what happened and give up | ||
| 61 | .endm | ||
| 62 | |||
| 63 | #else /* ZIMAGE */ | ||
| 64 | |||
| 65 | .macro store_primary_cpu_mode reg1:req, reg2:req, reg3:req | ||
| 66 | .endm | ||
| 67 | |||
| 68 | /* | ||
| 69 | * The zImage loader only runs on one CPU, so we don't bother with mult-CPU | ||
| 70 | * consistency checking: | ||
| 71 | */ | ||
| 72 | .macro compare_cpu_mode_with_primary mode, reg1, reg2, reg3 | ||
| 73 | cmp \mode, \mode | ||
| 74 | .endm | ||
| 75 | |||
| 76 | #endif /* ZIMAGE */ | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Hypervisor stub installation functions. | ||
| 80 | * | ||
| 81 | * These must be called with the MMU and D-cache off. | ||
| 82 | * They are not ABI compliant and are only intended to be called from the kernel | ||
| 83 | * entry points in head.S. | ||
| 84 | */ | ||
| 85 | @ Call this from the primary CPU | ||
| 86 | ENTRY(__hyp_stub_install) | ||
| 87 | store_primary_cpu_mode r4, r5, r6 | ||
| 88 | ENDPROC(__hyp_stub_install) | ||
| 89 | |||
| 90 | @ fall through... | ||
| 91 | |||
| 92 | @ Secondary CPUs should call here | ||
| 93 | ENTRY(__hyp_stub_install_secondary) | ||
| 94 | mrs r4, cpsr | ||
| 95 | and r4, r4, #MODE_MASK | ||
| 96 | |||
| 97 | /* | ||
| 98 | * If the secondary has booted with a different mode, give up | ||
| 99 | * immediately. | ||
| 100 | */ | ||
| 101 | compare_cpu_mode_with_primary r4, r5, r6, r7 | ||
| 102 | bxne lr | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Once we have given up on one CPU, we do not try to install the | ||
| 106 | * stub hypervisor on the remaining ones: because the saved boot mode | ||
| 107 | * is modified, it can't compare equal to the CPSR mode field any | ||
| 108 | * more. | ||
| 109 | * | ||
| 110 | * Otherwise... | ||
| 111 | */ | ||
| 112 | |||
| 113 | cmp r4, #HYP_MODE | ||
| 114 | bxne lr @ give up if the CPU is not in HYP mode | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Configure HSCTLR to set correct exception endianness/instruction set | ||
| 118 | * state etc. | ||
| 119 | * Turn off all traps | ||
| 120 | * Eventually, CPU-specific code might be needed -- assume not for now | ||
| 121 | * | ||
| 122 | * This code relies on the "eret" instruction to synchronize the | ||
| 123 | * various coprocessor accesses. | ||
| 124 | */ | ||
| 125 | @ Now install the hypervisor stub: | ||
| 126 | adr r7, __hyp_stub_vectors | ||
| 127 | mcr p15, 4, r7, c12, c0, 0 @ set hypervisor vector base (HVBAR) | ||
| 128 | |||
| 129 | @ Disable all traps, so we don't get any nasty surprise | ||
| 130 | mov r7, #0 | ||
| 131 | mcr p15, 4, r7, c1, c1, 0 @ HCR | ||
| 132 | mcr p15, 4, r7, c1, c1, 2 @ HCPTR | ||
| 133 | mcr p15, 4, r7, c1, c1, 3 @ HSTR | ||
| 134 | |||
| 135 | THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE | ||
| 136 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
| 137 | orr r7, #(1 << 9) @ HSCTLR.EE | ||
| 138 | #endif | ||
| 139 | mcr p15, 4, r7, c1, c0, 0 @ HSCTLR | ||
| 140 | |||
| 141 | mrc p15, 4, r7, c1, c1, 1 @ HDCR | ||
| 142 | and r7, #0x1f @ Preserve HPMN | ||
| 143 | mcr p15, 4, r7, c1, c1, 1 @ HDCR | ||
| 144 | |||
| 145 | #if !defined(ZIMAGE) && defined(CONFIG_ARM_ARCH_TIMER) | ||
| 146 | @ make CNTP_* and CNTPCT accessible from PL1 | ||
| 147 | mrc p15, 0, r7, c0, c1, 1 @ ID_PFR1 | ||
| 148 | lsr r7, #16 | ||
| 149 | and r7, #0xf | ||
| 150 | cmp r7, #1 | ||
| 151 | bne 1f | ||
| 152 | mrc p15, 4, r7, c14, c1, 0 @ CNTHCTL | ||
| 153 | orr r7, r7, #3 @ PL1PCEN | PL1PCTEN | ||
| 154 | mcr p15, 4, r7, c14, c1, 0 @ CNTHCTL | ||
| 155 | 1: | ||
| 156 | #endif | ||
| 157 | |||
| 158 | bic r7, r4, #MODE_MASK | ||
| 159 | orr r7, r7, #SVC_MODE | ||
| 160 | THUMB( orr r7, r7, #PSR_T_BIT ) | ||
| 161 | msr spsr_cxsf, r7 @ This is SPSR_hyp. | ||
| 162 | |||
| 163 | __MSR_ELR_HYP(14) @ msr elr_hyp, lr | ||
| 164 | __ERET @ return, switching to SVC mode | ||
| 165 | @ The boot CPU mode is left in r4. | ||
| 166 | ENDPROC(__hyp_stub_install_secondary) | ||
| 167 | |||
| 168 | __hyp_stub_do_trap: | ||
| 169 | cmp r0, #-1 | ||
| 170 | mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR | ||
| 171 | mcrne p15, 4, r0, c12, c0, 0 @ set HVBAR | ||
| 172 | __ERET | ||
| 173 | ENDPROC(__hyp_stub_do_trap) | ||
| 174 | |||
| 175 | /* | ||
| 176 | * __hyp_set_vectors: Call this after boot to set the initial hypervisor | ||
| 177 | * vectors as part of hypervisor installation. On an SMP system, this should | ||
| 178 | * be called on each CPU. | ||
| 179 | * | ||
| 180 | * r0 must be the physical address of the new vector table (which must lie in | ||
| 181 | * the bottom 4GB of physical address space. | ||
| 182 | * | ||
| 183 | * r0 must be 32-byte aligned. | ||
| 184 | * | ||
| 185 | * Before calling this, you must check that the stub hypervisor is installed | ||
| 186 | * everywhere, by waiting for any secondary CPUs to be brought up and then | ||
| 187 | * checking that BOOT_CPU_MODE_HAVE_HYP(__boot_cpu_mode) is true. | ||
| 188 | * | ||
| 189 | * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or | ||
| 190 | * something else went wrong... in such cases, trying to install a new | ||
| 191 | * hypervisor is unlikely to work as desired. | ||
| 192 | * | ||
| 193 | * When you call into your shiny new hypervisor, sp_hyp will contain junk, | ||
| 194 | * so you will need to set that to something sensible at the new hypervisor's | ||
| 195 | * initialisation entry point. | ||
| 196 | */ | ||
| 197 | ENTRY(__hyp_get_vectors) | ||
| 198 | mov r0, #-1 | ||
| 199 | ENDPROC(__hyp_get_vectors) | ||
| 200 | @ fall through | ||
| 201 | ENTRY(__hyp_set_vectors) | ||
| 202 | __HVC(0) | ||
| 203 | bx lr | ||
| 204 | ENDPROC(__hyp_set_vectors) | ||
| 205 | |||
| 206 | #ifndef ZIMAGE | ||
| 207 | .align 2 | ||
| 208 | .L__boot_cpu_mode_offset: | ||
| 209 | .long __boot_cpu_mode - . | ||
| 210 | #endif | ||
| 211 | |||
| 212 | .align 5 | ||
| 213 | __hyp_stub_vectors: | ||
| 214 | __hyp_stub_reset: W(b) . | ||
| 215 | __hyp_stub_und: W(b) . | ||
| 216 | __hyp_stub_svc: W(b) . | ||
| 217 | __hyp_stub_pabort: W(b) . | ||
| 218 | __hyp_stub_dabort: W(b) . | ||
| 219 | __hyp_stub_trap: W(b) __hyp_stub_do_trap | ||
| 220 | __hyp_stub_irq: W(b) . | ||
| 221 | __hyp_stub_fiq: W(b) . | ||
| 222 | ENDPROC(__hyp_stub_vectors) | ||
| 223 | |||
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index febafa0f552d..da1d1aa20ad9 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include <asm/traps.h> | 53 | #include <asm/traps.h> |
| 54 | #include <asm/unwind.h> | 54 | #include <asm/unwind.h> |
| 55 | #include <asm/memblock.h> | 55 | #include <asm/memblock.h> |
| 56 | #include <asm/virt.h> | ||
| 56 | 57 | ||
| 57 | #include "atags.h" | 58 | #include "atags.h" |
| 58 | #include "tcm.h" | 59 | #include "tcm.h" |
| @@ -703,6 +704,21 @@ static int __init meminfo_cmp(const void *_a, const void *_b) | |||
| 703 | return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; | 704 | return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; |
| 704 | } | 705 | } |
| 705 | 706 | ||
| 707 | void __init hyp_mode_check(void) | ||
| 708 | { | ||
| 709 | #ifdef CONFIG_ARM_VIRT_EXT | ||
| 710 | if (is_hyp_mode_available()) { | ||
| 711 | pr_info("CPU: All CPU(s) started in HYP mode.\n"); | ||
| 712 | pr_info("CPU: Virtualization extensions available.\n"); | ||
| 713 | } else if (is_hyp_mode_mismatched()) { | ||
| 714 | pr_warn("CPU: WARNING: CPU(s) started in wrong/inconsistent modes (primary CPU mode 0x%x)\n", | ||
| 715 | __boot_cpu_mode & MODE_MASK); | ||
| 716 | pr_warn("CPU: This may indicate a broken bootloader or firmware.\n"); | ||
| 717 | } else | ||
| 718 | pr_info("CPU: All CPU(s) started in SVC mode.\n"); | ||
| 719 | #endif | ||
| 720 | } | ||
| 721 | |||
| 706 | void __init setup_arch(char **cmdline_p) | 722 | void __init setup_arch(char **cmdline_p) |
| 707 | { | 723 | { |
| 708 | struct machine_desc *mdesc; | 724 | struct machine_desc *mdesc; |
| @@ -748,6 +764,10 @@ void __init setup_arch(char **cmdline_p) | |||
| 748 | smp_init_cpus(); | 764 | smp_init_cpus(); |
| 749 | } | 765 | } |
| 750 | #endif | 766 | #endif |
| 767 | |||
| 768 | if (!is_smp()) | ||
| 769 | hyp_mode_check(); | ||
| 770 | |||
| 751 | reserve_crashkernel(); | 771 | reserve_crashkernel(); |
| 752 | 772 | ||
| 753 | tcm_init(); | 773 | tcm_init(); |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d100eacdb798..8e20754dd31d 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <asm/ptrace.h> | 43 | #include <asm/ptrace.h> |
| 44 | #include <asm/localtimer.h> | 44 | #include <asm/localtimer.h> |
| 45 | #include <asm/smp_plat.h> | 45 | #include <asm/smp_plat.h> |
| 46 | #include <asm/virt.h> | ||
| 46 | #include <asm/mach/arch.h> | 47 | #include <asm/mach/arch.h> |
| 47 | 48 | ||
| 48 | /* | 49 | /* |
| @@ -202,8 +203,11 @@ int __cpuinit __cpu_disable(void) | |||
| 202 | /* | 203 | /* |
| 203 | * Flush user cache and TLB mappings, and then remove this CPU | 204 | * Flush user cache and TLB mappings, and then remove this CPU |
| 204 | * from the vm mask set of all processes. | 205 | * from the vm mask set of all processes. |
| 206 | * | ||
| 207 | * Caches are flushed to the Level of Unification Inner Shareable | ||
| 208 | * to write-back dirty lines to unified caches shared by all CPUs. | ||
| 205 | */ | 209 | */ |
| 206 | flush_cache_all(); | 210 | flush_cache_louis(); |
| 207 | local_flush_tlb_all(); | 211 | local_flush_tlb_all(); |
| 208 | 212 | ||
| 209 | clear_tasks_mm_cpumask(cpu); | 213 | clear_tasks_mm_cpumask(cpu); |
| @@ -355,6 +359,8 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
| 355 | num_online_cpus(), | 359 | num_online_cpus(), |
| 356 | bogosum / (500000/HZ), | 360 | bogosum / (500000/HZ), |
| 357 | (bogosum / (5000/HZ)) % 100); | 361 | (bogosum / (5000/HZ)) % 100); |
| 362 | |||
| 363 | hyp_mode_check(); | ||
| 358 | } | 364 | } |
| 359 | 365 | ||
| 360 | void __init smp_prepare_boot_cpu(void) | 366 | void __init smp_prepare_boot_cpu(void) |
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 1794cc3b0f18..358bca3a995e 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c | |||
| @@ -17,6 +17,8 @@ extern void cpu_resume_mmu(void); | |||
| 17 | */ | 17 | */ |
| 18 | void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) | 18 | void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) |
| 19 | { | 19 | { |
| 20 | u32 *ctx = ptr; | ||
| 21 | |||
| 20 | *save_ptr = virt_to_phys(ptr); | 22 | *save_ptr = virt_to_phys(ptr); |
| 21 | 23 | ||
| 22 | /* This must correspond to the LDM in cpu_resume() assembly */ | 24 | /* This must correspond to the LDM in cpu_resume() assembly */ |
| @@ -26,7 +28,20 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) | |||
| 26 | 28 | ||
| 27 | cpu_do_suspend(ptr); | 29 | cpu_do_suspend(ptr); |
| 28 | 30 | ||
| 29 | flush_cache_all(); | 31 | flush_cache_louis(); |
| 32 | |||
| 33 | /* | ||
| 34 | * flush_cache_louis does not guarantee that | ||
| 35 | * save_ptr and ptr are cleaned to main memory, | ||
| 36 | * just up to the Level of Unification Inner Shareable. | ||
| 37 | * Since the context pointer and context itself | ||
| 38 | * are to be retrieved with the MMU off that | ||
| 39 | * data must be cleaned from all cache levels | ||
| 40 | * to main memory using "area" cache primitives. | ||
| 41 | */ | ||
| 42 | __cpuc_flush_dcache_area(ctx, ptrsz); | ||
| 43 | __cpuc_flush_dcache_area(save_ptr, sizeof(*save_ptr)); | ||
| 44 | |||
| 30 | outer_clean_range(*save_ptr, *save_ptr + ptrsz); | 45 | outer_clean_range(*save_ptr, *save_ptr + ptrsz); |
| 31 | outer_clean_range(virt_to_phys(save_ptr), | 46 | outer_clean_range(virt_to_phys(save_ptr), |
| 32 | virt_to_phys(save_ptr) + sizeof(*save_ptr)); | 47 | virt_to_phys(save_ptr) + sizeof(*save_ptr)); |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 101b9681c08c..c9a4963b5c3d 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
| @@ -624,6 +624,23 @@ config ARM_THUMBEE | |||
| 624 | Say Y here if you have a CPU with the ThumbEE extension and code to | 624 | Say Y here if you have a CPU with the ThumbEE extension and code to |
| 625 | make use of it. Say N for code that can run on CPUs without ThumbEE. | 625 | make use of it. Say N for code that can run on CPUs without ThumbEE. |
| 626 | 626 | ||
| 627 | config ARM_VIRT_EXT | ||
| 628 | bool "Native support for the ARM Virtualization Extensions" | ||
| 629 | depends on MMU && CPU_V7 | ||
| 630 | help | ||
| 631 | Enable the kernel to make use of the ARM Virtualization | ||
| 632 | Extensions to install hypervisors without run-time firmware | ||
| 633 | assistance. | ||
| 634 | |||
| 635 | A compliant bootloader is required in order to make maximum | ||
| 636 | use of this feature. Refer to Documentation/arm/Booting for | ||
| 637 | details. | ||
| 638 | |||
| 639 | It is safe to enable this option even if the kernel may not be | ||
| 640 | booted in HYP mode, may not have support for the | ||
| 641 | virtualization extensions, or may be booted with a | ||
| 642 | non-compliant bootloader. | ||
| 643 | |||
| 627 | config SWP_EMULATE | 644 | config SWP_EMULATE |
| 628 | bool "Emulate SWP/SWPB instructions" | 645 | bool "Emulate SWP/SWPB instructions" |
| 629 | depends on !CPU_USE_DOMAINS && CPU_V7 | 646 | depends on !CPU_USE_DOMAINS && CPU_V7 |
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index 072016371093..e505befe51b5 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S | |||
| @@ -240,6 +240,9 @@ ENTRY(fa_dma_unmap_area) | |||
| 240 | mov pc, lr | 240 | mov pc, lr |
| 241 | ENDPROC(fa_dma_unmap_area) | 241 | ENDPROC(fa_dma_unmap_area) |
| 242 | 242 | ||
| 243 | .globl fa_flush_kern_cache_louis | ||
| 244 | .equ fa_flush_kern_cache_louis, fa_flush_kern_cache_all | ||
| 245 | |||
| 243 | __INITDATA | 246 | __INITDATA |
| 244 | 247 | ||
| 245 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 248 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index 52e35f32eefb..8a3fadece8d3 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S | |||
| @@ -128,6 +128,9 @@ ENTRY(v3_dma_map_area) | |||
| 128 | ENDPROC(v3_dma_unmap_area) | 128 | ENDPROC(v3_dma_unmap_area) |
| 129 | ENDPROC(v3_dma_map_area) | 129 | ENDPROC(v3_dma_map_area) |
| 130 | 130 | ||
| 131 | .globl v3_flush_kern_cache_louis | ||
| 132 | .equ v3_flush_kern_cache_louis, v3_flush_kern_cache_all | ||
| 133 | |||
| 131 | __INITDATA | 134 | __INITDATA |
| 132 | 135 | ||
| 133 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 136 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index 022135d2b7e4..43e5d77be677 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S | |||
| @@ -140,6 +140,9 @@ ENTRY(v4_dma_map_area) | |||
| 140 | ENDPROC(v4_dma_unmap_area) | 140 | ENDPROC(v4_dma_unmap_area) |
| 141 | ENDPROC(v4_dma_map_area) | 141 | ENDPROC(v4_dma_map_area) |
| 142 | 142 | ||
| 143 | .globl v4_flush_kern_cache_louis | ||
| 144 | .equ v4_flush_kern_cache_louis, v4_flush_kern_cache_all | ||
| 145 | |||
| 143 | __INITDATA | 146 | __INITDATA |
| 144 | 147 | ||
| 145 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 148 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 8f1eeae340c8..cd4945321407 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S | |||
| @@ -251,6 +251,9 @@ ENTRY(v4wb_dma_unmap_area) | |||
| 251 | mov pc, lr | 251 | mov pc, lr |
| 252 | ENDPROC(v4wb_dma_unmap_area) | 252 | ENDPROC(v4wb_dma_unmap_area) |
| 253 | 253 | ||
| 254 | .globl v4wb_flush_kern_cache_louis | ||
| 255 | .equ v4wb_flush_kern_cache_louis, v4wb_flush_kern_cache_all | ||
| 256 | |||
| 254 | __INITDATA | 257 | __INITDATA |
| 255 | 258 | ||
| 256 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 259 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index b34a5f908a82..11e5e5838bc5 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S | |||
| @@ -196,6 +196,9 @@ ENTRY(v4wt_dma_map_area) | |||
| 196 | ENDPROC(v4wt_dma_unmap_area) | 196 | ENDPROC(v4wt_dma_unmap_area) |
| 197 | ENDPROC(v4wt_dma_map_area) | 197 | ENDPROC(v4wt_dma_map_area) |
| 198 | 198 | ||
| 199 | .globl v4wt_flush_kern_cache_louis | ||
| 200 | .equ v4wt_flush_kern_cache_louis, v4wt_flush_kern_cache_all | ||
| 201 | |||
| 199 | __INITDATA | 202 | __INITDATA |
| 200 | 203 | ||
| 201 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 204 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 4b10760c56d6..d8fd4d4bd3d4 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S | |||
| @@ -326,6 +326,9 @@ ENTRY(v6_dma_unmap_area) | |||
| 326 | mov pc, lr | 326 | mov pc, lr |
| 327 | ENDPROC(v6_dma_unmap_area) | 327 | ENDPROC(v6_dma_unmap_area) |
| 328 | 328 | ||
| 329 | .globl v6_flush_kern_cache_louis | ||
| 330 | .equ v6_flush_kern_cache_louis, v6_flush_kern_cache_all | ||
| 331 | |||
| 329 | __INITDATA | 332 | __INITDATA |
| 330 | 333 | ||
| 331 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 334 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 3b172275262e..cd956647c21a 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S | |||
| @@ -33,6 +33,24 @@ ENTRY(v7_flush_icache_all) | |||
| 33 | mov pc, lr | 33 | mov pc, lr |
| 34 | ENDPROC(v7_flush_icache_all) | 34 | ENDPROC(v7_flush_icache_all) |
| 35 | 35 | ||
| 36 | /* | ||
| 37 | * v7_flush_dcache_louis() | ||
| 38 | * | ||
| 39 | * Flush the D-cache up to the Level of Unification Inner Shareable | ||
| 40 | * | ||
| 41 | * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) | ||
| 42 | */ | ||
| 43 | |||
| 44 | ENTRY(v7_flush_dcache_louis) | ||
| 45 | dmb @ ensure ordering with previous memory accesses | ||
| 46 | mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr | ||
| 47 | ands r3, r0, #0xe00000 @ extract LoUIS from clidr | ||
| 48 | mov r3, r3, lsr #20 @ r3 = LoUIS * 2 | ||
| 49 | moveq pc, lr @ return if level == 0 | ||
| 50 | mov r10, #0 @ r10 (starting level) = 0 | ||
| 51 | b flush_levels @ start flushing cache levels | ||
| 52 | ENDPROC(v7_flush_dcache_louis) | ||
| 53 | |||
| 36 | /* | 54 | /* |
| 37 | * v7_flush_dcache_all() | 55 | * v7_flush_dcache_all() |
| 38 | * | 56 | * |
| @@ -49,7 +67,7 @@ ENTRY(v7_flush_dcache_all) | |||
| 49 | mov r3, r3, lsr #23 @ left align loc bit field | 67 | mov r3, r3, lsr #23 @ left align loc bit field |
| 50 | beq finished @ if loc is 0, then no need to clean | 68 | beq finished @ if loc is 0, then no need to clean |
| 51 | mov r10, #0 @ start clean at cache level 0 | 69 | mov r10, #0 @ start clean at cache level 0 |
| 52 | loop1: | 70 | flush_levels: |
| 53 | add r2, r10, r10, lsr #1 @ work out 3x current cache level | 71 | add r2, r10, r10, lsr #1 @ work out 3x current cache level |
| 54 | mov r1, r0, lsr r2 @ extract cache type bits from clidr | 72 | mov r1, r0, lsr r2 @ extract cache type bits from clidr |
| 55 | and r1, r1, #7 @ mask of the bits for current cache only | 73 | and r1, r1, #7 @ mask of the bits for current cache only |
| @@ -71,9 +89,9 @@ loop1: | |||
| 71 | clz r5, r4 @ find bit position of way size increment | 89 | clz r5, r4 @ find bit position of way size increment |
| 72 | ldr r7, =0x7fff | 90 | ldr r7, =0x7fff |
| 73 | ands r7, r7, r1, lsr #13 @ extract max number of the index size | 91 | ands r7, r7, r1, lsr #13 @ extract max number of the index size |
| 74 | loop2: | 92 | loop1: |
| 75 | mov r9, r4 @ create working copy of max way size | 93 | mov r9, r4 @ create working copy of max way size |
| 76 | loop3: | 94 | loop2: |
| 77 | ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 | 95 | ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 |
| 78 | THUMB( lsl r6, r9, r5 ) | 96 | THUMB( lsl r6, r9, r5 ) |
| 79 | THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 | 97 | THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 |
| @@ -82,13 +100,13 @@ loop3: | |||
| 82 | THUMB( orr r11, r11, r6 ) @ factor index number into r11 | 100 | THUMB( orr r11, r11, r6 ) @ factor index number into r11 |
| 83 | mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way | 101 | mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way |
| 84 | subs r9, r9, #1 @ decrement the way | 102 | subs r9, r9, #1 @ decrement the way |
| 85 | bge loop3 | ||
| 86 | subs r7, r7, #1 @ decrement the index | ||
| 87 | bge loop2 | 103 | bge loop2 |
| 104 | subs r7, r7, #1 @ decrement the index | ||
| 105 | bge loop1 | ||
| 88 | skip: | 106 | skip: |
| 89 | add r10, r10, #2 @ increment cache number | 107 | add r10, r10, #2 @ increment cache number |
| 90 | cmp r3, r10 | 108 | cmp r3, r10 |
| 91 | bgt loop1 | 109 | bgt flush_levels |
| 92 | finished: | 110 | finished: |
| 93 | mov r10, #0 @ swith back to cache level 0 | 111 | mov r10, #0 @ swith back to cache level 0 |
| 94 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr | 112 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr |
| @@ -120,6 +138,24 @@ ENTRY(v7_flush_kern_cache_all) | |||
| 120 | mov pc, lr | 138 | mov pc, lr |
| 121 | ENDPROC(v7_flush_kern_cache_all) | 139 | ENDPROC(v7_flush_kern_cache_all) |
| 122 | 140 | ||
| 141 | /* | ||
| 142 | * v7_flush_kern_cache_louis(void) | ||
| 143 | * | ||
| 144 | * Flush the data cache up to Level of Unification Inner Shareable. | ||
| 145 | * Invalidate the I-cache to the point of unification. | ||
| 146 | */ | ||
| 147 | ENTRY(v7_flush_kern_cache_louis) | ||
| 148 | ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) | ||
| 149 | THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) | ||
| 150 | bl v7_flush_dcache_louis | ||
| 151 | mov r0, #0 | ||
| 152 | ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable | ||
| 153 | ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate | ||
| 154 | ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) | ||
| 155 | THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) | ||
| 156 | mov pc, lr | ||
| 157 | ENDPROC(v7_flush_kern_cache_louis) | ||
| 158 | |||
| 123 | /* | 159 | /* |
| 124 | * v7_flush_cache_all() | 160 | * v7_flush_cache_all() |
| 125 | * | 161 | * |
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 0650bb87c1e3..2bb61e703d6c 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S | |||
| @@ -368,6 +368,9 @@ ENTRY(arm1020_dma_unmap_area) | |||
| 368 | mov pc, lr | 368 | mov pc, lr |
| 369 | ENDPROC(arm1020_dma_unmap_area) | 369 | ENDPROC(arm1020_dma_unmap_area) |
| 370 | 370 | ||
| 371 | .globl arm1020_flush_kern_cache_louis | ||
| 372 | .equ arm1020_flush_kern_cache_louis, arm1020_flush_kern_cache_all | ||
| 373 | |||
| 371 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 374 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 372 | define_cache_functions arm1020 | 375 | define_cache_functions arm1020 |
| 373 | 376 | ||
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 4188478325a6..8f96aa40f510 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S | |||
| @@ -354,6 +354,9 @@ ENTRY(arm1020e_dma_unmap_area) | |||
| 354 | mov pc, lr | 354 | mov pc, lr |
| 355 | ENDPROC(arm1020e_dma_unmap_area) | 355 | ENDPROC(arm1020e_dma_unmap_area) |
| 356 | 356 | ||
| 357 | .globl arm1020e_flush_kern_cache_louis | ||
| 358 | .equ arm1020e_flush_kern_cache_louis, arm1020e_flush_kern_cache_all | ||
| 359 | |||
| 357 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 360 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 358 | define_cache_functions arm1020e | 361 | define_cache_functions arm1020e |
| 359 | 362 | ||
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 33c68824bff0..8ebe4a469a22 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S | |||
| @@ -343,6 +343,9 @@ ENTRY(arm1022_dma_unmap_area) | |||
| 343 | mov pc, lr | 343 | mov pc, lr |
| 344 | ENDPROC(arm1022_dma_unmap_area) | 344 | ENDPROC(arm1022_dma_unmap_area) |
| 345 | 345 | ||
| 346 | .globl arm1022_flush_kern_cache_louis | ||
| 347 | .equ arm1022_flush_kern_cache_louis, arm1022_flush_kern_cache_all | ||
| 348 | |||
| 346 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 349 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 347 | define_cache_functions arm1022 | 350 | define_cache_functions arm1022 |
| 348 | 351 | ||
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index fbc1d5fc24dc..093fc7e520c3 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S | |||
| @@ -337,6 +337,9 @@ ENTRY(arm1026_dma_unmap_area) | |||
| 337 | mov pc, lr | 337 | mov pc, lr |
| 338 | ENDPROC(arm1026_dma_unmap_area) | 338 | ENDPROC(arm1026_dma_unmap_area) |
| 339 | 339 | ||
| 340 | .globl arm1026_flush_kern_cache_louis | ||
| 341 | .equ arm1026_flush_kern_cache_louis, arm1026_flush_kern_cache_all | ||
| 342 | |||
| 340 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 343 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 341 | define_cache_functions arm1026 | 344 | define_cache_functions arm1026 |
| 342 | 345 | ||
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 1a8c138eb897..2c3b9421ab5e 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S | |||
| @@ -319,6 +319,9 @@ ENTRY(arm920_dma_unmap_area) | |||
| 319 | mov pc, lr | 319 | mov pc, lr |
| 320 | ENDPROC(arm920_dma_unmap_area) | 320 | ENDPROC(arm920_dma_unmap_area) |
| 321 | 321 | ||
| 322 | .globl arm920_flush_kern_cache_louis | ||
| 323 | .equ arm920_flush_kern_cache_louis, arm920_flush_kern_cache_all | ||
| 324 | |||
| 322 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 325 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 323 | define_cache_functions arm920 | 326 | define_cache_functions arm920 |
| 324 | #endif | 327 | #endif |
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 4c44d7e1c3ca..4464c49d7449 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S | |||
| @@ -321,6 +321,9 @@ ENTRY(arm922_dma_unmap_area) | |||
| 321 | mov pc, lr | 321 | mov pc, lr |
| 322 | ENDPROC(arm922_dma_unmap_area) | 322 | ENDPROC(arm922_dma_unmap_area) |
| 323 | 323 | ||
| 324 | .globl arm922_flush_kern_cache_louis | ||
| 325 | .equ arm922_flush_kern_cache_louis, arm922_flush_kern_cache_all | ||
| 326 | |||
| 324 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 327 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 325 | define_cache_functions arm922 | 328 | define_cache_functions arm922 |
| 326 | #endif | 329 | #endif |
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index ec5b1180994f..281eb9b9c1d6 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S | |||
| @@ -376,6 +376,9 @@ ENTRY(arm925_dma_unmap_area) | |||
| 376 | mov pc, lr | 376 | mov pc, lr |
| 377 | ENDPROC(arm925_dma_unmap_area) | 377 | ENDPROC(arm925_dma_unmap_area) |
| 378 | 378 | ||
| 379 | .globl arm925_flush_kern_cache_louis | ||
| 380 | .equ arm925_flush_kern_cache_louis, arm925_flush_kern_cache_all | ||
| 381 | |||
| 379 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 382 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 380 | define_cache_functions arm925 | 383 | define_cache_functions arm925 |
| 381 | 384 | ||
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index c31e62c606c0..f1803f7e2972 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S | |||
| @@ -339,6 +339,9 @@ ENTRY(arm926_dma_unmap_area) | |||
| 339 | mov pc, lr | 339 | mov pc, lr |
| 340 | ENDPROC(arm926_dma_unmap_area) | 340 | ENDPROC(arm926_dma_unmap_area) |
| 341 | 341 | ||
| 342 | .globl arm926_flush_kern_cache_louis | ||
| 343 | .equ arm926_flush_kern_cache_louis, arm926_flush_kern_cache_all | ||
| 344 | |||
| 342 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 345 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 343 | define_cache_functions arm926 | 346 | define_cache_functions arm926 |
| 344 | 347 | ||
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index a613a7dd7146..8da189d4a402 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S | |||
| @@ -267,6 +267,9 @@ ENTRY(arm940_dma_unmap_area) | |||
| 267 | mov pc, lr | 267 | mov pc, lr |
| 268 | ENDPROC(arm940_dma_unmap_area) | 268 | ENDPROC(arm940_dma_unmap_area) |
| 269 | 269 | ||
| 270 | .globl arm940_flush_kern_cache_louis | ||
| 271 | .equ arm940_flush_kern_cache_louis, arm940_flush_kern_cache_all | ||
| 272 | |||
| 270 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 273 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 271 | define_cache_functions arm940 | 274 | define_cache_functions arm940 |
| 272 | 275 | ||
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index 9f4f2999fdd0..f666cf34075a 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S | |||
| @@ -310,6 +310,9 @@ ENTRY(arm946_dma_unmap_area) | |||
| 310 | mov pc, lr | 310 | mov pc, lr |
| 311 | ENDPROC(arm946_dma_unmap_area) | 311 | ENDPROC(arm946_dma_unmap_area) |
| 312 | 312 | ||
| 313 | .globl arm946_flush_kern_cache_louis | ||
| 314 | .equ arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all | ||
| 315 | |||
| 313 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 316 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 314 | define_cache_functions arm946 | 317 | define_cache_functions arm946 |
| 315 | 318 | ||
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index 23a8e4c7f2bd..4106b09e0c29 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S | |||
| @@ -415,6 +415,9 @@ ENTRY(feroceon_dma_unmap_area) | |||
| 415 | mov pc, lr | 415 | mov pc, lr |
| 416 | ENDPROC(feroceon_dma_unmap_area) | 416 | ENDPROC(feroceon_dma_unmap_area) |
| 417 | 417 | ||
| 418 | .globl feroceon_flush_kern_cache_louis | ||
| 419 | .equ feroceon_flush_kern_cache_louis, feroceon_flush_kern_cache_all | ||
| 420 | |||
| 418 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 421 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 419 | define_cache_functions feroceon | 422 | define_cache_functions feroceon |
| 420 | 423 | ||
| @@ -431,6 +434,7 @@ ENDPROC(feroceon_dma_unmap_area) | |||
| 431 | range_alias flush_icache_all | 434 | range_alias flush_icache_all |
| 432 | range_alias flush_user_cache_all | 435 | range_alias flush_user_cache_all |
| 433 | range_alias flush_kern_cache_all | 436 | range_alias flush_kern_cache_all |
| 437 | range_alias flush_kern_cache_louis | ||
| 434 | range_alias flush_user_cache_range | 438 | range_alias flush_user_cache_range |
| 435 | range_alias coherent_kern_range | 439 | range_alias coherent_kern_range |
| 436 | range_alias coherent_user_range | 440 | range_alias coherent_user_range |
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 2d8ff3ad86d3..b29a2265af01 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S | |||
| @@ -299,6 +299,7 @@ ENTRY(\name\()_processor_functions) | |||
| 299 | ENTRY(\name\()_cache_fns) | 299 | ENTRY(\name\()_cache_fns) |
| 300 | .long \name\()_flush_icache_all | 300 | .long \name\()_flush_icache_all |
| 301 | .long \name\()_flush_kern_cache_all | 301 | .long \name\()_flush_kern_cache_all |
| 302 | .long \name\()_flush_kern_cache_louis | ||
| 302 | .long \name\()_flush_user_cache_all | 303 | .long \name\()_flush_user_cache_all |
| 303 | .long \name\()_flush_user_cache_range | 304 | .long \name\()_flush_user_cache_range |
| 304 | .long \name\()_coherent_kern_range | 305 | .long \name\()_coherent_kern_range |
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S index fbb2124a547d..82f9cdc751d6 100644 --- a/arch/arm/mm/proc-mohawk.S +++ b/arch/arm/mm/proc-mohawk.S | |||
| @@ -303,6 +303,9 @@ ENTRY(mohawk_dma_unmap_area) | |||
| 303 | mov pc, lr | 303 | mov pc, lr |
| 304 | ENDPROC(mohawk_dma_unmap_area) | 304 | ENDPROC(mohawk_dma_unmap_area) |
| 305 | 305 | ||
| 306 | .globl mohawk_flush_kern_cache_louis | ||
| 307 | .equ mohawk_flush_kern_cache_louis, mohawk_flush_kern_cache_all | ||
| 308 | |||
| 306 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 309 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 307 | define_cache_functions mohawk | 310 | define_cache_functions mohawk |
| 308 | 311 | ||
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index c2e2b66f72b5..846d279f3176 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
| @@ -172,7 +172,7 @@ __v7_ca15mp_setup: | |||
| 172 | __v7_setup: | 172 | __v7_setup: |
| 173 | adr r12, __v7_setup_stack @ the local stack | 173 | adr r12, __v7_setup_stack @ the local stack |
| 174 | stmia r12, {r0-r5, r7, r9, r11, lr} | 174 | stmia r12, {r0-r5, r7, r9, r11, lr} |
| 175 | bl v7_flush_dcache_all | 175 | bl v7_flush_dcache_louis |
| 176 | ldmia r12, {r0-r5, r7, r9, r11, lr} | 176 | ldmia r12, {r0-r5, r7, r9, r11, lr} |
| 177 | 177 | ||
| 178 | mrc p15, 0, r0, c0, c0, 0 @ read main ID register | 178 | mrc p15, 0, r0, c0, c0, 0 @ read main ID register |
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index b0d57869da2d..eb93d6487f35 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S | |||
| @@ -337,6 +337,9 @@ ENTRY(xsc3_dma_unmap_area) | |||
| 337 | mov pc, lr | 337 | mov pc, lr |
| 338 | ENDPROC(xsc3_dma_unmap_area) | 338 | ENDPROC(xsc3_dma_unmap_area) |
| 339 | 339 | ||
| 340 | .globl xsc3_flush_kern_cache_louis | ||
| 341 | .equ xsc3_flush_kern_cache_louis, xsc3_flush_kern_cache_all | ||
| 342 | |||
| 340 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 343 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 341 | define_cache_functions xsc3 | 344 | define_cache_functions xsc3 |
| 342 | 345 | ||
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 4ffebaa595ee..25510361aa18 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S | |||
| @@ -410,6 +410,9 @@ ENTRY(xscale_dma_unmap_area) | |||
| 410 | mov pc, lr | 410 | mov pc, lr |
| 411 | ENDPROC(xscale_dma_unmap_area) | 411 | ENDPROC(xscale_dma_unmap_area) |
| 412 | 412 | ||
| 413 | .globl xscale_flush_kern_cache_louis | ||
| 414 | .equ xscale_flush_kern_cache_louis, xscale_flush_kern_cache_all | ||
| 415 | |||
| 413 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 416 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
| 414 | define_cache_functions xscale | 417 | define_cache_functions xscale |
| 415 | 418 | ||
| @@ -439,6 +442,7 @@ ENDPROC(xscale_dma_unmap_area) | |||
| 439 | a0_alias flush_icache_all | 442 | a0_alias flush_icache_all |
| 440 | a0_alias flush_user_cache_all | 443 | a0_alias flush_user_cache_all |
| 441 | a0_alias flush_kern_cache_all | 444 | a0_alias flush_kern_cache_all |
| 445 | a0_alias flush_kern_cache_louis | ||
| 442 | a0_alias flush_user_cache_range | 446 | a0_alias flush_user_cache_range |
| 443 | a0_alias coherent_kern_range | 447 | a0_alias coherent_kern_range |
| 444 | a0_alias coherent_user_range | 448 | a0_alias coherent_user_range |
