diff options
88 files changed, 1985 insertions, 416 deletions
diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt index cbef09b5c8a7..69ddf9fad2dc 100644 --- a/Documentation/devicetree/bindings/arm/l2cc.txt +++ b/Documentation/devicetree/bindings/arm/l2cc.txt | |||
@@ -16,6 +16,9 @@ Required properties: | |||
16 | performs the same operation). | 16 | performs the same operation). |
17 | "marvell,"aurora-outer-cache: Marvell Controller designed to be | 17 | "marvell,"aurora-outer-cache: Marvell Controller designed to be |
18 | compatible with the ARM one with outer cache mode. | 18 | compatible with the ARM one with outer cache mode. |
19 | "bcm,bcm11351-a2-pl310-cache": For Broadcom bcm11351 chipset where an | ||
20 | offset needs to be added to the address before passing down to the L2 | ||
21 | cache controller | ||
19 | - cache-unified : Specifies the cache is a unified cache. | 22 | - cache-unified : Specifies the cache is a unified cache. |
20 | - cache-level : Should be set to 2 for a level 2 cache. | 23 | - cache-level : Should be set to 2 for a level 2 cache. |
21 | - reg : Physical base address and size of cache controller's memory mapped | 24 | - reg : Physical base address and size of cache controller's memory mapped |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index de7049bdea85..531cdda016f9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -175,6 +175,9 @@ config ARCH_HAS_CPUFREQ | |||
175 | and that the relevant menu configurations are displayed for | 175 | and that the relevant menu configurations are displayed for |
176 | it. | 176 | it. |
177 | 177 | ||
178 | config ARCH_HAS_BANDGAP | ||
179 | bool | ||
180 | |||
178 | config GENERIC_HWEIGHT | 181 | config GENERIC_HWEIGHT |
179 | bool | 182 | bool |
180 | default y | 183 | default y |
@@ -1450,7 +1453,7 @@ config SMP | |||
1450 | depends on CPU_V6K || CPU_V7 | 1453 | depends on CPU_V6K || CPU_V7 |
1451 | depends on GENERIC_CLOCKEVENTS | 1454 | depends on GENERIC_CLOCKEVENTS |
1452 | depends on HAVE_SMP | 1455 | depends on HAVE_SMP |
1453 | depends on MMU | 1456 | depends on MMU || ARM_MPU |
1454 | select USE_GENERIC_SMP_HELPERS | 1457 | select USE_GENERIC_SMP_HELPERS |
1455 | help | 1458 | help |
1456 | This enables support for systems with more than one CPU. If you have | 1459 | This enables support for systems with more than one CPU. If you have |
@@ -1471,7 +1474,7 @@ config SMP | |||
1471 | 1474 | ||
1472 | config SMP_ON_UP | 1475 | config SMP_ON_UP |
1473 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" | 1476 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" |
1474 | depends on SMP && !XIP_KERNEL | 1477 | depends on SMP && !XIP_KERNEL && MMU |
1475 | default y | 1478 | default y |
1476 | help | 1479 | help |
1477 | SMP kernels contain instructions which fail on non-SMP processors. | 1480 | SMP kernels contain instructions which fail on non-SMP processors. |
@@ -1744,6 +1747,14 @@ config HW_PERF_EVENTS | |||
1744 | Enable hardware performance counter support for perf events. If | 1747 | Enable hardware performance counter support for perf events. If |
1745 | disabled, perf events will use software events only. | 1748 | disabled, perf events will use software events only. |
1746 | 1749 | ||
1750 | config SYS_SUPPORTS_HUGETLBFS | ||
1751 | def_bool y | ||
1752 | depends on ARM_LPAE | ||
1753 | |||
1754 | config HAVE_ARCH_TRANSPARENT_HUGEPAGE | ||
1755 | def_bool y | ||
1756 | depends on ARM_LPAE | ||
1757 | |||
1747 | source "mm/Kconfig" | 1758 | source "mm/Kconfig" |
1748 | 1759 | ||
1749 | config FORCE_MAX_ZONEORDER | 1760 | config FORCE_MAX_ZONEORDER |
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu index c859495da480..aed66d5df7f1 100644 --- a/arch/arm/Kconfig-nommu +++ b/arch/arm/Kconfig-nommu | |||
@@ -50,3 +50,15 @@ config REMAP_VECTORS_TO_RAM | |||
50 | Otherwise, say 'y' here. In this case, the kernel will require | 50 | Otherwise, say 'y' here. In this case, the kernel will require |
51 | external support to redirect the hardware exception vectors to | 51 | external support to redirect the hardware exception vectors to |
52 | the writable versions located at DRAM_BASE. | 52 | the writable versions located at DRAM_BASE. |
53 | |||
54 | config ARM_MPU | ||
55 | bool 'Use the ARM v7 PMSA Compliant MPU' | ||
56 | depends on CPU_V7 | ||
57 | default y | ||
58 | help | ||
59 | Some ARM systems without an MMU have instead a Memory Protection | ||
60 | Unit (MPU) that defines the type and permissions for regions of | ||
61 | memory. | ||
62 | |||
63 | If your CPU has an MPU then you should choose 'y' here unless you | ||
64 | know that you do not want to use the MPU. | ||
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 77c1411c9a91..5b7be8d975b5 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -550,6 +550,13 @@ choice | |||
550 | of the tiles using the RS1 memory map, including all new A-class | 550 | of the tiles using the RS1 memory map, including all new A-class |
551 | core tiles, FPGA-based SMMs and software models. | 551 | core tiles, FPGA-based SMMs and software models. |
552 | 552 | ||
553 | config DEBUG_VEXPRESS_UART0_CRX | ||
554 | bool "Use PL011 UART0 at 0xb0090000 (Cortex-R compliant tiles)" | ||
555 | depends on ARCH_VEXPRESS && !MMU | ||
556 | help | ||
557 | This option selects UART0 at 0xb0090000. This is appropriate for | ||
558 | Cortex-R series tiles and SMMs, such as Cortex-R5 and Cortex-R7 | ||
559 | |||
553 | config DEBUG_VT8500_UART0 | 560 | config DEBUG_VT8500_UART0 |
554 | bool "Use UART0 on VIA/Wondermedia SoCs" | 561 | bool "Use UART0 on VIA/Wondermedia SoCs" |
555 | depends on ARCH_VT8500 | 562 | depends on ARCH_VT8500 |
@@ -789,7 +796,8 @@ config DEBUG_LL_INCLUDE | |||
789 | default "debug/u300.S" if DEBUG_U300_UART | 796 | default "debug/u300.S" if DEBUG_U300_UART |
790 | default "debug/ux500.S" if DEBUG_UX500_UART | 797 | default "debug/ux500.S" if DEBUG_UX500_UART |
791 | default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \ | 798 | default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \ |
792 | DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 | 799 | DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1 || \ |
800 | DEBUG_VEXPRESS_UART0_CRX | ||
793 | default "debug/vt8500.S" if DEBUG_VT8500_UART0 | 801 | default "debug/vt8500.S" if DEBUG_VT8500_UART0 |
794 | default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1 | 802 | default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1 |
795 | default "mach/debug-macro.S" | 803 | default "mach/debug-macro.S" |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 72caf82a8280..c0ac0f5e5e5c 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -59,38 +59,44 @@ comma = , | |||
59 | # Note that GCC does not numerically define an architecture version | 59 | # Note that GCC does not numerically define an architecture version |
60 | # macro, but instead defines a whole series of macros which makes | 60 | # macro, but instead defines a whole series of macros which makes |
61 | # testing for a specific architecture or later rather impossible. | 61 | # testing for a specific architecture or later rather impossible. |
62 | arch-$(CONFIG_CPU_32v7M) :=-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m | 62 | arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m |
63 | arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) | 63 | arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) |
64 | arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) | 64 | arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) |
65 | # Only override the compiler option if ARMv6. The ARMv6K extensions are | 65 | # Only override the compiler option if ARMv6. The ARMv6K extensions are |
66 | # always available in ARMv7 | 66 | # always available in ARMv7 |
67 | ifeq ($(CONFIG_CPU_32v6),y) | 67 | ifeq ($(CONFIG_CPU_32v6),y) |
68 | arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) | 68 | arch-$(CONFIG_CPU_32v6K) =-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) |
69 | endif | 69 | endif |
70 | arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) | 70 | arch-$(CONFIG_CPU_32v5) =-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) |
71 | arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t | 71 | arch-$(CONFIG_CPU_32v4T) =-D__LINUX_ARM_ARCH__=4 -march=armv4t |
72 | arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 | 72 | arch-$(CONFIG_CPU_32v4) =-D__LINUX_ARM_ARCH__=4 -march=armv4 |
73 | arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 | 73 | arch-$(CONFIG_CPU_32v3) =-D__LINUX_ARM_ARCH__=3 -march=armv3 |
74 | |||
75 | # Evaluate arch cc-option calls now | ||
76 | arch-y := $(arch-y) | ||
74 | 77 | ||
75 | # This selects how we optimise for the processor. | 78 | # This selects how we optimise for the processor. |
76 | tune-$(CONFIG_CPU_ARM7TDMI) :=-mtune=arm7tdmi | 79 | tune-$(CONFIG_CPU_ARM7TDMI) =-mtune=arm7tdmi |
77 | tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi | 80 | tune-$(CONFIG_CPU_ARM720T) =-mtune=arm7tdmi |
78 | tune-$(CONFIG_CPU_ARM740T) :=-mtune=arm7tdmi | 81 | tune-$(CONFIG_CPU_ARM740T) =-mtune=arm7tdmi |
79 | tune-$(CONFIG_CPU_ARM9TDMI) :=-mtune=arm9tdmi | 82 | tune-$(CONFIG_CPU_ARM9TDMI) =-mtune=arm9tdmi |
80 | tune-$(CONFIG_CPU_ARM940T) :=-mtune=arm9tdmi | 83 | tune-$(CONFIG_CPU_ARM940T) =-mtune=arm9tdmi |
81 | tune-$(CONFIG_CPU_ARM946E) :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi) | 84 | tune-$(CONFIG_CPU_ARM946E) =$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi) |
82 | tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi | 85 | tune-$(CONFIG_CPU_ARM920T) =-mtune=arm9tdmi |
83 | tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi | 86 | tune-$(CONFIG_CPU_ARM922T) =-mtune=arm9tdmi |
84 | tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi | 87 | tune-$(CONFIG_CPU_ARM925T) =-mtune=arm9tdmi |
85 | tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi | 88 | tune-$(CONFIG_CPU_ARM926T) =-mtune=arm9tdmi |
86 | tune-$(CONFIG_CPU_FA526) :=-mtune=arm9tdmi | 89 | tune-$(CONFIG_CPU_FA526) =-mtune=arm9tdmi |
87 | tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 | 90 | tune-$(CONFIG_CPU_SA110) =-mtune=strongarm110 |
88 | tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 | 91 | tune-$(CONFIG_CPU_SA1100) =-mtune=strongarm1100 |
89 | tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale | 92 | tune-$(CONFIG_CPU_XSCALE) =$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale |
90 | tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale | 93 | tune-$(CONFIG_CPU_XSC3) =$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale |
91 | tune-$(CONFIG_CPU_FEROCEON) :=$(call cc-option,-mtune=marvell-f,-mtune=xscale) | 94 | tune-$(CONFIG_CPU_FEROCEON) =$(call cc-option,-mtune=marvell-f,-mtune=xscale) |
92 | tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) | 95 | tune-$(CONFIG_CPU_V6) =$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) |
93 | tune-$(CONFIG_CPU_V6K) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) | 96 | tune-$(CONFIG_CPU_V6K) =$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) |
97 | |||
98 | # Evaluate tune cc-option calls now | ||
99 | tune-y := $(tune-y) | ||
94 | 100 | ||
95 | ifeq ($(CONFIG_AEABI),y) | 101 | ifeq ($(CONFIG_AEABI),y) |
96 | CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork | 102 | CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork |
@@ -295,9 +301,10 @@ zImage Image xipImage bootpImage uImage: vmlinux | |||
295 | zinstall uinstall install: vmlinux | 301 | zinstall uinstall install: vmlinux |
296 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ | 302 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ |
297 | 303 | ||
298 | %.dtb: scripts | 304 | %.dtb: | scripts |
299 | $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ | 305 | $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ |
300 | 306 | ||
307 | PHONY += dtbs | ||
301 | dtbs: scripts | 308 | dtbs: scripts |
302 | $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs | 309 | $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs |
303 | 310 | ||
diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c index aabc02a68482..d1153c8a765a 100644 --- a/arch/arm/boot/compressed/atags_to_fdt.c +++ b/arch/arm/boot/compressed/atags_to_fdt.c | |||
@@ -53,6 +53,17 @@ static const void *getprop(const void *fdt, const char *node_path, | |||
53 | return fdt_getprop(fdt, offset, property, len); | 53 | return fdt_getprop(fdt, offset, property, len); |
54 | } | 54 | } |
55 | 55 | ||
56 | static uint32_t get_cell_size(const void *fdt) | ||
57 | { | ||
58 | int len; | ||
59 | uint32_t cell_size = 1; | ||
60 | const uint32_t *size_len = getprop(fdt, "/", "#size-cells", &len); | ||
61 | |||
62 | if (size_len) | ||
63 | cell_size = fdt32_to_cpu(*size_len); | ||
64 | return cell_size; | ||
65 | } | ||
66 | |||
56 | static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) | 67 | static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) |
57 | { | 68 | { |
58 | char cmdline[COMMAND_LINE_SIZE]; | 69 | char cmdline[COMMAND_LINE_SIZE]; |
@@ -95,9 +106,11 @@ static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) | |||
95 | int atags_to_fdt(void *atag_list, void *fdt, int total_space) | 106 | int atags_to_fdt(void *atag_list, void *fdt, int total_space) |
96 | { | 107 | { |
97 | struct tag *atag = atag_list; | 108 | struct tag *atag = atag_list; |
98 | uint32_t mem_reg_property[2 * NR_BANKS]; | 109 | /* In the case of 64 bits memory size, need to reserve 2 cells for |
110 | * address and size for each bank */ | ||
111 | uint32_t mem_reg_property[2 * 2 * NR_BANKS]; | ||
99 | int memcount = 0; | 112 | int memcount = 0; |
100 | int ret; | 113 | int ret, memsize; |
101 | 114 | ||
102 | /* make sure we've got an aligned pointer */ | 115 | /* make sure we've got an aligned pointer */ |
103 | if ((u32)atag_list & 0x3) | 116 | if ((u32)atag_list & 0x3) |
@@ -137,8 +150,25 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space) | |||
137 | continue; | 150 | continue; |
138 | if (!atag->u.mem.size) | 151 | if (!atag->u.mem.size) |
139 | continue; | 152 | continue; |
140 | mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start); | 153 | memsize = get_cell_size(fdt); |
141 | mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size); | 154 | |
155 | if (memsize == 2) { | ||
156 | /* if memsize is 2, that means that | ||
157 | * each data needs 2 cells of 32 bits, | ||
158 | * so the data are 64 bits */ | ||
159 | uint64_t *mem_reg_prop64 = | ||
160 | (uint64_t *)mem_reg_property; | ||
161 | mem_reg_prop64[memcount++] = | ||
162 | cpu_to_fdt64(atag->u.mem.start); | ||
163 | mem_reg_prop64[memcount++] = | ||
164 | cpu_to_fdt64(atag->u.mem.size); | ||
165 | } else { | ||
166 | mem_reg_property[memcount++] = | ||
167 | cpu_to_fdt32(atag->u.mem.start); | ||
168 | mem_reg_property[memcount++] = | ||
169 | cpu_to_fdt32(atag->u.mem.size); | ||
170 | } | ||
171 | |||
142 | } else if (atag->hdr.tag == ATAG_INITRD2) { | 172 | } else if (atag->hdr.tag == ATAG_INITRD2) { |
143 | uint32_t initrd_start, initrd_size; | 173 | uint32_t initrd_start, initrd_size; |
144 | initrd_start = atag->u.initrd.start; | 174 | initrd_start = atag->u.initrd.start; |
@@ -150,8 +180,10 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space) | |||
150 | } | 180 | } |
151 | } | 181 | } |
152 | 182 | ||
153 | if (memcount) | 183 | if (memcount) { |
154 | setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount); | 184 | setprop(fdt, "/memory", "reg", mem_reg_property, |
185 | 4 * memcount * memsize); | ||
186 | } | ||
155 | 187 | ||
156 | return fdt_pack(fdt); | 188 | return fdt_pack(fdt); |
157 | } | 189 | } |
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 032a8d987148..75189f13cf54 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
@@ -142,7 +142,6 @@ start: | |||
142 | mov r7, r1 @ save architecture ID | 142 | mov r7, r1 @ save architecture ID |
143 | mov r8, r2 @ save atags pointer | 143 | mov r8, r2 @ save atags pointer |
144 | 144 | ||
145 | #ifndef __ARM_ARCH_2__ | ||
146 | /* | 145 | /* |
147 | * Booting from Angel - need to enter SVC mode and disable | 146 | * Booting from Angel - need to enter SVC mode and disable |
148 | * FIQs/IRQs (numeric definitions from angel arm.h source). | 147 | * FIQs/IRQs (numeric definitions from angel arm.h source). |
@@ -158,10 +157,6 @@ not_angel: | |||
158 | safe_svcmode_maskall r0 | 157 | safe_svcmode_maskall r0 |
159 | msr spsr_cxsf, r9 @ Save the CPU boot mode in | 158 | msr spsr_cxsf, r9 @ Save the CPU boot mode in |
160 | @ SPSR | 159 | @ SPSR |
161 | #else | ||
162 | teqp pc, #0x0c000003 @ turn off interrupts | ||
163 | #endif | ||
164 | |||
165 | /* | 160 | /* |
166 | * Note that some cache flushing and other stuff may | 161 | * Note that some cache flushing and other stuff may |
167 | * be needed here - is there an Angel SWI call for this? | 162 | * be needed here - is there an Angel SWI call for this? |
@@ -183,7 +178,19 @@ not_angel: | |||
183 | ldr r4, =zreladdr | 178 | ldr r4, =zreladdr |
184 | #endif | 179 | #endif |
185 | 180 | ||
186 | bl cache_on | 181 | /* |
182 | * Set up a page table only if it won't overwrite ourself. | ||
183 | * That means r4 < pc && r4 - 16k page directory > &_end. | ||
184 | * Given that r4 > &_end is most unfrequent, we add a rough | ||
185 | * additional 1MB of room for a possible appended DTB. | ||
186 | */ | ||
187 | mov r0, pc | ||
188 | cmp r0, r4 | ||
189 | ldrcc r0, LC0+32 | ||
190 | addcc r0, r0, pc | ||
191 | cmpcc r4, r0 | ||
192 | orrcc r4, r4, #1 @ remember we skipped cache_on | ||
193 | blcs cache_on | ||
187 | 194 | ||
188 | restart: adr r0, LC0 | 195 | restart: adr r0, LC0 |
189 | ldmia r0, {r1, r2, r3, r6, r10, r11, r12} | 196 | ldmia r0, {r1, r2, r3, r6, r10, r11, r12} |
@@ -229,7 +236,7 @@ restart: adr r0, LC0 | |||
229 | * r0 = delta | 236 | * r0 = delta |
230 | * r2 = BSS start | 237 | * r2 = BSS start |
231 | * r3 = BSS end | 238 | * r3 = BSS end |
232 | * r4 = final kernel address | 239 | * r4 = final kernel address (possibly with LSB set) |
233 | * r5 = appended dtb size (still unknown) | 240 | * r5 = appended dtb size (still unknown) |
234 | * r6 = _edata | 241 | * r6 = _edata |
235 | * r7 = architecture ID | 242 | * r7 = architecture ID |
@@ -277,6 +284,7 @@ restart: adr r0, LC0 | |||
277 | */ | 284 | */ |
278 | cmp r0, #1 | 285 | cmp r0, #1 |
279 | sub r0, r4, #TEXT_OFFSET | 286 | sub r0, r4, #TEXT_OFFSET |
287 | bic r0, r0, #1 | ||
280 | add r0, r0, #0x100 | 288 | add r0, r0, #0x100 |
281 | mov r1, r6 | 289 | mov r1, r6 |
282 | sub r2, sp, r6 | 290 | sub r2, sp, r6 |
@@ -323,12 +331,13 @@ dtb_check_done: | |||
323 | 331 | ||
324 | /* | 332 | /* |
325 | * Check to see if we will overwrite ourselves. | 333 | * Check to see if we will overwrite ourselves. |
326 | * r4 = final kernel address | 334 | * r4 = final kernel address (possibly with LSB set) |
327 | * r9 = size of decompressed image | 335 | * r9 = size of decompressed image |
328 | * r10 = end of this image, including bss/stack/malloc space if non XIP | 336 | * r10 = end of this image, including bss/stack/malloc space if non XIP |
329 | * We basically want: | 337 | * We basically want: |
330 | * r4 - 16k page directory >= r10 -> OK | 338 | * r4 - 16k page directory >= r10 -> OK |
331 | * r4 + image length <= address of wont_overwrite -> OK | 339 | * r4 + image length <= address of wont_overwrite -> OK |
340 | * Note: the possible LSB in r4 is harmless here. | ||
332 | */ | 341 | */ |
333 | add r10, r10, #16384 | 342 | add r10, r10, #16384 |
334 | cmp r4, r10 | 343 | cmp r4, r10 |
@@ -390,7 +399,8 @@ dtb_check_done: | |||
390 | add sp, sp, r6 | 399 | add sp, sp, r6 |
391 | #endif | 400 | #endif |
392 | 401 | ||
393 | bl cache_clean_flush | 402 | tst r4, #1 |
403 | bleq cache_clean_flush | ||
394 | 404 | ||
395 | adr r0, BSYM(restart) | 405 | adr r0, BSYM(restart) |
396 | add r0, r0, r6 | 406 | add r0, r0, r6 |
@@ -402,7 +412,7 @@ wont_overwrite: | |||
402 | * r0 = delta | 412 | * r0 = delta |
403 | * r2 = BSS start | 413 | * r2 = BSS start |
404 | * r3 = BSS end | 414 | * r3 = BSS end |
405 | * r4 = kernel execution address | 415 | * r4 = kernel execution address (possibly with LSB set) |
406 | * r5 = appended dtb size (0 if not present) | 416 | * r5 = appended dtb size (0 if not present) |
407 | * r7 = architecture ID | 417 | * r7 = architecture ID |
408 | * r8 = atags pointer | 418 | * r8 = atags pointer |
@@ -465,6 +475,15 @@ not_relocated: mov r0, #0 | |||
465 | cmp r2, r3 | 475 | cmp r2, r3 |
466 | blo 1b | 476 | blo 1b |
467 | 477 | ||
478 | /* | ||
479 | * Did we skip the cache setup earlier? | ||
480 | * That is indicated by the LSB in r4. | ||
481 | * Do it now if so. | ||
482 | */ | ||
483 | tst r4, #1 | ||
484 | bic r4, r4, #1 | ||
485 | blne cache_on | ||
486 | |||
468 | /* | 487 | /* |
469 | * The C runtime environment should now be setup sufficiently. | 488 | * The C runtime environment should now be setup sufficiently. |
470 | * Set up some pointers, and start decompressing. | 489 | * Set up some pointers, and start decompressing. |
@@ -513,6 +532,7 @@ LC0: .word LC0 @ r1 | |||
513 | .word _got_start @ r11 | 532 | .word _got_start @ r11 |
514 | .word _got_end @ ip | 533 | .word _got_end @ ip |
515 | .word .L_user_stack_end @ sp | 534 | .word .L_user_stack_end @ sp |
535 | .word _end - restart + 16384 + 1024*1024 | ||
516 | .size LC0, . - LC0 | 536 | .size LC0, . - LC0 |
517 | 537 | ||
518 | #ifdef CONFIG_ARCH_RPC | 538 | #ifdef CONFIG_ARCH_RPC |
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi index 17979d5f23b4..c0cdf66f8964 100644 --- a/arch/arm/boot/dts/bcm11351.dtsi +++ b/arch/arm/boot/dts/bcm11351.dtsi | |||
@@ -50,10 +50,10 @@ | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | L2: l2-cache { | 52 | L2: l2-cache { |
53 | compatible = "arm,pl310-cache"; | 53 | compatible = "bcm,bcm11351-a2-pl310-cache"; |
54 | reg = <0x3ff20000 0x1000>; | 54 | reg = <0x3ff20000 0x1000>; |
55 | cache-unified; | 55 | cache-unified; |
56 | cache-level = <2>; | 56 | cache-level = <2>; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | timer@35006000 { | 59 | timer@35006000 { |
diff --git a/arch/arm/common/mcpm_head.S b/arch/arm/common/mcpm_head.S index 8178705c4b24..80f033614a1f 100644 --- a/arch/arm/common/mcpm_head.S +++ b/arch/arm/common/mcpm_head.S | |||
@@ -32,11 +32,11 @@ | |||
32 | 1901: adr r0, 1902b | 32 | 1901: adr r0, 1902b |
33 | bl printascii | 33 | bl printascii |
34 | mov r0, r9 | 34 | mov r0, r9 |
35 | bl printhex8 | 35 | bl printhex2 |
36 | adr r0, 1903b | 36 | adr r0, 1903b |
37 | bl printascii | 37 | bl printascii |
38 | mov r0, r10 | 38 | mov r0, r10 |
39 | bl printhex8 | 39 | bl printhex2 |
40 | adr r0, 1904b | 40 | adr r0, 1904b |
41 | bl printascii | 41 | bl printascii |
42 | #endif | 42 | #endif |
diff --git a/arch/arm/common/mcpm_platsmp.c b/arch/arm/common/mcpm_platsmp.c index 3caed0db6986..510e5b13aa2e 100644 --- a/arch/arm/common/mcpm_platsmp.c +++ b/arch/arm/common/mcpm_platsmp.c | |||
@@ -19,10 +19,6 @@ | |||
19 | #include <asm/smp.h> | 19 | #include <asm/smp.h> |
20 | #include <asm/smp_plat.h> | 20 | #include <asm/smp_plat.h> |
21 | 21 | ||
22 | static void __init simple_smp_init_cpus(void) | ||
23 | { | ||
24 | } | ||
25 | |||
26 | static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle) | 22 | static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle) |
27 | { | 23 | { |
28 | unsigned int mpidr, pcpu, pcluster, ret; | 24 | unsigned int mpidr, pcpu, pcluster, ret; |
@@ -74,7 +70,6 @@ static void mcpm_cpu_die(unsigned int cpu) | |||
74 | #endif | 70 | #endif |
75 | 71 | ||
76 | static struct smp_operations __initdata mcpm_smp_ops = { | 72 | static struct smp_operations __initdata mcpm_smp_ops = { |
77 | .smp_init_cpus = simple_smp_init_cpus, | ||
78 | .smp_boot_secondary = mcpm_boot_secondary, | 73 | .smp_boot_secondary = mcpm_boot_secondary, |
79 | .smp_secondary_init = mcpm_secondary_init, | 74 | .smp_secondary_init = mcpm_secondary_init, |
80 | #ifdef CONFIG_HOTPLUG_CPU | 75 | #ifdef CONFIG_HOTPLUG_CPU |
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 7c1bfc0aea0c..accefe099182 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h | |||
@@ -80,15 +80,6 @@ static inline u32 arch_timer_get_cntfrq(void) | |||
80 | return val; | 80 | return val; |
81 | } | 81 | } |
82 | 82 | ||
83 | static inline u64 arch_counter_get_cntpct(void) | ||
84 | { | ||
85 | u64 cval; | ||
86 | |||
87 | isb(); | ||
88 | asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); | ||
89 | return cval; | ||
90 | } | ||
91 | |||
92 | static inline u64 arch_counter_get_cntvct(void) | 83 | static inline u64 arch_counter_get_cntvct(void) |
93 | { | 84 | { |
94 | u64 cval; | 85 | u64 cval; |
diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h index cedd3721318b..6493802f880a 100644 --- a/arch/arm/include/asm/cp15.h +++ b/arch/arm/include/asm/cp15.h | |||
@@ -23,6 +23,11 @@ | |||
23 | #define CR_RR (1 << 14) /* Round Robin cache replacement */ | 23 | #define CR_RR (1 << 14) /* Round Robin cache replacement */ |
24 | #define CR_L4 (1 << 15) /* LDR pc can set T bit */ | 24 | #define CR_L4 (1 << 15) /* LDR pc can set T bit */ |
25 | #define CR_DT (1 << 16) | 25 | #define CR_DT (1 << 16) |
26 | #ifdef CONFIG_MMU | ||
27 | #define CR_HA (1 << 17) /* Hardware management of Access Flag */ | ||
28 | #else | ||
29 | #define CR_BR (1 << 17) /* MPU Background region enable (PMSA) */ | ||
30 | #endif | ||
26 | #define CR_IT (1 << 18) | 31 | #define CR_IT (1 << 18) |
27 | #define CR_ST (1 << 19) | 32 | #define CR_ST (1 << 19) |
28 | #define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */ | 33 | #define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */ |
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index d7deb62554c9..8c25dc4e9851 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #define CPUID_CACHETYPE 1 | 8 | #define CPUID_CACHETYPE 1 |
9 | #define CPUID_TCM 2 | 9 | #define CPUID_TCM 2 |
10 | #define CPUID_TLBTYPE 3 | 10 | #define CPUID_TLBTYPE 3 |
11 | #define CPUID_MPUIR 4 | ||
11 | #define CPUID_MPIDR 5 | 12 | #define CPUID_MPIDR 5 |
12 | 13 | ||
13 | #ifdef CONFIG_CPU_V7M | 14 | #ifdef CONFIG_CPU_V7M |
diff --git a/arch/arm/include/asm/div64.h b/arch/arm/include/asm/div64.h index fe92ccf1d0b0..191ada6e4d2d 100644 --- a/arch/arm/include/asm/div64.h +++ b/arch/arm/include/asm/div64.h | |||
@@ -46,7 +46,7 @@ | |||
46 | __rem; \ | 46 | __rem; \ |
47 | }) | 47 | }) |
48 | 48 | ||
49 | #if __GNUC__ < 4 | 49 | #if __GNUC__ < 4 || !defined(CONFIG_AEABI) |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * gcc versions earlier than 4.0 are simply too problematic for the | 52 | * gcc versions earlier than 4.0 are simply too problematic for the |
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h index e6168c0c18e9..74a8b84f3cb1 100644 --- a/arch/arm/include/asm/glue-proc.h +++ b/arch/arm/include/asm/glue-proc.h | |||
@@ -230,21 +230,21 @@ | |||
230 | # endif | 230 | # endif |
231 | #endif | 231 | #endif |
232 | 232 | ||
233 | #ifdef CONFIG_CPU_PJ4B | 233 | #ifdef CONFIG_CPU_V7M |
234 | # ifdef CPU_NAME | 234 | # ifdef CPU_NAME |
235 | # undef MULTI_CPU | 235 | # undef MULTI_CPU |
236 | # define MULTI_CPU | 236 | # define MULTI_CPU |
237 | # else | 237 | # else |
238 | # define CPU_NAME cpu_pj4b | 238 | # define CPU_NAME cpu_v7m |
239 | # endif | 239 | # endif |
240 | #endif | 240 | #endif |
241 | 241 | ||
242 | #ifdef CONFIG_CPU_V7M | 242 | #ifdef CONFIG_CPU_PJ4B |
243 | # ifdef CPU_NAME | 243 | # ifdef CPU_NAME |
244 | # undef MULTI_CPU | 244 | # undef MULTI_CPU |
245 | # define MULTI_CPU | 245 | # define MULTI_CPU |
246 | # else | 246 | # else |
247 | # define CPU_NAME cpu_v7m | 247 | # define CPU_NAME cpu_pj4b |
248 | # endif | 248 | # endif |
249 | #endif | 249 | #endif |
250 | 250 | ||
diff --git a/arch/arm/include/asm/hugetlb-3level.h b/arch/arm/include/asm/hugetlb-3level.h new file mode 100644 index 000000000000..d4014fbe5ea3 --- /dev/null +++ b/arch/arm/include/asm/hugetlb-3level.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/hugetlb-3level.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * | ||
6 | * Based on arch/x86/include/asm/hugetlb.h. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef _ASM_ARM_HUGETLB_3LEVEL_H | ||
23 | #define _ASM_ARM_HUGETLB_3LEVEL_H | ||
24 | |||
25 | |||
26 | /* | ||
27 | * If our huge pte is non-zero then mark the valid bit. | ||
28 | * This allows pte_present(huge_ptep_get(ptep)) to return true for non-zero | ||
29 | * ptes. | ||
30 | * (The valid bit is automatically cleared by set_pte_at for PROT_NONE ptes). | ||
31 | */ | ||
32 | static inline pte_t huge_ptep_get(pte_t *ptep) | ||
33 | { | ||
34 | pte_t retval = *ptep; | ||
35 | if (pte_val(retval)) | ||
36 | pte_val(retval) |= L_PTE_VALID; | ||
37 | return retval; | ||
38 | } | ||
39 | |||
40 | static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | ||
41 | pte_t *ptep, pte_t pte) | ||
42 | { | ||
43 | set_pte_at(mm, addr, ptep, pte); | ||
44 | } | ||
45 | |||
46 | static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, | ||
47 | unsigned long addr, pte_t *ptep) | ||
48 | { | ||
49 | ptep_clear_flush(vma, addr, ptep); | ||
50 | } | ||
51 | |||
52 | static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, | ||
53 | unsigned long addr, pte_t *ptep) | ||
54 | { | ||
55 | ptep_set_wrprotect(mm, addr, ptep); | ||
56 | } | ||
57 | |||
58 | static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, | ||
59 | unsigned long addr, pte_t *ptep) | ||
60 | { | ||
61 | return ptep_get_and_clear(mm, addr, ptep); | ||
62 | } | ||
63 | |||
64 | static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, | ||
65 | unsigned long addr, pte_t *ptep, | ||
66 | pte_t pte, int dirty) | ||
67 | { | ||
68 | return ptep_set_access_flags(vma, addr, ptep, pte, dirty); | ||
69 | } | ||
70 | |||
71 | #endif /* _ASM_ARM_HUGETLB_3LEVEL_H */ | ||
diff --git a/arch/arm/include/asm/hugetlb.h b/arch/arm/include/asm/hugetlb.h new file mode 100644 index 000000000000..1f1b1cd112f3 --- /dev/null +++ b/arch/arm/include/asm/hugetlb.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/hugetlb.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * | ||
6 | * Based on arch/x86/include/asm/hugetlb.h | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef _ASM_ARM_HUGETLB_H | ||
23 | #define _ASM_ARM_HUGETLB_H | ||
24 | |||
25 | #include <asm/page.h> | ||
26 | #include <asm-generic/hugetlb.h> | ||
27 | |||
28 | #include <asm/hugetlb-3level.h> | ||
29 | |||
30 | static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, | ||
31 | unsigned long addr, unsigned long end, | ||
32 | unsigned long floor, | ||
33 | unsigned long ceiling) | ||
34 | { | ||
35 | free_pgd_range(tlb, addr, end, floor, ceiling); | ||
36 | } | ||
37 | |||
38 | |||
39 | static inline int is_hugepage_only_range(struct mm_struct *mm, | ||
40 | unsigned long addr, unsigned long len) | ||
41 | { | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static inline int prepare_hugepage_range(struct file *file, | ||
46 | unsigned long addr, unsigned long len) | ||
47 | { | ||
48 | struct hstate *h = hstate_file(file); | ||
49 | if (len & ~huge_page_mask(h)) | ||
50 | return -EINVAL; | ||
51 | if (addr & ~huge_page_mask(h)) | ||
52 | return -EINVAL; | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | static inline int huge_pte_none(pte_t pte) | ||
61 | { | ||
62 | return pte_none(pte); | ||
63 | } | ||
64 | |||
65 | static inline pte_t huge_pte_wrprotect(pte_t pte) | ||
66 | { | ||
67 | return pte_wrprotect(pte); | ||
68 | } | ||
69 | |||
70 | static inline int arch_prepare_hugepage(struct page *page) | ||
71 | { | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static inline void arch_release_hugepage(struct page *page) | ||
76 | { | ||
77 | } | ||
78 | |||
79 | static inline void arch_clear_hugepage_flags(struct page *page) | ||
80 | { | ||
81 | clear_bit(PG_dcache_clean, &page->flags); | ||
82 | } | ||
83 | |||
84 | #endif /* _ASM_ARM_HUGETLB_H */ | ||
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 652b56086de7..d070741b2b37 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h | |||
@@ -130,16 +130,16 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) | |||
130 | */ | 130 | */ |
131 | extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long, | 131 | extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long, |
132 | size_t, unsigned int, void *); | 132 | size_t, unsigned int, void *); |
133 | extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int, | 133 | extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int, |
134 | void *); | 134 | void *); |
135 | 135 | ||
136 | extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); | 136 | extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); |
137 | extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int); | 137 | extern void __iomem *__arm_ioremap(phys_addr_t, size_t, unsigned int); |
138 | extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached); | 138 | extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached); |
139 | extern void __iounmap(volatile void __iomem *addr); | 139 | extern void __iounmap(volatile void __iomem *addr); |
140 | extern void __arm_iounmap(volatile void __iomem *addr); | 140 | extern void __arm_iounmap(volatile void __iomem *addr); |
141 | 141 | ||
142 | extern void __iomem * (*arch_ioremap_caller)(unsigned long, size_t, | 142 | extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, |
143 | unsigned int, void *); | 143 | unsigned int, void *); |
144 | extern void (*arch_iounmap)(volatile void __iomem *); | 144 | extern void (*arch_iounmap)(volatile void __iomem *); |
145 | 145 | ||
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 57870ab313c5..584786f740f9 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/sizes.h> | 19 | #include <linux/sizes.h> |
20 | 20 | ||
21 | #include <asm/cache.h> | ||
22 | |||
21 | #ifdef CONFIG_NEED_MACH_MEMORY_H | 23 | #ifdef CONFIG_NEED_MACH_MEMORY_H |
22 | #include <mach/memory.h> | 24 | #include <mach/memory.h> |
23 | #endif | 25 | #endif |
@@ -141,6 +143,20 @@ | |||
141 | #define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) | 143 | #define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) |
142 | #define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) | 144 | #define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) |
143 | 145 | ||
146 | /* | ||
147 | * Minimum guaranted alignment in pgd_alloc(). The page table pointers passed | ||
148 | * around in head.S and proc-*.S are shifted by this amount, in order to | ||
149 | * leave spare high bits for systems with physical address extension. This | ||
150 | * does not fully accomodate the 40-bit addressing capability of ARM LPAE, but | ||
151 | * gives us about 38-bits or so. | ||
152 | */ | ||
153 | #ifdef CONFIG_ARM_LPAE | ||
154 | #define ARCH_PGD_SHIFT L1_CACHE_SHIFT | ||
155 | #else | ||
156 | #define ARCH_PGD_SHIFT 0 | ||
157 | #endif | ||
158 | #define ARCH_PGD_MASK ((1 << ARCH_PGD_SHIFT) - 1) | ||
159 | |||
144 | #ifndef __ASSEMBLY__ | 160 | #ifndef __ASSEMBLY__ |
145 | 161 | ||
146 | /* | 162 | /* |
@@ -207,7 +223,7 @@ static inline unsigned long __phys_to_virt(unsigned long x) | |||
207 | * direct-mapped view. We assume this is the first page | 223 | * direct-mapped view. We assume this is the first page |
208 | * of RAM in the mem_map as well. | 224 | * of RAM in the mem_map as well. |
209 | */ | 225 | */ |
210 | #define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) | 226 | #define PHYS_PFN_OFFSET ((unsigned long)(PHYS_OFFSET >> PAGE_SHIFT)) |
211 | 227 | ||
212 | /* | 228 | /* |
213 | * These are *only* valid on the kernel direct mapped RAM memory. | 229 | * These are *only* valid on the kernel direct mapped RAM memory. |
diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h index a7b85e0d0cc1..b5792b7fd8d3 100644 --- a/arch/arm/include/asm/mmu_context.h +++ b/arch/arm/include/asm/mmu_context.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
19 | #include <asm/cachetype.h> | 19 | #include <asm/cachetype.h> |
20 | #include <asm/proc-fns.h> | 20 | #include <asm/proc-fns.h> |
21 | #include <asm/smp_plat.h> | ||
21 | #include <asm-generic/mm_hooks.h> | 22 | #include <asm-generic/mm_hooks.h> |
22 | 23 | ||
23 | void __check_vmalloc_seq(struct mm_struct *mm); | 24 | void __check_vmalloc_seq(struct mm_struct *mm); |
@@ -27,7 +28,15 @@ void __check_vmalloc_seq(struct mm_struct *mm); | |||
27 | void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk); | 28 | void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk); |
28 | #define init_new_context(tsk,mm) ({ atomic64_set(&mm->context.id, 0); 0; }) | 29 | #define init_new_context(tsk,mm) ({ atomic64_set(&mm->context.id, 0); 0; }) |
29 | 30 | ||
30 | DECLARE_PER_CPU(atomic64_t, active_asids); | 31 | #ifdef CONFIG_ARM_ERRATA_798181 |
32 | void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm, | ||
33 | cpumask_t *mask); | ||
34 | #else /* !CONFIG_ARM_ERRATA_798181 */ | ||
35 | static inline void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm, | ||
36 | cpumask_t *mask) | ||
37 | { | ||
38 | } | ||
39 | #endif /* CONFIG_ARM_ERRATA_798181 */ | ||
31 | 40 | ||
32 | #else /* !CONFIG_CPU_HAS_ASID */ | 41 | #else /* !CONFIG_CPU_HAS_ASID */ |
33 | 42 | ||
@@ -98,12 +107,16 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, | |||
98 | #ifdef CONFIG_MMU | 107 | #ifdef CONFIG_MMU |
99 | unsigned int cpu = smp_processor_id(); | 108 | unsigned int cpu = smp_processor_id(); |
100 | 109 | ||
101 | #ifdef CONFIG_SMP | 110 | /* |
102 | /* check for possible thread migration */ | 111 | * __sync_icache_dcache doesn't broadcast the I-cache invalidation, |
103 | if (!cpumask_empty(mm_cpumask(next)) && | 112 | * so check for possible thread migration and invalidate the I-cache |
113 | * if we're new to this CPU. | ||
114 | */ | ||
115 | if (cache_ops_need_broadcast() && | ||
116 | !cpumask_empty(mm_cpumask(next)) && | ||
104 | !cpumask_test_cpu(cpu, mm_cpumask(next))) | 117 | !cpumask_test_cpu(cpu, mm_cpumask(next))) |
105 | __flush_icache_all(); | 118 | __flush_icache_all(); |
106 | #endif | 119 | |
107 | if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) { | 120 | if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) { |
108 | check_and_switch_context(next, tsk); | 121 | check_and_switch_context(next, tsk); |
109 | if (cache_is_vivt()) | 122 | if (cache_is_vivt()) |
diff --git a/arch/arm/include/asm/mpu.h b/arch/arm/include/asm/mpu.h new file mode 100644 index 000000000000..c3247cc2fe08 --- /dev/null +++ b/arch/arm/include/asm/mpu.h | |||
@@ -0,0 +1,76 @@ | |||
1 | #ifndef __ARM_MPU_H | ||
2 | #define __ARM_MPU_H | ||
3 | |||
4 | #ifdef CONFIG_ARM_MPU | ||
5 | |||
6 | /* MPUIR layout */ | ||
7 | #define MPUIR_nU 1 | ||
8 | #define MPUIR_DREGION 8 | ||
9 | #define MPUIR_IREGION 16 | ||
10 | #define MPUIR_DREGION_SZMASK (0xFF << MPUIR_DREGION) | ||
11 | #define MPUIR_IREGION_SZMASK (0xFF << MPUIR_IREGION) | ||
12 | |||
13 | /* ID_MMFR0 data relevant to MPU */ | ||
14 | #define MMFR0_PMSA (0xF << 4) | ||
15 | #define MMFR0_PMSAv7 (3 << 4) | ||
16 | |||
17 | /* MPU D/I Size Register fields */ | ||
18 | #define MPU_RSR_SZ 1 | ||
19 | #define MPU_RSR_EN 0 | ||
20 | |||
21 | /* The D/I RSR value for an enabled region spanning the whole of memory */ | ||
22 | #define MPU_RSR_ALL_MEM 63 | ||
23 | |||
24 | /* Individual bits in the DR/IR ACR */ | ||
25 | #define MPU_ACR_XN (1 << 12) | ||
26 | #define MPU_ACR_SHARED (1 << 2) | ||
27 | |||
28 | /* C, B and TEX[2:0] bits only have semantic meanings when grouped */ | ||
29 | #define MPU_RGN_CACHEABLE 0xB | ||
30 | #define MPU_RGN_SHARED_CACHEABLE (MPU_RGN_CACHEABLE | MPU_ACR_SHARED) | ||
31 | #define MPU_RGN_STRONGLY_ORDERED 0 | ||
32 | |||
33 | /* Main region should only be shared for SMP */ | ||
34 | #ifdef CONFIG_SMP | ||
35 | #define MPU_RGN_NORMAL (MPU_RGN_CACHEABLE | MPU_ACR_SHARED) | ||
36 | #else | ||
37 | #define MPU_RGN_NORMAL MPU_RGN_CACHEABLE | ||
38 | #endif | ||
39 | |||
40 | /* Access permission bits of ACR (only define those that we use)*/ | ||
41 | #define MPU_AP_PL1RW_PL0RW (0x3 << 8) | ||
42 | #define MPU_AP_PL1RW_PL0R0 (0x2 << 8) | ||
43 | #define MPU_AP_PL1RW_PL0NA (0x1 << 8) | ||
44 | |||
45 | /* For minimal static MPU region configurations */ | ||
46 | #define MPU_PROBE_REGION 0 | ||
47 | #define MPU_BG_REGION 1 | ||
48 | #define MPU_RAM_REGION 2 | ||
49 | #define MPU_VECTORS_REGION 3 | ||
50 | |||
51 | /* Maximum number of regions Linux is interested in */ | ||
52 | #define MPU_MAX_REGIONS 16 | ||
53 | |||
54 | #define MPU_DATA_SIDE 0 | ||
55 | #define MPU_INSTR_SIDE 1 | ||
56 | |||
57 | #ifndef __ASSEMBLY__ | ||
58 | |||
59 | struct mpu_rgn { | ||
60 | /* Assume same attributes for d/i-side */ | ||
61 | u32 drbar; | ||
62 | u32 drsr; | ||
63 | u32 dracr; | ||
64 | }; | ||
65 | |||
66 | struct mpu_rgn_info { | ||
67 | u32 mpuir; | ||
68 | struct mpu_rgn rgns[MPU_MAX_REGIONS]; | ||
69 | }; | ||
70 | extern struct mpu_rgn_info mpu_rgn_info; | ||
71 | |||
72 | #endif /* __ASSEMBLY__ */ | ||
73 | |||
74 | #endif /* CONFIG_ARM_MPU */ | ||
75 | |||
76 | #endif | ||
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index 812a4944e783..6363f3d1d505 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h | |||
@@ -13,7 +13,7 @@ | |||
13 | /* PAGE_SHIFT determines the page size */ | 13 | /* PAGE_SHIFT determines the page size */ |
14 | #define PAGE_SHIFT 12 | 14 | #define PAGE_SHIFT 12 |
15 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) | 15 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) |
16 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 16 | #define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) |
17 | 17 | ||
18 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
19 | 19 | ||
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index 18f5cef82ad5..626989fec4d3 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) | 30 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) |
31 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) | 31 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) |
32 | #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) | 32 | #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) |
33 | #define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1) | ||
33 | #define PMD_BIT4 (_AT(pmdval_t, 0)) | 34 | #define PMD_BIT4 (_AT(pmdval_t, 0)) |
34 | #define PMD_DOMAIN(x) (_AT(pmdval_t, 0)) | 35 | #define PMD_DOMAIN(x) (_AT(pmdval_t, 0)) |
35 | #define PMD_APTABLE_SHIFT (61) | 36 | #define PMD_APTABLE_SHIFT (61) |
@@ -41,6 +42,8 @@ | |||
41 | */ | 42 | */ |
42 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) | 43 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) |
43 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) | 44 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) |
45 | #define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */ | ||
46 | #define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */ | ||
44 | #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) | 47 | #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) |
45 | #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) | 48 | #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) |
46 | #define PMD_SECT_nG (_AT(pmdval_t, 1) << 11) | 49 | #define PMD_SECT_nG (_AT(pmdval_t, 1) << 11) |
@@ -66,6 +69,7 @@ | |||
66 | #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) | 69 | #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) |
67 | #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) | 70 | #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) |
68 | #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) | 71 | #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) |
72 | #define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1) | ||
69 | #define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ | 73 | #define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ |
70 | #define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ | 74 | #define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ |
71 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | 75 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ |
@@ -79,4 +83,24 @@ | |||
79 | #define PHYS_MASK_SHIFT (40) | 83 | #define PHYS_MASK_SHIFT (40) |
80 | #define PHYS_MASK ((1ULL << PHYS_MASK_SHIFT) - 1) | 84 | #define PHYS_MASK ((1ULL << PHYS_MASK_SHIFT) - 1) |
81 | 85 | ||
86 | /* | ||
87 | * TTBR0/TTBR1 split (PAGE_OFFSET): | ||
88 | * 0x40000000: T0SZ = 2, T1SZ = 0 (not used) | ||
89 | * 0x80000000: T0SZ = 0, T1SZ = 1 | ||
90 | * 0xc0000000: T0SZ = 0, T1SZ = 2 | ||
91 | * | ||
92 | * Only use this feature if PHYS_OFFSET <= PAGE_OFFSET, otherwise | ||
93 | * booting secondary CPUs would end up using TTBR1 for the identity | ||
94 | * mapping set up in TTBR0. | ||
95 | */ | ||
96 | #if defined CONFIG_VMSPLIT_2G | ||
97 | #define TTBR1_OFFSET 16 /* skip two L1 entries */ | ||
98 | #elif defined CONFIG_VMSPLIT_3G | ||
99 | #define TTBR1_OFFSET (4096 * (1 + 3)) /* only L2, skip pgd + 3*pmd */ | ||
100 | #else | ||
101 | #define TTBR1_OFFSET 0 | ||
102 | #endif | ||
103 | |||
104 | #define TTBR1_SIZE (((PAGE_OFFSET >> 30) - 1) << 16) | ||
105 | |||
82 | #endif | 106 | #endif |
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index 86b8fe398b95..5689c18c85f5 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h | |||
@@ -33,7 +33,7 @@ | |||
33 | #define PTRS_PER_PMD 512 | 33 | #define PTRS_PER_PMD 512 |
34 | #define PTRS_PER_PGD 4 | 34 | #define PTRS_PER_PGD 4 |
35 | 35 | ||
36 | #define PTE_HWTABLE_PTRS (PTRS_PER_PTE) | 36 | #define PTE_HWTABLE_PTRS (0) |
37 | #define PTE_HWTABLE_OFF (0) | 37 | #define PTE_HWTABLE_OFF (0) |
38 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64)) | 38 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64)) |
39 | 39 | ||
@@ -48,20 +48,28 @@ | |||
48 | #define PMD_SHIFT 21 | 48 | #define PMD_SHIFT 21 |
49 | 49 | ||
50 | #define PMD_SIZE (1UL << PMD_SHIFT) | 50 | #define PMD_SIZE (1UL << PMD_SHIFT) |
51 | #define PMD_MASK (~(PMD_SIZE-1)) | 51 | #define PMD_MASK (~((1 << PMD_SHIFT) - 1)) |
52 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | 52 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) |
53 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | 53 | #define PGDIR_MASK (~((1 << PGDIR_SHIFT) - 1)) |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * section address mask and size definitions. | 56 | * section address mask and size definitions. |
57 | */ | 57 | */ |
58 | #define SECTION_SHIFT 21 | 58 | #define SECTION_SHIFT 21 |
59 | #define SECTION_SIZE (1UL << SECTION_SHIFT) | 59 | #define SECTION_SIZE (1UL << SECTION_SHIFT) |
60 | #define SECTION_MASK (~(SECTION_SIZE-1)) | 60 | #define SECTION_MASK (~((1 << SECTION_SHIFT) - 1)) |
61 | 61 | ||
62 | #define USER_PTRS_PER_PGD (PAGE_OFFSET / PGDIR_SIZE) | 62 | #define USER_PTRS_PER_PGD (PAGE_OFFSET / PGDIR_SIZE) |
63 | 63 | ||
64 | /* | 64 | /* |
65 | * Hugetlb definitions. | ||
66 | */ | ||
67 | #define HPAGE_SHIFT PMD_SHIFT | ||
68 | #define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) | ||
69 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) | ||
70 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) | ||
71 | |||
72 | /* | ||
65 | * "Linux" PTE definitions for LPAE. | 73 | * "Linux" PTE definitions for LPAE. |
66 | * | 74 | * |
67 | * These bits overlap with the hardware bits but the naming is preserved for | 75 | * These bits overlap with the hardware bits but the naming is preserved for |
@@ -79,6 +87,11 @@ | |||
79 | #define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ | 87 | #define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ |
80 | #define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */ | 88 | #define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */ |
81 | 89 | ||
90 | #define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) | ||
91 | #define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) | ||
92 | #define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56) | ||
93 | #define PMD_SECT_NONE (_AT(pmdval_t, 1) << 57) | ||
94 | |||
82 | /* | 95 | /* |
83 | * To be used in assembly code with the upper page attributes. | 96 | * To be used in assembly code with the upper page attributes. |
84 | */ | 97 | */ |
@@ -166,8 +179,83 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | |||
166 | clean_pmd_entry(pmdp); \ | 179 | clean_pmd_entry(pmdp); \ |
167 | } while (0) | 180 | } while (0) |
168 | 181 | ||
182 | /* | ||
183 | * For 3 levels of paging the PTE_EXT_NG bit will be set for user address ptes | ||
184 | * that are written to a page table but not for ptes created with mk_pte. | ||
185 | * | ||
186 | * In hugetlb_no_page, a new huge pte (new_pte) is generated and passed to | ||
187 | * hugetlb_cow, where it is compared with an entry in a page table. | ||
188 | * This comparison test fails erroneously leading ultimately to a memory leak. | ||
189 | * | ||
190 | * To correct this behaviour, we mask off PTE_EXT_NG for any pte that is | ||
191 | * present before running the comparison. | ||
192 | */ | ||
193 | #define __HAVE_ARCH_PTE_SAME | ||
194 | #define pte_same(pte_a,pte_b) ((pte_present(pte_a) ? pte_val(pte_a) & ~PTE_EXT_NG \ | ||
195 | : pte_val(pte_a)) \ | ||
196 | == (pte_present(pte_b) ? pte_val(pte_b) & ~PTE_EXT_NG \ | ||
197 | : pte_val(pte_b))) | ||
198 | |||
169 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,__pte(pte_val(pte)|(ext))) | 199 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,__pte(pte_val(pte)|(ext))) |
170 | 200 | ||
201 | #define pte_huge(pte) (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT)) | ||
202 | #define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT)) | ||
203 | |||
204 | #define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) | ||
205 | |||
206 | #define __HAVE_ARCH_PMD_WRITE | ||
207 | #define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) | ||
208 | |||
209 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
210 | #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) | ||
211 | #define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) | ||
212 | #endif | ||
213 | |||
214 | #define PMD_BIT_FUNC(fn,op) \ | ||
215 | static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } | ||
216 | |||
217 | PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); | ||
218 | PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); | ||
219 | PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); | ||
220 | PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); | ||
221 | PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); | ||
222 | PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); | ||
223 | |||
224 | #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) | ||
225 | |||
226 | #define pmd_pfn(pmd) (((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT) | ||
227 | #define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) | ||
228 | #define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) | ||
229 | |||
230 | /* represent a notpresent pmd by zero, this is used by pmdp_invalidate */ | ||
231 | #define pmd_mknotpresent(pmd) (__pmd(0)) | ||
232 | |||
233 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
234 | { | ||
235 | const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY | | ||
236 | PMD_SECT_VALID | PMD_SECT_NONE; | ||
237 | pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); | ||
238 | return pmd; | ||
239 | } | ||
240 | |||
241 | static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, | ||
242 | pmd_t *pmdp, pmd_t pmd) | ||
243 | { | ||
244 | BUG_ON(addr >= TASK_SIZE); | ||
245 | |||
246 | /* create a faulting entry if PROT_NONE protected */ | ||
247 | if (pmd_val(pmd) & PMD_SECT_NONE) | ||
248 | pmd_val(pmd) &= ~PMD_SECT_VALID; | ||
249 | |||
250 | *pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG); | ||
251 | flush_pmd_entry(pmdp); | ||
252 | } | ||
253 | |||
254 | static inline int has_transparent_hugepage(void) | ||
255 | { | ||
256 | return 1; | ||
257 | } | ||
258 | |||
171 | #endif /* __ASSEMBLY__ */ | 259 | #endif /* __ASSEMBLY__ */ |
172 | 260 | ||
173 | #endif /* _ASM_PGTABLE_3LEVEL_H */ | 261 | #endif /* _ASM_PGTABLE_3LEVEL_H */ |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 229e0dde9c71..04aeb02d2e11 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -24,6 +24,9 @@ | |||
24 | #include <asm/memory.h> | 24 | #include <asm/memory.h> |
25 | #include <asm/pgtable-hwdef.h> | 25 | #include <asm/pgtable-hwdef.h> |
26 | 26 | ||
27 | |||
28 | #include <asm/tlbflush.h> | ||
29 | |||
27 | #ifdef CONFIG_ARM_LPAE | 30 | #ifdef CONFIG_ARM_LPAE |
28 | #include <asm/pgtable-3level.h> | 31 | #include <asm/pgtable-3level.h> |
29 | #else | 32 | #else |
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index f3628fb3d2b3..5324c1112f3a 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h | |||
@@ -60,7 +60,7 @@ extern struct processor { | |||
60 | /* | 60 | /* |
61 | * Set the page table | 61 | * Set the page table |
62 | */ | 62 | */ |
63 | void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm); | 63 | void (*switch_mm)(phys_addr_t pgd_phys, struct mm_struct *mm); |
64 | /* | 64 | /* |
65 | * Set a possibly extended PTE. Non-extended PTEs should | 65 | * Set a possibly extended PTE. Non-extended PTEs should |
66 | * ignore 'ext'. | 66 | * ignore 'ext'. |
@@ -82,7 +82,7 @@ extern void cpu_proc_init(void); | |||
82 | extern void cpu_proc_fin(void); | 82 | extern void cpu_proc_fin(void); |
83 | extern int cpu_do_idle(void); | 83 | extern int cpu_do_idle(void); |
84 | extern void cpu_dcache_clean_area(void *, int); | 84 | extern void cpu_dcache_clean_area(void *, int); |
85 | extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); | 85 | extern void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); |
86 | #ifdef CONFIG_ARM_LPAE | 86 | #ifdef CONFIG_ARM_LPAE |
87 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte); | 87 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte); |
88 | #else | 88 | #else |
@@ -116,13 +116,25 @@ extern void cpu_resume(void); | |||
116 | #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) | 116 | #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) |
117 | 117 | ||
118 | #ifdef CONFIG_ARM_LPAE | 118 | #ifdef CONFIG_ARM_LPAE |
119 | |||
120 | #define cpu_get_ttbr(nr) \ | ||
121 | ({ \ | ||
122 | u64 ttbr; \ | ||
123 | __asm__("mrrc p15, " #nr ", %Q0, %R0, c2" \ | ||
124 | : "=r" (ttbr)); \ | ||
125 | ttbr; \ | ||
126 | }) | ||
127 | |||
128 | #define cpu_set_ttbr(nr, val) \ | ||
129 | do { \ | ||
130 | u64 ttbr = val; \ | ||
131 | __asm__("mcrr p15, " #nr ", %Q0, %R0, c2" \ | ||
132 | : : "r" (ttbr)); \ | ||
133 | } while (0) | ||
134 | |||
119 | #define cpu_get_pgd() \ | 135 | #define cpu_get_pgd() \ |
120 | ({ \ | 136 | ({ \ |
121 | unsigned long pg, pg2; \ | 137 | u64 pg = cpu_get_ttbr(0); \ |
122 | __asm__("mrrc p15, 0, %0, %1, c2" \ | ||
123 | : "=r" (pg), "=r" (pg2) \ | ||
124 | : \ | ||
125 | : "cc"); \ | ||
126 | pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \ | 138 | pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \ |
127 | (pgd_t *)phys_to_virt(pg); \ | 139 | (pgd_t *)phys_to_virt(pg); \ |
128 | }) | 140 | }) |
@@ -137,6 +149,10 @@ extern void cpu_resume(void); | |||
137 | }) | 149 | }) |
138 | #endif | 150 | #endif |
139 | 151 | ||
152 | #else /*!CONFIG_MMU */ | ||
153 | |||
154 | #define cpu_switch_mm(pgd,mm) { } | ||
155 | |||
140 | #endif | 156 | #endif |
141 | 157 | ||
142 | #endif /* __ASSEMBLY__ */ | 158 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index d3a22bebe6ce..a8cae71caceb 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h | |||
@@ -65,7 +65,10 @@ asmlinkage void secondary_start_kernel(void); | |||
65 | * Initial data for bringing up a secondary CPU. | 65 | * Initial data for bringing up a secondary CPU. |
66 | */ | 66 | */ |
67 | struct secondary_data { | 67 | struct secondary_data { |
68 | unsigned long pgdir; | 68 | union { |
69 | unsigned long mpu_rgn_szr; | ||
70 | unsigned long pgdir; | ||
71 | }; | ||
69 | unsigned long swapper_pg_dir; | 72 | unsigned long swapper_pg_dir; |
70 | void *stack; | 73 | void *stack; |
71 | }; | 74 | }; |
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index e78983202737..6462a721ebd4 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h | |||
@@ -26,6 +26,9 @@ static inline bool is_smp(void) | |||
26 | } | 26 | } |
27 | 27 | ||
28 | /* all SMP configurations have the extended CPUID registers */ | 28 | /* all SMP configurations have the extended CPUID registers */ |
29 | #ifndef CONFIG_MMU | ||
30 | #define tlb_ops_need_broadcast() 0 | ||
31 | #else | ||
29 | static inline int tlb_ops_need_broadcast(void) | 32 | static inline int tlb_ops_need_broadcast(void) |
30 | { | 33 | { |
31 | if (!is_smp()) | 34 | if (!is_smp()) |
@@ -33,6 +36,7 @@ static inline int tlb_ops_need_broadcast(void) | |||
33 | 36 | ||
34 | return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2; | 37 | return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2; |
35 | } | 38 | } |
39 | #endif | ||
36 | 40 | ||
37 | #if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7 | 41 | #if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7 |
38 | #define cache_ops_need_broadcast() 0 | 42 | #define cache_ops_need_broadcast() 0 |
@@ -66,4 +70,22 @@ static inline int get_logical_index(u32 mpidr) | |||
66 | return -EINVAL; | 70 | return -EINVAL; |
67 | } | 71 | } |
68 | 72 | ||
73 | /* | ||
74 | * NOTE ! Assembly code relies on the following | ||
75 | * structure memory layout in order to carry out load | ||
76 | * multiple from its base address. For more | ||
77 | * information check arch/arm/kernel/sleep.S | ||
78 | */ | ||
79 | struct mpidr_hash { | ||
80 | u32 mask; /* used by sleep.S */ | ||
81 | u32 shift_aff[3]; /* used by sleep.S */ | ||
82 | u32 bits; | ||
83 | }; | ||
84 | |||
85 | extern struct mpidr_hash mpidr_hash; | ||
86 | |||
87 | static inline u32 mpidr_hash_size(void) | ||
88 | { | ||
89 | return 1 << mpidr_hash.bits; | ||
90 | } | ||
69 | #endif | 91 | #endif |
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index 6220e9fdf4c7..f8b8965666e9 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h | |||
@@ -97,19 +97,22 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) | |||
97 | 97 | ||
98 | static inline int arch_spin_trylock(arch_spinlock_t *lock) | 98 | static inline int arch_spin_trylock(arch_spinlock_t *lock) |
99 | { | 99 | { |
100 | unsigned long tmp; | 100 | unsigned long contended, res; |
101 | u32 slock; | 101 | u32 slock; |
102 | 102 | ||
103 | __asm__ __volatile__( | 103 | do { |
104 | " ldrex %0, [%2]\n" | 104 | __asm__ __volatile__( |
105 | " subs %1, %0, %0, ror #16\n" | 105 | " ldrex %0, [%3]\n" |
106 | " addeq %0, %0, %3\n" | 106 | " mov %2, #0\n" |
107 | " strexeq %1, %0, [%2]" | 107 | " subs %1, %0, %0, ror #16\n" |
108 | : "=&r" (slock), "=&r" (tmp) | 108 | " addeq %0, %0, %4\n" |
109 | : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) | 109 | " strexeq %2, %0, [%3]" |
110 | : "cc"); | 110 | : "=&r" (slock), "=&r" (contended), "=r" (res) |
111 | 111 | : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) | |
112 | if (tmp == 0) { | 112 | : "cc"); |
113 | } while (res); | ||
114 | |||
115 | if (!contended) { | ||
113 | smp_mb(); | 116 | smp_mb(); |
114 | return 1; | 117 | return 1; |
115 | } else { | 118 | } else { |
diff --git a/arch/arm/include/asm/suspend.h b/arch/arm/include/asm/suspend.h index 1c0a551ae375..cd20029bcd94 100644 --- a/arch/arm/include/asm/suspend.h +++ b/arch/arm/include/asm/suspend.h | |||
@@ -1,6 +1,11 @@ | |||
1 | #ifndef __ASM_ARM_SUSPEND_H | 1 | #ifndef __ASM_ARM_SUSPEND_H |
2 | #define __ASM_ARM_SUSPEND_H | 2 | #define __ASM_ARM_SUSPEND_H |
3 | 3 | ||
4 | struct sleep_save_sp { | ||
5 | u32 *save_ptr_stash; | ||
6 | u32 save_ptr_stash_phys; | ||
7 | }; | ||
8 | |||
4 | extern void cpu_resume(void); | 9 | extern void cpu_resume(void); |
5 | extern int cpu_suspend(unsigned long, int (*)(unsigned long)); | 10 | extern int cpu_suspend(unsigned long, int (*)(unsigned long)); |
6 | 11 | ||
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 1995d1a84060..214d4158089a 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h | |||
@@ -58,7 +58,7 @@ struct thread_info { | |||
58 | struct cpu_context_save cpu_context; /* cpu context */ | 58 | struct cpu_context_save cpu_context; /* cpu context */ |
59 | __u32 syscall; /* syscall number */ | 59 | __u32 syscall; /* syscall number */ |
60 | __u8 used_cp[16]; /* thread used copro */ | 60 | __u8 used_cp[16]; /* thread used copro */ |
61 | unsigned long tp_value; | 61 | unsigned long tp_value[2]; /* TLS registers */ |
62 | #ifdef CONFIG_CRUNCH | 62 | #ifdef CONFIG_CRUNCH |
63 | struct crunch_state crunchstate; | 63 | struct crunch_state crunchstate; |
64 | #endif | 64 | #endif |
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index bdf2b8458ec1..46e7cfb3e721 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h | |||
@@ -204,6 +204,12 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, | |||
204 | #endif | 204 | #endif |
205 | } | 205 | } |
206 | 206 | ||
207 | static inline void | ||
208 | tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr) | ||
209 | { | ||
210 | tlb_add_flush(tlb, addr); | ||
211 | } | ||
212 | |||
207 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) | 213 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) |
208 | #define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) | 214 | #define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) |
209 | #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) | 215 | #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) |
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index a3625d141c1d..fdbb9e369745 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h | |||
@@ -535,8 +535,33 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, | |||
535 | } | 535 | } |
536 | #endif | 536 | #endif |
537 | 537 | ||
538 | #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0) | ||
539 | |||
538 | #endif | 540 | #endif |
539 | 541 | ||
540 | #endif /* CONFIG_MMU */ | 542 | #elif defined(CONFIG_SMP) /* !CONFIG_MMU */ |
543 | |||
544 | #ifndef __ASSEMBLY__ | ||
545 | |||
546 | #include <linux/mm_types.h> | ||
547 | |||
548 | static inline void local_flush_tlb_all(void) { } | ||
549 | static inline void local_flush_tlb_mm(struct mm_struct *mm) { } | ||
550 | static inline void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) { } | ||
551 | static inline void local_flush_tlb_kernel_page(unsigned long kaddr) { } | ||
552 | static inline void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { } | ||
553 | static inline void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) { } | ||
554 | static inline void local_flush_bp_all(void) { } | ||
555 | |||
556 | extern void flush_tlb_all(void); | ||
557 | extern void flush_tlb_mm(struct mm_struct *mm); | ||
558 | extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr); | ||
559 | extern void flush_tlb_kernel_page(unsigned long kaddr); | ||
560 | extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); | ||
561 | extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); | ||
562 | extern void flush_bp_all(void); | ||
563 | #endif /* __ASSEMBLY__ */ | ||
564 | |||
565 | #endif | ||
541 | 566 | ||
542 | #endif | 567 | #endif |
diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h index 73409e6c0251..83259b873333 100644 --- a/arch/arm/include/asm/tls.h +++ b/arch/arm/include/asm/tls.h | |||
@@ -2,27 +2,30 @@ | |||
2 | #define __ASMARM_TLS_H | 2 | #define __ASMARM_TLS_H |
3 | 3 | ||
4 | #ifdef __ASSEMBLY__ | 4 | #ifdef __ASSEMBLY__ |
5 | .macro set_tls_none, tp, tmp1, tmp2 | 5 | #include <asm/asm-offsets.h> |
6 | .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2 | ||
6 | .endm | 7 | .endm |
7 | 8 | ||
8 | .macro set_tls_v6k, tp, tmp1, tmp2 | 9 | .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2 |
10 | mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register | ||
9 | mcr p15, 0, \tp, c13, c0, 3 @ set TLS register | 11 | mcr p15, 0, \tp, c13, c0, 3 @ set TLS register |
10 | mov \tmp1, #0 | 12 | mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register |
11 | mcr p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register | 13 | str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it |
12 | .endm | 14 | .endm |
13 | 15 | ||
14 | .macro set_tls_v6, tp, tmp1, tmp2 | 16 | .macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2 |
15 | ldr \tmp1, =elf_hwcap | 17 | ldr \tmp1, =elf_hwcap |
16 | ldr \tmp1, [\tmp1, #0] | 18 | ldr \tmp1, [\tmp1, #0] |
17 | mov \tmp2, #0xffff0fff | 19 | mov \tmp2, #0xffff0fff |
18 | tst \tmp1, #HWCAP_TLS @ hardware TLS available? | 20 | tst \tmp1, #HWCAP_TLS @ hardware TLS available? |
19 | mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register | ||
20 | movne \tmp1, #0 | ||
21 | mcrne p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register | ||
22 | streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0 | 21 | streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0 |
22 | mrcne p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register | ||
23 | mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register | ||
24 | mcrne p15, 0, \tpuser, c13, c0, 2 @ set user r/w register | ||
25 | strne \tmp2, [\base, #TI_TP_VALUE + 4] @ save it | ||
23 | .endm | 26 | .endm |
24 | 27 | ||
25 | .macro set_tls_software, tp, tmp1, tmp2 | 28 | .macro switch_tls_software, base, tp, tpuser, tmp1, tmp2 |
26 | mov \tmp1, #0xffff0fff | 29 | mov \tmp1, #0xffff0fff |
27 | str \tp, [\tmp1, #-15] @ set TLS value at 0xffff0ff0 | 30 | str \tp, [\tmp1, #-15] @ set TLS value at 0xffff0ff0 |
28 | .endm | 31 | .endm |
@@ -31,19 +34,30 @@ | |||
31 | #ifdef CONFIG_TLS_REG_EMUL | 34 | #ifdef CONFIG_TLS_REG_EMUL |
32 | #define tls_emu 1 | 35 | #define tls_emu 1 |
33 | #define has_tls_reg 1 | 36 | #define has_tls_reg 1 |
34 | #define set_tls set_tls_none | 37 | #define switch_tls switch_tls_none |
35 | #elif defined(CONFIG_CPU_V6) | 38 | #elif defined(CONFIG_CPU_V6) |
36 | #define tls_emu 0 | 39 | #define tls_emu 0 |
37 | #define has_tls_reg (elf_hwcap & HWCAP_TLS) | 40 | #define has_tls_reg (elf_hwcap & HWCAP_TLS) |
38 | #define set_tls set_tls_v6 | 41 | #define switch_tls switch_tls_v6 |
39 | #elif defined(CONFIG_CPU_32v6K) | 42 | #elif defined(CONFIG_CPU_32v6K) |
40 | #define tls_emu 0 | 43 | #define tls_emu 0 |
41 | #define has_tls_reg 1 | 44 | #define has_tls_reg 1 |
42 | #define set_tls set_tls_v6k | 45 | #define switch_tls switch_tls_v6k |
43 | #else | 46 | #else |
44 | #define tls_emu 0 | 47 | #define tls_emu 0 |
45 | #define has_tls_reg 0 | 48 | #define has_tls_reg 0 |
46 | #define set_tls set_tls_software | 49 | #define switch_tls switch_tls_software |
47 | #endif | 50 | #endif |
48 | 51 | ||
52 | #ifndef __ASSEMBLY__ | ||
53 | static inline unsigned long get_tpuser(void) | ||
54 | { | ||
55 | unsigned long reg = 0; | ||
56 | |||
57 | if (has_tls_reg && !tls_emu) | ||
58 | __asm__("mrc p15, 0, %0, c13, c0, 2" : "=r" (reg)); | ||
59 | |||
60 | return reg; | ||
61 | } | ||
62 | #endif | ||
49 | #endif /* __ASMARM_TLS_H */ | 63 | #endif /* __ASMARM_TLS_H */ |
diff --git a/arch/arm/include/debug/vexpress.S b/arch/arm/include/debug/vexpress.S index dc8e882a6257..acafb229e2b6 100644 --- a/arch/arm/include/debug/vexpress.S +++ b/arch/arm/include/debug/vexpress.S | |||
@@ -16,6 +16,8 @@ | |||
16 | #define DEBUG_LL_PHYS_BASE_RS1 0x1c000000 | 16 | #define DEBUG_LL_PHYS_BASE_RS1 0x1c000000 |
17 | #define DEBUG_LL_UART_OFFSET_RS1 0x00090000 | 17 | #define DEBUG_LL_UART_OFFSET_RS1 0x00090000 |
18 | 18 | ||
19 | #define DEBUG_LL_UART_PHYS_CRX 0xb0090000 | ||
20 | |||
19 | #define DEBUG_LL_VIRT_BASE 0xf8000000 | 21 | #define DEBUG_LL_VIRT_BASE 0xf8000000 |
20 | 22 | ||
21 | #if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT) | 23 | #if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT) |
@@ -67,6 +69,14 @@ | |||
67 | 69 | ||
68 | #include <asm/hardware/debug-pl01x.S> | 70 | #include <asm/hardware/debug-pl01x.S> |
69 | 71 | ||
72 | #elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CRX) | ||
73 | |||
74 | .macro addruart,rp,tmp,tmp2 | ||
75 | ldr \rp, =DEBUG_LL_UART_PHYS_CRX | ||
76 | .endm | ||
77 | |||
78 | #include <asm/hardware/debug-pl01x.S> | ||
79 | |||
70 | #else /* CONFIG_DEBUG_LL_UART_NONE */ | 80 | #else /* CONFIG_DEBUG_LL_UART_NONE */ |
71 | 81 | ||
72 | .macro addruart, rp, rv, tmp | 82 | .macro addruart, rp, rv, tmp |
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h index 3688fd15a32d..6d34d080372a 100644 --- a/arch/arm/include/uapi/asm/hwcap.h +++ b/arch/arm/include/uapi/asm/hwcap.h | |||
@@ -25,6 +25,6 @@ | |||
25 | #define HWCAP_IDIVT (1 << 18) | 25 | #define HWCAP_IDIVT (1 << 18) |
26 | #define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ | 26 | #define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ |
27 | #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) | 27 | #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) |
28 | 28 | #define HWCAP_LPAE (1 << 20) | |
29 | 29 | ||
30 | #endif /* _UAPI__ASMARM_HWCAP_H */ | 30 | #endif /* _UAPI__ASMARM_HWCAP_H */ |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index f4285b5ffb05..fccfbdb03df1 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -38,7 +38,10 @@ obj-$(CONFIG_ARTHUR) += arthur.o | |||
38 | obj-$(CONFIG_ISA_DMA) += dma-isa.o | 38 | obj-$(CONFIG_ISA_DMA) += dma-isa.o |
39 | obj-$(CONFIG_PCI) += bios32.o isa.o | 39 | obj-$(CONFIG_PCI) += bios32.o isa.o |
40 | obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o | 40 | obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o |
41 | obj-$(CONFIG_SMP) += smp.o smp_tlb.o | 41 | obj-$(CONFIG_SMP) += smp.o |
42 | ifdef CONFIG_MMU | ||
43 | obj-$(CONFIG_SMP) += smp_tlb.o | ||
44 | endif | ||
42 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o | 45 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o |
43 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o | 46 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o |
44 | obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o | 47 | obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o |
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index ee68cce6b48e..ded041711beb 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/thread_info.h> | 23 | #include <asm/thread_info.h> |
24 | #include <asm/memory.h> | 24 | #include <asm/memory.h> |
25 | #include <asm/procinfo.h> | 25 | #include <asm/procinfo.h> |
26 | #include <asm/suspend.h> | ||
26 | #include <asm/hardware/cache-l2x0.h> | 27 | #include <asm/hardware/cache-l2x0.h> |
27 | #include <linux/kbuild.h> | 28 | #include <linux/kbuild.h> |
28 | 29 | ||
@@ -145,6 +146,11 @@ int main(void) | |||
145 | #ifdef MULTI_CACHE | 146 | #ifdef MULTI_CACHE |
146 | DEFINE(CACHE_FLUSH_KERN_ALL, offsetof(struct cpu_cache_fns, flush_kern_all)); | 147 | DEFINE(CACHE_FLUSH_KERN_ALL, offsetof(struct cpu_cache_fns, flush_kern_all)); |
147 | #endif | 148 | #endif |
149 | #ifdef CONFIG_ARM_CPU_SUSPEND | ||
150 | DEFINE(SLEEP_SAVE_SP_SZ, sizeof(struct sleep_save_sp)); | ||
151 | DEFINE(SLEEP_SAVE_SP_PHYS, offsetof(struct sleep_save_sp, save_ptr_stash_phys)); | ||
152 | DEFINE(SLEEP_SAVE_SP_VIRT, offsetof(struct sleep_save_sp, save_ptr_stash)); | ||
153 | #endif | ||
148 | BLANK(); | 154 | BLANK(); |
149 | DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); | 155 | DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); |
150 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); | 156 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 582b405befc5..a39cfc2a1f90 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -685,15 +685,16 @@ ENTRY(__switch_to) | |||
685 | UNWIND(.fnstart ) | 685 | UNWIND(.fnstart ) |
686 | UNWIND(.cantunwind ) | 686 | UNWIND(.cantunwind ) |
687 | add ip, r1, #TI_CPU_SAVE | 687 | add ip, r1, #TI_CPU_SAVE |
688 | ldr r3, [r2, #TI_TP_VALUE] | ||
689 | ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack | 688 | ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack |
690 | THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack | 689 | THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack |
691 | THUMB( str sp, [ip], #4 ) | 690 | THUMB( str sp, [ip], #4 ) |
692 | THUMB( str lr, [ip], #4 ) | 691 | THUMB( str lr, [ip], #4 ) |
692 | ldr r4, [r2, #TI_TP_VALUE] | ||
693 | ldr r5, [r2, #TI_TP_VALUE + 4] | ||
693 | #ifdef CONFIG_CPU_USE_DOMAINS | 694 | #ifdef CONFIG_CPU_USE_DOMAINS |
694 | ldr r6, [r2, #TI_CPU_DOMAIN] | 695 | ldr r6, [r2, #TI_CPU_DOMAIN] |
695 | #endif | 696 | #endif |
696 | set_tls r3, r4, r5 | 697 | switch_tls r1, r4, r5, r3, r7 |
697 | #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) | 698 | #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) |
698 | ldr r7, [r2, #TI_TASK] | 699 | ldr r7, [r2, #TI_TASK] |
699 | ldr r8, =__stack_chk_guard | 700 | ldr r8, =__stack_chk_guard |
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 85a72b0809ca..94104bf69719 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -366,6 +366,16 @@ ENTRY(vector_swi) | |||
366 | #endif | 366 | #endif |
367 | zero_fp | 367 | zero_fp |
368 | 368 | ||
369 | #ifdef CONFIG_ALIGNMENT_TRAP | ||
370 | ldr ip, __cr_alignment | ||
371 | ldr ip, [ip] | ||
372 | mcr p15, 0, ip, c1, c0 @ update control register | ||
373 | #endif | ||
374 | |||
375 | enable_irq | ||
376 | ct_user_exit | ||
377 | get_thread_info tsk | ||
378 | |||
369 | /* | 379 | /* |
370 | * Get the system call number. | 380 | * Get the system call number. |
371 | */ | 381 | */ |
@@ -379,9 +389,9 @@ ENTRY(vector_swi) | |||
379 | #ifdef CONFIG_ARM_THUMB | 389 | #ifdef CONFIG_ARM_THUMB |
380 | tst r8, #PSR_T_BIT | 390 | tst r8, #PSR_T_BIT |
381 | movne r10, #0 @ no thumb OABI emulation | 391 | movne r10, #0 @ no thumb OABI emulation |
382 | ldreq r10, [lr, #-4] @ get SWI instruction | 392 | USER( ldreq r10, [lr, #-4] ) @ get SWI instruction |
383 | #else | 393 | #else |
384 | ldr r10, [lr, #-4] @ get SWI instruction | 394 | USER( ldr r10, [lr, #-4] ) @ get SWI instruction |
385 | #endif | 395 | #endif |
386 | #ifdef CONFIG_CPU_ENDIAN_BE8 | 396 | #ifdef CONFIG_CPU_ENDIAN_BE8 |
387 | rev r10, r10 @ little endian instruction | 397 | rev r10, r10 @ little endian instruction |
@@ -396,22 +406,13 @@ ENTRY(vector_swi) | |||
396 | /* Legacy ABI only, possibly thumb mode. */ | 406 | /* Legacy ABI only, possibly thumb mode. */ |
397 | tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs | 407 | tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs |
398 | addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in | 408 | addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in |
399 | ldreq scno, [lr, #-4] | 409 | USER( ldreq scno, [lr, #-4] ) |
400 | 410 | ||
401 | #else | 411 | #else |
402 | /* Legacy ABI only. */ | 412 | /* Legacy ABI only. */ |
403 | ldr scno, [lr, #-4] @ get SWI instruction | 413 | USER( ldr scno, [lr, #-4] ) @ get SWI instruction |
404 | #endif | 414 | #endif |
405 | 415 | ||
406 | #ifdef CONFIG_ALIGNMENT_TRAP | ||
407 | ldr ip, __cr_alignment | ||
408 | ldr ip, [ip] | ||
409 | mcr p15, 0, ip, c1, c0 @ update control register | ||
410 | #endif | ||
411 | enable_irq | ||
412 | ct_user_exit | ||
413 | |||
414 | get_thread_info tsk | ||
415 | adr tbl, sys_call_table @ load syscall table pointer | 416 | adr tbl, sys_call_table @ load syscall table pointer |
416 | 417 | ||
417 | #if defined(CONFIG_OABI_COMPAT) | 418 | #if defined(CONFIG_OABI_COMPAT) |
@@ -446,6 +447,21 @@ local_restart: | |||
446 | eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back | 447 | eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back |
447 | bcs arm_syscall | 448 | bcs arm_syscall |
448 | b sys_ni_syscall @ not private func | 449 | b sys_ni_syscall @ not private func |
450 | |||
451 | #if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI) | ||
452 | /* | ||
453 | * We failed to handle a fault trying to access the page | ||
454 | * containing the swi instruction, but we're not really in a | ||
455 | * position to return -EFAULT. Instead, return back to the | ||
456 | * instruction and re-enter the user fault handling path trying | ||
457 | * to page it in. This will likely result in sending SEGV to the | ||
458 | * current task. | ||
459 | */ | ||
460 | 9001: | ||
461 | sub lr, lr, #4 | ||
462 | str lr, [sp, #S_PC] | ||
463 | b ret_fast_syscall | ||
464 | #endif | ||
449 | ENDPROC(vector_swi) | 465 | ENDPROC(vector_swi) |
450 | 466 | ||
451 | /* | 467 | /* |
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 8812ce88f7a1..75f14cc3e073 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S | |||
@@ -17,9 +17,12 @@ | |||
17 | #include <asm/assembler.h> | 17 | #include <asm/assembler.h> |
18 | #include <asm/ptrace.h> | 18 | #include <asm/ptrace.h> |
19 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> |
20 | #include <asm/memory.h> | ||
20 | #include <asm/cp15.h> | 21 | #include <asm/cp15.h> |
21 | #include <asm/thread_info.h> | 22 | #include <asm/thread_info.h> |
22 | #include <asm/v7m.h> | 23 | #include <asm/v7m.h> |
24 | #include <asm/mpu.h> | ||
25 | #include <asm/page.h> | ||
23 | 26 | ||
24 | /* | 27 | /* |
25 | * Kernel startup entry point. | 28 | * Kernel startup entry point. |
@@ -63,12 +66,74 @@ ENTRY(stext) | |||
63 | movs r10, r5 @ invalid processor (r5=0)? | 66 | movs r10, r5 @ invalid processor (r5=0)? |
64 | beq __error_p @ yes, error 'p' | 67 | beq __error_p @ yes, error 'p' |
65 | 68 | ||
66 | adr lr, BSYM(__after_proc_init) @ return (PIC) address | 69 | #ifdef CONFIG_ARM_MPU |
70 | /* Calculate the size of a region covering just the kernel */ | ||
71 | ldr r5, =PHYS_OFFSET @ Region start: PHYS_OFFSET | ||
72 | ldr r6, =(_end) @ Cover whole kernel | ||
73 | sub r6, r6, r5 @ Minimum size of region to map | ||
74 | clz r6, r6 @ Region size must be 2^N... | ||
75 | rsb r6, r6, #31 @ ...so round up region size | ||
76 | lsl r6, r6, #MPU_RSR_SZ @ Put size in right field | ||
77 | orr r6, r6, #(1 << MPU_RSR_EN) @ Set region enabled bit | ||
78 | bl __setup_mpu | ||
79 | #endif | ||
80 | ldr r13, =__mmap_switched @ address to jump to after | ||
81 | @ initialising sctlr | ||
82 | adr lr, BSYM(1f) @ return (PIC) address | ||
67 | ARM( add pc, r10, #PROCINFO_INITFUNC ) | 83 | ARM( add pc, r10, #PROCINFO_INITFUNC ) |
68 | THUMB( add r12, r10, #PROCINFO_INITFUNC ) | 84 | THUMB( add r12, r10, #PROCINFO_INITFUNC ) |
69 | THUMB( mov pc, r12 ) | 85 | THUMB( mov pc, r12 ) |
86 | 1: b __after_proc_init | ||
70 | ENDPROC(stext) | 87 | ENDPROC(stext) |
71 | 88 | ||
89 | #ifdef CONFIG_SMP | ||
90 | __CPUINIT | ||
91 | ENTRY(secondary_startup) | ||
92 | /* | ||
93 | * Common entry point for secondary CPUs. | ||
94 | * | ||
95 | * Ensure that we're in SVC mode, and IRQs are disabled. Lookup | ||
96 | * the processor type - there is no need to check the machine type | ||
97 | * as it has already been validated by the primary processor. | ||
98 | */ | ||
99 | setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 | ||
100 | #ifndef CONFIG_CPU_CP15 | ||
101 | ldr r9, =CONFIG_PROCESSOR_ID | ||
102 | #else | ||
103 | mrc p15, 0, r9, c0, c0 @ get processor id | ||
104 | #endif | ||
105 | bl __lookup_processor_type @ r5=procinfo r9=cpuid | ||
106 | movs r10, r5 @ invalid processor? | ||
107 | beq __error_p @ yes, error 'p' | ||
108 | |||
109 | adr r4, __secondary_data | ||
110 | ldmia r4, {r7, r12} | ||
111 | |||
112 | #ifdef CONFIG_ARM_MPU | ||
113 | /* Use MPU region info supplied by __cpu_up */ | ||
114 | ldr r6, [r7] @ get secondary_data.mpu_szr | ||
115 | bl __setup_mpu @ Initialize the MPU | ||
116 | #endif | ||
117 | |||
118 | adr lr, BSYM(__after_proc_init) @ return address | ||
119 | mov r13, r12 @ __secondary_switched address | ||
120 | ARM( add pc, r10, #PROCINFO_INITFUNC ) | ||
121 | THUMB( add r12, r10, #PROCINFO_INITFUNC ) | ||
122 | THUMB( mov pc, r12 ) | ||
123 | ENDPROC(secondary_startup) | ||
124 | |||
125 | ENTRY(__secondary_switched) | ||
126 | ldr sp, [r7, #8] @ set up the stack pointer | ||
127 | mov fp, #0 | ||
128 | b secondary_start_kernel | ||
129 | ENDPROC(__secondary_switched) | ||
130 | |||
131 | .type __secondary_data, %object | ||
132 | __secondary_data: | ||
133 | .long secondary_data | ||
134 | .long __secondary_switched | ||
135 | #endif /* CONFIG_SMP */ | ||
136 | |||
72 | /* | 137 | /* |
73 | * Set the Control Register and Read the process ID. | 138 | * Set the Control Register and Read the process ID. |
74 | */ | 139 | */ |
@@ -99,10 +164,97 @@ __after_proc_init: | |||
99 | #endif | 164 | #endif |
100 | mcr p15, 0, r0, c1, c0, 0 @ write control reg | 165 | mcr p15, 0, r0, c1, c0, 0 @ write control reg |
101 | #endif /* CONFIG_CPU_CP15 */ | 166 | #endif /* CONFIG_CPU_CP15 */ |
102 | 167 | mov pc, r13 | |
103 | b __mmap_switched @ clear the BSS and jump | ||
104 | @ to start_kernel | ||
105 | ENDPROC(__after_proc_init) | 168 | ENDPROC(__after_proc_init) |
106 | .ltorg | 169 | .ltorg |
107 | 170 | ||
171 | #ifdef CONFIG_ARM_MPU | ||
172 | |||
173 | |||
174 | /* Set which MPU region should be programmed */ | ||
175 | .macro set_region_nr tmp, rgnr | ||
176 | mov \tmp, \rgnr @ Use static region numbers | ||
177 | mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR | ||
178 | .endm | ||
179 | |||
180 | /* Setup a single MPU region, either D or I side (D-side for unified) */ | ||
181 | .macro setup_region bar, acr, sr, side = MPU_DATA_SIDE | ||
182 | mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR | ||
183 | mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR | ||
184 | mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR | ||
185 | .endm | ||
186 | |||
187 | /* | ||
188 | * Setup the MPU and initial MPU Regions. We create the following regions: | ||
189 | * Region 0: Use this for probing the MPU details, so leave disabled. | ||
190 | * Region 1: Background region - covers the whole of RAM as strongly ordered | ||
191 | * Region 2: Normal, Shared, cacheable for RAM. From PHYS_OFFSET, size from r6 | ||
192 | * Region 3: Normal, shared, inaccessible from PL0 to protect the vectors page | ||
193 | * | ||
194 | * r6: Value to be written to DRSR (and IRSR if required) for MPU_RAM_REGION | ||
195 | */ | ||
196 | |||
197 | ENTRY(__setup_mpu) | ||
198 | |||
199 | /* Probe for v7 PMSA compliance */ | ||
200 | mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0 | ||
201 | and r0, r0, #(MMFR0_PMSA) @ PMSA field | ||
202 | teq r0, #(MMFR0_PMSAv7) @ PMSA v7 | ||
203 | bne __error_p @ Fail: ARM_MPU on NOT v7 PMSA | ||
204 | |||
205 | /* Determine whether the D/I-side memory map is unified. We set the | ||
206 | * flags here and continue to use them for the rest of this function */ | ||
207 | mrc p15, 0, r0, c0, c0, 4 @ MPUIR | ||
208 | ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU | ||
209 | beq __error_p @ Fail: ARM_MPU and no MPU | ||
210 | tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified | ||
211 | |||
212 | /* Setup second region first to free up r6 */ | ||
213 | set_region_nr r0, #MPU_RAM_REGION | ||
214 | isb | ||
215 | /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */ | ||
216 | ldr r0, =PHYS_OFFSET @ RAM starts at PHYS_OFFSET | ||
217 | ldr r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL) | ||
218 | |||
219 | setup_region r0, r5, r6, MPU_DATA_SIDE @ PHYS_OFFSET, shared, enabled | ||
220 | beq 1f @ Memory-map not unified | ||
221 | setup_region r0, r5, r6, MPU_INSTR_SIDE @ PHYS_OFFSET, shared, enabled | ||
222 | 1: isb | ||
223 | |||
224 | /* First/background region */ | ||
225 | set_region_nr r0, #MPU_BG_REGION | ||
226 | isb | ||
227 | /* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */ | ||
228 | mov r0, #0 @ BG region starts at 0x0 | ||
229 | ldr r5,=(MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA) | ||
230 | mov r6, #MPU_RSR_ALL_MEM @ 4GB region, enabled | ||
231 | |||
232 | setup_region r0, r5, r6, MPU_DATA_SIDE @ 0x0, BG region, enabled | ||
233 | beq 2f @ Memory-map not unified | ||
234 | setup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled | ||
235 | 2: isb | ||
236 | |||
237 | /* Vectors region */ | ||
238 | set_region_nr r0, #MPU_VECTORS_REGION | ||
239 | isb | ||
240 | /* Shared, inaccessible to PL0, rw PL1 */ | ||
241 | mov r0, #CONFIG_VECTORS_BASE @ Cover from VECTORS_BASE | ||
242 | ldr r5,=(MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL) | ||
243 | /* Writing N to bits 5:1 (RSR_SZ) --> region size 2^N+1 */ | ||
244 | mov r6, #(((PAGE_SHIFT - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN) | ||
245 | |||
246 | setup_region r0, r5, r6, MPU_DATA_SIDE @ VECTORS_BASE, PL0 NA, enabled | ||
247 | beq 3f @ Memory-map not unified | ||
248 | setup_region r0, r5, r6, MPU_INSTR_SIDE @ VECTORS_BASE, PL0 NA, enabled | ||
249 | 3: isb | ||
250 | |||
251 | /* Enable the MPU */ | ||
252 | mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR | ||
253 | bic r0, r0, #CR_BR @ Disable the 'default mem-map' | ||
254 | orr r0, r0, #CR_M @ Set SCTRL.M (MPU on) | ||
255 | mcr p15, 0, r0, c1, c0, 0 @ Enable MPU | ||
256 | isb | ||
257 | mov pc,lr | ||
258 | ENDPROC(__setup_mpu) | ||
259 | #endif | ||
108 | #include "head-common.S" | 260 | #include "head-common.S" |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 8bac553fe213..45e8935cae4e 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -156,7 +156,7 @@ ENDPROC(stext) | |||
156 | * | 156 | * |
157 | * Returns: | 157 | * Returns: |
158 | * r0, r3, r5-r7 corrupted | 158 | * r0, r3, r5-r7 corrupted |
159 | * r4 = physical page table address | 159 | * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h) |
160 | */ | 160 | */ |
161 | __create_page_tables: | 161 | __create_page_tables: |
162 | pgtbl r4, r8 @ page table address | 162 | pgtbl r4, r8 @ page table address |
@@ -331,6 +331,7 @@ __create_page_tables: | |||
331 | #endif | 331 | #endif |
332 | #ifdef CONFIG_ARM_LPAE | 332 | #ifdef CONFIG_ARM_LPAE |
333 | sub r4, r4, #0x1000 @ point to the PGD table | 333 | sub r4, r4, #0x1000 @ point to the PGD table |
334 | mov r4, r4, lsr #ARCH_PGD_SHIFT | ||
334 | #endif | 335 | #endif |
335 | mov pc, lr | 336 | mov pc, lr |
336 | ENDPROC(__create_page_tables) | 337 | ENDPROC(__create_page_tables) |
@@ -408,7 +409,7 @@ __secondary_data: | |||
408 | * r0 = cp#15 control register | 409 | * r0 = cp#15 control register |
409 | * r1 = machine ID | 410 | * r1 = machine ID |
410 | * r2 = atags or dtb pointer | 411 | * r2 = atags or dtb pointer |
411 | * r4 = page table pointer | 412 | * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h) |
412 | * r9 = processor ID | 413 | * r9 = processor ID |
413 | * r13 = *virtual* address to jump to upon completion | 414 | * r13 = *virtual* address to jump to upon completion |
414 | */ | 415 | */ |
@@ -427,10 +428,7 @@ __enable_mmu: | |||
427 | #ifdef CONFIG_CPU_ICACHE_DISABLE | 428 | #ifdef CONFIG_CPU_ICACHE_DISABLE |
428 | bic r0, r0, #CR_I | 429 | bic r0, r0, #CR_I |
429 | #endif | 430 | #endif |
430 | #ifdef CONFIG_ARM_LPAE | 431 | #ifndef CONFIG_ARM_LPAE |
431 | mov r5, #0 | ||
432 | mcrr p15, 0, r4, r5, c2 @ load TTBR0 | ||
433 | #else | ||
434 | mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ | 432 | mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ |
435 | domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ | 433 | domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ |
436 | domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ | 434 | domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ |
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S index 1315c4ccfa56..4910232c4833 100644 --- a/arch/arm/kernel/hyp-stub.S +++ b/arch/arm/kernel/hyp-stub.S | |||
@@ -153,6 +153,13 @@ THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE | |||
153 | mrc p15, 4, r7, c14, c1, 0 @ CNTHCTL | 153 | mrc p15, 4, r7, c14, c1, 0 @ CNTHCTL |
154 | orr r7, r7, #3 @ PL1PCEN | PL1PCTEN | 154 | orr r7, r7, #3 @ PL1PCEN | PL1PCTEN |
155 | mcr p15, 4, r7, c14, c1, 0 @ CNTHCTL | 155 | mcr p15, 4, r7, c14, c1, 0 @ CNTHCTL |
156 | mov r7, #0 | ||
157 | mcrr p15, 4, r7, r7, c14 @ CNTVOFF | ||
158 | |||
159 | @ Disable virtual timer in case it was counting | ||
160 | mrc p15, 0, r7, c14, c3, 1 @ CNTV_CTL | ||
161 | bic r7, #1 @ Clear ENABLE | ||
162 | mcr p15, 0, r7, c14, c3, 1 @ CNTV_CTL | ||
156 | 1: | 163 | 1: |
157 | #endif | 164 | #endif |
158 | 165 | ||
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 8c3094d0f7b7..d9f5cd4e533f 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -569,6 +569,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
569 | return; | 569 | return; |
570 | } | 570 | } |
571 | 571 | ||
572 | perf_callchain_store(entry, regs->ARM_pc); | ||
572 | tail = (struct frame_tail __user *)regs->ARM_fp - 1; | 573 | tail = (struct frame_tail __user *)regs->ARM_fp - 1; |
573 | 574 | ||
574 | while ((entry->nr < PERF_MAX_STACK_DEPTH) && | 575 | while ((entry->nr < PERF_MAX_STACK_DEPTH) && |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 6e8931ccf13e..7f1efcd4a6e9 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <asm/thread_notify.h> | 39 | #include <asm/thread_notify.h> |
40 | #include <asm/stacktrace.h> | 40 | #include <asm/stacktrace.h> |
41 | #include <asm/mach/time.h> | 41 | #include <asm/mach/time.h> |
42 | #include <asm/tls.h> | ||
42 | 43 | ||
43 | #ifdef CONFIG_CC_STACKPROTECTOR | 44 | #ifdef CONFIG_CC_STACKPROTECTOR |
44 | #include <linux/stackprotector.h> | 45 | #include <linux/stackprotector.h> |
@@ -374,7 +375,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, | |||
374 | clear_ptrace_hw_breakpoint(p); | 375 | clear_ptrace_hw_breakpoint(p); |
375 | 376 | ||
376 | if (clone_flags & CLONE_SETTLS) | 377 | if (clone_flags & CLONE_SETTLS) |
377 | thread->tp_value = childregs->ARM_r3; | 378 | thread->tp_value[0] = childregs->ARM_r3; |
379 | thread->tp_value[1] = get_tpuser(); | ||
378 | 380 | ||
379 | thread_notify(THREAD_NOTIFY_COPY, thread); | 381 | thread_notify(THREAD_NOTIFY_COPY, thread); |
380 | 382 | ||
diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index 23a11424c568..219f1d73572a 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c | |||
@@ -68,8 +68,6 @@ void __ref psci_cpu_die(unsigned int cpu) | |||
68 | /* We should never return */ | 68 | /* We should never return */ |
69 | panic("psci: cpu %d failed to shutdown\n", cpu); | 69 | panic("psci: cpu %d failed to shutdown\n", cpu); |
70 | } | 70 | } |
71 | #else | ||
72 | #define psci_cpu_die NULL | ||
73 | #endif | 71 | #endif |
74 | 72 | ||
75 | bool __init psci_smp_available(void) | 73 | bool __init psci_smp_available(void) |
@@ -80,5 +78,7 @@ bool __init psci_smp_available(void) | |||
80 | 78 | ||
81 | struct smp_operations __initdata psci_smp_ops = { | 79 | struct smp_operations __initdata psci_smp_ops = { |
82 | .smp_boot_secondary = psci_boot_secondary, | 80 | .smp_boot_secondary = psci_boot_secondary, |
81 | #ifdef CONFIG_HOTPLUG_CPU | ||
83 | .cpu_die = psci_cpu_die, | 82 | .cpu_die = psci_cpu_die, |
83 | #endif | ||
84 | }; | 84 | }; |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 03deeffd9f6d..2bc1514d6dbe 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -849,7 +849,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
849 | #endif | 849 | #endif |
850 | 850 | ||
851 | case PTRACE_GET_THREAD_AREA: | 851 | case PTRACE_GET_THREAD_AREA: |
852 | ret = put_user(task_thread_info(child)->tp_value, | 852 | ret = put_user(task_thread_info(child)->tp_value[0], |
853 | datap); | 853 | datap); |
854 | break; | 854 | break; |
855 | 855 | ||
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 1c8278de6c46..9b653278c9e8 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -367,7 +367,7 @@ void __init early_print(const char *str, ...) | |||
367 | 367 | ||
368 | static void __init cpuid_init_hwcaps(void) | 368 | static void __init cpuid_init_hwcaps(void) |
369 | { | 369 | { |
370 | unsigned int divide_instrs; | 370 | unsigned int divide_instrs, vmsa; |
371 | 371 | ||
372 | if (cpu_architecture() < CPU_ARCH_ARMv7) | 372 | if (cpu_architecture() < CPU_ARCH_ARMv7) |
373 | return; | 373 | return; |
@@ -380,6 +380,11 @@ static void __init cpuid_init_hwcaps(void) | |||
380 | case 1: | 380 | case 1: |
381 | elf_hwcap |= HWCAP_IDIVT; | 381 | elf_hwcap |= HWCAP_IDIVT; |
382 | } | 382 | } |
383 | |||
384 | /* LPAE implies atomic ldrd/strd instructions */ | ||
385 | vmsa = (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xf) >> 0; | ||
386 | if (vmsa >= 5) | ||
387 | elf_hwcap |= HWCAP_LPAE; | ||
383 | } | 388 | } |
384 | 389 | ||
385 | static void __init feat_v6_fixup(void) | 390 | static void __init feat_v6_fixup(void) |
@@ -470,9 +475,82 @@ void __init smp_setup_processor_id(void) | |||
470 | for (i = 1; i < nr_cpu_ids; ++i) | 475 | for (i = 1; i < nr_cpu_ids; ++i) |
471 | cpu_logical_map(i) = i == cpu ? 0 : i; | 476 | cpu_logical_map(i) = i == cpu ? 0 : i; |
472 | 477 | ||
478 | /* | ||
479 | * clear __my_cpu_offset on boot CPU to avoid hang caused by | ||
480 | * using percpu variable early, for example, lockdep will | ||
481 | * access percpu variable inside lock_release | ||
482 | */ | ||
483 | set_my_cpu_offset(0); | ||
484 | |||
473 | printk(KERN_INFO "Booting Linux on physical CPU 0x%x\n", mpidr); | 485 | printk(KERN_INFO "Booting Linux on physical CPU 0x%x\n", mpidr); |
474 | } | 486 | } |
475 | 487 | ||
488 | struct mpidr_hash mpidr_hash; | ||
489 | #ifdef CONFIG_SMP | ||
490 | /** | ||
491 | * smp_build_mpidr_hash - Pre-compute shifts required at each affinity | ||
492 | * level in order to build a linear index from an | ||
493 | * MPIDR value. Resulting algorithm is a collision | ||
494 | * free hash carried out through shifting and ORing | ||
495 | */ | ||
496 | static void __init smp_build_mpidr_hash(void) | ||
497 | { | ||
498 | u32 i, affinity; | ||
499 | u32 fs[3], bits[3], ls, mask = 0; | ||
500 | /* | ||
501 | * Pre-scan the list of MPIDRS and filter out bits that do | ||
502 | * not contribute to affinity levels, ie they never toggle. | ||
503 | */ | ||
504 | for_each_possible_cpu(i) | ||
505 | mask |= (cpu_logical_map(i) ^ cpu_logical_map(0)); | ||
506 | pr_debug("mask of set bits 0x%x\n", mask); | ||
507 | /* | ||
508 | * Find and stash the last and first bit set at all affinity levels to | ||
509 | * check how many bits are required to represent them. | ||
510 | */ | ||
511 | for (i = 0; i < 3; i++) { | ||
512 | affinity = MPIDR_AFFINITY_LEVEL(mask, i); | ||
513 | /* | ||
514 | * Find the MSB bit and LSB bits position | ||
515 | * to determine how many bits are required | ||
516 | * to express the affinity level. | ||
517 | */ | ||
518 | ls = fls(affinity); | ||
519 | fs[i] = affinity ? ffs(affinity) - 1 : 0; | ||
520 | bits[i] = ls - fs[i]; | ||
521 | } | ||
522 | /* | ||
523 | * An index can be created from the MPIDR by isolating the | ||
524 | * significant bits at each affinity level and by shifting | ||
525 | * them in order to compress the 24 bits values space to a | ||
526 | * compressed set of values. This is equivalent to hashing | ||
527 | * the MPIDR through shifting and ORing. It is a collision free | ||
528 | * hash though not minimal since some levels might contain a number | ||
529 | * of CPUs that is not an exact power of 2 and their bit | ||
530 | * representation might contain holes, eg MPIDR[7:0] = {0x2, 0x80}. | ||
531 | */ | ||
532 | mpidr_hash.shift_aff[0] = fs[0]; | ||
533 | mpidr_hash.shift_aff[1] = MPIDR_LEVEL_BITS + fs[1] - bits[0]; | ||
534 | mpidr_hash.shift_aff[2] = 2*MPIDR_LEVEL_BITS + fs[2] - | ||
535 | (bits[1] + bits[0]); | ||
536 | mpidr_hash.mask = mask; | ||
537 | mpidr_hash.bits = bits[2] + bits[1] + bits[0]; | ||
538 | pr_debug("MPIDR hash: aff0[%u] aff1[%u] aff2[%u] mask[0x%x] bits[%u]\n", | ||
539 | mpidr_hash.shift_aff[0], | ||
540 | mpidr_hash.shift_aff[1], | ||
541 | mpidr_hash.shift_aff[2], | ||
542 | mpidr_hash.mask, | ||
543 | mpidr_hash.bits); | ||
544 | /* | ||
545 | * 4x is an arbitrary value used to warn on a hash table much bigger | ||
546 | * than expected on most systems. | ||
547 | */ | ||
548 | if (mpidr_hash_size() > 4 * num_possible_cpus()) | ||
549 | pr_warn("Large number of MPIDR hash buckets detected\n"); | ||
550 | sync_cache_w(&mpidr_hash); | ||
551 | } | ||
552 | #endif | ||
553 | |||
476 | static void __init setup_processor(void) | 554 | static void __init setup_processor(void) |
477 | { | 555 | { |
478 | struct proc_info_list *list; | 556 | struct proc_info_list *list; |
@@ -820,6 +898,7 @@ void __init setup_arch(char **cmdline_p) | |||
820 | smp_set_ops(mdesc->smp); | 898 | smp_set_ops(mdesc->smp); |
821 | } | 899 | } |
822 | smp_init_cpus(); | 900 | smp_init_cpus(); |
901 | smp_build_mpidr_hash(); | ||
823 | } | 902 | } |
824 | #endif | 903 | #endif |
825 | 904 | ||
@@ -892,6 +971,7 @@ static const char *hwcap_str[] = { | |||
892 | "vfpv4", | 971 | "vfpv4", |
893 | "idiva", | 972 | "idiva", |
894 | "idivt", | 973 | "idivt", |
974 | "lpae", | ||
895 | NULL | 975 | NULL |
896 | }; | 976 | }; |
897 | 977 | ||
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 296786bdbb73..1c16c35c271a 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -392,14 +392,19 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, | |||
392 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) | 392 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
393 | idx += 3; | 393 | idx += 3; |
394 | 394 | ||
395 | /* | ||
396 | * Put the sigreturn code on the stack no matter which return | ||
397 | * mechanism we use in order to remain ABI compliant | ||
398 | */ | ||
395 | if (__put_user(sigreturn_codes[idx], rc) || | 399 | if (__put_user(sigreturn_codes[idx], rc) || |
396 | __put_user(sigreturn_codes[idx+1], rc+1)) | 400 | __put_user(sigreturn_codes[idx+1], rc+1)) |
397 | return 1; | 401 | return 1; |
398 | 402 | ||
399 | if (cpsr & MODE32_BIT) { | 403 | if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) { |
400 | /* | 404 | /* |
401 | * 32-bit code can use the new high-page | 405 | * 32-bit code can use the new high-page |
402 | * signal return code support. | 406 | * signal return code support except when the MPU has |
407 | * protected the vectors page from PL0 | ||
403 | */ | 408 | */ |
404 | retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; | 409 | retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; |
405 | } else { | 410 | } else { |
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index 987dcf33415c..db1536b8b30b 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S | |||
@@ -7,6 +7,49 @@ | |||
7 | .text | 7 | .text |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Implementation of MPIDR hash algorithm through shifting | ||
11 | * and OR'ing. | ||
12 | * | ||
13 | * @dst: register containing hash result | ||
14 | * @rs0: register containing affinity level 0 bit shift | ||
15 | * @rs1: register containing affinity level 1 bit shift | ||
16 | * @rs2: register containing affinity level 2 bit shift | ||
17 | * @mpidr: register containing MPIDR value | ||
18 | * @mask: register containing MPIDR mask | ||
19 | * | ||
20 | * Pseudo C-code: | ||
21 | * | ||
22 | *u32 dst; | ||
23 | * | ||
24 | *compute_mpidr_hash(u32 rs0, u32 rs1, u32 rs2, u32 mpidr, u32 mask) { | ||
25 | * u32 aff0, aff1, aff2; | ||
26 | * u32 mpidr_masked = mpidr & mask; | ||
27 | * aff0 = mpidr_masked & 0xff; | ||
28 | * aff1 = mpidr_masked & 0xff00; | ||
29 | * aff2 = mpidr_masked & 0xff0000; | ||
30 | * dst = (aff0 >> rs0 | aff1 >> rs1 | aff2 >> rs2); | ||
31 | *} | ||
32 | * Input registers: rs0, rs1, rs2, mpidr, mask | ||
33 | * Output register: dst | ||
34 | * Note: input and output registers must be disjoint register sets | ||
35 | (eg: a macro instance with mpidr = r1 and dst = r1 is invalid) | ||
36 | */ | ||
37 | .macro compute_mpidr_hash dst, rs0, rs1, rs2, mpidr, mask | ||
38 | and \mpidr, \mpidr, \mask @ mask out MPIDR bits | ||
39 | and \dst, \mpidr, #0xff @ mask=aff0 | ||
40 | ARM( mov \dst, \dst, lsr \rs0 ) @ dst=aff0>>rs0 | ||
41 | THUMB( lsr \dst, \dst, \rs0 ) | ||
42 | and \mask, \mpidr, #0xff00 @ mask = aff1 | ||
43 | ARM( orr \dst, \dst, \mask, lsr \rs1 ) @ dst|=(aff1>>rs1) | ||
44 | THUMB( lsr \mask, \mask, \rs1 ) | ||
45 | THUMB( orr \dst, \dst, \mask ) | ||
46 | and \mask, \mpidr, #0xff0000 @ mask = aff2 | ||
47 | ARM( orr \dst, \dst, \mask, lsr \rs2 ) @ dst|=(aff2>>rs2) | ||
48 | THUMB( lsr \mask, \mask, \rs2 ) | ||
49 | THUMB( orr \dst, \dst, \mask ) | ||
50 | .endm | ||
51 | |||
52 | /* | ||
10 | * Save CPU state for a suspend. This saves the CPU general purpose | 53 | * Save CPU state for a suspend. This saves the CPU general purpose |
11 | * registers, and allocates space on the kernel stack to save the CPU | 54 | * registers, and allocates space on the kernel stack to save the CPU |
12 | * specific registers and some other data for resume. | 55 | * specific registers and some other data for resume. |
@@ -29,12 +72,18 @@ ENTRY(__cpu_suspend) | |||
29 | mov r1, r4 @ size of save block | 72 | mov r1, r4 @ size of save block |
30 | mov r2, r5 @ virtual SP | 73 | mov r2, r5 @ virtual SP |
31 | ldr r3, =sleep_save_sp | 74 | ldr r3, =sleep_save_sp |
32 | #ifdef CONFIG_SMP | 75 | ldr r3, [r3, #SLEEP_SAVE_SP_VIRT] |
33 | ALT_SMP(mrc p15, 0, lr, c0, c0, 5) | 76 | ALT_SMP(mrc p15, 0, r9, c0, c0, 5) |
34 | ALT_UP(mov lr, #0) | 77 | ALT_UP_B(1f) |
35 | and lr, lr, #15 | 78 | ldr r8, =mpidr_hash |
79 | /* | ||
80 | * This ldmia relies on the memory layout of the mpidr_hash | ||
81 | * struct mpidr_hash. | ||
82 | */ | ||
83 | ldmia r8, {r4-r7} @ r4 = mpidr mask (r5,r6,r7) = l[0,1,2] shifts | ||
84 | compute_mpidr_hash lr, r5, r6, r7, r9, r4 | ||
36 | add r3, r3, lr, lsl #2 | 85 | add r3, r3, lr, lsl #2 |
37 | #endif | 86 | 1: |
38 | bl __cpu_suspend_save | 87 | bl __cpu_suspend_save |
39 | adr lr, BSYM(cpu_suspend_abort) | 88 | adr lr, BSYM(cpu_suspend_abort) |
40 | ldmfd sp!, {r0, pc} @ call suspend fn | 89 | ldmfd sp!, {r0, pc} @ call suspend fn |
@@ -81,15 +130,23 @@ ENDPROC(cpu_resume_after_mmu) | |||
81 | .data | 130 | .data |
82 | .align | 131 | .align |
83 | ENTRY(cpu_resume) | 132 | ENTRY(cpu_resume) |
84 | #ifdef CONFIG_SMP | 133 | mov r1, #0 |
85 | adr r0, sleep_save_sp | 134 | ALT_SMP(mrc p15, 0, r0, c0, c0, 5) |
86 | ALT_SMP(mrc p15, 0, r1, c0, c0, 5) | 135 | ALT_UP_B(1f) |
87 | ALT_UP(mov r1, #0) | 136 | adr r2, mpidr_hash_ptr |
88 | and r1, r1, #15 | 137 | ldr r3, [r2] |
89 | ldr r0, [r0, r1, lsl #2] @ stack phys addr | 138 | add r2, r2, r3 @ r2 = struct mpidr_hash phys address |
90 | #else | 139 | /* |
91 | ldr r0, sleep_save_sp @ stack phys addr | 140 | * This ldmia relies on the memory layout of the mpidr_hash |
92 | #endif | 141 | * struct mpidr_hash. |
142 | */ | ||
143 | ldmia r2, { r3-r6 } @ r3 = mpidr mask (r4,r5,r6) = l[0,1,2] shifts | ||
144 | compute_mpidr_hash r1, r4, r5, r6, r0, r3 | ||
145 | 1: | ||
146 | adr r0, _sleep_save_sp | ||
147 | ldr r0, [r0, #SLEEP_SAVE_SP_PHYS] | ||
148 | ldr r0, [r0, r1, lsl #2] | ||
149 | |||
93 | setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off | 150 | setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off |
94 | @ load phys pgd, stack, resume fn | 151 | @ load phys pgd, stack, resume fn |
95 | ARM( ldmia r0!, {r1, sp, pc} ) | 152 | ARM( ldmia r0!, {r1, sp, pc} ) |
@@ -98,7 +155,11 @@ THUMB( mov sp, r2 ) | |||
98 | THUMB( bx r3 ) | 155 | THUMB( bx r3 ) |
99 | ENDPROC(cpu_resume) | 156 | ENDPROC(cpu_resume) |
100 | 157 | ||
101 | sleep_save_sp: | 158 | .align 2 |
102 | .rept CONFIG_NR_CPUS | 159 | mpidr_hash_ptr: |
103 | .long 0 @ preserve stack phys ptr here | 160 | .long mpidr_hash - . @ mpidr_hash struct offset |
104 | .endr | 161 | |
162 | .type sleep_save_sp, #object | ||
163 | ENTRY(sleep_save_sp) | ||
164 | _sleep_save_sp: | ||
165 | .space SLEEP_SAVE_SP_SZ @ struct sleep_save_sp | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 5919eb451bb9..c5fb5469054b 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/smp_plat.h> | 45 | #include <asm/smp_plat.h> |
46 | #include <asm/virt.h> | 46 | #include <asm/virt.h> |
47 | #include <asm/mach/arch.h> | 47 | #include <asm/mach/arch.h> |
48 | #include <asm/mpu.h> | ||
48 | 49 | ||
49 | /* | 50 | /* |
50 | * as from 2.5, kernels no longer have an init_tasks structure | 51 | * as from 2.5, kernels no longer have an init_tasks structure |
@@ -78,6 +79,13 @@ void __init smp_set_ops(struct smp_operations *ops) | |||
78 | smp_ops = *ops; | 79 | smp_ops = *ops; |
79 | }; | 80 | }; |
80 | 81 | ||
82 | static unsigned long get_arch_pgd(pgd_t *pgd) | ||
83 | { | ||
84 | phys_addr_t pgdir = virt_to_phys(pgd); | ||
85 | BUG_ON(pgdir & ARCH_PGD_MASK); | ||
86 | return pgdir >> ARCH_PGD_SHIFT; | ||
87 | } | ||
88 | |||
81 | int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | 89 | int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) |
82 | { | 90 | { |
83 | int ret; | 91 | int ret; |
@@ -87,8 +95,14 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | |||
87 | * its stack and the page tables. | 95 | * its stack and the page tables. |
88 | */ | 96 | */ |
89 | secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; | 97 | secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; |
90 | secondary_data.pgdir = virt_to_phys(idmap_pgd); | 98 | #ifdef CONFIG_ARM_MPU |
91 | secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir); | 99 | secondary_data.mpu_rgn_szr = mpu_rgn_info.rgns[MPU_RAM_REGION].drsr; |
100 | #endif | ||
101 | |||
102 | #ifdef CONFIG_MMU | ||
103 | secondary_data.pgdir = get_arch_pgd(idmap_pgd); | ||
104 | secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir); | ||
105 | #endif | ||
92 | __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data)); | 106 | __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data)); |
93 | outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1)); | 107 | outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1)); |
94 | 108 | ||
@@ -112,9 +126,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | |||
112 | pr_err("CPU%u: failed to boot: %d\n", cpu, ret); | 126 | pr_err("CPU%u: failed to boot: %d\n", cpu, ret); |
113 | } | 127 | } |
114 | 128 | ||
115 | secondary_data.stack = NULL; | ||
116 | secondary_data.pgdir = 0; | ||
117 | 129 | ||
130 | memset(&secondary_data, 0, sizeof(secondary_data)); | ||
118 | return ret; | 131 | return ret; |
119 | } | 132 | } |
120 | 133 | ||
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c index 9a52a07aa40e..a98b62dca2fa 100644 --- a/arch/arm/kernel/smp_tlb.c +++ b/arch/arm/kernel/smp_tlb.c | |||
@@ -103,7 +103,7 @@ static void broadcast_tlb_a15_erratum(void) | |||
103 | 103 | ||
104 | static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm) | 104 | static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm) |
105 | { | 105 | { |
106 | int cpu, this_cpu; | 106 | int this_cpu; |
107 | cpumask_t mask = { CPU_BITS_NONE }; | 107 | cpumask_t mask = { CPU_BITS_NONE }; |
108 | 108 | ||
109 | if (!erratum_a15_798181()) | 109 | if (!erratum_a15_798181()) |
@@ -111,21 +111,7 @@ static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm) | |||
111 | 111 | ||
112 | dummy_flush_tlb_a15_erratum(); | 112 | dummy_flush_tlb_a15_erratum(); |
113 | this_cpu = get_cpu(); | 113 | this_cpu = get_cpu(); |
114 | for_each_online_cpu(cpu) { | 114 | a15_erratum_get_cpumask(this_cpu, mm, &mask); |
115 | if (cpu == this_cpu) | ||
116 | continue; | ||
117 | /* | ||
118 | * We only need to send an IPI if the other CPUs are running | ||
119 | * the same ASID as the one being invalidated. There is no | ||
120 | * need for locking around the active_asids check since the | ||
121 | * switch_mm() function has at least one dmb() (as required by | ||
122 | * this workaround) in case a context switch happens on | ||
123 | * another CPU after the condition below. | ||
124 | */ | ||
125 | if (atomic64_read(&mm->context.id) == | ||
126 | atomic64_read(&per_cpu(active_asids, cpu))) | ||
127 | cpumask_set_cpu(cpu, &mask); | ||
128 | } | ||
129 | smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1); | 115 | smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1); |
130 | put_cpu(); | 116 | put_cpu(); |
131 | } | 117 | } |
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index c59c97ea8268..41cf3cbf756d 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c | |||
@@ -1,15 +1,54 @@ | |||
1 | #include <linux/init.h> | 1 | #include <linux/init.h> |
2 | #include <linux/slab.h> | ||
2 | 3 | ||
4 | #include <asm/cacheflush.h> | ||
3 | #include <asm/idmap.h> | 5 | #include <asm/idmap.h> |
4 | #include <asm/pgalloc.h> | 6 | #include <asm/pgalloc.h> |
5 | #include <asm/pgtable.h> | 7 | #include <asm/pgtable.h> |
6 | #include <asm/memory.h> | 8 | #include <asm/memory.h> |
9 | #include <asm/smp_plat.h> | ||
7 | #include <asm/suspend.h> | 10 | #include <asm/suspend.h> |
8 | #include <asm/tlbflush.h> | 11 | #include <asm/tlbflush.h> |
9 | 12 | ||
10 | extern int __cpu_suspend(unsigned long, int (*)(unsigned long)); | 13 | extern int __cpu_suspend(unsigned long, int (*)(unsigned long)); |
11 | extern void cpu_resume_mmu(void); | 14 | extern void cpu_resume_mmu(void); |
12 | 15 | ||
16 | #ifdef CONFIG_MMU | ||
17 | /* | ||
18 | * Hide the first two arguments to __cpu_suspend - these are an implementation | ||
19 | * detail which platform code shouldn't have to know about. | ||
20 | */ | ||
21 | int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | ||
22 | { | ||
23 | struct mm_struct *mm = current->active_mm; | ||
24 | int ret; | ||
25 | |||
26 | if (!idmap_pgd) | ||
27 | return -EINVAL; | ||
28 | |||
29 | /* | ||
30 | * Provide a temporary page table with an identity mapping for | ||
31 | * the MMU-enable code, required for resuming. On successful | ||
32 | * resume (indicated by a zero return code), we need to switch | ||
33 | * back to the correct page tables. | ||
34 | */ | ||
35 | ret = __cpu_suspend(arg, fn); | ||
36 | if (ret == 0) { | ||
37 | cpu_switch_mm(mm->pgd, mm); | ||
38 | local_flush_bp_all(); | ||
39 | local_flush_tlb_all(); | ||
40 | } | ||
41 | |||
42 | return ret; | ||
43 | } | ||
44 | #else | ||
45 | int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | ||
46 | { | ||
47 | return __cpu_suspend(arg, fn); | ||
48 | } | ||
49 | #define idmap_pgd NULL | ||
50 | #endif | ||
51 | |||
13 | /* | 52 | /* |
14 | * This is called by __cpu_suspend() to save the state, and do whatever | 53 | * This is called by __cpu_suspend() to save the state, and do whatever |
15 | * flushing is required to ensure that when the CPU goes to sleep we have | 54 | * flushing is required to ensure that when the CPU goes to sleep we have |
@@ -47,30 +86,19 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) | |||
47 | virt_to_phys(save_ptr) + sizeof(*save_ptr)); | 86 | virt_to_phys(save_ptr) + sizeof(*save_ptr)); |
48 | } | 87 | } |
49 | 88 | ||
50 | /* | 89 | extern struct sleep_save_sp sleep_save_sp; |
51 | * Hide the first two arguments to __cpu_suspend - these are an implementation | ||
52 | * detail which platform code shouldn't have to know about. | ||
53 | */ | ||
54 | int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | ||
55 | { | ||
56 | struct mm_struct *mm = current->active_mm; | ||
57 | int ret; | ||
58 | |||
59 | if (!idmap_pgd) | ||
60 | return -EINVAL; | ||
61 | 90 | ||
62 | /* | 91 | static int cpu_suspend_alloc_sp(void) |
63 | * Provide a temporary page table with an identity mapping for | 92 | { |
64 | * the MMU-enable code, required for resuming. On successful | 93 | void *ctx_ptr; |
65 | * resume (indicated by a zero return code), we need to switch | 94 | /* ctx_ptr is an array of physical addresses */ |
66 | * back to the correct page tables. | 95 | ctx_ptr = kcalloc(mpidr_hash_size(), sizeof(u32), GFP_KERNEL); |
67 | */ | ||
68 | ret = __cpu_suspend(arg, fn); | ||
69 | if (ret == 0) { | ||
70 | cpu_switch_mm(mm->pgd, mm); | ||
71 | local_flush_bp_all(); | ||
72 | local_flush_tlb_all(); | ||
73 | } | ||
74 | 96 | ||
75 | return ret; | 97 | if (WARN_ON(!ctx_ptr)) |
98 | return -ENOMEM; | ||
99 | sleep_save_sp.save_ptr_stash = ctx_ptr; | ||
100 | sleep_save_sp.save_ptr_stash_phys = virt_to_phys(ctx_ptr); | ||
101 | sync_cache_w(&sleep_save_sp); | ||
102 | return 0; | ||
76 | } | 103 | } |
104 | early_initcall(cpu_suspend_alloc_sp); | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 486e12a0f26a..cab094c234ee 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -581,7 +581,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) | |||
581 | return regs->ARM_r0; | 581 | return regs->ARM_r0; |
582 | 582 | ||
583 | case NR(set_tls): | 583 | case NR(set_tls): |
584 | thread->tp_value = regs->ARM_r0; | 584 | thread->tp_value[0] = regs->ARM_r0; |
585 | if (tls_emu) | 585 | if (tls_emu) |
586 | return 0; | 586 | return 0; |
587 | if (has_tls_reg) { | 587 | if (has_tls_reg) { |
@@ -699,7 +699,7 @@ static int get_tp_trap(struct pt_regs *regs, unsigned int instr) | |||
699 | int reg = (instr >> 12) & 15; | 699 | int reg = (instr >> 12) & 15; |
700 | if (reg == 15) | 700 | if (reg == 15) |
701 | return 1; | 701 | return 1; |
702 | regs->uregs[reg] = current_thread_info()->tp_value; | 702 | regs->uregs[reg] = current_thread_info()->tp_value[0]; |
703 | regs->ARM_pc += 4; | 703 | regs->ARM_pc += 4; |
704 | return 0; | 704 | return 0; |
705 | } | 705 | } |
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S index 3c8f2f0b4c5e..d43cfb5b37c4 100644 --- a/arch/arm/kvm/interrupts_head.S +++ b/arch/arm/kvm/interrupts_head.S | |||
@@ -497,6 +497,10 @@ vcpu .req r0 @ vcpu pointer always in r0 | |||
497 | add r5, vcpu, r4 | 497 | add r5, vcpu, r4 |
498 | strd r2, r3, [r5] | 498 | strd r2, r3, [r5] |
499 | 499 | ||
500 | @ Ensure host CNTVCT == CNTPCT | ||
501 | mov r2, #0 | ||
502 | mcrr p15, 4, r2, r2, c14 @ CNTVOFF | ||
503 | |||
500 | 1: | 504 | 1: |
501 | #endif | 505 | #endif |
502 | @ Allow physical timer/counter access for the host | 506 | @ Allow physical timer/counter access for the host |
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index b13cc74114db..8a53f346cdb3 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c | |||
@@ -116,7 +116,7 @@ static void __init ebsa110_map_io(void) | |||
116 | iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc)); | 116 | iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc)); |
117 | } | 117 | } |
118 | 118 | ||
119 | static void __iomem *ebsa110_ioremap_caller(unsigned long cookie, size_t size, | 119 | static void __iomem *ebsa110_ioremap_caller(phys_addr_t cookie, size_t size, |
120 | unsigned int flags, void *caller) | 120 | unsigned int flags, void *caller) |
121 | { | 121 | { |
122 | return (void __iomem *)cookie; | 122 | return (void __iomem *)cookie; |
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 2d503b3684c4..f5f65b58181e 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig | |||
@@ -93,7 +93,7 @@ config SOC_EXYNOS5440 | |||
93 | default y | 93 | default y |
94 | depends on ARCH_EXYNOS5 | 94 | depends on ARCH_EXYNOS5 |
95 | select ARCH_HAS_OPP | 95 | select ARCH_HAS_OPP |
96 | select ARM_ARCH_TIMER | 96 | select HAVE_ARM_ARCH_TIMER |
97 | select AUTO_ZRELADDR | 97 | select AUTO_ZRELADDR |
98 | select MIGHT_HAVE_PCI | 98 | select MIGHT_HAVE_PCI |
99 | select PCI_DOMAINS if PCI | 99 | select PCI_DOMAINS if PCI |
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index 8f0f60697f55..0884ca90d15a 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c | |||
@@ -65,7 +65,7 @@ static void imx3_idle(void) | |||
65 | : "=r" (reg)); | 65 | : "=r" (reg)); |
66 | } | 66 | } |
67 | 67 | ||
68 | static void __iomem *imx3_ioremap_caller(unsigned long phys_addr, size_t size, | 68 | static void __iomem *imx3_ioremap_caller(phys_addr_t phys_addr, size_t size, |
69 | unsigned int mtype, void *caller) | 69 | unsigned int mtype, void *caller) |
70 | { | 70 | { |
71 | if (mtype == MT_DEVICE) { | 71 | if (mtype == MT_DEVICE) { |
diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c index 183dc8b5511b..faaf7d4482c5 100644 --- a/arch/arm/mach-iop13xx/io.c +++ b/arch/arm/mach-iop13xx/io.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | #include "pci.h" | 24 | #include "pci.h" |
25 | 25 | ||
26 | static void __iomem *__iop13xx_ioremap_caller(unsigned long cookie, | 26 | static void __iomem *__iop13xx_ioremap_caller(phys_addr_t cookie, |
27 | size_t size, unsigned int mtype, void *caller) | 27 | size_t size, unsigned int mtype, void *caller) |
28 | { | 28 | { |
29 | void __iomem * retval; | 29 | void __iomem * retval; |
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 6600cff6bd92..d7223b3b81f3 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
@@ -559,7 +559,7 @@ void ixp4xx_restart(char mode, const char *cmd) | |||
559 | * fallback to the default. | 559 | * fallback to the default. |
560 | */ | 560 | */ |
561 | 561 | ||
562 | static void __iomem *ixp4xx_ioremap_caller(unsigned long addr, size_t size, | 562 | static void __iomem *ixp4xx_ioremap_caller(phys_addr_t addr, size_t size, |
563 | unsigned int mtype, void *caller) | 563 | unsigned int mtype, void *caller) |
564 | { | 564 | { |
565 | if (!is_pci_memory(addr)) | 565 | if (!is_pci_memory(addr)) |
diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h index ce8215a269e5..421cf7751a80 100644 --- a/arch/arm/mach-msm/common.h +++ b/arch/arm/mach-msm/common.h | |||
@@ -23,7 +23,7 @@ extern void msm_map_msm8x60_io(void); | |||
23 | extern void msm_map_msm8960_io(void); | 23 | extern void msm_map_msm8960_io(void); |
24 | extern void msm_map_qsd8x50_io(void); | 24 | extern void msm_map_qsd8x50_io(void); |
25 | 25 | ||
26 | extern void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size, | 26 | extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size, |
27 | unsigned int mtype, void *caller); | 27 | unsigned int mtype, void *caller); |
28 | 28 | ||
29 | extern struct smp_operations msm_smp_ops; | 29 | extern struct smp_operations msm_smp_ops; |
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c index efa113e4de86..3dc04ccaf59f 100644 --- a/arch/arm/mach-msm/io.c +++ b/arch/arm/mach-msm/io.c | |||
@@ -168,7 +168,7 @@ void __init msm_map_msm7x30_io(void) | |||
168 | } | 168 | } |
169 | #endif /* CONFIG_ARCH_MSM7X30 */ | 169 | #endif /* CONFIG_ARCH_MSM7X30 */ |
170 | 170 | ||
171 | void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size, | 171 | void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size, |
172 | unsigned int mtype, void *caller) | 172 | unsigned int mtype, void *caller) |
173 | { | 173 | { |
174 | if (mtype == MT_DEVICE) { | 174 | if (mtype == MT_DEVICE) { |
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1fdb46216590..c7b32a966f67 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -4,6 +4,7 @@ config ARCH_OMAP | |||
4 | config ARCH_OMAP2PLUS | 4 | config ARCH_OMAP2PLUS |
5 | bool "TI OMAP2/3/4/5 SoCs with device tree support" if (ARCH_MULTI_V6 || ARCH_MULTI_V7) | 5 | bool "TI OMAP2/3/4/5 SoCs with device tree support" if (ARCH_MULTI_V6 || ARCH_MULTI_V7) |
6 | select ARCH_HAS_CPUFREQ | 6 | select ARCH_HAS_CPUFREQ |
7 | select ARCH_HAS_BANDGAP | ||
7 | select ARCH_HAS_HOLES_MEMORYMODEL | 8 | select ARCH_HAS_HOLES_MEMORYMODEL |
8 | select ARCH_OMAP | 9 | select ARCH_OMAP |
9 | select ARCH_REQUIRE_GPIOLIB | 10 | select ARCH_REQUIRE_GPIOLIB |
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index db27e8eef192..3912ce91fee4 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
@@ -23,7 +23,7 @@ config ARCH_R8A73A4 | |||
23 | select ARCH_WANT_OPTIONAL_GPIOLIB | 23 | select ARCH_WANT_OPTIONAL_GPIOLIB |
24 | select ARM_GIC | 24 | select ARM_GIC |
25 | select CPU_V7 | 25 | select CPU_V7 |
26 | select ARM_ARCH_TIMER | 26 | select HAVE_ARM_ARCH_TIMER |
27 | select SH_CLK_CPG | 27 | select SH_CLK_CPG |
28 | select RENESAS_IRQC | 28 | select RENESAS_IRQC |
29 | 29 | ||
@@ -59,7 +59,7 @@ config ARCH_R8A7790 | |||
59 | select ARCH_WANT_OPTIONAL_GPIOLIB | 59 | select ARCH_WANT_OPTIONAL_GPIOLIB |
60 | select ARM_GIC | 60 | select ARM_GIC |
61 | select CPU_V7 | 61 | select CPU_V7 |
62 | select ARM_ARCH_TIMER | 62 | select HAVE_ARM_ARCH_TIMER |
63 | select SH_CLK_CPG | 63 | select SH_CLK_CPG |
64 | select RENESAS_IRQC | 64 | select RENESAS_IRQC |
65 | 65 | ||
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 84d72fc36dfe..65c5ae6fa386 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig | |||
@@ -60,7 +60,7 @@ config ARCH_TEGRA_3x_SOC | |||
60 | 60 | ||
61 | config ARCH_TEGRA_114_SOC | 61 | config ARCH_TEGRA_114_SOC |
62 | bool "Enable support for Tegra114 family" | 62 | bool "Enable support for Tegra114 family" |
63 | select ARM_ARCH_TIMER | 63 | select HAVE_ARM_ARCH_TIMER |
64 | select ARM_GIC | 64 | select ARM_GIC |
65 | select ARM_L1_CACHE_SHIFT_6 | 65 | select ARM_L1_CACHE_SHIFT_6 |
66 | select CPU_FREQ_TABLE if CPU_FREQ | 66 | select CPU_FREQ_TABLE if CPU_FREQ |
diff --git a/arch/arm/mach-virt/Kconfig b/arch/arm/mach-virt/Kconfig index 8958f0d896bc..081d46929436 100644 --- a/arch/arm/mach-virt/Kconfig +++ b/arch/arm/mach-virt/Kconfig | |||
@@ -2,7 +2,7 @@ config ARCH_VIRT | |||
2 | bool "Dummy Virtual Machine" if ARCH_MULTI_V7 | 2 | bool "Dummy Virtual Machine" if ARCH_MULTI_V7 |
3 | select ARCH_WANT_OPTIONAL_GPIOLIB | 3 | select ARCH_WANT_OPTIONAL_GPIOLIB |
4 | select ARM_GIC | 4 | select ARM_GIC |
5 | select ARM_ARCH_TIMER | 5 | select HAVE_ARM_ARCH_TIMER |
6 | select ARM_PSCI | 6 | select ARM_PSCI |
7 | select HAVE_SMP | 7 | select HAVE_SMP |
8 | select CPU_V7 | 8 | select CPU_V7 |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 9e8101ecd63e..6cacdc8dd654 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -392,7 +392,8 @@ config CPU_V7 | |||
392 | select CPU_CACHE_V7 | 392 | select CPU_CACHE_V7 |
393 | select CPU_CACHE_VIPT | 393 | select CPU_CACHE_VIPT |
394 | select CPU_COPY_V6 if MMU | 394 | select CPU_COPY_V6 if MMU |
395 | select CPU_CP15_MMU | 395 | select CPU_CP15_MMU if MMU |
396 | select CPU_CP15_MPU if !MMU | ||
396 | select CPU_HAS_ASID if MMU | 397 | select CPU_HAS_ASID if MMU |
397 | select CPU_PABRT_V7 | 398 | select CPU_PABRT_V7 |
398 | select CPU_TLB_V7 if MMU | 399 | select CPU_TLB_V7 if MMU |
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index ee558a01f390..ecfe6e53f6e0 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_MODULES) += proc-syms.o | |||
16 | 16 | ||
17 | obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o | 17 | obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o |
18 | obj-$(CONFIG_HIGHMEM) += highmem.o | 18 | obj-$(CONFIG_HIGHMEM) += highmem.o |
19 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | ||
19 | 20 | ||
20 | obj-$(CONFIG_CPU_ABRT_NOMMU) += abort-nommu.o | 21 | obj-$(CONFIG_CPU_ABRT_NOMMU) += abort-nommu.o |
21 | obj-$(CONFIG_CPU_ABRT_EV4) += abort-ev4.o | 22 | obj-$(CONFIG_CPU_ABRT_EV4) += abort-ev4.o |
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index c465faca51b0..d70e0aba0c9d 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -523,6 +523,147 @@ static void aurora_flush_range(unsigned long start, unsigned long end) | |||
523 | } | 523 | } |
524 | } | 524 | } |
525 | 525 | ||
526 | /* | ||
527 | * For certain Broadcom SoCs, depending on the address range, different offsets | ||
528 | * need to be added to the address before passing it to L2 for | ||
529 | * invalidation/clean/flush | ||
530 | * | ||
531 | * Section Address Range Offset EMI | ||
532 | * 1 0x00000000 - 0x3FFFFFFF 0x80000000 VC | ||
533 | * 2 0x40000000 - 0xBFFFFFFF 0x40000000 SYS | ||
534 | * 3 0xC0000000 - 0xFFFFFFFF 0x80000000 VC | ||
535 | * | ||
536 | * When the start and end addresses have crossed two different sections, we | ||
537 | * need to break the L2 operation into two, each within its own section. | ||
538 | * For example, if we need to invalidate addresses starts at 0xBFFF0000 and | ||
539 | * ends at 0xC0001000, we need do invalidate 1) 0xBFFF0000 - 0xBFFFFFFF and 2) | ||
540 | * 0xC0000000 - 0xC0001000 | ||
541 | * | ||
542 | * Note 1: | ||
543 | * By breaking a single L2 operation into two, we may potentially suffer some | ||
544 | * performance hit, but keep in mind the cross section case is very rare | ||
545 | * | ||
546 | * Note 2: | ||
547 | * We do not need to handle the case when the start address is in | ||
548 | * Section 1 and the end address is in Section 3, since it is not a valid use | ||
549 | * case | ||
550 | * | ||
551 | * Note 3: | ||
552 | * Section 1 in practical terms can no longer be used on rev A2. Because of | ||
553 | * that the code does not need to handle section 1 at all. | ||
554 | * | ||
555 | */ | ||
556 | #define BCM_SYS_EMI_START_ADDR 0x40000000UL | ||
557 | #define BCM_VC_EMI_SEC3_START_ADDR 0xC0000000UL | ||
558 | |||
559 | #define BCM_SYS_EMI_OFFSET 0x40000000UL | ||
560 | #define BCM_VC_EMI_OFFSET 0x80000000UL | ||
561 | |||
562 | static inline int bcm_addr_is_sys_emi(unsigned long addr) | ||
563 | { | ||
564 | return (addr >= BCM_SYS_EMI_START_ADDR) && | ||
565 | (addr < BCM_VC_EMI_SEC3_START_ADDR); | ||
566 | } | ||
567 | |||
568 | static inline unsigned long bcm_l2_phys_addr(unsigned long addr) | ||
569 | { | ||
570 | if (bcm_addr_is_sys_emi(addr)) | ||
571 | return addr + BCM_SYS_EMI_OFFSET; | ||
572 | else | ||
573 | return addr + BCM_VC_EMI_OFFSET; | ||
574 | } | ||
575 | |||
576 | static void bcm_inv_range(unsigned long start, unsigned long end) | ||
577 | { | ||
578 | unsigned long new_start, new_end; | ||
579 | |||
580 | BUG_ON(start < BCM_SYS_EMI_START_ADDR); | ||
581 | |||
582 | if (unlikely(end <= start)) | ||
583 | return; | ||
584 | |||
585 | new_start = bcm_l2_phys_addr(start); | ||
586 | new_end = bcm_l2_phys_addr(end); | ||
587 | |||
588 | /* normal case, no cross section between start and end */ | ||
589 | if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { | ||
590 | l2x0_inv_range(new_start, new_end); | ||
591 | return; | ||
592 | } | ||
593 | |||
594 | /* They cross sections, so it can only be a cross from section | ||
595 | * 2 to section 3 | ||
596 | */ | ||
597 | l2x0_inv_range(new_start, | ||
598 | bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); | ||
599 | l2x0_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), | ||
600 | new_end); | ||
601 | } | ||
602 | |||
603 | static void bcm_clean_range(unsigned long start, unsigned long end) | ||
604 | { | ||
605 | unsigned long new_start, new_end; | ||
606 | |||
607 | BUG_ON(start < BCM_SYS_EMI_START_ADDR); | ||
608 | |||
609 | if (unlikely(end <= start)) | ||
610 | return; | ||
611 | |||
612 | if ((end - start) >= l2x0_size) { | ||
613 | l2x0_clean_all(); | ||
614 | return; | ||
615 | } | ||
616 | |||
617 | new_start = bcm_l2_phys_addr(start); | ||
618 | new_end = bcm_l2_phys_addr(end); | ||
619 | |||
620 | /* normal case, no cross section between start and end */ | ||
621 | if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { | ||
622 | l2x0_clean_range(new_start, new_end); | ||
623 | return; | ||
624 | } | ||
625 | |||
626 | /* They cross sections, so it can only be a cross from section | ||
627 | * 2 to section 3 | ||
628 | */ | ||
629 | l2x0_clean_range(new_start, | ||
630 | bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); | ||
631 | l2x0_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), | ||
632 | new_end); | ||
633 | } | ||
634 | |||
635 | static void bcm_flush_range(unsigned long start, unsigned long end) | ||
636 | { | ||
637 | unsigned long new_start, new_end; | ||
638 | |||
639 | BUG_ON(start < BCM_SYS_EMI_START_ADDR); | ||
640 | |||
641 | if (unlikely(end <= start)) | ||
642 | return; | ||
643 | |||
644 | if ((end - start) >= l2x0_size) { | ||
645 | l2x0_flush_all(); | ||
646 | return; | ||
647 | } | ||
648 | |||
649 | new_start = bcm_l2_phys_addr(start); | ||
650 | new_end = bcm_l2_phys_addr(end); | ||
651 | |||
652 | /* normal case, no cross section between start and end */ | ||
653 | if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { | ||
654 | l2x0_flush_range(new_start, new_end); | ||
655 | return; | ||
656 | } | ||
657 | |||
658 | /* They cross sections, so it can only be a cross from section | ||
659 | * 2 to section 3 | ||
660 | */ | ||
661 | l2x0_flush_range(new_start, | ||
662 | bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); | ||
663 | l2x0_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), | ||
664 | new_end); | ||
665 | } | ||
666 | |||
526 | static void __init l2x0_of_setup(const struct device_node *np, | 667 | static void __init l2x0_of_setup(const struct device_node *np, |
527 | u32 *aux_val, u32 *aux_mask) | 668 | u32 *aux_val, u32 *aux_mask) |
528 | { | 669 | { |
@@ -765,6 +906,21 @@ static const struct l2x0_of_data aurora_no_outer_data = { | |||
765 | }, | 906 | }, |
766 | }; | 907 | }; |
767 | 908 | ||
909 | static const struct l2x0_of_data bcm_l2x0_data = { | ||
910 | .setup = pl310_of_setup, | ||
911 | .save = pl310_save, | ||
912 | .outer_cache = { | ||
913 | .resume = pl310_resume, | ||
914 | .inv_range = bcm_inv_range, | ||
915 | .clean_range = bcm_clean_range, | ||
916 | .flush_range = bcm_flush_range, | ||
917 | .sync = l2x0_cache_sync, | ||
918 | .flush_all = l2x0_flush_all, | ||
919 | .inv_all = l2x0_inv_all, | ||
920 | .disable = l2x0_disable, | ||
921 | }, | ||
922 | }; | ||
923 | |||
768 | static const struct of_device_id l2x0_ids[] __initconst = { | 924 | static const struct of_device_id l2x0_ids[] __initconst = { |
769 | { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, | 925 | { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, |
770 | { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, | 926 | { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, |
@@ -773,6 +929,8 @@ static const struct of_device_id l2x0_ids[] __initconst = { | |||
773 | .data = (void *)&aurora_no_outer_data}, | 929 | .data = (void *)&aurora_no_outer_data}, |
774 | { .compatible = "marvell,aurora-outer-cache", | 930 | { .compatible = "marvell,aurora-outer-cache", |
775 | .data = (void *)&aurora_with_outer_data}, | 931 | .data = (void *)&aurora_with_outer_data}, |
932 | { .compatible = "bcm,bcm11351-a2-pl310-cache", | ||
933 | .data = (void *)&bcm_l2x0_data}, | ||
776 | {} | 934 | {} |
777 | }; | 935 | }; |
778 | 936 | ||
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 2ac37372ef52..b55b1015724b 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/smp_plat.h> | 20 | #include <asm/smp_plat.h> |
21 | #include <asm/thread_notify.h> | 21 | #include <asm/thread_notify.h> |
22 | #include <asm/tlbflush.h> | 22 | #include <asm/tlbflush.h> |
23 | #include <asm/proc-fns.h> | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * On ARMv6, we have the following structure in the Context ID: | 26 | * On ARMv6, we have the following structure in the Context ID: |
@@ -39,33 +40,51 @@ | |||
39 | * non 64-bit operations. | 40 | * non 64-bit operations. |
40 | */ | 41 | */ |
41 | #define ASID_FIRST_VERSION (1ULL << ASID_BITS) | 42 | #define ASID_FIRST_VERSION (1ULL << ASID_BITS) |
42 | #define NUM_USER_ASIDS (ASID_FIRST_VERSION - 1) | 43 | #define NUM_USER_ASIDS ASID_FIRST_VERSION |
43 | |||
44 | #define ASID_TO_IDX(asid) ((asid & ~ASID_MASK) - 1) | ||
45 | #define IDX_TO_ASID(idx) ((idx + 1) & ~ASID_MASK) | ||
46 | 44 | ||
47 | static DEFINE_RAW_SPINLOCK(cpu_asid_lock); | 45 | static DEFINE_RAW_SPINLOCK(cpu_asid_lock); |
48 | static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION); | 46 | static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION); |
49 | static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS); | 47 | static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS); |
50 | 48 | ||
51 | DEFINE_PER_CPU(atomic64_t, active_asids); | 49 | static DEFINE_PER_CPU(atomic64_t, active_asids); |
52 | static DEFINE_PER_CPU(u64, reserved_asids); | 50 | static DEFINE_PER_CPU(u64, reserved_asids); |
53 | static cpumask_t tlb_flush_pending; | 51 | static cpumask_t tlb_flush_pending; |
54 | 52 | ||
53 | #ifdef CONFIG_ARM_ERRATA_798181 | ||
54 | void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm, | ||
55 | cpumask_t *mask) | ||
56 | { | ||
57 | int cpu; | ||
58 | unsigned long flags; | ||
59 | u64 context_id, asid; | ||
60 | |||
61 | raw_spin_lock_irqsave(&cpu_asid_lock, flags); | ||
62 | context_id = mm->context.id.counter; | ||
63 | for_each_online_cpu(cpu) { | ||
64 | if (cpu == this_cpu) | ||
65 | continue; | ||
66 | /* | ||
67 | * We only need to send an IPI if the other CPUs are | ||
68 | * running the same ASID as the one being invalidated. | ||
69 | */ | ||
70 | asid = per_cpu(active_asids, cpu).counter; | ||
71 | if (asid == 0) | ||
72 | asid = per_cpu(reserved_asids, cpu); | ||
73 | if (context_id == asid) | ||
74 | cpumask_set_cpu(cpu, mask); | ||
75 | } | ||
76 | raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); | ||
77 | } | ||
78 | #endif | ||
79 | |||
55 | #ifdef CONFIG_ARM_LPAE | 80 | #ifdef CONFIG_ARM_LPAE |
56 | static void cpu_set_reserved_ttbr0(void) | 81 | static void cpu_set_reserved_ttbr0(void) |
57 | { | 82 | { |
58 | unsigned long ttbl = __pa(swapper_pg_dir); | ||
59 | unsigned long ttbh = 0; | ||
60 | |||
61 | /* | 83 | /* |
62 | * Set TTBR0 to swapper_pg_dir which contains only global entries. The | 84 | * Set TTBR0 to swapper_pg_dir which contains only global entries. The |
63 | * ASID is set to 0. | 85 | * ASID is set to 0. |
64 | */ | 86 | */ |
65 | asm volatile( | 87 | cpu_set_ttbr(0, __pa(swapper_pg_dir)); |
66 | " mcrr p15, 0, %0, %1, c2 @ set TTBR0\n" | ||
67 | : | ||
68 | : "r" (ttbl), "r" (ttbh)); | ||
69 | isb(); | 88 | isb(); |
70 | } | 89 | } |
71 | #else | 90 | #else |
@@ -128,7 +147,16 @@ static void flush_context(unsigned int cpu) | |||
128 | asid = 0; | 147 | asid = 0; |
129 | } else { | 148 | } else { |
130 | asid = atomic64_xchg(&per_cpu(active_asids, i), 0); | 149 | asid = atomic64_xchg(&per_cpu(active_asids, i), 0); |
131 | __set_bit(ASID_TO_IDX(asid), asid_map); | 150 | /* |
151 | * If this CPU has already been through a | ||
152 | * rollover, but hasn't run another task in | ||
153 | * the meantime, we must preserve its reserved | ||
154 | * ASID, as this is the only trace we have of | ||
155 | * the process it is still running. | ||
156 | */ | ||
157 | if (asid == 0) | ||
158 | asid = per_cpu(reserved_asids, i); | ||
159 | __set_bit(asid & ~ASID_MASK, asid_map); | ||
132 | } | 160 | } |
133 | per_cpu(reserved_asids, i) = asid; | 161 | per_cpu(reserved_asids, i) = asid; |
134 | } | 162 | } |
@@ -167,17 +195,19 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) | |||
167 | /* | 195 | /* |
168 | * Allocate a free ASID. If we can't find one, take a | 196 | * Allocate a free ASID. If we can't find one, take a |
169 | * note of the currently active ASIDs and mark the TLBs | 197 | * note of the currently active ASIDs and mark the TLBs |
170 | * as requiring flushes. | 198 | * as requiring flushes. We always count from ASID #1, |
199 | * as we reserve ASID #0 to switch via TTBR0 and indicate | ||
200 | * rollover events. | ||
171 | */ | 201 | */ |
172 | asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS); | 202 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); |
173 | if (asid == NUM_USER_ASIDS) { | 203 | if (asid == NUM_USER_ASIDS) { |
174 | generation = atomic64_add_return(ASID_FIRST_VERSION, | 204 | generation = atomic64_add_return(ASID_FIRST_VERSION, |
175 | &asid_generation); | 205 | &asid_generation); |
176 | flush_context(cpu); | 206 | flush_context(cpu); |
177 | asid = find_first_zero_bit(asid_map, NUM_USER_ASIDS); | 207 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); |
178 | } | 208 | } |
179 | __set_bit(asid, asid_map); | 209 | __set_bit(asid, asid_map); |
180 | asid = generation | IDX_TO_ASID(asid); | 210 | asid |= generation; |
181 | cpumask_clear(mm_cpumask(mm)); | 211 | cpumask_clear(mm_cpumask(mm)); |
182 | } | 212 | } |
183 | 213 | ||
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index ef3e0f3aac96..7ec02961dfa0 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -250,7 +250,7 @@ static void __dma_free_buffer(struct page *page, size_t size) | |||
250 | 250 | ||
251 | #ifdef CONFIG_MMU | 251 | #ifdef CONFIG_MMU |
252 | #ifdef CONFIG_HUGETLB_PAGE | 252 | #ifdef CONFIG_HUGETLB_PAGE |
253 | #error ARM Coherent DMA allocator does not (yet) support huge TLB | 253 | #warning ARM Coherent DMA allocator does not (yet) support huge TLB |
254 | #endif | 254 | #endif |
255 | 255 | ||
256 | static void *__alloc_from_contiguous(struct device *dev, size_t size, | 256 | static void *__alloc_from_contiguous(struct device *dev, size_t size, |
@@ -880,10 +880,24 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off, | |||
880 | dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); | 880 | dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); |
881 | 881 | ||
882 | /* | 882 | /* |
883 | * Mark the D-cache clean for this page to avoid extra flushing. | 883 | * Mark the D-cache clean for these pages to avoid extra flushing. |
884 | */ | 884 | */ |
885 | if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE) | 885 | if (dir != DMA_TO_DEVICE && size >= PAGE_SIZE) { |
886 | set_bit(PG_dcache_clean, &page->flags); | 886 | unsigned long pfn; |
887 | size_t left = size; | ||
888 | |||
889 | pfn = page_to_pfn(page) + off / PAGE_SIZE; | ||
890 | off %= PAGE_SIZE; | ||
891 | if (off) { | ||
892 | pfn++; | ||
893 | left -= PAGE_SIZE - off; | ||
894 | } | ||
895 | while (left >= PAGE_SIZE) { | ||
896 | page = pfn_to_page(pfn++); | ||
897 | set_bit(PG_dcache_clean, &page->flags); | ||
898 | left -= PAGE_SIZE; | ||
899 | } | ||
900 | } | ||
887 | } | 901 | } |
888 | 902 | ||
889 | /** | 903 | /** |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 5dbf13f954f6..c97f7940cb95 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -491,12 +491,14 @@ do_translation_fault(unsigned long addr, unsigned int fsr, | |||
491 | * Some section permission faults need to be handled gracefully. | 491 | * Some section permission faults need to be handled gracefully. |
492 | * They can happen due to a __{get,put}_user during an oops. | 492 | * They can happen due to a __{get,put}_user during an oops. |
493 | */ | 493 | */ |
494 | #ifndef CONFIG_ARM_LPAE | ||
494 | static int | 495 | static int |
495 | do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | 496 | do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) |
496 | { | 497 | { |
497 | do_bad_area(addr, fsr, regs); | 498 | do_bad_area(addr, fsr, regs); |
498 | return 0; | 499 | return 0; |
499 | } | 500 | } |
501 | #endif /* CONFIG_ARM_LPAE */ | ||
500 | 502 | ||
501 | /* | 503 | /* |
502 | * This abort handler always returns "fault". | 504 | * This abort handler always returns "fault". |
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 32aa5861119f..6d5ba9afb16a 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/highmem.h> | 17 | #include <asm/highmem.h> |
18 | #include <asm/smp_plat.h> | 18 | #include <asm/smp_plat.h> |
19 | #include <asm/tlbflush.h> | 19 | #include <asm/tlbflush.h> |
20 | #include <linux/hugetlb.h> | ||
20 | 21 | ||
21 | #include "mm.h" | 22 | #include "mm.h" |
22 | 23 | ||
@@ -168,19 +169,23 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page) | |||
168 | * coherent with the kernels mapping. | 169 | * coherent with the kernels mapping. |
169 | */ | 170 | */ |
170 | if (!PageHighMem(page)) { | 171 | if (!PageHighMem(page)) { |
171 | __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); | 172 | size_t page_size = PAGE_SIZE << compound_order(page); |
173 | __cpuc_flush_dcache_area(page_address(page), page_size); | ||
172 | } else { | 174 | } else { |
173 | void *addr; | 175 | unsigned long i; |
174 | |||
175 | if (cache_is_vipt_nonaliasing()) { | 176 | if (cache_is_vipt_nonaliasing()) { |
176 | addr = kmap_atomic(page); | 177 | for (i = 0; i < (1 << compound_order(page)); i++) { |
177 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); | 178 | void *addr = kmap_atomic(page); |
178 | kunmap_atomic(addr); | ||
179 | } else { | ||
180 | addr = kmap_high_get(page); | ||
181 | if (addr) { | ||
182 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); | 179 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); |
183 | kunmap_high(page); | 180 | kunmap_atomic(addr); |
181 | } | ||
182 | } else { | ||
183 | for (i = 0; i < (1 << compound_order(page)); i++) { | ||
184 | void *addr = kmap_high_get(page); | ||
185 | if (addr) { | ||
186 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); | ||
187 | kunmap_high(page); | ||
188 | } | ||
184 | } | 189 | } |
185 | } | 190 | } |
186 | } | 191 | } |
@@ -287,7 +292,7 @@ void flush_dcache_page(struct page *page) | |||
287 | mapping = page_mapping(page); | 292 | mapping = page_mapping(page); |
288 | 293 | ||
289 | if (!cache_ops_need_broadcast() && | 294 | if (!cache_ops_need_broadcast() && |
290 | mapping && !mapping_mapped(mapping)) | 295 | mapping && !page_mapped(page)) |
291 | clear_bit(PG_dcache_clean, &page->flags); | 296 | clear_bit(PG_dcache_clean, &page->flags); |
292 | else { | 297 | else { |
293 | __flush_dcache_page(mapping, page); | 298 | __flush_dcache_page(mapping, page); |
diff --git a/arch/arm/mm/fsr-3level.c b/arch/arm/mm/fsr-3level.c index 05a4e9431836..ab4409a2307e 100644 --- a/arch/arm/mm/fsr-3level.c +++ b/arch/arm/mm/fsr-3level.c | |||
@@ -9,11 +9,11 @@ static struct fsr_info fsr_info[] = { | |||
9 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, | 9 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, |
10 | { do_bad, SIGBUS, 0, "reserved access flag fault" }, | 10 | { do_bad, SIGBUS, 0, "reserved access flag fault" }, |
11 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, | 11 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, |
12 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, | 12 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, |
13 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" }, | 13 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" }, |
14 | { do_bad, SIGBUS, 0, "reserved permission fault" }, | 14 | { do_bad, SIGBUS, 0, "reserved permission fault" }, |
15 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" }, | 15 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" }, |
16 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" }, | 16 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" }, |
17 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" }, | 17 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" }, |
18 | { do_bad, SIGBUS, 0, "synchronous external abort" }, | 18 | { do_bad, SIGBUS, 0, "synchronous external abort" }, |
19 | { do_bad, SIGBUS, 0, "asynchronous external abort" }, | 19 | { do_bad, SIGBUS, 0, "asynchronous external abort" }, |
diff --git a/arch/arm/mm/hugetlbpage.c b/arch/arm/mm/hugetlbpage.c new file mode 100644 index 000000000000..3d1e4a205b0b --- /dev/null +++ b/arch/arm/mm/hugetlbpage.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * arch/arm/mm/hugetlbpage.c | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * | ||
6 | * Based on arch/x86/include/asm/hugetlb.h and Bill Carson's patches | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/hugetlb.h> | ||
26 | #include <linux/pagemap.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/sysctl.h> | ||
29 | #include <asm/mman.h> | ||
30 | #include <asm/tlb.h> | ||
31 | #include <asm/tlbflush.h> | ||
32 | #include <asm/pgalloc.h> | ||
33 | |||
34 | /* | ||
35 | * On ARM, huge pages are backed by pmd's rather than pte's, so we do a lot | ||
36 | * of type casting from pmd_t * to pte_t *. | ||
37 | */ | ||
38 | |||
39 | pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) | ||
40 | { | ||
41 | pgd_t *pgd; | ||
42 | pud_t *pud; | ||
43 | pmd_t *pmd = NULL; | ||
44 | |||
45 | pgd = pgd_offset(mm, addr); | ||
46 | if (pgd_present(*pgd)) { | ||
47 | pud = pud_offset(pgd, addr); | ||
48 | if (pud_present(*pud)) | ||
49 | pmd = pmd_offset(pud, addr); | ||
50 | } | ||
51 | |||
52 | return (pte_t *)pmd; | ||
53 | } | ||
54 | |||
55 | struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, | ||
56 | int write) | ||
57 | { | ||
58 | return ERR_PTR(-EINVAL); | ||
59 | } | ||
60 | |||
61 | int pud_huge(pud_t pud) | ||
62 | { | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) | ||
67 | { | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | pte_t *huge_pte_alloc(struct mm_struct *mm, | ||
72 | unsigned long addr, unsigned long sz) | ||
73 | { | ||
74 | pgd_t *pgd; | ||
75 | pud_t *pud; | ||
76 | pte_t *pte = NULL; | ||
77 | |||
78 | pgd = pgd_offset(mm, addr); | ||
79 | pud = pud_alloc(mm, pgd, addr); | ||
80 | if (pud) | ||
81 | pte = (pte_t *)pmd_alloc(mm, pud, addr); | ||
82 | |||
83 | return pte; | ||
84 | } | ||
85 | |||
86 | struct page * | ||
87 | follow_huge_pmd(struct mm_struct *mm, unsigned long address, | ||
88 | pmd_t *pmd, int write) | ||
89 | { | ||
90 | struct page *page; | ||
91 | |||
92 | page = pte_page(*(pte_t *)pmd); | ||
93 | if (page) | ||
94 | page += ((address & ~PMD_MASK) >> PAGE_SHIFT); | ||
95 | return page; | ||
96 | } | ||
97 | |||
98 | int pmd_huge(pmd_t pmd) | ||
99 | { | ||
100 | return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT); | ||
101 | } | ||
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 9a5cdc01fcdf..2ffee02d1d5c 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -36,12 +36,13 @@ | |||
36 | 36 | ||
37 | #include "mm.h" | 37 | #include "mm.h" |
38 | 38 | ||
39 | static unsigned long phys_initrd_start __initdata = 0; | 39 | static phys_addr_t phys_initrd_start __initdata = 0; |
40 | static unsigned long phys_initrd_size __initdata = 0; | 40 | static unsigned long phys_initrd_size __initdata = 0; |
41 | 41 | ||
42 | static int __init early_initrd(char *p) | 42 | static int __init early_initrd(char *p) |
43 | { | 43 | { |
44 | unsigned long start, size; | 44 | phys_addr_t start; |
45 | unsigned long size; | ||
45 | char *endp; | 46 | char *endp; |
46 | 47 | ||
47 | start = memparse(p, &endp); | 48 | start = memparse(p, &endp); |
@@ -350,14 +351,14 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) | |||
350 | #ifdef CONFIG_BLK_DEV_INITRD | 351 | #ifdef CONFIG_BLK_DEV_INITRD |
351 | if (phys_initrd_size && | 352 | if (phys_initrd_size && |
352 | !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { | 353 | !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { |
353 | pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n", | 354 | pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n", |
354 | phys_initrd_start, phys_initrd_size); | 355 | (u64)phys_initrd_start, phys_initrd_size); |
355 | phys_initrd_start = phys_initrd_size = 0; | 356 | phys_initrd_start = phys_initrd_size = 0; |
356 | } | 357 | } |
357 | if (phys_initrd_size && | 358 | if (phys_initrd_size && |
358 | memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { | 359 | memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { |
359 | pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n", | 360 | pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n", |
360 | phys_initrd_start, phys_initrd_size); | 361 | (u64)phys_initrd_start, phys_initrd_size); |
361 | phys_initrd_start = phys_initrd_size = 0; | 362 | phys_initrd_start = phys_initrd_size = 0; |
362 | } | 363 | } |
363 | if (phys_initrd_size) { | 364 | if (phys_initrd_size) { |
@@ -442,7 +443,7 @@ static inline void | |||
442 | free_memmap(unsigned long start_pfn, unsigned long end_pfn) | 443 | free_memmap(unsigned long start_pfn, unsigned long end_pfn) |
443 | { | 444 | { |
444 | struct page *start_pg, *end_pg; | 445 | struct page *start_pg, *end_pg; |
445 | unsigned long pg, pgend; | 446 | phys_addr_t pg, pgend; |
446 | 447 | ||
447 | /* | 448 | /* |
448 | * Convert start_pfn/end_pfn to a struct page pointer. | 449 | * Convert start_pfn/end_pfn to a struct page pointer. |
@@ -454,8 +455,8 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn) | |||
454 | * Convert to physical addresses, and | 455 | * Convert to physical addresses, and |
455 | * round start upwards and end downwards. | 456 | * round start upwards and end downwards. |
456 | */ | 457 | */ |
457 | pg = (unsigned long)PAGE_ALIGN(__pa(start_pg)); | 458 | pg = PAGE_ALIGN(__pa(start_pg)); |
458 | pgend = (unsigned long)__pa(end_pg) & PAGE_MASK; | 459 | pgend = __pa(end_pg) & PAGE_MASK; |
459 | 460 | ||
460 | /* | 461 | /* |
461 | * If there are free pages between these, | 462 | * If there are free pages between these, |
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 04d9006eab1f..f123d6eb074b 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
@@ -331,10 +331,10 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, | |||
331 | return (void __iomem *) (offset + addr); | 331 | return (void __iomem *) (offset + addr); |
332 | } | 332 | } |
333 | 333 | ||
334 | void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size, | 334 | void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, |
335 | unsigned int mtype, void *caller) | 335 | unsigned int mtype, void *caller) |
336 | { | 336 | { |
337 | unsigned long last_addr; | 337 | phys_addr_t last_addr; |
338 | unsigned long offset = phys_addr & ~PAGE_MASK; | 338 | unsigned long offset = phys_addr & ~PAGE_MASK; |
339 | unsigned long pfn = __phys_to_pfn(phys_addr); | 339 | unsigned long pfn = __phys_to_pfn(phys_addr); |
340 | 340 | ||
@@ -367,12 +367,12 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, | |||
367 | } | 367 | } |
368 | EXPORT_SYMBOL(__arm_ioremap_pfn); | 368 | EXPORT_SYMBOL(__arm_ioremap_pfn); |
369 | 369 | ||
370 | void __iomem * (*arch_ioremap_caller)(unsigned long, size_t, | 370 | void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, |
371 | unsigned int, void *) = | 371 | unsigned int, void *) = |
372 | __arm_ioremap_caller; | 372 | __arm_ioremap_caller; |
373 | 373 | ||
374 | void __iomem * | 374 | void __iomem * |
375 | __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) | 375 | __arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype) |
376 | { | 376 | { |
377 | return arch_ioremap_caller(phys_addr, size, mtype, | 377 | return arch_ioremap_caller(phys_addr, size, mtype, |
378 | __builtin_return_address(0)); | 378 | __builtin_return_address(0)); |
@@ -387,7 +387,7 @@ EXPORT_SYMBOL(__arm_ioremap); | |||
387 | * CONFIG_GENERIC_ALLOCATOR for allocating external memory. | 387 | * CONFIG_GENERIC_ALLOCATOR for allocating external memory. |
388 | */ | 388 | */ |
389 | void __iomem * | 389 | void __iomem * |
390 | __arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached) | 390 | __arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached) |
391 | { | 391 | { |
392 | unsigned int mtype; | 392 | unsigned int mtype; |
393 | 393 | ||
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index d1d1cefa1f93..d7229d28c7f8 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -675,7 +675,8 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | |||
675 | } | 675 | } |
676 | 676 | ||
677 | static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, | 677 | static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, |
678 | unsigned long end, unsigned long phys, const struct mem_type *type) | 678 | unsigned long end, phys_addr_t phys, |
679 | const struct mem_type *type) | ||
679 | { | 680 | { |
680 | pud_t *pud = pud_offset(pgd, addr); | 681 | pud_t *pud = pud_offset(pgd, addr); |
681 | unsigned long next; | 682 | unsigned long next; |
@@ -989,27 +990,28 @@ phys_addr_t arm_lowmem_limit __initdata = 0; | |||
989 | void __init sanity_check_meminfo(void) | 990 | void __init sanity_check_meminfo(void) |
990 | { | 991 | { |
991 | int i, j, highmem = 0; | 992 | int i, j, highmem = 0; |
993 | phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; | ||
992 | 994 | ||
993 | for (i = 0, j = 0; i < meminfo.nr_banks; i++) { | 995 | for (i = 0, j = 0; i < meminfo.nr_banks; i++) { |
994 | struct membank *bank = &meminfo.bank[j]; | 996 | struct membank *bank = &meminfo.bank[j]; |
995 | *bank = meminfo.bank[i]; | 997 | phys_addr_t size_limit; |
996 | 998 | ||
997 | if (bank->start > ULONG_MAX) | 999 | *bank = meminfo.bank[i]; |
998 | highmem = 1; | 1000 | size_limit = bank->size; |
999 | 1001 | ||
1000 | #ifdef CONFIG_HIGHMEM | 1002 | if (bank->start >= vmalloc_limit) |
1001 | if (__va(bank->start) >= vmalloc_min || | ||
1002 | __va(bank->start) < (void *)PAGE_OFFSET) | ||
1003 | highmem = 1; | 1003 | highmem = 1; |
1004 | else | ||
1005 | size_limit = vmalloc_limit - bank->start; | ||
1004 | 1006 | ||
1005 | bank->highmem = highmem; | 1007 | bank->highmem = highmem; |
1006 | 1008 | ||
1009 | #ifdef CONFIG_HIGHMEM | ||
1007 | /* | 1010 | /* |
1008 | * Split those memory banks which are partially overlapping | 1011 | * Split those memory banks which are partially overlapping |
1009 | * the vmalloc area greatly simplifying things later. | 1012 | * the vmalloc area greatly simplifying things later. |
1010 | */ | 1013 | */ |
1011 | if (!highmem && __va(bank->start) < vmalloc_min && | 1014 | if (!highmem && bank->size > size_limit) { |
1012 | bank->size > vmalloc_min - __va(bank->start)) { | ||
1013 | if (meminfo.nr_banks >= NR_BANKS) { | 1015 | if (meminfo.nr_banks >= NR_BANKS) { |
1014 | printk(KERN_CRIT "NR_BANKS too low, " | 1016 | printk(KERN_CRIT "NR_BANKS too low, " |
1015 | "ignoring high memory\n"); | 1017 | "ignoring high memory\n"); |
@@ -1018,16 +1020,14 @@ void __init sanity_check_meminfo(void) | |||
1018 | (meminfo.nr_banks - i) * sizeof(*bank)); | 1020 | (meminfo.nr_banks - i) * sizeof(*bank)); |
1019 | meminfo.nr_banks++; | 1021 | meminfo.nr_banks++; |
1020 | i++; | 1022 | i++; |
1021 | bank[1].size -= vmalloc_min - __va(bank->start); | 1023 | bank[1].size -= size_limit; |
1022 | bank[1].start = __pa(vmalloc_min - 1) + 1; | 1024 | bank[1].start = vmalloc_limit; |
1023 | bank[1].highmem = highmem = 1; | 1025 | bank[1].highmem = highmem = 1; |
1024 | j++; | 1026 | j++; |
1025 | } | 1027 | } |
1026 | bank->size = vmalloc_min - __va(bank->start); | 1028 | bank->size = size_limit; |
1027 | } | 1029 | } |
1028 | #else | 1030 | #else |
1029 | bank->highmem = highmem; | ||
1030 | |||
1031 | /* | 1031 | /* |
1032 | * Highmem banks not allowed with !CONFIG_HIGHMEM. | 1032 | * Highmem banks not allowed with !CONFIG_HIGHMEM. |
1033 | */ | 1033 | */ |
@@ -1040,31 +1040,16 @@ void __init sanity_check_meminfo(void) | |||
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | /* | 1042 | /* |
1043 | * Check whether this memory bank would entirely overlap | ||
1044 | * the vmalloc area. | ||
1045 | */ | ||
1046 | if (__va(bank->start) >= vmalloc_min || | ||
1047 | __va(bank->start) < (void *)PAGE_OFFSET) { | ||
1048 | printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx " | ||
1049 | "(vmalloc region overlap).\n", | ||
1050 | (unsigned long long)bank->start, | ||
1051 | (unsigned long long)bank->start + bank->size - 1); | ||
1052 | continue; | ||
1053 | } | ||
1054 | |||
1055 | /* | ||
1056 | * Check whether this memory bank would partially overlap | 1043 | * Check whether this memory bank would partially overlap |
1057 | * the vmalloc area. | 1044 | * the vmalloc area. |
1058 | */ | 1045 | */ |
1059 | if (__va(bank->start + bank->size - 1) >= vmalloc_min || | 1046 | if (bank->size > size_limit) { |
1060 | __va(bank->start + bank->size - 1) <= __va(bank->start)) { | ||
1061 | unsigned long newsize = vmalloc_min - __va(bank->start); | ||
1062 | printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " | 1047 | printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " |
1063 | "to -%.8llx (vmalloc region overlap).\n", | 1048 | "to -%.8llx (vmalloc region overlap).\n", |
1064 | (unsigned long long)bank->start, | 1049 | (unsigned long long)bank->start, |
1065 | (unsigned long long)bank->start + bank->size - 1, | 1050 | (unsigned long long)bank->start + bank->size - 1, |
1066 | (unsigned long long)bank->start + newsize - 1); | 1051 | (unsigned long long)bank->start + size_limit - 1); |
1067 | bank->size = newsize; | 1052 | bank->size = size_limit; |
1068 | } | 1053 | } |
1069 | #endif | 1054 | #endif |
1070 | if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit) | 1055 | if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit) |
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 5a3aba614a40..1fa50100ab6a 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/pagemap.h> | 8 | #include <linux/pagemap.h> |
9 | #include <linux/io.h> | 9 | #include <linux/io.h> |
10 | #include <linux/memblock.h> | 10 | #include <linux/memblock.h> |
11 | #include <linux/kernel.h> | ||
11 | 12 | ||
12 | #include <asm/cacheflush.h> | 13 | #include <asm/cacheflush.h> |
13 | #include <asm/sections.h> | 14 | #include <asm/sections.h> |
@@ -15,9 +16,260 @@ | |||
15 | #include <asm/setup.h> | 16 | #include <asm/setup.h> |
16 | #include <asm/traps.h> | 17 | #include <asm/traps.h> |
17 | #include <asm/mach/arch.h> | 18 | #include <asm/mach/arch.h> |
19 | #include <asm/cputype.h> | ||
20 | #include <asm/mpu.h> | ||
18 | 21 | ||
19 | #include "mm.h" | 22 | #include "mm.h" |
20 | 23 | ||
24 | #ifdef CONFIG_ARM_MPU | ||
25 | struct mpu_rgn_info mpu_rgn_info; | ||
26 | |||
27 | /* Region number */ | ||
28 | static void rgnr_write(u32 v) | ||
29 | { | ||
30 | asm("mcr p15, 0, %0, c6, c2, 0" : : "r" (v)); | ||
31 | } | ||
32 | |||
33 | /* Data-side / unified region attributes */ | ||
34 | |||
35 | /* Region access control register */ | ||
36 | static void dracr_write(u32 v) | ||
37 | { | ||
38 | asm("mcr p15, 0, %0, c6, c1, 4" : : "r" (v)); | ||
39 | } | ||
40 | |||
41 | /* Region size register */ | ||
42 | static void drsr_write(u32 v) | ||
43 | { | ||
44 | asm("mcr p15, 0, %0, c6, c1, 2" : : "r" (v)); | ||
45 | } | ||
46 | |||
47 | /* Region base address register */ | ||
48 | static void drbar_write(u32 v) | ||
49 | { | ||
50 | asm("mcr p15, 0, %0, c6, c1, 0" : : "r" (v)); | ||
51 | } | ||
52 | |||
53 | static u32 drbar_read(void) | ||
54 | { | ||
55 | u32 v; | ||
56 | asm("mrc p15, 0, %0, c6, c1, 0" : "=r" (v)); | ||
57 | return v; | ||
58 | } | ||
59 | /* Optional instruction-side region attributes */ | ||
60 | |||
61 | /* I-side Region access control register */ | ||
62 | static void iracr_write(u32 v) | ||
63 | { | ||
64 | asm("mcr p15, 0, %0, c6, c1, 5" : : "r" (v)); | ||
65 | } | ||
66 | |||
67 | /* I-side Region size register */ | ||
68 | static void irsr_write(u32 v) | ||
69 | { | ||
70 | asm("mcr p15, 0, %0, c6, c1, 3" : : "r" (v)); | ||
71 | } | ||
72 | |||
73 | /* I-side Region base address register */ | ||
74 | static void irbar_write(u32 v) | ||
75 | { | ||
76 | asm("mcr p15, 0, %0, c6, c1, 1" : : "r" (v)); | ||
77 | } | ||
78 | |||
79 | static unsigned long irbar_read(void) | ||
80 | { | ||
81 | unsigned long v; | ||
82 | asm("mrc p15, 0, %0, c6, c1, 1" : "=r" (v)); | ||
83 | return v; | ||
84 | } | ||
85 | |||
86 | /* MPU initialisation functions */ | ||
87 | void __init sanity_check_meminfo_mpu(void) | ||
88 | { | ||
89 | int i; | ||
90 | struct membank *bank = meminfo.bank; | ||
91 | phys_addr_t phys_offset = PHYS_OFFSET; | ||
92 | phys_addr_t aligned_region_size, specified_mem_size, rounded_mem_size; | ||
93 | |||
94 | /* Initially only use memory continuous from PHYS_OFFSET */ | ||
95 | if (bank_phys_start(&bank[0]) != phys_offset) | ||
96 | panic("First memory bank must be contiguous from PHYS_OFFSET"); | ||
97 | |||
98 | /* Banks have already been sorted by start address */ | ||
99 | for (i = 1; i < meminfo.nr_banks; i++) { | ||
100 | if (bank[i].start <= bank_phys_end(&bank[0]) && | ||
101 | bank_phys_end(&bank[i]) > bank_phys_end(&bank[0])) { | ||
102 | bank[0].size = bank_phys_end(&bank[i]) - bank[0].start; | ||
103 | } else { | ||
104 | pr_notice("Ignoring RAM after 0x%.8lx. " | ||
105 | "First non-contiguous (ignored) bank start: 0x%.8lx\n", | ||
106 | (unsigned long)bank_phys_end(&bank[0]), | ||
107 | (unsigned long)bank_phys_start(&bank[i])); | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | /* All contiguous banks are now merged in to the first bank */ | ||
112 | meminfo.nr_banks = 1; | ||
113 | specified_mem_size = bank[0].size; | ||
114 | |||
115 | /* | ||
116 | * MPU has curious alignment requirements: Size must be power of 2, and | ||
117 | * region start must be aligned to the region size | ||
118 | */ | ||
119 | if (phys_offset != 0) | ||
120 | pr_info("PHYS_OFFSET != 0 => MPU Region size constrained by alignment requirements\n"); | ||
121 | |||
122 | /* | ||
123 | * Maximum aligned region might overflow phys_addr_t if phys_offset is | ||
124 | * 0. Hence we keep everything below 4G until we take the smaller of | ||
125 | * the aligned_region_size and rounded_mem_size, one of which is | ||
126 | * guaranteed to be smaller than the maximum physical address. | ||
127 | */ | ||
128 | aligned_region_size = (phys_offset - 1) ^ (phys_offset); | ||
129 | /* Find the max power-of-two sized region that fits inside our bank */ | ||
130 | rounded_mem_size = (1 << __fls(bank[0].size)) - 1; | ||
131 | |||
132 | /* The actual region size is the smaller of the two */ | ||
133 | aligned_region_size = aligned_region_size < rounded_mem_size | ||
134 | ? aligned_region_size + 1 | ||
135 | : rounded_mem_size + 1; | ||
136 | |||
137 | if (aligned_region_size != specified_mem_size) | ||
138 | pr_warn("Truncating memory from 0x%.8lx to 0x%.8lx (MPU region constraints)", | ||
139 | (unsigned long)specified_mem_size, | ||
140 | (unsigned long)aligned_region_size); | ||
141 | |||
142 | meminfo.bank[0].size = aligned_region_size; | ||
143 | pr_debug("MPU Region from 0x%.8lx size 0x%.8lx (end 0x%.8lx))\n", | ||
144 | (unsigned long)phys_offset, | ||
145 | (unsigned long)aligned_region_size, | ||
146 | (unsigned long)bank_phys_end(&bank[0])); | ||
147 | |||
148 | } | ||
149 | |||
150 | static int mpu_present(void) | ||
151 | { | ||
152 | return ((read_cpuid_ext(CPUID_EXT_MMFR0) & MMFR0_PMSA) == MMFR0_PMSAv7); | ||
153 | } | ||
154 | |||
155 | static int mpu_max_regions(void) | ||
156 | { | ||
157 | /* | ||
158 | * We don't support a different number of I/D side regions so if we | ||
159 | * have separate instruction and data memory maps then return | ||
160 | * whichever side has a smaller number of supported regions. | ||
161 | */ | ||
162 | u32 dregions, iregions, mpuir; | ||
163 | mpuir = read_cpuid(CPUID_MPUIR); | ||
164 | |||
165 | dregions = iregions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION; | ||
166 | |||
167 | /* Check for separate d-side and i-side memory maps */ | ||
168 | if (mpuir & MPUIR_nU) | ||
169 | iregions = (mpuir & MPUIR_IREGION_SZMASK) >> MPUIR_IREGION; | ||
170 | |||
171 | /* Use the smallest of the two maxima */ | ||
172 | return min(dregions, iregions); | ||
173 | } | ||
174 | |||
175 | static int mpu_iside_independent(void) | ||
176 | { | ||
177 | /* MPUIR.nU specifies whether there is *not* a unified memory map */ | ||
178 | return read_cpuid(CPUID_MPUIR) & MPUIR_nU; | ||
179 | } | ||
180 | |||
181 | static int mpu_min_region_order(void) | ||
182 | { | ||
183 | u32 drbar_result, irbar_result; | ||
184 | /* We've kept a region free for this probing */ | ||
185 | rgnr_write(MPU_PROBE_REGION); | ||
186 | isb(); | ||
187 | /* | ||
188 | * As per ARM ARM, write 0xFFFFFFFC to DRBAR to find the minimum | ||
189 | * region order | ||
190 | */ | ||
191 | drbar_write(0xFFFFFFFC); | ||
192 | drbar_result = irbar_result = drbar_read(); | ||
193 | drbar_write(0x0); | ||
194 | /* If the MPU is non-unified, we use the larger of the two minima*/ | ||
195 | if (mpu_iside_independent()) { | ||
196 | irbar_write(0xFFFFFFFC); | ||
197 | irbar_result = irbar_read(); | ||
198 | irbar_write(0x0); | ||
199 | } | ||
200 | isb(); /* Ensure that MPU region operations have completed */ | ||
201 | /* Return whichever result is larger */ | ||
202 | return __ffs(max(drbar_result, irbar_result)); | ||
203 | } | ||
204 | |||
205 | static int mpu_setup_region(unsigned int number, phys_addr_t start, | ||
206 | unsigned int size_order, unsigned int properties) | ||
207 | { | ||
208 | u32 size_data; | ||
209 | |||
210 | /* We kept a region free for probing resolution of MPU regions*/ | ||
211 | if (number > mpu_max_regions() || number == MPU_PROBE_REGION) | ||
212 | return -ENOENT; | ||
213 | |||
214 | if (size_order > 32) | ||
215 | return -ENOMEM; | ||
216 | |||
217 | if (size_order < mpu_min_region_order()) | ||
218 | return -ENOMEM; | ||
219 | |||
220 | /* Writing N to bits 5:1 (RSR_SZ) specifies region size 2^N+1 */ | ||
221 | size_data = ((size_order - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN; | ||
222 | |||
223 | dsb(); /* Ensure all previous data accesses occur with old mappings */ | ||
224 | rgnr_write(number); | ||
225 | isb(); | ||
226 | drbar_write(start); | ||
227 | dracr_write(properties); | ||
228 | isb(); /* Propagate properties before enabling region */ | ||
229 | drsr_write(size_data); | ||
230 | |||
231 | /* Check for independent I-side registers */ | ||
232 | if (mpu_iside_independent()) { | ||
233 | irbar_write(start); | ||
234 | iracr_write(properties); | ||
235 | isb(); | ||
236 | irsr_write(size_data); | ||
237 | } | ||
238 | isb(); | ||
239 | |||
240 | /* Store region info (we treat i/d side the same, so only store d) */ | ||
241 | mpu_rgn_info.rgns[number].dracr = properties; | ||
242 | mpu_rgn_info.rgns[number].drbar = start; | ||
243 | mpu_rgn_info.rgns[number].drsr = size_data; | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Set up default MPU regions, doing nothing if there is no MPU | ||
249 | */ | ||
250 | void __init mpu_setup(void) | ||
251 | { | ||
252 | int region_err; | ||
253 | if (!mpu_present()) | ||
254 | return; | ||
255 | |||
256 | region_err = mpu_setup_region(MPU_RAM_REGION, PHYS_OFFSET, | ||
257 | ilog2(meminfo.bank[0].size), | ||
258 | MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL); | ||
259 | if (region_err) { | ||
260 | panic("MPU region initialization failure! %d", region_err); | ||
261 | } else { | ||
262 | pr_info("Using ARMv7 PMSA Compliant MPU. " | ||
263 | "Region independence: %s, Max regions: %d\n", | ||
264 | mpu_iside_independent() ? "Yes" : "No", | ||
265 | mpu_max_regions()); | ||
266 | } | ||
267 | } | ||
268 | #else | ||
269 | static void sanity_check_meminfo_mpu(void) {} | ||
270 | static void __init mpu_setup(void) {} | ||
271 | #endif /* CONFIG_ARM_MPU */ | ||
272 | |||
21 | void __init arm_mm_memblock_reserve(void) | 273 | void __init arm_mm_memblock_reserve(void) |
22 | { | 274 | { |
23 | #ifndef CONFIG_CPU_V7M | 275 | #ifndef CONFIG_CPU_V7M |
@@ -37,7 +289,9 @@ void __init arm_mm_memblock_reserve(void) | |||
37 | 289 | ||
38 | void __init sanity_check_meminfo(void) | 290 | void __init sanity_check_meminfo(void) |
39 | { | 291 | { |
40 | phys_addr_t end = bank_phys_end(&meminfo.bank[meminfo.nr_banks - 1]); | 292 | phys_addr_t end; |
293 | sanity_check_meminfo_mpu(); | ||
294 | end = bank_phys_end(&meminfo.bank[meminfo.nr_banks - 1]); | ||
41 | high_memory = __va(end - 1) + 1; | 295 | high_memory = __va(end - 1) + 1; |
42 | } | 296 | } |
43 | 297 | ||
@@ -48,6 +302,7 @@ void __init sanity_check_meminfo(void) | |||
48 | void __init paging_init(struct machine_desc *mdesc) | 302 | void __init paging_init(struct machine_desc *mdesc) |
49 | { | 303 | { |
50 | early_trap_init((void *)CONFIG_VECTORS_BASE); | 304 | early_trap_init((void *)CONFIG_VECTORS_BASE); |
305 | mpu_setup(); | ||
51 | bootmem_init(); | 306 | bootmem_init(); |
52 | } | 307 | } |
53 | 308 | ||
@@ -94,16 +349,16 @@ void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, | |||
94 | return __arm_ioremap_pfn(pfn, offset, size, mtype); | 349 | return __arm_ioremap_pfn(pfn, offset, size, mtype); |
95 | } | 350 | } |
96 | 351 | ||
97 | void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, | 352 | void __iomem *__arm_ioremap(phys_addr_t phys_addr, size_t size, |
98 | unsigned int mtype) | 353 | unsigned int mtype) |
99 | { | 354 | { |
100 | return (void __iomem *)phys_addr; | 355 | return (void __iomem *)phys_addr; |
101 | } | 356 | } |
102 | EXPORT_SYMBOL(__arm_ioremap); | 357 | EXPORT_SYMBOL(__arm_ioremap); |
103 | 358 | ||
104 | void __iomem * (*arch_ioremap_caller)(unsigned long, size_t, unsigned int, void *); | 359 | void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); |
105 | 360 | ||
106 | void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size, | 361 | void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, |
107 | unsigned int mtype, void *caller) | 362 | unsigned int mtype, void *caller) |
108 | { | 363 | { |
109 | return __arm_ioremap(phys_addr, size, mtype); | 364 | return __arm_ioremap(phys_addr, size, mtype); |
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 919405e20b80..2d1ef87328a1 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S | |||
@@ -140,8 +140,10 @@ ENTRY(cpu_v6_set_pte_ext) | |||
140 | ENTRY(cpu_v6_do_suspend) | 140 | ENTRY(cpu_v6_do_suspend) |
141 | stmfd sp!, {r4 - r9, lr} | 141 | stmfd sp!, {r4 - r9, lr} |
142 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID | 142 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID |
143 | #ifdef CONFIG_MMU | ||
143 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID | 144 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID |
144 | mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1 | 145 | mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1 |
146 | #endif | ||
145 | mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register | 147 | mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register |
146 | mrc p15, 0, r8, c1, c0, 2 @ co-processor access control | 148 | mrc p15, 0, r8, c1, c0, 2 @ co-processor access control |
147 | mrc p15, 0, r9, c1, c0, 0 @ control register | 149 | mrc p15, 0, r9, c1, c0, 0 @ control register |
@@ -158,14 +160,16 @@ ENTRY(cpu_v6_do_resume) | |||
158 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID | 160 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID |
159 | ldmia r0, {r4 - r9} | 161 | ldmia r0, {r4 - r9} |
160 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID | 162 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID |
163 | #ifdef CONFIG_MMU | ||
161 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID | 164 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID |
162 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) | 165 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) |
163 | ALT_UP(orr r1, r1, #TTB_FLAGS_UP) | 166 | ALT_UP(orr r1, r1, #TTB_FLAGS_UP) |
164 | mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0 | 167 | mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0 |
165 | mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1 | 168 | mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1 |
169 | mcr p15, 0, ip, c2, c0, 2 @ TTB control register | ||
170 | #endif | ||
166 | mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register | 171 | mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register |
167 | mcr p15, 0, r8, c1, c0, 2 @ co-processor access control | 172 | mcr p15, 0, r8, c1, c0, 2 @ co-processor access control |
168 | mcr p15, 0, ip, c2, c0, 2 @ TTB control register | ||
169 | mcr p15, 0, ip, c7, c5, 4 @ ISB | 173 | mcr p15, 0, ip, c7, c5, 4 @ ISB |
170 | mov r0, r9 @ control register | 174 | mov r0, r9 @ control register |
171 | b cpu_resume_mmu | 175 | b cpu_resume_mmu |
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S index 363027e811d6..5ffe1956c6d9 100644 --- a/arch/arm/mm/proc-v7-3level.S +++ b/arch/arm/mm/proc-v7-3level.S | |||
@@ -39,6 +39,14 @@ | |||
39 | #define TTB_FLAGS_SMP (TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA) | 39 | #define TTB_FLAGS_SMP (TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA) |
40 | #define PMD_FLAGS_SMP (PMD_SECT_WBWA|PMD_SECT_S) | 40 | #define PMD_FLAGS_SMP (PMD_SECT_WBWA|PMD_SECT_S) |
41 | 41 | ||
42 | #ifndef __ARMEB__ | ||
43 | # define rpgdl r0 | ||
44 | # define rpgdh r1 | ||
45 | #else | ||
46 | # define rpgdl r1 | ||
47 | # define rpgdh r0 | ||
48 | #endif | ||
49 | |||
42 | /* | 50 | /* |
43 | * cpu_v7_switch_mm(pgd_phys, tsk) | 51 | * cpu_v7_switch_mm(pgd_phys, tsk) |
44 | * | 52 | * |
@@ -47,10 +55,10 @@ | |||
47 | */ | 55 | */ |
48 | ENTRY(cpu_v7_switch_mm) | 56 | ENTRY(cpu_v7_switch_mm) |
49 | #ifdef CONFIG_MMU | 57 | #ifdef CONFIG_MMU |
50 | mmid r1, r1 @ get mm->context.id | 58 | mmid r2, r2 |
51 | asid r3, r1 | 59 | asid r2, r2 |
52 | mov r3, r3, lsl #(48 - 32) @ ASID | 60 | orr rpgdh, rpgdh, r2, lsl #(48 - 32) @ upper 32-bits of pgd |
53 | mcrr p15, 0, r0, r3, c2 @ set TTB 0 | 61 | mcrr p15, 0, rpgdl, rpgdh, c2 @ set TTB 0 |
54 | isb | 62 | isb |
55 | #endif | 63 | #endif |
56 | mov pc, lr | 64 | mov pc, lr |
@@ -106,7 +114,8 @@ ENDPROC(cpu_v7_set_pte_ext) | |||
106 | */ | 114 | */ |
107 | .macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp | 115 | .macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp |
108 | ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address | 116 | ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address |
109 | cmp \ttbr1, \tmp @ PHYS_OFFSET > PAGE_OFFSET? (branch below) | 117 | mov \tmp, \tmp, lsr #ARCH_PGD_SHIFT |
118 | cmp \ttbr1, \tmp @ PHYS_OFFSET > PAGE_OFFSET? | ||
110 | mrc p15, 0, \tmp, c2, c0, 2 @ TTB control register | 119 | mrc p15, 0, \tmp, c2, c0, 2 @ TTB control register |
111 | orr \tmp, \tmp, #TTB_EAE | 120 | orr \tmp, \tmp, #TTB_EAE |
112 | ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP) | 121 | ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP) |
@@ -114,27 +123,21 @@ ENDPROC(cpu_v7_set_pte_ext) | |||
114 | ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP << 16) | 123 | ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP << 16) |
115 | ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP << 16) | 124 | ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP << 16) |
116 | /* | 125 | /* |
117 | * TTBR0/TTBR1 split (PAGE_OFFSET): | 126 | * Only use split TTBRs if PHYS_OFFSET <= PAGE_OFFSET (cmp above), |
118 | * 0x40000000: T0SZ = 2, T1SZ = 0 (not used) | 127 | * otherwise booting secondary CPUs would end up using TTBR1 for the |
119 | * 0x80000000: T0SZ = 0, T1SZ = 1 | 128 | * identity mapping set up in TTBR0. |
120 | * 0xc0000000: T0SZ = 0, T1SZ = 2 | ||
121 | * | ||
122 | * Only use this feature if PHYS_OFFSET <= PAGE_OFFSET, otherwise | ||
123 | * booting secondary CPUs would end up using TTBR1 for the identity | ||
124 | * mapping set up in TTBR0. | ||
125 | */ | 129 | */ |
126 | bhi 9001f @ PHYS_OFFSET > PAGE_OFFSET? | 130 | orrls \tmp, \tmp, #TTBR1_SIZE @ TTBCR.T1SZ |
127 | orr \tmp, \tmp, #(((PAGE_OFFSET >> 30) - 1) << 16) @ TTBCR.T1SZ | 131 | mcr p15, 0, \tmp, c2, c0, 2 @ TTBCR |
128 | #if defined CONFIG_VMSPLIT_2G | 132 | mov \tmp, \ttbr1, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits |
129 | /* PAGE_OFFSET == 0x80000000, T1SZ == 1 */ | 133 | mov \ttbr1, \ttbr1, lsl #ARCH_PGD_SHIFT @ lower bits |
130 | add \ttbr1, \ttbr1, #1 << 4 @ skip two L1 entries | 134 | addls \ttbr1, \ttbr1, #TTBR1_OFFSET |
131 | #elif defined CONFIG_VMSPLIT_3G | 135 | mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1 |
132 | /* PAGE_OFFSET == 0xc0000000, T1SZ == 2 */ | 136 | mov \tmp, \ttbr0, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits |
133 | add \ttbr1, \ttbr1, #4096 * (1 + 3) @ only L2 used, skip pgd+3*pmd | 137 | mov \ttbr0, \ttbr0, lsl #ARCH_PGD_SHIFT @ lower bits |
134 | #endif | 138 | mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0 |
135 | /* CONFIG_VMSPLIT_1G does not need TTBR1 adjustment */ | 139 | mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1 |
136 | 9001: mcr p15, 0, \tmp, c2, c0, 2 @ TTB control register | 140 | mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0 |
137 | mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1 | ||
138 | .endm | 141 | .endm |
139 | 142 | ||
140 | __CPUINIT | 143 | __CPUINIT |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index e35fec34453e..7ef3ad05df39 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -98,9 +98,11 @@ ENTRY(cpu_v7_do_suspend) | |||
98 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID | 98 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID |
99 | mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID | 99 | mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID |
100 | stmia r0!, {r4 - r5} | 100 | stmia r0!, {r4 - r5} |
101 | #ifdef CONFIG_MMU | ||
101 | mrc p15, 0, r6, c3, c0, 0 @ Domain ID | 102 | mrc p15, 0, r6, c3, c0, 0 @ Domain ID |
102 | mrc p15, 0, r7, c2, c0, 1 @ TTB 1 | 103 | mrc p15, 0, r7, c2, c0, 1 @ TTB 1 |
103 | mrc p15, 0, r11, c2, c0, 2 @ TTB control register | 104 | mrc p15, 0, r11, c2, c0, 2 @ TTB control register |
105 | #endif | ||
104 | mrc p15, 0, r8, c1, c0, 0 @ Control register | 106 | mrc p15, 0, r8, c1, c0, 0 @ Control register |
105 | mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register | 107 | mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register |
106 | mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control | 108 | mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control |
@@ -110,13 +112,14 @@ ENDPROC(cpu_v7_do_suspend) | |||
110 | 112 | ||
111 | ENTRY(cpu_v7_do_resume) | 113 | ENTRY(cpu_v7_do_resume) |
112 | mov ip, #0 | 114 | mov ip, #0 |
113 | mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs | ||
114 | mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache | 115 | mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache |
115 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID | 116 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID |
116 | ldmia r0!, {r4 - r5} | 117 | ldmia r0!, {r4 - r5} |
117 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID | 118 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID |
118 | mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID | 119 | mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID |
119 | ldmia r0, {r6 - r11} | 120 | ldmia r0, {r6 - r11} |
121 | #ifdef CONFIG_MMU | ||
122 | mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs | ||
120 | mcr p15, 0, r6, c3, c0, 0 @ Domain ID | 123 | mcr p15, 0, r6, c3, c0, 0 @ Domain ID |
121 | #ifndef CONFIG_ARM_LPAE | 124 | #ifndef CONFIG_ARM_LPAE |
122 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) | 125 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) |
@@ -125,14 +128,15 @@ ENTRY(cpu_v7_do_resume) | |||
125 | mcr p15, 0, r1, c2, c0, 0 @ TTB 0 | 128 | mcr p15, 0, r1, c2, c0, 0 @ TTB 0 |
126 | mcr p15, 0, r7, c2, c0, 1 @ TTB 1 | 129 | mcr p15, 0, r7, c2, c0, 1 @ TTB 1 |
127 | mcr p15, 0, r11, c2, c0, 2 @ TTB control register | 130 | mcr p15, 0, r11, c2, c0, 2 @ TTB control register |
128 | mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register | ||
129 | teq r4, r9 @ Is it already set? | ||
130 | mcrne p15, 0, r9, c1, c0, 1 @ No, so write it | ||
131 | mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control | ||
132 | ldr r4, =PRRR @ PRRR | 131 | ldr r4, =PRRR @ PRRR |
133 | ldr r5, =NMRR @ NMRR | 132 | ldr r5, =NMRR @ NMRR |
134 | mcr p15, 0, r4, c10, c2, 0 @ write PRRR | 133 | mcr p15, 0, r4, c10, c2, 0 @ write PRRR |
135 | mcr p15, 0, r5, c10, c2, 1 @ write NMRR | 134 | mcr p15, 0, r5, c10, c2, 1 @ write NMRR |
135 | #endif /* CONFIG_MMU */ | ||
136 | mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register | ||
137 | teq r4, r9 @ Is it already set? | ||
138 | mcrne p15, 0, r9, c1, c0, 1 @ No, so write it | ||
139 | mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control | ||
136 | isb | 140 | isb |
137 | dsb | 141 | dsb |
138 | mov r0, r8 @ control register | 142 | mov r0, r8 @ control register |
@@ -178,7 +182,8 @@ ENDPROC(cpu_pj4b_do_idle) | |||
178 | */ | 182 | */ |
179 | __v7_ca5mp_setup: | 183 | __v7_ca5mp_setup: |
180 | __v7_ca9mp_setup: | 184 | __v7_ca9mp_setup: |
181 | mov r10, #(1 << 0) @ TLB ops broadcasting | 185 | __v7_cr7mp_setup: |
186 | mov r10, #(1 << 0) @ Cache/TLB ops broadcasting | ||
182 | b 1f | 187 | b 1f |
183 | __v7_ca7mp_setup: | 188 | __v7_ca7mp_setup: |
184 | __v7_ca15mp_setup: | 189 | __v7_ca15mp_setup: |
@@ -443,6 +448,16 @@ __v7_pj4b_proc_info: | |||
443 | #endif | 448 | #endif |
444 | 449 | ||
445 | /* | 450 | /* |
451 | * ARM Ltd. Cortex R7 processor. | ||
452 | */ | ||
453 | .type __v7_cr7mp_proc_info, #object | ||
454 | __v7_cr7mp_proc_info: | ||
455 | .long 0x410fc170 | ||
456 | .long 0xff0ffff0 | ||
457 | __v7_proc __v7_cr7mp_setup | ||
458 | .size __v7_cr7mp_proc_info, . - __v7_cr7mp_proc_info | ||
459 | |||
460 | /* | ||
446 | * ARM Ltd. Cortex A7 processor. | 461 | * ARM Ltd. Cortex A7 processor. |
447 | */ | 462 | */ |
448 | .type __v7_ca7mp_proc_info, #object | 463 | .type __v7_ca7mp_proc_info, #object |
diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S index b178d44e9eaa..2677bc3762d7 100644 --- a/arch/arm/plat-versatile/headsmp.S +++ b/arch/arm/plat-versatile/headsmp.S | |||
@@ -11,8 +11,6 @@ | |||
11 | #include <linux/linkage.h> | 11 | #include <linux/linkage.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | 13 | ||
14 | __INIT | ||
15 | |||
16 | /* | 14 | /* |
17 | * Realview/Versatile Express specific entry point for secondary CPUs. | 15 | * Realview/Versatile Express specific entry point for secondary CPUs. |
18 | * This provides a "holding pen" into which all secondary cores are held | 16 | * This provides a "holding pen" into which all secondary cores are held |
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index bf6ab242f047..d56ed11ba9a3 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h | |||
@@ -110,16 +110,6 @@ static inline void __cpuinit arch_counter_set_user_access(void) | |||
110 | asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); | 110 | asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); |
111 | } | 111 | } |
112 | 112 | ||
113 | static inline u64 arch_counter_get_cntpct(void) | ||
114 | { | ||
115 | u64 cval; | ||
116 | |||
117 | isb(); | ||
118 | asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); | ||
119 | |||
120 | return cval; | ||
121 | } | ||
122 | |||
123 | static inline u64 arch_counter_get_cntvct(void) | 113 | static inline u64 arch_counter_get_cntvct(void) |
124 | { | 114 | { |
125 | u64 cval; | 115 | u64 cval; |
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index a2b254189782..053d846ab5b1 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -186,27 +186,19 @@ u32 arch_timer_get_rate(void) | |||
186 | return arch_timer_rate; | 186 | return arch_timer_rate; |
187 | } | 187 | } |
188 | 188 | ||
189 | /* | 189 | u64 arch_timer_read_counter(void) |
190 | * Some external users of arch_timer_read_counter (e.g. sched_clock) may try to | ||
191 | * call it before it has been initialised. Rather than incur a performance | ||
192 | * penalty checking for initialisation, provide a default implementation that | ||
193 | * won't lead to time appearing to jump backwards. | ||
194 | */ | ||
195 | static u64 arch_timer_read_zero(void) | ||
196 | { | 190 | { |
197 | return 0; | 191 | return arch_counter_get_cntvct(); |
198 | } | 192 | } |
199 | 193 | ||
200 | u64 (*arch_timer_read_counter)(void) = arch_timer_read_zero; | ||
201 | |||
202 | static cycle_t arch_counter_read(struct clocksource *cs) | 194 | static cycle_t arch_counter_read(struct clocksource *cs) |
203 | { | 195 | { |
204 | return arch_timer_read_counter(); | 196 | return arch_counter_get_cntvct(); |
205 | } | 197 | } |
206 | 198 | ||
207 | static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) | 199 | static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) |
208 | { | 200 | { |
209 | return arch_timer_read_counter(); | 201 | return arch_counter_get_cntvct(); |
210 | } | 202 | } |
211 | 203 | ||
212 | static struct clocksource clocksource_counter = { | 204 | static struct clocksource clocksource_counter = { |
@@ -287,7 +279,7 @@ static int __init arch_timer_register(void) | |||
287 | cyclecounter.mult = clocksource_counter.mult; | 279 | cyclecounter.mult = clocksource_counter.mult; |
288 | cyclecounter.shift = clocksource_counter.shift; | 280 | cyclecounter.shift = clocksource_counter.shift; |
289 | timecounter_init(&timecounter, &cyclecounter, | 281 | timecounter_init(&timecounter, &cyclecounter, |
290 | arch_counter_get_cntpct()); | 282 | arch_counter_get_cntvct()); |
291 | 283 | ||
292 | if (arch_timer_use_virtual) { | 284 | if (arch_timer_use_virtual) { |
293 | ppi = arch_timer_ppi[VIRT_PPI]; | 285 | ppi = arch_timer_ppi[VIRT_PPI]; |
@@ -376,11 +368,6 @@ static void __init arch_timer_init(struct device_node *np) | |||
376 | } | 368 | } |
377 | } | 369 | } |
378 | 370 | ||
379 | if (arch_timer_use_virtual) | ||
380 | arch_timer_read_counter = arch_counter_get_cntvct; | ||
381 | else | ||
382 | arch_timer_read_counter = arch_counter_get_cntpct; | ||
383 | |||
384 | arch_timer_register(); | 371 | arch_timer_register(); |
385 | arch_timer_arch_init(); | 372 | arch_timer_arch_init(); |
386 | } | 373 | } |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index f4f3038c1df0..c3785edc0e92 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -61,6 +61,7 @@ static unsigned int fmax = 515633; | |||
61 | * @pwrreg_powerup: power up value for MMCIPOWER register | 61 | * @pwrreg_powerup: power up value for MMCIPOWER register |
62 | * @signal_direction: input/out direction of bus signals can be indicated | 62 | * @signal_direction: input/out direction of bus signals can be indicated |
63 | * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock | 63 | * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock |
64 | * @busy_detect: true if busy detection on dat0 is supported | ||
64 | */ | 65 | */ |
65 | struct variant_data { | 66 | struct variant_data { |
66 | unsigned int clkreg; | 67 | unsigned int clkreg; |
@@ -74,6 +75,7 @@ struct variant_data { | |||
74 | u32 pwrreg_powerup; | 75 | u32 pwrreg_powerup; |
75 | bool signal_direction; | 76 | bool signal_direction; |
76 | bool pwrreg_clkgate; | 77 | bool pwrreg_clkgate; |
78 | bool busy_detect; | ||
77 | }; | 79 | }; |
78 | 80 | ||
79 | static struct variant_data variant_arm = { | 81 | static struct variant_data variant_arm = { |
@@ -132,6 +134,7 @@ static struct variant_data variant_ux500 = { | |||
132 | .pwrreg_powerup = MCI_PWR_ON, | 134 | .pwrreg_powerup = MCI_PWR_ON, |
133 | .signal_direction = true, | 135 | .signal_direction = true, |
134 | .pwrreg_clkgate = true, | 136 | .pwrreg_clkgate = true, |
137 | .busy_detect = true, | ||
135 | }; | 138 | }; |
136 | 139 | ||
137 | static struct variant_data variant_ux500v2 = { | 140 | static struct variant_data variant_ux500v2 = { |
@@ -146,8 +149,28 @@ static struct variant_data variant_ux500v2 = { | |||
146 | .pwrreg_powerup = MCI_PWR_ON, | 149 | .pwrreg_powerup = MCI_PWR_ON, |
147 | .signal_direction = true, | 150 | .signal_direction = true, |
148 | .pwrreg_clkgate = true, | 151 | .pwrreg_clkgate = true, |
152 | .busy_detect = true, | ||
149 | }; | 153 | }; |
150 | 154 | ||
155 | static int mmci_card_busy(struct mmc_host *mmc) | ||
156 | { | ||
157 | struct mmci_host *host = mmc_priv(mmc); | ||
158 | unsigned long flags; | ||
159 | int busy = 0; | ||
160 | |||
161 | pm_runtime_get_sync(mmc_dev(mmc)); | ||
162 | |||
163 | spin_lock_irqsave(&host->lock, flags); | ||
164 | if (readl(host->base + MMCISTATUS) & MCI_ST_CARDBUSY) | ||
165 | busy = 1; | ||
166 | spin_unlock_irqrestore(&host->lock, flags); | ||
167 | |||
168 | pm_runtime_mark_last_busy(mmc_dev(mmc)); | ||
169 | pm_runtime_put_autosuspend(mmc_dev(mmc)); | ||
170 | |||
171 | return busy; | ||
172 | } | ||
173 | |||
151 | /* | 174 | /* |
152 | * Validate mmc prerequisites | 175 | * Validate mmc prerequisites |
153 | */ | 176 | */ |
@@ -191,11 +214,28 @@ static void mmci_write_pwrreg(struct mmci_host *host, u32 pwr) | |||
191 | /* | 214 | /* |
192 | * This must be called with host->lock held | 215 | * This must be called with host->lock held |
193 | */ | 216 | */ |
217 | static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl) | ||
218 | { | ||
219 | /* Keep ST Micro busy mode if enabled */ | ||
220 | datactrl |= host->datactrl_reg & MCI_ST_DPSM_BUSYMODE; | ||
221 | |||
222 | if (host->datactrl_reg != datactrl) { | ||
223 | host->datactrl_reg = datactrl; | ||
224 | writel(datactrl, host->base + MMCIDATACTRL); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * This must be called with host->lock held | ||
230 | */ | ||
194 | static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | 231 | static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) |
195 | { | 232 | { |
196 | struct variant_data *variant = host->variant; | 233 | struct variant_data *variant = host->variant; |
197 | u32 clk = variant->clkreg; | 234 | u32 clk = variant->clkreg; |
198 | 235 | ||
236 | /* Make sure cclk reflects the current calculated clock */ | ||
237 | host->cclk = 0; | ||
238 | |||
199 | if (desired) { | 239 | if (desired) { |
200 | if (desired >= host->mclk) { | 240 | if (desired >= host->mclk) { |
201 | clk = MCI_CLK_BYPASS; | 241 | clk = MCI_CLK_BYPASS; |
@@ -230,6 +270,9 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | |||
230 | /* clk |= MCI_CLK_PWRSAVE; */ | 270 | /* clk |= MCI_CLK_PWRSAVE; */ |
231 | } | 271 | } |
232 | 272 | ||
273 | /* Set actual clock for debug */ | ||
274 | host->mmc->actual_clock = host->cclk; | ||
275 | |||
233 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) | 276 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) |
234 | clk |= MCI_4BIT_BUS; | 277 | clk |= MCI_4BIT_BUS; |
235 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) | 278 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) |
@@ -275,7 +318,7 @@ static void mmci_set_mask1(struct mmci_host *host, unsigned int mask) | |||
275 | 318 | ||
276 | static void mmci_stop_data(struct mmci_host *host) | 319 | static void mmci_stop_data(struct mmci_host *host) |
277 | { | 320 | { |
278 | writel(0, host->base + MMCIDATACTRL); | 321 | mmci_write_datactrlreg(host, 0); |
279 | mmci_set_mask1(host, 0); | 322 | mmci_set_mask1(host, 0); |
280 | host->data = NULL; | 323 | host->data = NULL; |
281 | } | 324 | } |
@@ -304,10 +347,8 @@ static void mmci_dma_setup(struct mmci_host *host) | |||
304 | const char *rxname, *txname; | 347 | const char *rxname, *txname; |
305 | dma_cap_mask_t mask; | 348 | dma_cap_mask_t mask; |
306 | 349 | ||
307 | if (!plat || !plat->dma_filter) { | 350 | host->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc), "rx"); |
308 | dev_info(mmc_dev(host->mmc), "no DMA platform data\n"); | 351 | host->dma_tx_channel = dma_request_slave_channel(mmc_dev(host->mmc), "tx"); |
309 | return; | ||
310 | } | ||
311 | 352 | ||
312 | /* initialize pre request cookie */ | 353 | /* initialize pre request cookie */ |
313 | host->next_data.cookie = 1; | 354 | host->next_data.cookie = 1; |
@@ -316,30 +357,33 @@ static void mmci_dma_setup(struct mmci_host *host) | |||
316 | dma_cap_zero(mask); | 357 | dma_cap_zero(mask); |
317 | dma_cap_set(DMA_SLAVE, mask); | 358 | dma_cap_set(DMA_SLAVE, mask); |
318 | 359 | ||
319 | /* | 360 | if (plat && plat->dma_filter) { |
320 | * If only an RX channel is specified, the driver will | 361 | if (!host->dma_rx_channel && plat->dma_rx_param) { |
321 | * attempt to use it bidirectionally, however if it is | 362 | host->dma_rx_channel = dma_request_channel(mask, |
322 | * is specified but cannot be located, DMA will be disabled. | ||
323 | */ | ||
324 | if (plat->dma_rx_param) { | ||
325 | host->dma_rx_channel = dma_request_channel(mask, | ||
326 | plat->dma_filter, | 363 | plat->dma_filter, |
327 | plat->dma_rx_param); | 364 | plat->dma_rx_param); |
328 | /* E.g if no DMA hardware is present */ | 365 | /* E.g if no DMA hardware is present */ |
329 | if (!host->dma_rx_channel) | 366 | if (!host->dma_rx_channel) |
330 | dev_err(mmc_dev(host->mmc), "no RX DMA channel\n"); | 367 | dev_err(mmc_dev(host->mmc), "no RX DMA channel\n"); |
331 | } | 368 | } |
332 | 369 | ||
333 | if (plat->dma_tx_param) { | 370 | if (!host->dma_tx_channel && plat->dma_tx_param) { |
334 | host->dma_tx_channel = dma_request_channel(mask, | 371 | host->dma_tx_channel = dma_request_channel(mask, |
335 | plat->dma_filter, | 372 | plat->dma_filter, |
336 | plat->dma_tx_param); | 373 | plat->dma_tx_param); |
337 | if (!host->dma_tx_channel) | 374 | if (!host->dma_tx_channel) |
338 | dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n"); | 375 | dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n"); |
339 | } else { | 376 | } |
340 | host->dma_tx_channel = host->dma_rx_channel; | ||
341 | } | 377 | } |
342 | 378 | ||
379 | /* | ||
380 | * If only an RX channel is specified, the driver will | ||
381 | * attempt to use it bidirectionally, however if it is | ||
382 | * is specified but cannot be located, DMA will be disabled. | ||
383 | */ | ||
384 | if (host->dma_rx_channel && !host->dma_tx_channel) | ||
385 | host->dma_tx_channel = host->dma_rx_channel; | ||
386 | |||
343 | if (host->dma_rx_channel) | 387 | if (host->dma_rx_channel) |
344 | rxname = dma_chan_name(host->dma_rx_channel); | 388 | rxname = dma_chan_name(host->dma_rx_channel); |
345 | else | 389 | else |
@@ -552,7 +596,7 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) | |||
552 | datactrl |= MCI_DPSM_DMAENABLE; | 596 | datactrl |= MCI_DPSM_DMAENABLE; |
553 | 597 | ||
554 | /* Trigger the DMA transfer */ | 598 | /* Trigger the DMA transfer */ |
555 | writel(datactrl, host->base + MMCIDATACTRL); | 599 | mmci_write_datactrlreg(host, datactrl); |
556 | 600 | ||
557 | /* | 601 | /* |
558 | * Let the MMCI say when the data is ended and it's time | 602 | * Let the MMCI say when the data is ended and it's time |
@@ -750,7 +794,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
750 | irqmask = MCI_TXFIFOHALFEMPTYMASK; | 794 | irqmask = MCI_TXFIFOHALFEMPTYMASK; |
751 | } | 795 | } |
752 | 796 | ||
753 | writel(datactrl, base + MMCIDATACTRL); | 797 | mmci_write_datactrlreg(host, datactrl); |
754 | writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); | 798 | writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); |
755 | mmci_set_mask1(host, irqmask); | 799 | mmci_set_mask1(host, irqmask); |
756 | } | 800 | } |
@@ -842,7 +886,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | |||
842 | /* The error clause is handled above, success! */ | 886 | /* The error clause is handled above, success! */ |
843 | data->bytes_xfered = data->blksz * data->blocks; | 887 | data->bytes_xfered = data->blksz * data->blocks; |
844 | 888 | ||
845 | if (!data->stop) { | 889 | if (!data->stop || host->mrq->sbc) { |
846 | mmci_request_end(host, data->mrq); | 890 | mmci_request_end(host, data->mrq); |
847 | } else { | 891 | } else { |
848 | mmci_start_command(host, data->stop, 0); | 892 | mmci_start_command(host, data->stop, 0); |
@@ -855,6 +899,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, | |||
855 | unsigned int status) | 899 | unsigned int status) |
856 | { | 900 | { |
857 | void __iomem *base = host->base; | 901 | void __iomem *base = host->base; |
902 | bool sbc = (cmd == host->mrq->sbc); | ||
858 | 903 | ||
859 | host->cmd = NULL; | 904 | host->cmd = NULL; |
860 | 905 | ||
@@ -869,7 +914,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, | |||
869 | cmd->resp[3] = readl(base + MMCIRESPONSE3); | 914 | cmd->resp[3] = readl(base + MMCIRESPONSE3); |
870 | } | 915 | } |
871 | 916 | ||
872 | if (!cmd->data || cmd->error) { | 917 | if ((!sbc && !cmd->data) || cmd->error) { |
873 | if (host->data) { | 918 | if (host->data) { |
874 | /* Terminate the DMA transfer */ | 919 | /* Terminate the DMA transfer */ |
875 | if (dma_inprogress(host)) { | 920 | if (dma_inprogress(host)) { |
@@ -878,7 +923,9 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, | |||
878 | } | 923 | } |
879 | mmci_stop_data(host); | 924 | mmci_stop_data(host); |
880 | } | 925 | } |
881 | mmci_request_end(host, cmd->mrq); | 926 | mmci_request_end(host, host->mrq); |
927 | } else if (sbc) { | ||
928 | mmci_start_command(host, host->mrq->cmd, 0); | ||
882 | } else if (!(cmd->data->flags & MMC_DATA_READ)) { | 929 | } else if (!(cmd->data->flags & MMC_DATA_READ)) { |
883 | mmci_start_data(host, cmd->data); | 930 | mmci_start_data(host, cmd->data); |
884 | } | 931 | } |
@@ -1119,7 +1166,10 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1119 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) | 1166 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) |
1120 | mmci_start_data(host, mrq->data); | 1167 | mmci_start_data(host, mrq->data); |
1121 | 1168 | ||
1122 | mmci_start_command(host, mrq->cmd, 0); | 1169 | if (mrq->sbc) |
1170 | mmci_start_command(host, mrq->sbc, 0); | ||
1171 | else | ||
1172 | mmci_start_command(host, mrq->cmd, 0); | ||
1123 | 1173 | ||
1124 | spin_unlock_irqrestore(&host->lock, flags); | 1174 | spin_unlock_irqrestore(&host->lock, flags); |
1125 | } | 1175 | } |
@@ -1143,9 +1193,10 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1143 | if (!IS_ERR(mmc->supply.vmmc)) | 1193 | if (!IS_ERR(mmc->supply.vmmc)) |
1144 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); | 1194 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); |
1145 | 1195 | ||
1146 | if (!IS_ERR(mmc->supply.vqmmc) && | 1196 | if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { |
1147 | regulator_is_enabled(mmc->supply.vqmmc)) | ||
1148 | regulator_disable(mmc->supply.vqmmc); | 1197 | regulator_disable(mmc->supply.vqmmc); |
1198 | host->vqmmc_enabled = false; | ||
1199 | } | ||
1149 | 1200 | ||
1150 | break; | 1201 | break; |
1151 | case MMC_POWER_UP: | 1202 | case MMC_POWER_UP: |
@@ -1161,12 +1212,13 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1161 | 1212 | ||
1162 | break; | 1213 | break; |
1163 | case MMC_POWER_ON: | 1214 | case MMC_POWER_ON: |
1164 | if (!IS_ERR(mmc->supply.vqmmc) && | 1215 | if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { |
1165 | !regulator_is_enabled(mmc->supply.vqmmc)) { | ||
1166 | ret = regulator_enable(mmc->supply.vqmmc); | 1216 | ret = regulator_enable(mmc->supply.vqmmc); |
1167 | if (ret < 0) | 1217 | if (ret < 0) |
1168 | dev_err(mmc_dev(mmc), | 1218 | dev_err(mmc_dev(mmc), |
1169 | "failed to enable vqmmc regulator\n"); | 1219 | "failed to enable vqmmc regulator\n"); |
1220 | else | ||
1221 | host->vqmmc_enabled = true; | ||
1170 | } | 1222 | } |
1171 | 1223 | ||
1172 | pwr |= MCI_PWR_ON; | 1224 | pwr |= MCI_PWR_ON; |
@@ -1251,6 +1303,39 @@ static int mmci_get_cd(struct mmc_host *mmc) | |||
1251 | return status; | 1303 | return status; |
1252 | } | 1304 | } |
1253 | 1305 | ||
1306 | static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) | ||
1307 | { | ||
1308 | int ret = 0; | ||
1309 | |||
1310 | if (!IS_ERR(mmc->supply.vqmmc)) { | ||
1311 | |||
1312 | pm_runtime_get_sync(mmc_dev(mmc)); | ||
1313 | |||
1314 | switch (ios->signal_voltage) { | ||
1315 | case MMC_SIGNAL_VOLTAGE_330: | ||
1316 | ret = regulator_set_voltage(mmc->supply.vqmmc, | ||
1317 | 2700000, 3600000); | ||
1318 | break; | ||
1319 | case MMC_SIGNAL_VOLTAGE_180: | ||
1320 | ret = regulator_set_voltage(mmc->supply.vqmmc, | ||
1321 | 1700000, 1950000); | ||
1322 | break; | ||
1323 | case MMC_SIGNAL_VOLTAGE_120: | ||
1324 | ret = regulator_set_voltage(mmc->supply.vqmmc, | ||
1325 | 1100000, 1300000); | ||
1326 | break; | ||
1327 | } | ||
1328 | |||
1329 | if (ret) | ||
1330 | dev_warn(mmc_dev(mmc), "Voltage switch failed\n"); | ||
1331 | |||
1332 | pm_runtime_mark_last_busy(mmc_dev(mmc)); | ||
1333 | pm_runtime_put_autosuspend(mmc_dev(mmc)); | ||
1334 | } | ||
1335 | |||
1336 | return ret; | ||
1337 | } | ||
1338 | |||
1254 | static irqreturn_t mmci_cd_irq(int irq, void *dev_id) | 1339 | static irqreturn_t mmci_cd_irq(int irq, void *dev_id) |
1255 | { | 1340 | { |
1256 | struct mmci_host *host = dev_id; | 1341 | struct mmci_host *host = dev_id; |
@@ -1260,13 +1345,14 @@ static irqreturn_t mmci_cd_irq(int irq, void *dev_id) | |||
1260 | return IRQ_HANDLED; | 1345 | return IRQ_HANDLED; |
1261 | } | 1346 | } |
1262 | 1347 | ||
1263 | static const struct mmc_host_ops mmci_ops = { | 1348 | static struct mmc_host_ops mmci_ops = { |
1264 | .request = mmci_request, | 1349 | .request = mmci_request, |
1265 | .pre_req = mmci_pre_request, | 1350 | .pre_req = mmci_pre_request, |
1266 | .post_req = mmci_post_request, | 1351 | .post_req = mmci_post_request, |
1267 | .set_ios = mmci_set_ios, | 1352 | .set_ios = mmci_set_ios, |
1268 | .get_ro = mmci_get_ro, | 1353 | .get_ro = mmci_get_ro, |
1269 | .get_cd = mmci_get_cd, | 1354 | .get_cd = mmci_get_cd, |
1355 | .start_signal_voltage_switch = mmci_sig_volt_switch, | ||
1270 | }; | 1356 | }; |
1271 | 1357 | ||
1272 | #ifdef CONFIG_OF | 1358 | #ifdef CONFIG_OF |
@@ -1362,16 +1448,15 @@ static int mmci_probe(struct amba_device *dev, | |||
1362 | dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); | 1448 | dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); |
1363 | dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision); | 1449 | dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision); |
1364 | 1450 | ||
1365 | host->clk = clk_get(&dev->dev, NULL); | 1451 | host->clk = devm_clk_get(&dev->dev, NULL); |
1366 | if (IS_ERR(host->clk)) { | 1452 | if (IS_ERR(host->clk)) { |
1367 | ret = PTR_ERR(host->clk); | 1453 | ret = PTR_ERR(host->clk); |
1368 | host->clk = NULL; | ||
1369 | goto host_free; | 1454 | goto host_free; |
1370 | } | 1455 | } |
1371 | 1456 | ||
1372 | ret = clk_prepare_enable(host->clk); | 1457 | ret = clk_prepare_enable(host->clk); |
1373 | if (ret) | 1458 | if (ret) |
1374 | goto clk_free; | 1459 | goto host_free; |
1375 | 1460 | ||
1376 | host->plat = plat; | 1461 | host->plat = plat; |
1377 | host->variant = variant; | 1462 | host->variant = variant; |
@@ -1396,6 +1481,11 @@ static int mmci_probe(struct amba_device *dev, | |||
1396 | goto clk_disable; | 1481 | goto clk_disable; |
1397 | } | 1482 | } |
1398 | 1483 | ||
1484 | if (variant->busy_detect) { | ||
1485 | mmci_ops.card_busy = mmci_card_busy; | ||
1486 | mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); | ||
1487 | } | ||
1488 | |||
1399 | mmc->ops = &mmci_ops; | 1489 | mmc->ops = &mmci_ops; |
1400 | /* | 1490 | /* |
1401 | * The ARM and ST versions of the block have slightly different | 1491 | * The ARM and ST versions of the block have slightly different |
@@ -1576,8 +1666,6 @@ static int mmci_probe(struct amba_device *dev, | |||
1576 | iounmap(host->base); | 1666 | iounmap(host->base); |
1577 | clk_disable: | 1667 | clk_disable: |
1578 | clk_disable_unprepare(host->clk); | 1668 | clk_disable_unprepare(host->clk); |
1579 | clk_free: | ||
1580 | clk_put(host->clk); | ||
1581 | host_free: | 1669 | host_free: |
1582 | mmc_free_host(mmc); | 1670 | mmc_free_host(mmc); |
1583 | rel_regions: | 1671 | rel_regions: |
@@ -1623,7 +1711,6 @@ static int mmci_remove(struct amba_device *dev) | |||
1623 | 1711 | ||
1624 | iounmap(host->base); | 1712 | iounmap(host->base); |
1625 | clk_disable_unprepare(host->clk); | 1713 | clk_disable_unprepare(host->clk); |
1626 | clk_put(host->clk); | ||
1627 | 1714 | ||
1628 | mmc_free_host(mmc); | 1715 | mmc_free_host(mmc); |
1629 | 1716 | ||
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 1f33ad5333a0..69080fab6375 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
@@ -94,6 +94,7 @@ | |||
94 | /* Extended status bits for the ST Micro variants */ | 94 | /* Extended status bits for the ST Micro variants */ |
95 | #define MCI_ST_SDIOIT (1 << 22) | 95 | #define MCI_ST_SDIOIT (1 << 22) |
96 | #define MCI_ST_CEATAEND (1 << 23) | 96 | #define MCI_ST_CEATAEND (1 << 23) |
97 | #define MCI_ST_CARDBUSY (1 << 24) | ||
97 | 98 | ||
98 | #define MMCICLEAR 0x038 | 99 | #define MMCICLEAR 0x038 |
99 | #define MCI_CMDCRCFAILCLR (1 << 0) | 100 | #define MCI_CMDCRCFAILCLR (1 << 0) |
@@ -110,6 +111,7 @@ | |||
110 | /* Extended status bits for the ST Micro variants */ | 111 | /* Extended status bits for the ST Micro variants */ |
111 | #define MCI_ST_SDIOITC (1 << 22) | 112 | #define MCI_ST_SDIOITC (1 << 22) |
112 | #define MCI_ST_CEATAENDC (1 << 23) | 113 | #define MCI_ST_CEATAENDC (1 << 23) |
114 | #define MCI_ST_BUSYENDC (1 << 24) | ||
113 | 115 | ||
114 | #define MMCIMASK0 0x03c | 116 | #define MMCIMASK0 0x03c |
115 | #define MCI_CMDCRCFAILMASK (1 << 0) | 117 | #define MCI_CMDCRCFAILMASK (1 << 0) |
@@ -183,6 +185,8 @@ struct mmci_host { | |||
183 | unsigned int cclk; | 185 | unsigned int cclk; |
184 | u32 pwr_reg; | 186 | u32 pwr_reg; |
185 | u32 clk_reg; | 187 | u32 clk_reg; |
188 | u32 datactrl_reg; | ||
189 | bool vqmmc_enabled; | ||
186 | struct mmci_platform_data *plat; | 190 | struct mmci_platform_data *plat; |
187 | struct variant_data *variant; | 191 | struct variant_data *variant; |
188 | 192 | ||
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index e6c9c4cc9b23..c463ce990c48 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h | |||
@@ -32,7 +32,7 @@ | |||
32 | #ifdef CONFIG_ARM_ARCH_TIMER | 32 | #ifdef CONFIG_ARM_ARCH_TIMER |
33 | 33 | ||
34 | extern u32 arch_timer_get_rate(void); | 34 | extern u32 arch_timer_get_rate(void); |
35 | extern u64 (*arch_timer_read_counter)(void); | 35 | extern u64 arch_timer_read_counter(void); |
36 | extern struct timecounter *arch_timer_get_timecounter(void); | 36 | extern struct timecounter *arch_timer_get_timecounter(void); |
37 | 37 | ||
38 | #else | 38 | #else |