diff options
author | Praneeth Bajjuri | 2014-08-20 17:29:32 -0500 |
---|---|---|
committer | Praneeth Bajjuri | 2014-08-20 17:29:32 -0500 |
commit | 1bac0d75dddea95fed777f36b793b13745432fa2 (patch) | |
tree | 8d64f81acf2074b6e215d3f7cfcd4f1323e963dc | |
parent | a9c8e3d8d78dab930e133884a7c887e5c97c114b (diff) | |
parent | 4811ec8cfa2f8d959cee6c7bd99f58f4b6d82a48 (diff) | |
download | kernel-video-1bac0d75dddea95fed777f36b793b13745432fa2.tar.gz kernel-video-1bac0d75dddea95fed777f36b793b13745432fa2.tar.xz kernel-video-1bac0d75dddea95fed777f36b793b13745432fa2.zip |
Merge branch 'linux-linaro-lsk-v3.14-android' of git://git.linaro.org/kernel/linux-linaro-stable into p-ti-linux-3.14.y
* 'linux-linaro-lsk-v3.14-android' of git://git.linaro.org/kernel/linux-linaro-stable: (47 commits)
usb: Fix H20AHB driver for big-endian
configs: Enable fanotify
lib: add fdt_empty_tree.c
of/fdt: Convert FDT functions to use libfdt
of/fdt: update of_get_flat_dt_prop in prep for libfdt
of/fdt: remove unused of_scan_flat_dt_by_path
of: Fix the section mismatch warnings.
of: only scan for reserved mem when fdt present
drivers: of: add support for custom reserved memory drivers
drivers: of: add initialization code for dynamic reserved memory
drivers: of: add initialization code for static reserved memory
arm64: Fix barriers used for page table modifications
arm64: mm: Optimise tlb flush logic where we have >4K granule
arm64: KVM: define HYP and Stage-2 translation page flags
arm64: Fix for the arm64 kern_addr_valid() function
arm64: Clean up the default pgprot setting
arm64: Add function to create identity mappings
arm64: head: create a new function for setting the boot_cpu_mode flag
arm64: introduce virt_to_pfn
Revert "arm64: Introduce execute-only page access permissions"
...
Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
59 files changed, 1300 insertions, 707 deletions
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt index 5e054bfe4dd..1b84f2b7e65 100644 --- a/Documentation/arm64/memory.txt +++ b/Documentation/arm64/memory.txt | |||
@@ -35,7 +35,11 @@ ffffffbc00000000 ffffffbdffffffff 8GB vmemmap | |||
35 | 35 | ||
36 | ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] | 36 | ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] |
37 | 37 | ||
38 | ffffffbffbc00000 ffffffbffbdfffff 2MB earlyprintk device | 38 | ffffffbffa000000 ffffffbffaffffff 16MB PCI I/O space |
39 | |||
40 | ffffffbffb000000 ffffffbffbbfffff 12MB [guard] | ||
41 | |||
42 | ffffffbffbc00000 ffffffbffbdfffff 2MB fixed mappings | ||
39 | 43 | ||
40 | ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space | 44 | ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space |
41 | 45 | ||
@@ -60,7 +64,11 @@ fffffdfc00000000 fffffdfdffffffff 8GB vmemmap | |||
60 | 64 | ||
61 | fffffdfe00000000 fffffdfffbbfffff ~8GB [guard, future vmmemap] | 65 | fffffdfe00000000 fffffdfffbbfffff ~8GB [guard, future vmmemap] |
62 | 66 | ||
63 | fffffdfffbc00000 fffffdfffbdfffff 2MB earlyprintk device | 67 | fffffdfffa000000 fffffdfffaffffff 16MB PCI I/O space |
68 | |||
69 | fffffdfffb000000 fffffdfffbbfffff 12MB [guard] | ||
70 | |||
71 | fffffdfffbc00000 fffffdfffbdfffff 2MB fixed mappings | ||
64 | 72 | ||
65 | fffffdfffbe00000 fffffdfffbe0ffff 64KB PCI I/O space | 73 | fffffdfffbe00000 fffffdfffbe0ffff 64KB PCI I/O space |
66 | 74 | ||
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index b6dc4e21fd3..0b3ef4025d8 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c | |||
@@ -42,7 +42,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) | |||
42 | const struct machine_desc *mdesc; | 42 | const struct machine_desc *mdesc; |
43 | unsigned long dt_root; | 43 | unsigned long dt_root; |
44 | void *clk; | 44 | void *clk; |
45 | unsigned long len; | 45 | int len; |
46 | 46 | ||
47 | if (!early_init_dt_scan(dt)) | 47 | if (!early_init_dt_scan(dt)) |
48 | return NULL; | 48 | return NULL; |
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index f751714d52c..97707977144 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c | |||
@@ -212,7 +212,7 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) | |||
212 | 212 | ||
213 | if (!mdesc) { | 213 | if (!mdesc) { |
214 | const char *prop; | 214 | const char *prop; |
215 | long size; | 215 | int size; |
216 | unsigned long dt_root; | 216 | unsigned long dt_root; |
217 | 217 | ||
218 | early_print("\nError: unrecognized/unsupported " | 218 | early_print("\nError: unrecognized/unsupported " |
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index f18be40e5b2..1bf303f8dfe 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c | |||
@@ -322,7 +322,7 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, | |||
322 | { | 322 | { |
323 | struct map_desc iodesc; | 323 | struct map_desc iodesc; |
324 | __be32 *reg; | 324 | __be32 *reg; |
325 | unsigned long len; | 325 | int len; |
326 | 326 | ||
327 | if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") && | 327 | if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") && |
328 | !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock")) | 328 | !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock")) |
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 993c9ae5dc5..b4a5f0d8390 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c | |||
@@ -53,7 +53,7 @@ static int __init vexpress_dt_find_scu(unsigned long node, | |||
53 | { | 53 | { |
54 | if (of_flat_dt_match(node, vexpress_dt_cortex_a9_match)) { | 54 | if (of_flat_dt_match(node, vexpress_dt_cortex_a9_match)) { |
55 | phys_addr_t phys_addr; | 55 | phys_addr_t phys_addr; |
56 | __be32 *reg = of_get_flat_dt_prop(node, "reg", NULL); | 56 | const __be32 *reg = of_get_flat_dt_prop(node, "reg", NULL); |
57 | 57 | ||
58 | if (WARN_ON(!reg)) | 58 | if (WARN_ON(!reg)) |
59 | return -EINVAL; | 59 | return -EINVAL; |
diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c index ad51f85fbd0..97ece99521c 100644 --- a/arch/arm/plat-samsung/s5p-dev-mfc.c +++ b/arch/arm/plat-samsung/s5p-dev-mfc.c | |||
@@ -125,29 +125,29 @@ device_initcall(s5p_mfc_memory_init); | |||
125 | int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname, | 125 | int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname, |
126 | int depth, void *data) | 126 | int depth, void *data) |
127 | { | 127 | { |
128 | __be32 *prop; | 128 | const __be32 *prop; |
129 | unsigned long len; | 129 | int len; |
130 | struct s5p_mfc_dt_meminfo *mfc_mem = data; | 130 | struct s5p_mfc_dt_meminfo mfc_mem; |
131 | 131 | ||
132 | if (!data) | 132 | if (!data) |
133 | return 0; | 133 | return 0; |
134 | 134 | ||
135 | if (!of_flat_dt_is_compatible(node, mfc_mem->compatible)) | 135 | if (!of_flat_dt_is_compatible(node, mfc_mem.compatible)) |
136 | return 0; | 136 | return 0; |
137 | 137 | ||
138 | prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len); | 138 | prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len); |
139 | if (!prop || (len != 2 * sizeof(unsigned long))) | 139 | if (!prop || (len != 2 * sizeof(unsigned long))) |
140 | return 0; | 140 | return 0; |
141 | 141 | ||
142 | mfc_mem->loff = be32_to_cpu(prop[0]); | 142 | mfc_mem.loff = be32_to_cpu(prop[0]); |
143 | mfc_mem->lsize = be32_to_cpu(prop[1]); | 143 | mfc_mem.lsize = be32_to_cpu(prop[1]); |
144 | 144 | ||
145 | prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len); | 145 | prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len); |
146 | if (!prop || (len != 2 * sizeof(unsigned long))) | 146 | if (!prop || (len != 2 * sizeof(unsigned long))) |
147 | return 0; | 147 | return 0; |
148 | 148 | ||
149 | mfc_mem->roff = be32_to_cpu(prop[0]); | 149 | mfc_mem.roff = be32_to_cpu(prop[0]); |
150 | mfc_mem->rsize = be32_to_cpu(prop[1]); | 150 | mfc_mem.rsize = be32_to_cpu(prop[1]); |
151 | 151 | ||
152 | return 1; | 152 | return 1; |
153 | } | 153 | } |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7c5276fce96..372075b4e67 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -19,6 +19,7 @@ config ARM64 | |||
19 | select GENERIC_CLOCKEVENTS | 19 | select GENERIC_CLOCKEVENTS |
20 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP | 20 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP |
21 | select GENERIC_CPU_AUTOPROBE | 21 | select GENERIC_CPU_AUTOPROBE |
22 | select GENERIC_EARLY_IOREMAP | ||
22 | select GENERIC_IOMAP | 23 | select GENERIC_IOMAP |
23 | select GENERIC_IRQ_PROBE | 24 | select GENERIC_IRQ_PROBE |
24 | select GENERIC_IRQ_SHOW | 25 | select GENERIC_IRQ_SHOW |
@@ -118,6 +119,9 @@ config IOMMU_HELPER | |||
118 | config KERNEL_MODE_NEON | 119 | config KERNEL_MODE_NEON |
119 | def_bool y | 120 | def_bool y |
120 | 121 | ||
122 | config FIX_EARLYCON_MEM | ||
123 | def_bool y | ||
124 | |||
121 | source "init/Kconfig" | 125 | source "init/Kconfig" |
122 | 126 | ||
123 | source "kernel/Kconfig.freezer" | 127 | source "kernel/Kconfig.freezer" |
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi index 40aa96ce13c..03431d25123 100644 --- a/arch/arm64/boot/dts/apm-storm.dtsi +++ b/arch/arm64/boot/dts/apm-storm.dtsi | |||
@@ -345,57 +345,5 @@ | |||
345 | apm,tx-boost-gain = <31 31 31 31 31 31>; | 345 | apm,tx-boost-gain = <31 31 31 31 31 31>; |
346 | apm,tx-eye-tuning = <2 10 10 2 10 10>; | 346 | apm,tx-eye-tuning = <2 10 10 2 10 10>; |
347 | }; | 347 | }; |
348 | |||
349 | sata1: sata@1a000000 { | ||
350 | compatible = "apm,xgene-ahci"; | ||
351 | reg = <0x0 0x1a000000 0x0 0x1000>, | ||
352 | <0x0 0x1f210000 0x0 0x1000>, | ||
353 | <0x0 0x1f21d000 0x0 0x1000>, | ||
354 | <0x0 0x1f21e000 0x0 0x1000>, | ||
355 | <0x0 0x1f217000 0x0 0x1000>; | ||
356 | interrupts = <0x0 0x86 0x4>; | ||
357 | dma-coherent; | ||
358 | status = "disabled"; | ||
359 | clocks = <&sata01clk 0>; | ||
360 | phys = <&phy1 0>; | ||
361 | phy-names = "sata-phy"; | ||
362 | }; | ||
363 | |||
364 | sata2: sata@1a400000 { | ||
365 | compatible = "apm,xgene-ahci"; | ||
366 | reg = <0x0 0x1a400000 0x0 0x1000>, | ||
367 | <0x0 0x1f220000 0x0 0x1000>, | ||
368 | <0x0 0x1f22d000 0x0 0x1000>, | ||
369 | <0x0 0x1f22e000 0x0 0x1000>, | ||
370 | <0x0 0x1f227000 0x0 0x1000>; | ||
371 | interrupts = <0x0 0x87 0x4>; | ||
372 | dma-coherent; | ||
373 | status = "ok"; | ||
374 | clocks = <&sata23clk 0>; | ||
375 | phys = <&phy2 0>; | ||
376 | phy-names = "sata-phy"; | ||
377 | }; | ||
378 | |||
379 | sata3: sata@1a800000 { | ||
380 | compatible = "apm,xgene-ahci"; | ||
381 | reg = <0x0 0x1a800000 0x0 0x1000>, | ||
382 | <0x0 0x1f230000 0x0 0x1000>, | ||
383 | <0x0 0x1f23d000 0x0 0x1000>, | ||
384 | <0x0 0x1f23e000 0x0 0x1000>; | ||
385 | interrupts = <0x0 0x88 0x4>; | ||
386 | dma-coherent; | ||
387 | status = "ok"; | ||
388 | clocks = <&sata45clk 0>; | ||
389 | phys = <&phy3 0>; | ||
390 | phy-names = "sata-phy"; | ||
391 | }; | ||
392 | |||
393 | rtc: rtc@10510000 { | ||
394 | compatible = "apm,xgene-rtc"; | ||
395 | reg = <0x0 0x10510000 0x0 0x400>; | ||
396 | interrupts = <0x0 0x46 0x4>; | ||
397 | #clock-cells = <1>; | ||
398 | clocks = <&rtcclk 0>; | ||
399 | }; | ||
400 | }; | 348 | }; |
401 | }; | 349 | }; |
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index 43a2c9d2d6f..bd36b3013f8 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild | |||
@@ -10,6 +10,7 @@ generic-y += delay.h | |||
10 | generic-y += div64.h | 10 | generic-y += div64.h |
11 | generic-y += dma.h | 11 | generic-y += dma.h |
12 | generic-y += emergency-restart.h | 12 | generic-y += emergency-restart.h |
13 | generic-y += early_ioremap.h | ||
13 | generic-y += errno.h | 14 | generic-y += errno.h |
14 | generic-y += ftrace.h | 15 | generic-y += ftrace.h |
15 | generic-y += hw_irq.h | 16 | generic-y += hw_irq.h |
diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h index 0237f0867e3..9c48d74652c 100644 --- a/arch/arm64/include/asm/atomic.h +++ b/arch/arm64/include/asm/atomic.h | |||
@@ -162,7 +162,7 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) | |||
162 | */ | 162 | */ |
163 | #define ATOMIC64_INIT(i) { (i) } | 163 | #define ATOMIC64_INIT(i) { (i) } |
164 | 164 | ||
165 | #define atomic64_read(v) (*(volatile long long *)&(v)->counter) | 165 | #define atomic64_read(v) (*(volatile long *)&(v)->counter) |
166 | #define atomic64_set(v,i) (((v)->counter) = (i)) | 166 | #define atomic64_set(v,i) (((v)->counter) = (i)) |
167 | 167 | ||
168 | static inline void atomic64_add(u64 i, atomic64_t *v) | 168 | static inline void atomic64_add(u64 i, atomic64_t *v) |
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 409ca370cfe..5c436e3457d 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define isb() asm volatile("isb" : : : "memory") | 27 | #define isb() asm volatile("isb" : : : "memory") |
28 | #define dsb(opt) asm volatile("dsb sy" : : : "memory") | 28 | #define dsb(opt) asm volatile("dsb sy" : : : "memory") |
29 | 29 | ||
30 | #define mb() dsb() | 30 | #define mb() dsb(sy) |
31 | #define rmb() asm volatile("dsb ld" : : : "memory") | 31 | #define rmb() asm volatile("dsb ld" : : : "memory") |
32 | #define wmb() asm volatile("dsb st" : : : "memory") | 32 | #define wmb() asm volatile("dsb st" : : : "memory") |
33 | 33 | ||
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h index 4c60e64a801..f2defe1c380 100644 --- a/arch/arm64/include/asm/cacheflush.h +++ b/arch/arm64/include/asm/cacheflush.h | |||
@@ -123,7 +123,7 @@ extern void flush_dcache_page(struct page *); | |||
123 | static inline void __flush_icache_all(void) | 123 | static inline void __flush_icache_all(void) |
124 | { | 124 | { |
125 | asm("ic ialluis"); | 125 | asm("ic ialluis"); |
126 | dsb(); | 126 | dsb(ish); |
127 | } | 127 | } |
128 | 128 | ||
129 | #define flush_dcache_mmap_lock(mapping) \ | 129 | #define flush_dcache_mmap_lock(mapping) \ |
@@ -138,19 +138,10 @@ static inline void __flush_icache_all(void) | |||
138 | #define flush_icache_page(vma,page) do { } while (0) | 138 | #define flush_icache_page(vma,page) do { } while (0) |
139 | 139 | ||
140 | /* | 140 | /* |
141 | * flush_cache_vmap() is used when creating mappings (eg, via vmap, | 141 | * Not required on AArch64 (PIPT or VIPT non-aliasing D-cache). |
142 | * vmalloc, ioremap etc) in kernel space for pages. On non-VIPT | ||
143 | * caches, since the direct-mappings of these pages may contain cached | ||
144 | * data, we need to do a full cache flush to ensure that writebacks | ||
145 | * don't corrupt data placed into these pages via the new mappings. | ||
146 | */ | 142 | */ |
147 | static inline void flush_cache_vmap(unsigned long start, unsigned long end) | 143 | static inline void flush_cache_vmap(unsigned long start, unsigned long end) |
148 | { | 144 | { |
149 | /* | ||
150 | * set_pte_at() called from vmap_pte_range() does not | ||
151 | * have a DSB after cleaning the cache line. | ||
152 | */ | ||
153 | dsb(); | ||
154 | } | 145 | } |
155 | 146 | ||
156 | static inline void flush_cache_vunmap(unsigned long start, unsigned long end) | 147 | static inline void flush_cache_vunmap(unsigned long start, unsigned long end) |
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index 57c0fa7bf71..ddb9d783055 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h | |||
@@ -72,7 +72,12 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size | |||
72 | } | 72 | } |
73 | 73 | ||
74 | #define xchg(ptr,x) \ | 74 | #define xchg(ptr,x) \ |
75 | ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | 75 | ({ \ |
76 | __typeof__(*(ptr)) __ret; \ | ||
77 | __ret = (__typeof__(*(ptr))) \ | ||
78 | __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))); \ | ||
79 | __ret; \ | ||
80 | }) | ||
76 | 81 | ||
77 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | 82 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, |
78 | unsigned long new, int size) | 83 | unsigned long new, int size) |
diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h new file mode 100644 index 00000000000..5f7bfe6df72 --- /dev/null +++ b/arch/arm64/include/asm/fixmap.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * fixmap.h: compile-time virtual memory allocation | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 1998 Ingo Molnar | ||
9 | * Copyright (C) 2013 Mark Salter <msalter@redhat.com> | ||
10 | * | ||
11 | * Adapted from arch/x86_64 version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifndef _ASM_ARM64_FIXMAP_H | ||
16 | #define _ASM_ARM64_FIXMAP_H | ||
17 | |||
18 | #ifndef __ASSEMBLY__ | ||
19 | #include <linux/kernel.h> | ||
20 | #include <asm/page.h> | ||
21 | |||
22 | /* | ||
23 | * Here we define all the compile-time 'special' virtual | ||
24 | * addresses. The point is to have a constant address at | ||
25 | * compile time, but to set the physical address only | ||
26 | * in the boot process. | ||
27 | * | ||
28 | * These 'compile-time allocated' memory buffers are | ||
29 | * page-sized. Use set_fixmap(idx,phys) to associate | ||
30 | * physical memory with fixmap indices. | ||
31 | * | ||
32 | */ | ||
33 | enum fixed_addresses { | ||
34 | FIX_EARLYCON_MEM_BASE, | ||
35 | __end_of_permanent_fixed_addresses, | ||
36 | |||
37 | /* | ||
38 | * Temporary boot-time mappings, used by early_ioremap(), | ||
39 | * before ioremap() is functional. | ||
40 | */ | ||
41 | #ifdef CONFIG_ARM64_64K_PAGES | ||
42 | #define NR_FIX_BTMAPS 4 | ||
43 | #else | ||
44 | #define NR_FIX_BTMAPS 64 | ||
45 | #endif | ||
46 | #define FIX_BTMAPS_SLOTS 7 | ||
47 | #define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) | ||
48 | |||
49 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses, | ||
50 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1, | ||
51 | __end_of_fixed_addresses | ||
52 | }; | ||
53 | |||
54 | #define FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) | ||
55 | #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) | ||
56 | |||
57 | #define FIXMAP_PAGE_IO __pgprot(PROT_DEVICE_nGnRE) | ||
58 | |||
59 | extern void __early_set_fixmap(enum fixed_addresses idx, | ||
60 | phys_addr_t phys, pgprot_t flags); | ||
61 | |||
62 | #define __set_fixmap __early_set_fixmap | ||
63 | |||
64 | #include <asm-generic/fixmap.h> | ||
65 | |||
66 | #endif /* !__ASSEMBLY__ */ | ||
67 | #endif /* _ASM_ARM64_FIXMAP_H */ | ||
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 4cc813eddac..6d5e328575d 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/byteorder.h> | 27 | #include <asm/byteorder.h> |
28 | #include <asm/barrier.h> | 28 | #include <asm/barrier.h> |
29 | #include <asm/pgtable.h> | 29 | #include <asm/pgtable.h> |
30 | #include <asm/early_ioremap.h> | ||
30 | 31 | ||
31 | #include <xen/xen.h> | 32 | #include <xen/xen.h> |
32 | 33 | ||
@@ -229,19 +230,11 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot | |||
229 | extern void __iounmap(volatile void __iomem *addr); | 230 | extern void __iounmap(volatile void __iomem *addr); |
230 | extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); | 231 | extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); |
231 | 232 | ||
232 | #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY) | ||
233 | #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) | ||
234 | #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) | ||
235 | #define PROT_NORMAL (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) | ||
236 | |||
237 | #define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) | 233 | #define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) |
238 | #define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) | 234 | #define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) |
239 | #define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC)) | 235 | #define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC)) |
240 | #define iounmap __iounmap | 236 | #define iounmap __iounmap |
241 | 237 | ||
242 | #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF) | ||
243 | #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PTE_PXN | PTE_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) | ||
244 | |||
245 | #define ARCH_HAS_IOREMAP_WC | 238 | #define ARCH_HAS_IOREMAP_WC |
246 | #include <asm-generic/iomap.h> | 239 | #include <asm-generic/iomap.h> |
247 | 240 | ||
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 11ad59b856c..902eb708804 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h | |||
@@ -49,7 +49,7 @@ | |||
49 | #define PAGE_OFFSET (UL(0xffffffffffffffff) << (VA_BITS - 1)) | 49 | #define PAGE_OFFSET (UL(0xffffffffffffffff) << (VA_BITS - 1)) |
50 | #define MODULES_END (PAGE_OFFSET) | 50 | #define MODULES_END (PAGE_OFFSET) |
51 | #define MODULES_VADDR (MODULES_END - SZ_64M) | 51 | #define MODULES_VADDR (MODULES_END - SZ_64M) |
52 | #define EARLYCON_IOBASE (MODULES_VADDR - SZ_4M) | 52 | #define FIXADDR_TOP (MODULES_VADDR - SZ_2M - PAGE_SIZE) |
53 | #define TASK_SIZE_64 (UL(1) << VA_BITS) | 53 | #define TASK_SIZE_64 (UL(1) << VA_BITS) |
54 | 54 | ||
55 | #ifdef CONFIG_COMPAT | 55 | #ifdef CONFIG_COMPAT |
@@ -140,6 +140,7 @@ static inline void *phys_to_virt(phys_addr_t x) | |||
140 | #define __pa(x) __virt_to_phys((unsigned long)(x)) | 140 | #define __pa(x) __virt_to_phys((unsigned long)(x)) |
141 | #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) | 141 | #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) |
142 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | 142 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) |
143 | #define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys(x)) | ||
143 | 144 | ||
144 | /* | 145 | /* |
145 | * virt_to_page(k) convert a _valid_ virtual address to struct page * | 146 | * virt_to_page(k) convert a _valid_ virtual address to struct page * |
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 2494fc01896..c2f006c48bd 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h | |||
@@ -22,10 +22,16 @@ typedef struct { | |||
22 | void *vdso; | 22 | void *vdso; |
23 | } mm_context_t; | 23 | } mm_context_t; |
24 | 24 | ||
25 | #define INIT_MM_CONTEXT(name) \ | ||
26 | .context.id_lock = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock), | ||
27 | |||
25 | #define ASID(mm) ((mm)->context.id & 0xffff) | 28 | #define ASID(mm) ((mm)->context.id & 0xffff) |
26 | 29 | ||
27 | extern void paging_init(void); | 30 | extern void paging_init(void); |
28 | extern void setup_mm_for_reboot(void); | 31 | extern void setup_mm_for_reboot(void); |
29 | extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); | 32 | extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); |
33 | extern void init_mem_pgprot(void); | ||
34 | /* create an identity mapping for memory (or io if map_io is true) */ | ||
35 | extern void create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io); | ||
30 | 36 | ||
31 | #endif | 37 | #endif |
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index b1d2e26c3c8..2e9d83673ef 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h | |||
@@ -85,8 +85,6 @@ | |||
85 | #define PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[2:1] */ | 85 | #define PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[2:1] */ |
86 | #define PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ | 86 | #define PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */ |
87 | 87 | ||
88 | #define PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */ | ||
89 | |||
90 | /* | 88 | /* |
91 | * Memory Attribute override for Stage-2 (MemAttr[3:0]) | 89 | * Memory Attribute override for Stage-2 (MemAttr[3:0]) |
92 | */ | 90 | */ |
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 549c1c9921f..33608f263ad 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
@@ -52,66 +52,60 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
52 | #endif | 52 | #endif |
53 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) | 53 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) |
54 | 54 | ||
55 | /* | 55 | #ifdef CONFIG_SMP |
56 | * The pgprot_* and protection_map entries will be fixed up at runtime to | 56 | #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) |
57 | * include the cachable and bufferable bits based on memory policy, as well as | 57 | #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) |
58 | * any architecture dependent bits like global/ASID and SMP shared mapping | 58 | #else |
59 | * bits. | 59 | #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF) |
60 | */ | 60 | #define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF) |
61 | #define _PAGE_DEFAULT PTE_TYPE_PAGE | PTE_AF | 61 | #endif |
62 | 62 | ||
63 | extern pgprot_t pgprot_default; | 63 | #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) |
64 | #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC)) | ||
65 | #define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL)) | ||
64 | 66 | ||
65 | #define __pgprot_modify(prot,mask,bits) \ | 67 | #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) |
66 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | 68 | #define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) |
69 | #define PROT_SECT_NORMAL_EXEC (PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) | ||
67 | 70 | ||
68 | #define _MOD_PROT(p, b) __pgprot_modify(p, 0, b) | 71 | #define _PAGE_DEFAULT (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) |
69 | 72 | ||
70 | #define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE | PTE_PXN | PTE_UXN) | 73 | #define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) |
71 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) | 74 | #define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) |
72 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE) | ||
73 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | ||
74 | #define PAGE_COPY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) | ||
75 | #define PAGE_READONLY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | ||
76 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) | ||
77 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) | ||
78 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY | PTE_WRITE) | ||
79 | 75 | ||
80 | #define PAGE_HYP _MOD_PROT(pgprot_default, PTE_HYP) | 76 | #define PAGE_HYP __pgprot(_PAGE_DEFAULT | PTE_HYP) |
81 | #define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP) | 77 | #define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP) |
82 | 78 | ||
83 | #define PAGE_S2 __pgprot_modify(pgprot_default, PTE_S2_MEMATTR_MASK, PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) | 79 | #define PAGE_S2 __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) |
84 | #define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDWR | PTE_UXN) | 80 | #define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDWR | PTE_UXN) |
85 | 81 | ||
86 | #define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_PXN | PTE_UXN) | 82 | #define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_PXN | PTE_UXN) |
87 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) | 83 | #define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) |
88 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE) | 84 | #define PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE) |
89 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 85 | #define PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
90 | #define __PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) | 86 | #define PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) |
91 | #define __PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 87 | #define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
92 | #define __PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) | 88 | #define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) |
93 | 89 | #define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN) | |
94 | #endif /* __ASSEMBLY__ */ | 90 | |
95 | 91 | #define __P000 PAGE_NONE | |
96 | #define __P000 __PAGE_NONE | 92 | #define __P001 PAGE_READONLY |
97 | #define __P001 __PAGE_READONLY | 93 | #define __P010 PAGE_COPY |
98 | #define __P010 __PAGE_COPY | 94 | #define __P011 PAGE_COPY |
99 | #define __P011 __PAGE_COPY | 95 | #define __P100 PAGE_READONLY_EXEC |
100 | #define __P100 __PAGE_READONLY_EXEC | 96 | #define __P101 PAGE_READONLY_EXEC |
101 | #define __P101 __PAGE_READONLY_EXEC | 97 | #define __P110 PAGE_COPY_EXEC |
102 | #define __P110 __PAGE_COPY_EXEC | 98 | #define __P111 PAGE_COPY_EXEC |
103 | #define __P111 __PAGE_COPY_EXEC | 99 | |
104 | 100 | #define __S000 PAGE_NONE | |
105 | #define __S000 __PAGE_NONE | 101 | #define __S001 PAGE_READONLY |
106 | #define __S001 __PAGE_READONLY | 102 | #define __S010 PAGE_SHARED |
107 | #define __S010 __PAGE_SHARED | 103 | #define __S011 PAGE_SHARED |
108 | #define __S011 __PAGE_SHARED | 104 | #define __S100 PAGE_READONLY_EXEC |
109 | #define __S100 __PAGE_READONLY_EXEC | 105 | #define __S101 PAGE_READONLY_EXEC |
110 | #define __S101 __PAGE_READONLY_EXEC | 106 | #define __S110 PAGE_SHARED_EXEC |
111 | #define __S110 __PAGE_SHARED_EXEC | 107 | #define __S111 PAGE_SHARED_EXEC |
112 | #define __S111 __PAGE_SHARED_EXEC | ||
113 | 108 | ||
114 | #ifndef __ASSEMBLY__ | ||
115 | /* | 109 | /* |
116 | * ZERO_PAGE is a global shared page that is always zero: used | 110 | * ZERO_PAGE is a global shared page that is always zero: used |
117 | * for zero-mapped memory areas etc.. | 111 | * for zero-mapped memory areas etc.. |
@@ -145,6 +139,8 @@ extern struct page *empty_zero_page; | |||
145 | 139 | ||
146 | #define pte_valid_user(pte) \ | 140 | #define pte_valid_user(pte) \ |
147 | ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) | 141 | ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) |
142 | #define pte_valid_not_user(pte) \ | ||
143 | ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID) | ||
148 | 144 | ||
149 | static inline pte_t pte_wrprotect(pte_t pte) | 145 | static inline pte_t pte_wrprotect(pte_t pte) |
150 | { | 146 | { |
@@ -191,6 +187,15 @@ static inline pte_t pte_mkspecial(pte_t pte) | |||
191 | static inline void set_pte(pte_t *ptep, pte_t pte) | 187 | static inline void set_pte(pte_t *ptep, pte_t pte) |
192 | { | 188 | { |
193 | *ptep = pte; | 189 | *ptep = pte; |
190 | |||
191 | /* | ||
192 | * Only if the new pte is valid and kernel, otherwise TLB maintenance | ||
193 | * or update_mmu_cache() have the necessary barriers. | ||
194 | */ | ||
195 | if (pte_valid_not_user(pte)) { | ||
196 | dsb(ishst); | ||
197 | isb(); | ||
198 | } | ||
194 | } | 199 | } |
195 | 200 | ||
196 | extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); | 201 | extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); |
@@ -266,13 +271,16 @@ static inline pmd_t pte_pmd(pte_t pte) | |||
266 | 271 | ||
267 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | 272 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) |
268 | 273 | ||
269 | #define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd)) | 274 | #define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) |
270 | 275 | ||
271 | static inline int has_transparent_hugepage(void) | 276 | static inline int has_transparent_hugepage(void) |
272 | { | 277 | { |
273 | return 1; | 278 | return 1; |
274 | } | 279 | } |
275 | 280 | ||
281 | #define __pgprot_modify(prot,mask,bits) \ | ||
282 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
283 | |||
276 | /* | 284 | /* |
277 | * Mark the prot value as uncacheable and unbufferable. | 285 | * Mark the prot value as uncacheable and unbufferable. |
278 | */ | 286 | */ |
@@ -280,8 +288,6 @@ static inline int has_transparent_hugepage(void) | |||
280 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN) | 288 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN) |
281 | #define pgprot_writecombine(prot) \ | 289 | #define pgprot_writecombine(prot) \ |
282 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) | 290 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) |
283 | #define pgprot_dmacoherent(prot) \ | ||
284 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) | ||
285 | #define __HAVE_PHYS_MEM_ACCESS_PROT | 291 | #define __HAVE_PHYS_MEM_ACCESS_PROT |
286 | struct file; | 292 | struct file; |
287 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | 293 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
@@ -301,7 +307,8 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | |||
301 | static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) | 307 | static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) |
302 | { | 308 | { |
303 | *pmdp = pmd; | 309 | *pmdp = pmd; |
304 | dsb(); | 310 | dsb(ishst); |
311 | isb(); | ||
305 | } | 312 | } |
306 | 313 | ||
307 | static inline void pmd_clear(pmd_t *pmdp) | 314 | static inline void pmd_clear(pmd_t *pmdp) |
@@ -331,7 +338,8 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
331 | static inline void set_pud(pud_t *pudp, pud_t pud) | 338 | static inline void set_pud(pud_t *pudp, pud_t pud) |
332 | { | 339 | { |
333 | *pudp = pud; | 340 | *pudp = pud; |
334 | dsb(); | 341 | dsb(ishst); |
342 | isb(); | ||
335 | } | 343 | } |
336 | 344 | ||
337 | static inline void pud_clear(pud_t *pudp) | 345 | static inline void pud_clear(pud_t *pudp) |
@@ -405,7 +413,7 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | |||
405 | 413 | ||
406 | /* | 414 | /* |
407 | * Ensure that there are not more swap files than can be encoded in the kernel | 415 | * Ensure that there are not more swap files than can be encoded in the kernel |
408 | * the PTEs. | 416 | * PTEs. |
409 | */ | 417 | */ |
410 | #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) | 418 | #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) |
411 | 419 | ||
diff --git a/arch/arm64/include/asm/sigcontext.h b/arch/arm64/include/asm/sigcontext.h deleted file mode 100644 index dca1094acc7..00000000000 --- a/arch/arm64/include/asm/sigcontext.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SIGCONTEXT_H | ||
17 | #define __ASM_SIGCONTEXT_H | ||
18 | |||
19 | #include <uapi/asm/sigcontext.h> | ||
20 | |||
21 | /* | ||
22 | * Auxiliary context saved in the sigcontext.__reserved array. Not exported to | ||
23 | * user space as it will change with the addition of new context. User space | ||
24 | * should check the magic/size information. | ||
25 | */ | ||
26 | struct aux_context { | ||
27 | struct fpsimd_context fpsimd; | ||
28 | /* additional context to be added before "end" */ | ||
29 | struct _aarch64_ctx end; | ||
30 | }; | ||
31 | #endif | ||
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index 8b482035cfc..3796ea6bb73 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h | |||
@@ -72,9 +72,9 @@ extern struct cpu_tlb_fns cpu_tlb; | |||
72 | */ | 72 | */ |
73 | static inline void flush_tlb_all(void) | 73 | static inline void flush_tlb_all(void) |
74 | { | 74 | { |
75 | dsb(); | 75 | dsb(ishst); |
76 | asm("tlbi vmalle1is"); | 76 | asm("tlbi vmalle1is"); |
77 | dsb(); | 77 | dsb(ish); |
78 | isb(); | 78 | isb(); |
79 | } | 79 | } |
80 | 80 | ||
@@ -82,9 +82,9 @@ static inline void flush_tlb_mm(struct mm_struct *mm) | |||
82 | { | 82 | { |
83 | unsigned long asid = (unsigned long)ASID(mm) << 48; | 83 | unsigned long asid = (unsigned long)ASID(mm) << 48; |
84 | 84 | ||
85 | dsb(); | 85 | dsb(ishst); |
86 | asm("tlbi aside1is, %0" : : "r" (asid)); | 86 | asm("tlbi aside1is, %0" : : "r" (asid)); |
87 | dsb(); | 87 | dsb(ish); |
88 | } | 88 | } |
89 | 89 | ||
90 | static inline void flush_tlb_page(struct vm_area_struct *vma, | 90 | static inline void flush_tlb_page(struct vm_area_struct *vma, |
@@ -93,16 +93,37 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, | |||
93 | unsigned long addr = uaddr >> 12 | | 93 | unsigned long addr = uaddr >> 12 | |
94 | ((unsigned long)ASID(vma->vm_mm) << 48); | 94 | ((unsigned long)ASID(vma->vm_mm) << 48); |
95 | 95 | ||
96 | dsb(); | 96 | dsb(ishst); |
97 | asm("tlbi vae1is, %0" : : "r" (addr)); | 97 | asm("tlbi vae1is, %0" : : "r" (addr)); |
98 | dsb(); | 98 | dsb(ish); |
99 | } | 99 | } |
100 | 100 | ||
101 | /* | 101 | static inline void flush_tlb_range(struct vm_area_struct *vma, |
102 | * Convert calls to our calling convention. | 102 | unsigned long start, unsigned long end) |
103 | */ | 103 | { |
104 | #define flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma) | 104 | unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48; |
105 | #define flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e) | 105 | unsigned long addr; |
106 | start = asid | (start >> 12); | ||
107 | end = asid | (end >> 12); | ||
108 | |||
109 | dsb(ishst); | ||
110 | for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) | ||
111 | asm("tlbi vae1is, %0" : : "r"(addr)); | ||
112 | dsb(ish); | ||
113 | } | ||
114 | |||
115 | static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) | ||
116 | { | ||
117 | unsigned long addr; | ||
118 | start >>= 12; | ||
119 | end >>= 12; | ||
120 | |||
121 | dsb(ishst); | ||
122 | for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) | ||
123 | asm("tlbi vaae1is, %0" : : "r"(addr)); | ||
124 | dsb(ish); | ||
125 | isb(); | ||
126 | } | ||
106 | 127 | ||
107 | /* | 128 | /* |
108 | * On AArch64, the cache coherency is handled via the set_pte_at() function. | 129 | * On AArch64, the cache coherency is handled via the set_pte_at() function. |
@@ -111,10 +132,10 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, | |||
111 | unsigned long addr, pte_t *ptep) | 132 | unsigned long addr, pte_t *ptep) |
112 | { | 133 | { |
113 | /* | 134 | /* |
114 | * set_pte() does not have a DSB, so make sure that the page table | 135 | * set_pte() does not have a DSB for user mappings, so make sure that |
115 | * write is visible. | 136 | * the page table write is visible. |
116 | */ | 137 | */ |
117 | dsb(); | 138 | dsb(ishst); |
118 | } | 139 | } |
119 | 140 | ||
120 | #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0) | 141 | #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0) |
diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c index fbb6e184365..ffbbdde7aba 100644 --- a/arch/arm64/kernel/early_printk.c +++ b/arch/arm64/kernel/early_printk.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/amba/serial.h> | 26 | #include <linux/amba/serial.h> |
27 | #include <linux/serial_reg.h> | 27 | #include <linux/serial_reg.h> |
28 | 28 | ||
29 | #include <asm/fixmap.h> | ||
30 | |||
29 | static void __iomem *early_base; | 31 | static void __iomem *early_base; |
30 | static void (*printch)(char ch); | 32 | static void (*printch)(char ch); |
31 | 33 | ||
@@ -141,8 +143,10 @@ static int __init setup_early_printk(char *buf) | |||
141 | } | 143 | } |
142 | /* no options parsing yet */ | 144 | /* no options parsing yet */ |
143 | 145 | ||
144 | if (paddr) | 146 | if (paddr) { |
145 | early_base = early_io_map(paddr, EARLYCON_IOBASE); | 147 | set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr); |
148 | early_base = (void __iomem *)fix_to_virt(FIX_EARLYCON_MEM_BASE); | ||
149 | } | ||
146 | 150 | ||
147 | printch = match->printch; | 151 | printch = match->printch; |
148 | early_console = &early_console_dev; | 152 | early_console = &early_console_dev; |
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 05a104c5951..65d6ed069f1 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S | |||
@@ -218,11 +218,7 @@ ENTRY(set_cpu_boot_mode_flag) | |||
218 | cmp w20, #BOOT_CPU_MODE_EL2 | 218 | cmp w20, #BOOT_CPU_MODE_EL2 |
219 | b.ne 1f | 219 | b.ne 1f |
220 | add x1, x1, #4 | 220 | add x1, x1, #4 |
221 | 1: dc cvac, x1 // Clean potentially dirty cache line | 221 | 1: str w20, [x1] // This CPU has booted in EL1 |
222 | dsb sy | ||
223 | str w20, [x1] // This CPU has booted in EL1 | ||
224 | dc civac, x1 // Clean&invalidate potentially stale cache line | ||
225 | dsb sy | ||
226 | ret | 222 | ret |
227 | ENDPROC(set_cpu_boot_mode_flag) | 223 | ENDPROC(set_cpu_boot_mode_flag) |
228 | 224 | ||
@@ -403,7 +399,7 @@ ENDPROC(__calc_phys_offset) | |||
403 | * - identity mapping to enable the MMU (low address, TTBR0) | 399 | * - identity mapping to enable the MMU (low address, TTBR0) |
404 | * - first few MB of the kernel linear mapping to jump to once the MMU has | 400 | * - first few MB of the kernel linear mapping to jump to once the MMU has |
405 | * been enabled, including the FDT blob (TTBR1) | 401 | * been enabled, including the FDT blob (TTBR1) |
406 | * - UART mapping if CONFIG_EARLY_PRINTK is enabled (TTBR1) | 402 | * - pgd entry for fixed mappings (TTBR1) |
407 | */ | 403 | */ |
408 | __create_page_tables: | 404 | __create_page_tables: |
409 | pgtbl x25, x26, x28 // idmap_pg_dir and swapper_pg_dir addresses | 405 | pgtbl x25, x26, x28 // idmap_pg_dir and swapper_pg_dir addresses |
@@ -469,15 +465,12 @@ __create_page_tables: | |||
469 | sub x6, x6, #1 // inclusive range | 465 | sub x6, x6, #1 // inclusive range |
470 | create_block_map x0, x7, x3, x5, x6 | 466 | create_block_map x0, x7, x3, x5, x6 |
471 | 1: | 467 | 1: |
472 | #ifdef CONFIG_EARLY_PRINTK | ||
473 | /* | 468 | /* |
474 | * Create the pgd entry for the UART mapping. The full mapping is done | 469 | * Create the pgd entry for the fixed mappings. |
475 | * later based earlyprintk kernel parameter. | ||
476 | */ | 470 | */ |
477 | ldr x5, =EARLYCON_IOBASE // UART virtual address | 471 | ldr x5, =FIXADDR_TOP // Fixed mapping virtual address |
478 | add x0, x26, #2 * PAGE_SIZE // section table address | 472 | add x0, x26, #2 * PAGE_SIZE // section table address |
479 | create_pgd_entry x26, x0, x5, x6, x7 | 473 | create_pgd_entry x26, x0, x5, x6, x7 |
480 | #endif | ||
481 | 474 | ||
482 | /* | 475 | /* |
483 | * Since the page tables have been populated with non-cacheable | 476 | * Since the page tables have been populated with non-cacheable |
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index fc8a3872a5b..0e9ce28145d 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c | |||
@@ -295,7 +295,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
295 | * Complete any pending TLB or cache maintenance on this CPU in case | 295 | * Complete any pending TLB or cache maintenance on this CPU in case |
296 | * the thread migrates to a different CPU. | 296 | * the thread migrates to a different CPU. |
297 | */ | 297 | */ |
298 | dsb(); | 298 | dsb(ish); |
299 | 299 | ||
300 | /* the actual thread switch */ | 300 | /* the actual thread switch */ |
301 | last = cpu_switch_to(prev, next); | 301 | last = cpu_switch_to(prev, next); |
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index e633c5e9b05..46b441679d8 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/of_fdt.h> | 42 | #include <linux/of_fdt.h> |
43 | #include <linux/of_platform.h> | 43 | #include <linux/of_platform.h> |
44 | 44 | ||
45 | #include <asm/fixmap.h> | ||
45 | #include <asm/cputype.h> | 46 | #include <asm/cputype.h> |
46 | #include <asm/elf.h> | 47 | #include <asm/elf.h> |
47 | #include <asm/cputable.h> | 48 | #include <asm/cputable.h> |
@@ -360,6 +361,8 @@ void __init setup_arch(char **cmdline_p) | |||
360 | 361 | ||
361 | *cmdline_p = boot_command_line; | 362 | *cmdline_p = boot_command_line; |
362 | 363 | ||
364 | early_ioremap_init(); | ||
365 | |||
363 | parse_early_param(); | 366 | parse_early_param(); |
364 | 367 | ||
365 | arm64_memblock_init(); | 368 | arm64_memblock_init(); |
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 4a0998962fc..e3cf0962624 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c | |||
@@ -100,8 +100,7 @@ static int restore_sigframe(struct pt_regs *regs, | |||
100 | { | 100 | { |
101 | sigset_t set; | 101 | sigset_t set; |
102 | int i, err; | 102 | int i, err; |
103 | struct aux_context __user *aux = | 103 | void *aux = sf->uc.uc_mcontext.__reserved; |
104 | (struct aux_context __user *)sf->uc.uc_mcontext.__reserved; | ||
105 | 104 | ||
106 | err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); | 105 | err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); |
107 | if (err == 0) | 106 | if (err == 0) |
@@ -121,8 +120,11 @@ static int restore_sigframe(struct pt_regs *regs, | |||
121 | 120 | ||
122 | err |= !valid_user_regs(®s->user_regs); | 121 | err |= !valid_user_regs(®s->user_regs); |
123 | 122 | ||
124 | if (err == 0) | 123 | if (err == 0) { |
125 | err |= restore_fpsimd_context(&aux->fpsimd); | 124 | struct fpsimd_context *fpsimd_ctx = |
125 | container_of(aux, struct fpsimd_context, head); | ||
126 | err |= restore_fpsimd_context(fpsimd_ctx); | ||
127 | } | ||
126 | 128 | ||
127 | return err; | 129 | return err; |
128 | } | 130 | } |
@@ -167,8 +169,8 @@ static int setup_sigframe(struct rt_sigframe __user *sf, | |||
167 | struct pt_regs *regs, sigset_t *set) | 169 | struct pt_regs *regs, sigset_t *set) |
168 | { | 170 | { |
169 | int i, err = 0; | 171 | int i, err = 0; |
170 | struct aux_context __user *aux = | 172 | void *aux = sf->uc.uc_mcontext.__reserved; |
171 | (struct aux_context __user *)sf->uc.uc_mcontext.__reserved; | 173 | struct _aarch64_ctx *end; |
172 | 174 | ||
173 | /* set up the stack frame for unwinding */ | 175 | /* set up the stack frame for unwinding */ |
174 | __put_user_error(regs->regs[29], &sf->fp, err); | 176 | __put_user_error(regs->regs[29], &sf->fp, err); |
@@ -185,12 +187,17 @@ static int setup_sigframe(struct rt_sigframe __user *sf, | |||
185 | 187 | ||
186 | err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); | 188 | err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); |
187 | 189 | ||
188 | if (err == 0) | 190 | if (err == 0) { |
189 | err |= preserve_fpsimd_context(&aux->fpsimd); | 191 | struct fpsimd_context *fpsimd_ctx = |
192 | container_of(aux, struct fpsimd_context, head); | ||
193 | err |= preserve_fpsimd_context(fpsimd_ctx); | ||
194 | aux += sizeof(*fpsimd_ctx); | ||
195 | } | ||
190 | 196 | ||
191 | /* set the "end" magic */ | 197 | /* set the "end" magic */ |
192 | __put_user_error(0, &aux->end.magic, err); | 198 | end = aux; |
193 | __put_user_error(0, &aux->end.size, err); | 199 | __put_user_error(0, &end->magic, err); |
200 | __put_user_error(0, &end->size, err); | ||
194 | 201 | ||
195 | return err; | 202 | return err; |
196 | } | 203 | } |
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c index 44c22805d2e..0347d38eea2 100644 --- a/arch/arm64/kernel/smp_spin_table.c +++ b/arch/arm64/kernel/smp_spin_table.c | |||
@@ -30,7 +30,6 @@ extern void secondary_holding_pen(void); | |||
30 | volatile unsigned long secondary_holding_pen_release = INVALID_HWID; | 30 | volatile unsigned long secondary_holding_pen_release = INVALID_HWID; |
31 | 31 | ||
32 | static phys_addr_t cpu_release_addr[NR_CPUS]; | 32 | static phys_addr_t cpu_release_addr[NR_CPUS]; |
33 | static DEFINE_RAW_SPINLOCK(boot_lock); | ||
34 | 33 | ||
35 | /* | 34 | /* |
36 | * Write secondary_holding_pen_release in a way that is guaranteed to be | 35 | * Write secondary_holding_pen_release in a way that is guaranteed to be |
@@ -94,14 +93,6 @@ static int smp_spin_table_cpu_prepare(unsigned int cpu) | |||
94 | 93 | ||
95 | static int smp_spin_table_cpu_boot(unsigned int cpu) | 94 | static int smp_spin_table_cpu_boot(unsigned int cpu) |
96 | { | 95 | { |
97 | unsigned long timeout; | ||
98 | |||
99 | /* | ||
100 | * Set synchronisation state between this boot processor | ||
101 | * and the secondary one | ||
102 | */ | ||
103 | raw_spin_lock(&boot_lock); | ||
104 | |||
105 | /* | 96 | /* |
106 | * Update the pen release flag. | 97 | * Update the pen release flag. |
107 | */ | 98 | */ |
@@ -112,34 +103,7 @@ static int smp_spin_table_cpu_boot(unsigned int cpu) | |||
112 | */ | 103 | */ |
113 | sev(); | 104 | sev(); |
114 | 105 | ||
115 | timeout = jiffies + (1 * HZ); | 106 | return 0; |
116 | while (time_before(jiffies, timeout)) { | ||
117 | if (secondary_holding_pen_release == INVALID_HWID) | ||
118 | break; | ||
119 | udelay(10); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Now the secondary core is starting up let it run its | ||
124 | * calibrations, then wait for it to finish | ||
125 | */ | ||
126 | raw_spin_unlock(&boot_lock); | ||
127 | |||
128 | return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0; | ||
129 | } | ||
130 | |||
131 | void smp_spin_table_cpu_postboot(void) | ||
132 | { | ||
133 | /* | ||
134 | * Let the primary processor know we're out of the pen. | ||
135 | */ | ||
136 | write_pen_release(INVALID_HWID); | ||
137 | |||
138 | /* | ||
139 | * Synchronise with the boot thread. | ||
140 | */ | ||
141 | raw_spin_lock(&boot_lock); | ||
142 | raw_spin_unlock(&boot_lock); | ||
143 | } | 107 | } |
144 | 108 | ||
145 | const struct cpu_operations smp_spin_table_ops = { | 109 | const struct cpu_operations smp_spin_table_ops = { |
@@ -147,5 +111,4 @@ const struct cpu_operations smp_spin_table_ops = { | |||
147 | .cpu_init = smp_spin_table_cpu_init, | 111 | .cpu_init = smp_spin_table_cpu_init, |
148 | .cpu_prepare = smp_spin_table_cpu_prepare, | 112 | .cpu_prepare = smp_spin_table_cpu_prepare, |
149 | .cpu_boot = smp_spin_table_cpu_boot, | 113 | .cpu_boot = smp_spin_table_cpu_boot, |
150 | .cpu_postboot = smp_spin_table_cpu_postboot, | ||
151 | }; | 114 | }; |
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 02e9d09e1d8..d800dbc8693 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c | |||
@@ -70,13 +70,13 @@ static u32 get_ccsidr(u32 csselr) | |||
70 | static void do_dc_cisw(u32 val) | 70 | static void do_dc_cisw(u32 val) |
71 | { | 71 | { |
72 | asm volatile("dc cisw, %x0" : : "r" (val)); | 72 | asm volatile("dc cisw, %x0" : : "r" (val)); |
73 | dsb(); | 73 | dsb(ish); |
74 | } | 74 | } |
75 | 75 | ||
76 | static void do_dc_csw(u32 val) | 76 | static void do_dc_csw(u32 val) |
77 | { | 77 | { |
78 | asm volatile("dc csw, %x0" : : "r" (val)); | 78 | asm volatile("dc csw, %x0" : : "r" (val)); |
79 | dsb(); | 79 | dsb(ish); |
80 | } | 80 | } |
81 | 81 | ||
82 | /* See note at ARM ARM B1.14.4 */ | 82 | /* See note at ARM ARM B1.14.4 */ |
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index b51d36401d8..3ecb56c624d 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-y := dma-mapping.o extable.o fault.o init.o \ | 1 | obj-y := dma-mapping.o extable.o fault.o init.o \ |
2 | cache.o copypage.o flush.o \ | 2 | cache.o copypage.o flush.o \ |
3 | ioremap.o mmap.o pgd.o mmu.o \ | 3 | ioremap.o mmap.o pgd.o mmu.o \ |
4 | context.o tlb.o proc.o | 4 | context.o proc.o |
5 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 5 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 9337524601e..4164c5ace9f 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c | |||
@@ -36,10 +36,8 @@ EXPORT_SYMBOL(dma_ops); | |||
36 | static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot, | 36 | static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot, |
37 | bool coherent) | 37 | bool coherent) |
38 | { | 38 | { |
39 | if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) | 39 | if (!coherent || dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) |
40 | return pgprot_writecombine(prot); | 40 | return pgprot_writecombine(prot); |
41 | else if (!coherent) | ||
42 | return pgprot_dmacoherent(prot); | ||
43 | return prot; | 41 | return prot; |
44 | } | 42 | } |
45 | 43 | ||
@@ -117,7 +115,7 @@ static void *__dma_alloc_noncoherent(struct device *dev, size_t size, | |||
117 | for (i = 0; i < (size >> PAGE_SHIFT); i++) | 115 | for (i = 0; i < (size >> PAGE_SHIFT); i++) |
118 | map[i] = page + i; | 116 | map[i] = page + i; |
119 | coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP, | 117 | coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP, |
120 | __get_dma_pgprot(attrs, pgprot_default, false)); | 118 | __get_dma_pgprot(attrs, __pgprot(PROT_NORMAL_NC), false)); |
121 | kfree(map); | 119 | kfree(map); |
122 | if (!coherent_ptr) | 120 | if (!coherent_ptr) |
123 | goto no_map; | 121 | goto no_map; |
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c index 2bb1d586664..7ec328392ae 100644 --- a/arch/arm64/mm/ioremap.c +++ b/arch/arm64/mm/ioremap.c | |||
@@ -25,6 +25,10 @@ | |||
25 | #include <linux/vmalloc.h> | 25 | #include <linux/vmalloc.h> |
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | 27 | ||
28 | #include <asm/fixmap.h> | ||
29 | #include <asm/tlbflush.h> | ||
30 | #include <asm/pgalloc.h> | ||
31 | |||
28 | static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, | 32 | static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, |
29 | pgprot_t prot, void *caller) | 33 | pgprot_t prot, void *caller) |
30 | { | 34 | { |
@@ -98,3 +102,84 @@ void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size) | |||
98 | __builtin_return_address(0)); | 102 | __builtin_return_address(0)); |
99 | } | 103 | } |
100 | EXPORT_SYMBOL(ioremap_cache); | 104 | EXPORT_SYMBOL(ioremap_cache); |
105 | |||
106 | #ifndef CONFIG_ARM64_64K_PAGES | ||
107 | static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss; | ||
108 | #endif | ||
109 | |||
110 | static inline pmd_t * __init early_ioremap_pmd(unsigned long addr) | ||
111 | { | ||
112 | pgd_t *pgd; | ||
113 | pud_t *pud; | ||
114 | |||
115 | pgd = pgd_offset_k(addr); | ||
116 | BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd)); | ||
117 | |||
118 | pud = pud_offset(pgd, addr); | ||
119 | BUG_ON(pud_none(*pud) || pud_bad(*pud)); | ||
120 | |||
121 | return pmd_offset(pud, addr); | ||
122 | } | ||
123 | |||
124 | static inline pte_t * __init early_ioremap_pte(unsigned long addr) | ||
125 | { | ||
126 | pmd_t *pmd = early_ioremap_pmd(addr); | ||
127 | |||
128 | BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd)); | ||
129 | |||
130 | return pte_offset_kernel(pmd, addr); | ||
131 | } | ||
132 | |||
133 | void __init early_ioremap_init(void) | ||
134 | { | ||
135 | pmd_t *pmd; | ||
136 | |||
137 | pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)); | ||
138 | #ifndef CONFIG_ARM64_64K_PAGES | ||
139 | /* need to populate pmd for 4k pagesize only */ | ||
140 | pmd_populate_kernel(&init_mm, pmd, bm_pte); | ||
141 | #endif | ||
142 | /* | ||
143 | * The boot-ioremap range spans multiple pmds, for which | ||
144 | * we are not prepared: | ||
145 | */ | ||
146 | BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT) | ||
147 | != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT)); | ||
148 | |||
149 | if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) { | ||
150 | WARN_ON(1); | ||
151 | pr_warn("pmd %p != %p\n", | ||
152 | pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))); | ||
153 | pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n", | ||
154 | fix_to_virt(FIX_BTMAP_BEGIN)); | ||
155 | pr_warn("fix_to_virt(FIX_BTMAP_END): %08lx\n", | ||
156 | fix_to_virt(FIX_BTMAP_END)); | ||
157 | |||
158 | pr_warn("FIX_BTMAP_END: %d\n", FIX_BTMAP_END); | ||
159 | pr_warn("FIX_BTMAP_BEGIN: %d\n", | ||
160 | FIX_BTMAP_BEGIN); | ||
161 | } | ||
162 | |||
163 | early_ioremap_setup(); | ||
164 | } | ||
165 | |||
166 | void __init __early_set_fixmap(enum fixed_addresses idx, | ||
167 | phys_addr_t phys, pgprot_t flags) | ||
168 | { | ||
169 | unsigned long addr = __fix_to_virt(idx); | ||
170 | pte_t *pte; | ||
171 | |||
172 | if (idx >= __end_of_fixed_addresses) { | ||
173 | BUG(); | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | pte = early_ioremap_pte(addr); | ||
178 | |||
179 | if (pgprot_val(flags)) | ||
180 | set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags)); | ||
181 | else { | ||
182 | pte_clear(&init_mm, addr, pte); | ||
183 | flush_tlb_kernel_range(addr, addr+PAGE_SIZE); | ||
184 | } | ||
185 | } | ||
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index f8dc7e8fce6..a2155ca6921 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c | |||
@@ -43,11 +43,6 @@ | |||
43 | struct page *empty_zero_page; | 43 | struct page *empty_zero_page; |
44 | EXPORT_SYMBOL(empty_zero_page); | 44 | EXPORT_SYMBOL(empty_zero_page); |
45 | 45 | ||
46 | pgprot_t pgprot_default; | ||
47 | EXPORT_SYMBOL(pgprot_default); | ||
48 | |||
49 | static pmdval_t prot_sect_kernel; | ||
50 | |||
51 | struct cachepolicy { | 46 | struct cachepolicy { |
52 | const char policy[16]; | 47 | const char policy[16]; |
53 | u64 mair; | 48 | u64 mair; |
@@ -122,33 +117,6 @@ static int __init early_cachepolicy(char *p) | |||
122 | } | 117 | } |
123 | early_param("cachepolicy", early_cachepolicy); | 118 | early_param("cachepolicy", early_cachepolicy); |
124 | 119 | ||
125 | /* | ||
126 | * Adjust the PMD section entries according to the CPU in use. | ||
127 | */ | ||
128 | static void __init init_mem_pgprot(void) | ||
129 | { | ||
130 | pteval_t default_pgprot; | ||
131 | int i; | ||
132 | |||
133 | default_pgprot = PTE_ATTRINDX(MT_NORMAL); | ||
134 | prot_sect_kernel = PMD_TYPE_SECT | PMD_SECT_AF | PMD_ATTRINDX(MT_NORMAL); | ||
135 | |||
136 | #ifdef CONFIG_SMP | ||
137 | /* | ||
138 | * Mark memory with the "shared" attribute for SMP systems | ||
139 | */ | ||
140 | default_pgprot |= PTE_SHARED; | ||
141 | prot_sect_kernel |= PMD_SECT_S; | ||
142 | #endif | ||
143 | |||
144 | for (i = 0; i < 16; i++) { | ||
145 | unsigned long v = pgprot_val(protection_map[i]); | ||
146 | protection_map[i] = __pgprot(v | default_pgprot); | ||
147 | } | ||
148 | |||
149 | pgprot_default = __pgprot(PTE_TYPE_PAGE | PTE_AF | default_pgprot); | ||
150 | } | ||
151 | |||
152 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | 120 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, |
153 | unsigned long size, pgprot_t vma_prot) | 121 | unsigned long size, pgprot_t vma_prot) |
154 | { | 122 | { |
@@ -168,7 +136,8 @@ static void __init *early_alloc(unsigned long sz) | |||
168 | } | 136 | } |
169 | 137 | ||
170 | static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | 138 | static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, |
171 | unsigned long end, unsigned long pfn) | 139 | unsigned long end, unsigned long pfn, |
140 | pgprot_t prot) | ||
172 | { | 141 | { |
173 | pte_t *pte; | 142 | pte_t *pte; |
174 | 143 | ||
@@ -180,16 +149,28 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | |||
180 | 149 | ||
181 | pte = pte_offset_kernel(pmd, addr); | 150 | pte = pte_offset_kernel(pmd, addr); |
182 | do { | 151 | do { |
183 | set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); | 152 | set_pte(pte, pfn_pte(pfn, prot)); |
184 | pfn++; | 153 | pfn++; |
185 | } while (pte++, addr += PAGE_SIZE, addr != end); | 154 | } while (pte++, addr += PAGE_SIZE, addr != end); |
186 | } | 155 | } |
187 | 156 | ||
188 | static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | 157 | static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, |
189 | unsigned long end, phys_addr_t phys) | 158 | unsigned long end, phys_addr_t phys, |
159 | int map_io) | ||
190 | { | 160 | { |
191 | pmd_t *pmd; | 161 | pmd_t *pmd; |
192 | unsigned long next; | 162 | unsigned long next; |
163 | pmdval_t prot_sect; | ||
164 | pgprot_t prot_pte; | ||
165 | |||
166 | if (map_io) { | ||
167 | prot_sect = PMD_TYPE_SECT | PMD_SECT_AF | | ||
168 | PMD_ATTRINDX(MT_DEVICE_nGnRE); | ||
169 | prot_pte = __pgprot(PROT_DEVICE_nGnRE); | ||
170 | } else { | ||
171 | prot_sect = PROT_SECT_NORMAL_EXEC; | ||
172 | prot_pte = PAGE_KERNEL_EXEC; | ||
173 | } | ||
193 | 174 | ||
194 | /* | 175 | /* |
195 | * Check for initial section mappings in the pgd/pud and remove them. | 176 | * Check for initial section mappings in the pgd/pud and remove them. |
@@ -205,7 +186,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | |||
205 | /* try section mapping first */ | 186 | /* try section mapping first */ |
206 | if (((addr | next | phys) & ~SECTION_MASK) == 0) { | 187 | if (((addr | next | phys) & ~SECTION_MASK) == 0) { |
207 | pmd_t old_pmd =*pmd; | 188 | pmd_t old_pmd =*pmd; |
208 | set_pmd(pmd, __pmd(phys | prot_sect_kernel)); | 189 | set_pmd(pmd, __pmd(phys | prot_sect)); |
209 | /* | 190 | /* |
210 | * Check for previous table entries created during | 191 | * Check for previous table entries created during |
211 | * boot (__create_page_tables) and flush them. | 192 | * boot (__create_page_tables) and flush them. |
@@ -213,21 +194,23 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | |||
213 | if (!pmd_none(old_pmd)) | 194 | if (!pmd_none(old_pmd)) |
214 | flush_tlb_all(); | 195 | flush_tlb_all(); |
215 | } else { | 196 | } else { |
216 | alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys)); | 197 | alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), |
198 | prot_pte); | ||
217 | } | 199 | } |
218 | phys += next - addr; | 200 | phys += next - addr; |
219 | } while (pmd++, addr = next, addr != end); | 201 | } while (pmd++, addr = next, addr != end); |
220 | } | 202 | } |
221 | 203 | ||
222 | static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, | 204 | static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, |
223 | unsigned long end, unsigned long phys) | 205 | unsigned long end, unsigned long phys, |
206 | int map_io) | ||
224 | { | 207 | { |
225 | pud_t *pud = pud_offset(pgd, addr); | 208 | pud_t *pud = pud_offset(pgd, addr); |
226 | unsigned long next; | 209 | unsigned long next; |
227 | 210 | ||
228 | do { | 211 | do { |
229 | next = pud_addr_end(addr, end); | 212 | next = pud_addr_end(addr, end); |
230 | alloc_init_pmd(pud, addr, next, phys); | 213 | alloc_init_pmd(pud, addr, next, phys, map_io); |
231 | phys += next - addr; | 214 | phys += next - addr; |
232 | } while (pud++, addr = next, addr != end); | 215 | } while (pud++, addr = next, addr != end); |
233 | } | 216 | } |
@@ -236,70 +219,43 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, | |||
236 | * Create the page directory entries and any necessary page tables for the | 219 | * Create the page directory entries and any necessary page tables for the |
237 | * mapping specified by 'md'. | 220 | * mapping specified by 'md'. |
238 | */ | 221 | */ |
239 | static void __init create_mapping(phys_addr_t phys, unsigned long virt, | 222 | static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys, |
240 | phys_addr_t size) | 223 | unsigned long virt, phys_addr_t size, |
224 | int map_io) | ||
241 | { | 225 | { |
242 | unsigned long addr, length, end, next; | 226 | unsigned long addr, length, end, next; |
243 | pgd_t *pgd; | ||
244 | |||
245 | if (virt < VMALLOC_START) { | ||
246 | pr_warning("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n", | ||
247 | phys, virt); | ||
248 | return; | ||
249 | } | ||
250 | 227 | ||
251 | addr = virt & PAGE_MASK; | 228 | addr = virt & PAGE_MASK; |
252 | length = PAGE_ALIGN(size + (virt & ~PAGE_MASK)); | 229 | length = PAGE_ALIGN(size + (virt & ~PAGE_MASK)); |
253 | 230 | ||
254 | pgd = pgd_offset_k(addr); | ||
255 | end = addr + length; | 231 | end = addr + length; |
256 | do { | 232 | do { |
257 | next = pgd_addr_end(addr, end); | 233 | next = pgd_addr_end(addr, end); |
258 | alloc_init_pud(pgd, addr, next, phys); | 234 | alloc_init_pud(pgd, addr, next, phys, map_io); |
259 | phys += next - addr; | 235 | phys += next - addr; |
260 | } while (pgd++, addr = next, addr != end); | 236 | } while (pgd++, addr = next, addr != end); |
261 | } | 237 | } |
262 | 238 | ||
263 | #ifdef CONFIG_EARLY_PRINTK | 239 | static void __init create_mapping(phys_addr_t phys, unsigned long virt, |
264 | /* | 240 | phys_addr_t size) |
265 | * Create an early I/O mapping using the pgd/pmd entries already populated | ||
266 | * in head.S as this function is called too early to allocated any memory. The | ||
267 | * mapping size is 2MB with 4KB pages or 64KB or 64KB pages. | ||
268 | */ | ||
269 | void __iomem * __init early_io_map(phys_addr_t phys, unsigned long virt) | ||
270 | { | 241 | { |
271 | unsigned long size, mask; | 242 | if (virt < VMALLOC_START) { |
272 | bool page64k = IS_ENABLED(CONFIG_ARM64_64K_PAGES); | 243 | pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", |
273 | pgd_t *pgd; | 244 | &phys, virt); |
274 | pud_t *pud; | 245 | return; |
275 | pmd_t *pmd; | ||
276 | pte_t *pte; | ||
277 | |||
278 | /* | ||
279 | * No early pte entries with !ARM64_64K_PAGES configuration, so using | ||
280 | * sections (pmd). | ||
281 | */ | ||
282 | size = page64k ? PAGE_SIZE : SECTION_SIZE; | ||
283 | mask = ~(size - 1); | ||
284 | |||
285 | pgd = pgd_offset_k(virt); | ||
286 | pud = pud_offset(pgd, virt); | ||
287 | if (pud_none(*pud)) | ||
288 | return NULL; | ||
289 | pmd = pmd_offset(pud, virt); | ||
290 | |||
291 | if (page64k) { | ||
292 | if (pmd_none(*pmd)) | ||
293 | return NULL; | ||
294 | pte = pte_offset_kernel(pmd, virt); | ||
295 | set_pte(pte, __pte((phys & mask) | PROT_DEVICE_nGnRE)); | ||
296 | } else { | ||
297 | set_pmd(pmd, __pmd((phys & mask) | PROT_SECT_DEVICE_nGnRE)); | ||
298 | } | 246 | } |
247 | __create_mapping(pgd_offset_k(virt & PAGE_MASK), phys, virt, size, 0); | ||
248 | } | ||
299 | 249 | ||
300 | return (void __iomem *)((virt & mask) + (phys & ~mask)); | 250 | void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io) |
251 | { | ||
252 | if ((addr >> PGDIR_SHIFT) >= ARRAY_SIZE(idmap_pg_dir)) { | ||
253 | pr_warn("BUG: not creating id mapping for %pa\n", &addr); | ||
254 | return; | ||
255 | } | ||
256 | __create_mapping(&idmap_pg_dir[pgd_index(addr)], | ||
257 | addr, addr, size, map_io); | ||
301 | } | 258 | } |
302 | #endif | ||
303 | 259 | ||
304 | static void __init map_mem(void) | 260 | static void __init map_mem(void) |
305 | { | 261 | { |
@@ -357,7 +313,6 @@ void __init paging_init(void) | |||
357 | { | 313 | { |
358 | void *zero_page; | 314 | void *zero_page; |
359 | 315 | ||
360 | init_mem_pgprot(); | ||
361 | map_mem(); | 316 | map_mem(); |
362 | 317 | ||
363 | /* | 318 | /* |
@@ -416,6 +371,9 @@ int kern_addr_valid(unsigned long addr) | |||
416 | if (pmd_none(*pmd)) | 371 | if (pmd_none(*pmd)) |
417 | return 0; | 372 | return 0; |
418 | 373 | ||
374 | if (pmd_sect(*pmd)) | ||
375 | return pfn_valid(pmd_pfn(*pmd)); | ||
376 | |||
419 | pte = pte_offset_kernel(pmd, addr); | 377 | pte = pte_offset_kernel(pmd, addr); |
420 | if (pte_none(*pte)) | 378 | if (pte_none(*pte)) |
421 | return 0; | 379 | return 0; |
@@ -456,7 +414,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node) | |||
456 | if (!p) | 414 | if (!p) |
457 | return -ENOMEM; | 415 | return -ENOMEM; |
458 | 416 | ||
459 | set_pmd(pmd, __pmd(__pa(p) | prot_sect_kernel)); | 417 | set_pmd(pmd, __pmd(__pa(p) | PROT_SECT_NORMAL)); |
460 | } else | 418 | } else |
461 | vmemmap_verify((pte_t *)pmd, node, addr, next); | 419 | vmemmap_verify((pte_t *)pmd, node, addr, next); |
462 | } while (addr = next, addr != end); | 420 | } while (addr = next, addr != end); |
diff --git a/arch/arm64/mm/tlb.S b/arch/arm64/mm/tlb.S deleted file mode 100644 index 19da91e0cd2..00000000000 --- a/arch/arm64/mm/tlb.S +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/tlb.S | ||
3 | * | ||
4 | * Copyright (C) 1997-2002 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * Written by Catalin Marinas <catalin.marinas@arm.com> | ||
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, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | #include <linux/linkage.h> | ||
21 | #include <asm/assembler.h> | ||
22 | #include <asm/asm-offsets.h> | ||
23 | #include <asm/page.h> | ||
24 | #include <asm/tlbflush.h> | ||
25 | #include "proc-macros.S" | ||
26 | |||
27 | /* | ||
28 | * __cpu_flush_user_tlb_range(start, end, vma) | ||
29 | * | ||
30 | * Invalidate a range of TLB entries in the specified address space. | ||
31 | * | ||
32 | * - start - start address (may not be aligned) | ||
33 | * - end - end address (exclusive, may not be aligned) | ||
34 | * - vma - vma_struct describing address range | ||
35 | */ | ||
36 | ENTRY(__cpu_flush_user_tlb_range) | ||
37 | vma_vm_mm x3, x2 // get vma->vm_mm | ||
38 | mmid w3, x3 // get vm_mm->context.id | ||
39 | dsb sy | ||
40 | lsr x0, x0, #12 // align address | ||
41 | lsr x1, x1, #12 | ||
42 | bfi x0, x3, #48, #16 // start VA and ASID | ||
43 | bfi x1, x3, #48, #16 // end VA and ASID | ||
44 | 1: tlbi vae1is, x0 // TLB invalidate by address and ASID | ||
45 | add x0, x0, #1 | ||
46 | cmp x0, x1 | ||
47 | b.lo 1b | ||
48 | dsb sy | ||
49 | ret | ||
50 | ENDPROC(__cpu_flush_user_tlb_range) | ||
51 | |||
52 | /* | ||
53 | * __cpu_flush_kern_tlb_range(start,end) | ||
54 | * | ||
55 | * Invalidate a range of kernel TLB entries. | ||
56 | * | ||
57 | * - start - start address (may not be aligned) | ||
58 | * - end - end address (exclusive, may not be aligned) | ||
59 | */ | ||
60 | ENTRY(__cpu_flush_kern_tlb_range) | ||
61 | dsb sy | ||
62 | lsr x0, x0, #12 // align address | ||
63 | lsr x1, x1, #12 | ||
64 | 1: tlbi vaae1is, x0 // TLB invalidate by address | ||
65 | add x0, x0, #1 | ||
66 | cmp x0, x1 | ||
67 | b.lo 1b | ||
68 | dsb sy | ||
69 | isb | ||
70 | ret | ||
71 | ENDPROC(__cpu_flush_kern_tlb_range) | ||
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index abdfb10e7ec..c7663060305 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c | |||
@@ -43,13 +43,13 @@ | |||
43 | #include <asm/pci-bridge.h> | 43 | #include <asm/pci-bridge.h> |
44 | 44 | ||
45 | #ifdef CONFIG_EARLY_PRINTK | 45 | #ifdef CONFIG_EARLY_PRINTK |
46 | static char *stdout; | 46 | static const char *stdout; |
47 | 47 | ||
48 | static int __init early_init_dt_scan_chosen_serial(unsigned long node, | 48 | static int __init early_init_dt_scan_chosen_serial(unsigned long node, |
49 | const char *uname, int depth, void *data) | 49 | const char *uname, int depth, void *data) |
50 | { | 50 | { |
51 | unsigned long l; | 51 | int l; |
52 | char *p; | 52 | const char *p; |
53 | 53 | ||
54 | pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname); | 54 | pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname); |
55 | 55 | ||
@@ -80,7 +80,7 @@ static int __init early_init_dt_scan_chosen_serial(unsigned long node, | |||
80 | (strncmp(p, "xlnx,opb-uartlite", 17) == 0) || | 80 | (strncmp(p, "xlnx,opb-uartlite", 17) == 0) || |
81 | (strncmp(p, "xlnx,axi-uartlite", 17) == 0) || | 81 | (strncmp(p, "xlnx,axi-uartlite", 17) == 0) || |
82 | (strncmp(p, "xlnx,mdm", 8) == 0)) { | 82 | (strncmp(p, "xlnx,mdm", 8) == 0)) { |
83 | unsigned int *addrp; | 83 | const unsigned int *addrp; |
84 | 84 | ||
85 | *(u32 *)data = UARTLITE; | 85 | *(u32 *)data = UARTLITE; |
86 | 86 | ||
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c index 7898be90f2d..d64e92b22dd 100644 --- a/arch/powerpc/kernel/epapr_paravirt.c +++ b/arch/powerpc/kernel/epapr_paravirt.c | |||
@@ -36,7 +36,7 @@ static int __init early_init_dt_scan_epapr(unsigned long node, | |||
36 | int depth, void *data) | 36 | int depth, void *data) |
37 | { | 37 | { |
38 | const u32 *insts; | 38 | const u32 *insts; |
39 | unsigned long len; | 39 | int len; |
40 | int i; | 40 | int i; |
41 | 41 | ||
42 | insts = of_get_flat_dt_prop(node, "hcall-instructions", &len); | 42 | insts = of_get_flat_dt_prop(node, "hcall-instructions", &len); |
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 2230fd0ca3e..7213d930918 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c | |||
@@ -55,9 +55,9 @@ int crash_mem_ranges; | |||
55 | int __init early_init_dt_scan_fw_dump(unsigned long node, | 55 | int __init early_init_dt_scan_fw_dump(unsigned long node, |
56 | const char *uname, int depth, void *data) | 56 | const char *uname, int depth, void *data) |
57 | { | 57 | { |
58 | __be32 *sections; | 58 | const __be32 *sections; |
59 | int i, num_sections; | 59 | int i, num_sections; |
60 | unsigned long size; | 60 | int size; |
61 | const int *token; | 61 | const int *token; |
62 | 62 | ||
63 | if (depth != 1 || strcmp(uname, "rtas") != 0) | 63 | if (depth != 1 || strcmp(uname, "rtas") != 0) |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f58c0d3aaeb..8dd5a093195 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -162,7 +162,7 @@ static struct ibm_pa_feature { | |||
162 | {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, | 162 | {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, |
163 | }; | 163 | }; |
164 | 164 | ||
165 | static void __init scan_features(unsigned long node, unsigned char *ftrs, | 165 | static void __init scan_features(unsigned long node, const unsigned char *ftrs, |
166 | unsigned long tablelen, | 166 | unsigned long tablelen, |
167 | struct ibm_pa_feature *fp, | 167 | struct ibm_pa_feature *fp, |
168 | unsigned long ft_size) | 168 | unsigned long ft_size) |
@@ -201,8 +201,8 @@ static void __init scan_features(unsigned long node, unsigned char *ftrs, | |||
201 | 201 | ||
202 | static void __init check_cpu_pa_features(unsigned long node) | 202 | static void __init check_cpu_pa_features(unsigned long node) |
203 | { | 203 | { |
204 | unsigned char *pa_ftrs; | 204 | const unsigned char *pa_ftrs; |
205 | unsigned long tablelen; | 205 | int tablelen; |
206 | 206 | ||
207 | pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); | 207 | pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); |
208 | if (pa_ftrs == NULL) | 208 | if (pa_ftrs == NULL) |
@@ -215,7 +215,7 @@ static void __init check_cpu_pa_features(unsigned long node) | |||
215 | #ifdef CONFIG_PPC_STD_MMU_64 | 215 | #ifdef CONFIG_PPC_STD_MMU_64 |
216 | static void __init check_cpu_slb_size(unsigned long node) | 216 | static void __init check_cpu_slb_size(unsigned long node) |
217 | { | 217 | { |
218 | __be32 *slb_size_ptr; | 218 | const __be32 *slb_size_ptr; |
219 | 219 | ||
220 | slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL); | 220 | slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL); |
221 | if (slb_size_ptr != NULL) { | 221 | if (slb_size_ptr != NULL) { |
@@ -256,7 +256,7 @@ static struct feature_property { | |||
256 | static inline void identical_pvr_fixup(unsigned long node) | 256 | static inline void identical_pvr_fixup(unsigned long node) |
257 | { | 257 | { |
258 | unsigned int pvr; | 258 | unsigned int pvr; |
259 | char *model = of_get_flat_dt_prop(node, "model", NULL); | 259 | const char *model = of_get_flat_dt_prop(node, "model", NULL); |
260 | 260 | ||
261 | /* | 261 | /* |
262 | * Since 440GR(x)/440EP(x) processors have the same pvr, | 262 | * Since 440GR(x)/440EP(x) processors have the same pvr, |
@@ -294,11 +294,11 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
294 | const char *uname, int depth, | 294 | const char *uname, int depth, |
295 | void *data) | 295 | void *data) |
296 | { | 296 | { |
297 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 297 | const char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
298 | const __be32 *prop; | 298 | const __be32 *prop; |
299 | const __be32 *intserv; | 299 | const __be32 *intserv; |
300 | int i, nthreads; | 300 | int i, nthreads; |
301 | unsigned long len; | 301 | int len; |
302 | int found = -1; | 302 | int found = -1; |
303 | int found_thread = 0; | 303 | int found_thread = 0; |
304 | 304 | ||
@@ -391,7 +391,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
391 | int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname, | 391 | int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname, |
392 | int depth, void *data) | 392 | int depth, void *data) |
393 | { | 393 | { |
394 | unsigned long *lprop; /* All these set by kernel, so no need to convert endian */ | 394 | const unsigned long *lprop; /* All these set by kernel, so no need to convert endian */ |
395 | 395 | ||
396 | /* Use common scan routine to determine if this is the chosen node */ | 396 | /* Use common scan routine to determine if this is the chosen node */ |
397 | if (early_init_dt_scan_chosen(node, uname, depth, data) == 0) | 397 | if (early_init_dt_scan_chosen(node, uname, depth, data) == 0) |
@@ -442,8 +442,9 @@ int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname, | |||
442 | */ | 442 | */ |
443 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) | 443 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) |
444 | { | 444 | { |
445 | __be32 *dm, *ls, *usm; | 445 | const __be32 *dm, *ls, *usm; |
446 | unsigned long l, n, flags; | 446 | int l; |
447 | unsigned long n, flags; | ||
447 | u64 base, size, memblock_size; | 448 | u64 base, size, memblock_size; |
448 | unsigned int is_kexec_kdump = 0, rngs; | 449 | unsigned int is_kexec_kdump = 0, rngs; |
449 | 450 | ||
@@ -563,7 +564,8 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) | |||
563 | 564 | ||
564 | static void __init early_reserve_mem_dt(void) | 565 | static void __init early_reserve_mem_dt(void) |
565 | { | 566 | { |
566 | unsigned long i, len, dt_root; | 567 | unsigned long i, dt_root; |
568 | int len; | ||
567 | const __be32 *prop; | 569 | const __be32 *prop; |
568 | 570 | ||
569 | dt_root = of_get_flat_dt_root(); | 571 | dt_root = of_get_flat_dt_root(); |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4cf674d7d5a..8c923bac430 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -1135,7 +1135,7 @@ void __init rtas_initialize(void) | |||
1135 | int __init early_init_dt_scan_rtas(unsigned long node, | 1135 | int __init early_init_dt_scan_rtas(unsigned long node, |
1136 | const char *uname, int depth, void *data) | 1136 | const char *uname, int depth, void *data) |
1137 | { | 1137 | { |
1138 | u32 *basep, *entryp, *sizep; | 1138 | const u32 *basep, *entryp, *sizep; |
1139 | 1139 | ||
1140 | if (depth != 1 || strcmp(uname, "rtas") != 0) | 1140 | if (depth != 1 || strcmp(uname, "rtas") != 0) |
1141 | return 0; | 1141 | return 0; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 6650699eb3b..ff27d169fa8 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -265,9 +265,9 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node, | |||
265 | const char *uname, int depth, | 265 | const char *uname, int depth, |
266 | void *data) | 266 | void *data) |
267 | { | 267 | { |
268 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 268 | const char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
269 | __be32 *prop; | 269 | const __be32 *prop; |
270 | unsigned long size = 0; | 270 | int size = 0; |
271 | 271 | ||
272 | /* We are scanning "cpu" nodes only */ | 272 | /* We are scanning "cpu" nodes only */ |
273 | if (type == NULL || strcmp(type, "cpu") != 0) | 273 | if (type == NULL || strcmp(type, "cpu") != 0) |
@@ -320,9 +320,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, | |||
320 | const char *uname, int depth, | 320 | const char *uname, int depth, |
321 | void *data) | 321 | void *data) |
322 | { | 322 | { |
323 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 323 | const char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
324 | __be32 *prop; | 324 | const __be32 *prop; |
325 | unsigned long size = 0; | 325 | int size = 0; |
326 | 326 | ||
327 | /* We are scanning "cpu" nodes only */ | 327 | /* We are scanning "cpu" nodes only */ |
328 | if (type == NULL || strcmp(type, "cpu") != 0) | 328 | if (type == NULL || strcmp(type, "cpu") != 0) |
@@ -402,9 +402,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, | |||
402 | static int __init htab_dt_scan_hugepage_blocks(unsigned long node, | 402 | static int __init htab_dt_scan_hugepage_blocks(unsigned long node, |
403 | const char *uname, int depth, | 403 | const char *uname, int depth, |
404 | void *data) { | 404 | void *data) { |
405 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 405 | const char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
406 | __be64 *addr_prop; | 406 | const __be64 *addr_prop; |
407 | __be32 *page_count_prop; | 407 | const __be32 *page_count_prop; |
408 | unsigned int expected_pages; | 408 | unsigned int expected_pages; |
409 | long unsigned int phys_addr; | 409 | long unsigned int phys_addr; |
410 | long unsigned int block_size; | 410 | long unsigned int block_size; |
@@ -546,8 +546,8 @@ static int __init htab_dt_scan_pftsize(unsigned long node, | |||
546 | const char *uname, int depth, | 546 | const char *uname, int depth, |
547 | void *data) | 547 | void *data) |
548 | { | 548 | { |
549 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 549 | const char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
550 | __be32 *prop; | 550 | const __be32 *prop; |
551 | 551 | ||
552 | /* We are scanning "cpu" nodes only */ | 552 | /* We are scanning "cpu" nodes only */ |
553 | if (type == NULL || strcmp(type, "cpu") != 0) | 553 | if (type == NULL || strcmp(type, "cpu") != 0) |
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 18c10482019..6e19b0ad5d2 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
@@ -199,8 +199,8 @@ static void __init efika_setup_arch(void) | |||
199 | 199 | ||
200 | static int __init efika_probe(void) | 200 | static int __init efika_probe(void) |
201 | { | 201 | { |
202 | char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), | 202 | const char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), |
203 | "model", NULL); | 203 | "model", NULL); |
204 | 204 | ||
205 | if (model == NULL) | 205 | if (model == NULL) |
206 | return 0; | 206 | return 0; |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index c665d7de6c9..7044fd36197 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -574,8 +574,8 @@ chrp_init2(void) | |||
574 | 574 | ||
575 | static int __init chrp_probe(void) | 575 | static int __init chrp_probe(void) |
576 | { | 576 | { |
577 | char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), | 577 | const char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), |
578 | "device_type", NULL); | 578 | "device_type", NULL); |
579 | if (dtype == NULL) | 579 | if (dtype == NULL) |
580 | return 0; | 580 | return 0; |
581 | if (strcmp(dtype, "chrp")) | 581 | if (strcmp(dtype, "chrp")) |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 65499adaecf..3bf1eb43311 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -50,7 +50,7 @@ int __init early_init_dt_scan_opal(unsigned long node, | |||
50 | const char *uname, int depth, void *data) | 50 | const char *uname, int depth, void *data) |
51 | { | 51 | { |
52 | const void *basep, *entryp; | 52 | const void *basep, *entryp; |
53 | unsigned long basesz, entrysz; | 53 | int basesz, entrysz, runtimesz; |
54 | 54 | ||
55 | if (depth != 1 || strcmp(uname, "ibm,opal") != 0) | 55 | if (depth != 1 || strcmp(uname, "ibm,opal") != 0) |
56 | return 0; | 56 | return 0; |
@@ -64,10 +64,10 @@ int __init early_init_dt_scan_opal(unsigned long node, | |||
64 | opal.base = of_read_number(basep, basesz/4); | 64 | opal.base = of_read_number(basep, basesz/4); |
65 | opal.entry = of_read_number(entryp, entrysz/4); | 65 | opal.entry = of_read_number(entryp, entrysz/4); |
66 | 66 | ||
67 | pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n", | 67 | pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%d)\n", |
68 | opal.base, basep, basesz); | 68 | opal.base, basep, basesz); |
69 | pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n", | 69 | pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n", |
70 | opal.entry, entryp, entrysz); | 70 | opal.size, sizep, runtimesz); |
71 | 71 | ||
72 | powerpc_firmware_features |= FW_FEATURE_OPAL; | 72 | powerpc_firmware_features |= FW_FEATURE_OPAL; |
73 | if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { | 73 | if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { |
@@ -84,6 +84,68 @@ int __init early_init_dt_scan_opal(unsigned long node, | |||
84 | return 1; | 84 | return 1; |
85 | } | 85 | } |
86 | 86 | ||
87 | <<<<<<< HEAD | ||
88 | ======= | ||
89 | int __init early_init_dt_scan_recoverable_ranges(unsigned long node, | ||
90 | const char *uname, int depth, void *data) | ||
91 | { | ||
92 | int i, psize, size; | ||
93 | const __be32 *prop; | ||
94 | |||
95 | if (depth != 1 || strcmp(uname, "ibm,opal") != 0) | ||
96 | return 0; | ||
97 | |||
98 | prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize); | ||
99 | |||
100 | if (!prop) | ||
101 | return 1; | ||
102 | |||
103 | pr_debug("Found machine check recoverable ranges.\n"); | ||
104 | |||
105 | /* | ||
106 | * Calculate number of available entries. | ||
107 | * | ||
108 | * Each recoverable address range entry is (start address, len, | ||
109 | * recovery address), 2 cells each for start and recovery address, | ||
110 | * 1 cell for len, totalling 5 cells per entry. | ||
111 | */ | ||
112 | mc_recoverable_range_len = psize / (sizeof(*prop) * 5); | ||
113 | |||
114 | /* Sanity check */ | ||
115 | if (!mc_recoverable_range_len) | ||
116 | return 1; | ||
117 | |||
118 | /* Size required to hold all the entries. */ | ||
119 | size = mc_recoverable_range_len * | ||
120 | sizeof(struct mcheck_recoverable_range); | ||
121 | |||
122 | /* | ||
123 | * Allocate a buffer to hold the MC recoverable ranges. We would be | ||
124 | * accessing them in real mode, hence it needs to be within | ||
125 | * RMO region. | ||
126 | */ | ||
127 | mc_recoverable_range =__va(memblock_alloc_base(size, __alignof__(u64), | ||
128 | ppc64_rma_size)); | ||
129 | memset(mc_recoverable_range, 0, size); | ||
130 | |||
131 | for (i = 0; i < mc_recoverable_range_len; i++) { | ||
132 | mc_recoverable_range[i].start_addr = | ||
133 | of_read_number(prop + (i * 5) + 0, 2); | ||
134 | mc_recoverable_range[i].end_addr = | ||
135 | mc_recoverable_range[i].start_addr + | ||
136 | of_read_number(prop + (i * 5) + 2, 1); | ||
137 | mc_recoverable_range[i].recover_addr = | ||
138 | of_read_number(prop + (i * 5) + 3, 2); | ||
139 | |||
140 | pr_debug("Machine check recoverable range: %llx..%llx: %llx\n", | ||
141 | mc_recoverable_range[i].start_addr, | ||
142 | mc_recoverable_range[i].end_addr, | ||
143 | mc_recoverable_range[i].recover_addr); | ||
144 | } | ||
145 | return 1; | ||
146 | } | ||
147 | |||
148 | >>>>>>> 9d0c4dfedd96... of/fdt: update of_get_flat_dt_prop in prep for libfdt | ||
87 | static int __init opal_register_exception_handlers(void) | 149 | static int __init opal_register_exception_handlers(void) |
88 | { | 150 | { |
89 | #ifdef __BIG_ENDIAN__ | 151 | #ifdef __BIG_ENDIAN__ |
@@ -269,7 +331,7 @@ int opal_get_chars(uint32_t vtermno, char *buf, int count) | |||
269 | if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0) | 331 | if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0) |
270 | return 0; | 332 | return 0; |
271 | len = cpu_to_be64(count); | 333 | len = cpu_to_be64(count); |
272 | rc = opal_console_read(vtermno, &len, buf); | 334 | rc = opal_console_read(vtermno, &len, buf); |
273 | if (rc == OPAL_SUCCESS) | 335 | if (rc == OPAL_SUCCESS) |
274 | return be64_to_cpu(len); | 336 | return be64_to_cpu(len); |
275 | return 0; | 337 | return 0; |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 972df0ffd4d..0b84df948ed 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -671,7 +671,7 @@ static int __init pseries_probe_fw_features(unsigned long node, | |||
671 | void *data) | 671 | void *data) |
672 | { | 672 | { |
673 | const char *prop; | 673 | const char *prop; |
674 | unsigned long len; | 674 | int len; |
675 | static int hypertas_found; | 675 | static int hypertas_found; |
676 | static int vec5_found; | 676 | static int vec5_found; |
677 | 677 | ||
@@ -704,7 +704,7 @@ static int __init pseries_probe_fw_features(unsigned long node, | |||
704 | static int __init pSeries_probe(void) | 704 | static int __init pSeries_probe(void) |
705 | { | 705 | { |
706 | unsigned long root = of_get_flat_dt_root(); | 706 | unsigned long root = of_get_flat_dt_root(); |
707 | char *dtype = of_get_flat_dt_prop(root, "device_type", NULL); | 707 | const char *dtype = of_get_flat_dt_prop(root, "device_type", NULL); |
708 | 708 | ||
709 | if (dtype == NULL) | 709 | if (dtype == NULL) |
710 | return 0; | 710 | return 0; |
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 84fe931bb60..555f75cff7d 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -221,7 +221,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname, | |||
221 | int depth, void *data) | 221 | int depth, void *data) |
222 | { | 222 | { |
223 | const __be32 *ranges; | 223 | const __be32 *ranges; |
224 | unsigned long len; | 224 | int len; |
225 | 225 | ||
226 | if (depth > 1) | 226 | if (depth > 1) |
227 | return 0; | 227 | return 0; |
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index c6973f101a3..ec919a9160a 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -28,6 +28,7 @@ config OF_SELFTEST | |||
28 | config OF_FLATTREE | 28 | config OF_FLATTREE |
29 | bool | 29 | bool |
30 | select DTC | 30 | select DTC |
31 | select LIBFDT | ||
31 | 32 | ||
32 | config OF_EARLY_FLATTREE | 33 | config OF_EARLY_FLATTREE |
33 | bool | 34 | bool |
@@ -75,4 +76,10 @@ config OF_MTD | |||
75 | depends on MTD | 76 | depends on MTD |
76 | def_bool y | 77 | def_bool y |
77 | 78 | ||
79 | config OF_RESERVED_MEM | ||
80 | depends on OF_EARLY_FLATTREE | ||
81 | bool | ||
82 | help | ||
83 | Helpers to allow for reservation of memory regions | ||
84 | |||
78 | endmenu # OF | 85 | endmenu # OF |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index efd05102c40..9891232f999 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -9,3 +9,6 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o | |||
9 | obj-$(CONFIG_OF_PCI) += of_pci.o | 9 | obj-$(CONFIG_OF_PCI) += of_pci.o |
10 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 10 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
11 | obj-$(CONFIG_OF_MTD) += of_mtd.o | 11 | obj-$(CONFIG_OF_MTD) += of_mtd.o |
12 | obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o | ||
13 | |||
14 | CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt | ||
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 758b4f8b30b..024b8f99d48 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -15,9 +15,12 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_fdt.h> | 17 | #include <linux/of_fdt.h> |
18 | #include <linux/of_reserved_mem.h> | ||
19 | #include <linux/sizes.h> | ||
18 | #include <linux/string.h> | 20 | #include <linux/string.h> |
19 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
20 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/libfdt.h> | ||
21 | 24 | ||
22 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ | 25 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ |
23 | #ifdef CONFIG_PPC | 26 | #ifdef CONFIG_PPC |
@@ -26,54 +29,6 @@ | |||
26 | 29 | ||
27 | #include <asm/page.h> | 30 | #include <asm/page.h> |
28 | 31 | ||
29 | char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) | ||
30 | { | ||
31 | return ((char *)blob) + | ||
32 | be32_to_cpu(blob->off_dt_strings) + offset; | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * of_fdt_get_property - Given a node in the given flat blob, return | ||
37 | * the property ptr | ||
38 | */ | ||
39 | void *of_fdt_get_property(struct boot_param_header *blob, | ||
40 | unsigned long node, const char *name, | ||
41 | unsigned long *size) | ||
42 | { | ||
43 | unsigned long p = node; | ||
44 | |||
45 | do { | ||
46 | u32 tag = be32_to_cpup((__be32 *)p); | ||
47 | u32 sz, noff; | ||
48 | const char *nstr; | ||
49 | |||
50 | p += 4; | ||
51 | if (tag == OF_DT_NOP) | ||
52 | continue; | ||
53 | if (tag != OF_DT_PROP) | ||
54 | return NULL; | ||
55 | |||
56 | sz = be32_to_cpup((__be32 *)p); | ||
57 | noff = be32_to_cpup((__be32 *)(p + 4)); | ||
58 | p += 8; | ||
59 | if (be32_to_cpu(blob->version) < 0x10) | ||
60 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
61 | |||
62 | nstr = of_fdt_get_string(blob, noff); | ||
63 | if (nstr == NULL) { | ||
64 | pr_warning("Can't find property index name !\n"); | ||
65 | return NULL; | ||
66 | } | ||
67 | if (strcmp(name, nstr) == 0) { | ||
68 | if (size) | ||
69 | *size = sz; | ||
70 | return (void *)p; | ||
71 | } | ||
72 | p += sz; | ||
73 | p = ALIGN(p, 4); | ||
74 | } while (1); | ||
75 | } | ||
76 | |||
77 | /** | 32 | /** |
78 | * of_fdt_is_compatible - Return true if given node from the given blob has | 33 | * of_fdt_is_compatible - Return true if given node from the given blob has |
79 | * compat in its compatible list | 34 | * compat in its compatible list |
@@ -88,9 +43,10 @@ int of_fdt_is_compatible(struct boot_param_header *blob, | |||
88 | unsigned long node, const char *compat) | 43 | unsigned long node, const char *compat) |
89 | { | 44 | { |
90 | const char *cp; | 45 | const char *cp; |
91 | unsigned long cplen, l, score = 0; | 46 | int cplen; |
47 | unsigned long l, score = 0; | ||
92 | 48 | ||
93 | cp = of_fdt_get_property(blob, node, "compatible", &cplen); | 49 | cp = fdt_getprop(blob, node, "compatible", &cplen); |
94 | if (cp == NULL) | 50 | if (cp == NULL) |
95 | return 0; | 51 | return 0; |
96 | while (cplen > 0) { | 52 | while (cplen > 0) { |
@@ -149,28 +105,27 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size, | |||
149 | */ | 105 | */ |
150 | static void * unflatten_dt_node(struct boot_param_header *blob, | 106 | static void * unflatten_dt_node(struct boot_param_header *blob, |
151 | void *mem, | 107 | void *mem, |
152 | void **p, | 108 | int *poffset, |
153 | struct device_node *dad, | 109 | struct device_node *dad, |
154 | struct device_node ***allnextpp, | 110 | struct device_node ***allnextpp, |
155 | unsigned long fpsize) | 111 | unsigned long fpsize) |
156 | { | 112 | { |
113 | const __be32 *p; | ||
157 | struct device_node *np; | 114 | struct device_node *np; |
158 | struct property *pp, **prev_pp = NULL; | 115 | struct property *pp, **prev_pp = NULL; |
159 | char *pathp; | 116 | const char *pathp; |
160 | u32 tag; | ||
161 | unsigned int l, allocl; | 117 | unsigned int l, allocl; |
118 | static int depth = 0; | ||
119 | int old_depth; | ||
120 | int offset; | ||
162 | int has_name = 0; | 121 | int has_name = 0; |
163 | int new_format = 0; | 122 | int new_format = 0; |
164 | 123 | ||
165 | tag = be32_to_cpup(*p); | 124 | pathp = fdt_get_name(blob, *poffset, &l); |
166 | if (tag != OF_DT_BEGIN_NODE) { | 125 | if (!pathp) |
167 | pr_err("Weird tag at start of node: %x\n", tag); | ||
168 | return mem; | 126 | return mem; |
169 | } | 127 | |
170 | *p += 4; | 128 | allocl = l++; |
171 | pathp = *p; | ||
172 | l = allocl = strlen(pathp) + 1; | ||
173 | *p = PTR_ALIGN(*p + l, 4); | ||
174 | 129 | ||
175 | /* version 0x10 has a more compact unit name here instead of the full | 130 | /* version 0x10 has a more compact unit name here instead of the full |
176 | * path. we accumulate the full path size using "fpsize", we'll rebuild | 131 | * path. we accumulate the full path size using "fpsize", we'll rebuild |
@@ -188,7 +143,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
188 | fpsize = 1; | 143 | fpsize = 1; |
189 | allocl = 2; | 144 | allocl = 2; |
190 | l = 1; | 145 | l = 1; |
191 | *pathp = '\0'; | 146 | pathp = ""; |
192 | } else { | 147 | } else { |
193 | /* account for '/' and path size minus terminal 0 | 148 | /* account for '/' and path size minus terminal 0 |
194 | * already in 'l' | 149 | * already in 'l' |
@@ -235,32 +190,23 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
235 | kref_init(&np->kref); | 190 | kref_init(&np->kref); |
236 | } | 191 | } |
237 | /* process properties */ | 192 | /* process properties */ |
238 | while (1) { | 193 | for (offset = fdt_first_property_offset(blob, *poffset); |
239 | u32 sz, noff; | 194 | (offset >= 0); |
240 | char *pname; | 195 | (offset = fdt_next_property_offset(blob, offset))) { |
241 | 196 | const char *pname; | |
242 | tag = be32_to_cpup(*p); | 197 | u32 sz; |
243 | if (tag == OF_DT_NOP) { | 198 | |
244 | *p += 4; | 199 | if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) { |
245 | continue; | 200 | offset = -FDT_ERR_INTERNAL; |
246 | } | ||
247 | if (tag != OF_DT_PROP) | ||
248 | break; | 201 | break; |
249 | *p += 4; | 202 | } |
250 | sz = be32_to_cpup(*p); | 203 | |
251 | noff = be32_to_cpup(*p + 4); | ||
252 | *p += 8; | ||
253 | if (be32_to_cpu(blob->version) < 0x10) | ||
254 | *p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4); | ||
255 | |||
256 | pname = of_fdt_get_string(blob, noff); | ||
257 | if (pname == NULL) { | 204 | if (pname == NULL) { |
258 | pr_info("Can't find property name in list !\n"); | 205 | pr_info("Can't find property name in list !\n"); |
259 | break; | 206 | break; |
260 | } | 207 | } |
261 | if (strcmp(pname, "name") == 0) | 208 | if (strcmp(pname, "name") == 0) |
262 | has_name = 1; | 209 | has_name = 1; |
263 | l = strlen(pname) + 1; | ||
264 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), | 210 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), |
265 | __alignof__(struct property)); | 211 | __alignof__(struct property)); |
266 | if (allnextpp) { | 212 | if (allnextpp) { |
@@ -272,26 +218,25 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
272 | if ((strcmp(pname, "phandle") == 0) || | 218 | if ((strcmp(pname, "phandle") == 0) || |
273 | (strcmp(pname, "linux,phandle") == 0)) { | 219 | (strcmp(pname, "linux,phandle") == 0)) { |
274 | if (np->phandle == 0) | 220 | if (np->phandle == 0) |
275 | np->phandle = be32_to_cpup((__be32*)*p); | 221 | np->phandle = be32_to_cpup(p); |
276 | } | 222 | } |
277 | /* And we process the "ibm,phandle" property | 223 | /* And we process the "ibm,phandle" property |
278 | * used in pSeries dynamic device tree | 224 | * used in pSeries dynamic device tree |
279 | * stuff */ | 225 | * stuff */ |
280 | if (strcmp(pname, "ibm,phandle") == 0) | 226 | if (strcmp(pname, "ibm,phandle") == 0) |
281 | np->phandle = be32_to_cpup((__be32 *)*p); | 227 | np->phandle = be32_to_cpup(p); |
282 | pp->name = pname; | 228 | pp->name = (char *)pname; |
283 | pp->length = sz; | 229 | pp->length = sz; |
284 | pp->value = *p; | 230 | pp->value = (__be32 *)p; |
285 | *prev_pp = pp; | 231 | *prev_pp = pp; |
286 | prev_pp = &pp->next; | 232 | prev_pp = &pp->next; |
287 | } | 233 | } |
288 | *p = PTR_ALIGN((*p) + sz, 4); | ||
289 | } | 234 | } |
290 | /* with version 0x10 we may not have the name property, recreate | 235 | /* with version 0x10 we may not have the name property, recreate |
291 | * it here from the unit name if absent | 236 | * it here from the unit name if absent |
292 | */ | 237 | */ |
293 | if (!has_name) { | 238 | if (!has_name) { |
294 | char *p1 = pathp, *ps = pathp, *pa = NULL; | 239 | const char *p1 = pathp, *ps = pathp, *pa = NULL; |
295 | int sz; | 240 | int sz; |
296 | 241 | ||
297 | while (*p1) { | 242 | while (*p1) { |
@@ -328,19 +273,18 @@ static void * unflatten_dt_node(struct boot_param_header *blob, | |||
328 | if (!np->type) | 273 | if (!np->type) |
329 | np->type = "<NULL>"; | 274 | np->type = "<NULL>"; |
330 | } | 275 | } |
331 | while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { | 276 | |
332 | if (tag == OF_DT_NOP) | 277 | old_depth = depth; |
333 | *p += 4; | 278 | *poffset = fdt_next_node(blob, *poffset, &depth); |
334 | else | 279 | if (depth < 0) |
335 | mem = unflatten_dt_node(blob, mem, p, np, allnextpp, | 280 | depth = 0; |
336 | fpsize); | 281 | while (*poffset > 0 && depth > old_depth) |
337 | tag = be32_to_cpup(*p); | 282 | mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp, |
338 | } | 283 | fpsize); |
339 | if (tag != OF_DT_END_NODE) { | 284 | |
340 | pr_err("Weird tag at end of node: %x\n", tag); | 285 | if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) |
341 | return mem; | 286 | pr_err("unflatten: error %d processing FDT\n", *poffset); |
342 | } | 287 | |
343 | *p += 4; | ||
344 | return mem; | 288 | return mem; |
345 | } | 289 | } |
346 | 290 | ||
@@ -361,7 +305,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, | |||
361 | void * (*dt_alloc)(u64 size, u64 align)) | 305 | void * (*dt_alloc)(u64 size, u64 align)) |
362 | { | 306 | { |
363 | unsigned long size; | 307 | unsigned long size; |
364 | void *start, *mem; | 308 | int start; |
309 | void *mem; | ||
365 | struct device_node **allnextp = mynodes; | 310 | struct device_node **allnextp = mynodes; |
366 | 311 | ||
367 | pr_debug(" -> unflatten_device_tree()\n"); | 312 | pr_debug(" -> unflatten_device_tree()\n"); |
@@ -382,7 +327,7 @@ static void __unflatten_device_tree(struct boot_param_header *blob, | |||
382 | } | 327 | } |
383 | 328 | ||
384 | /* First pass, scan for size */ | 329 | /* First pass, scan for size */ |
385 | start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); | 330 | start = 0; |
386 | size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); | 331 | size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); |
387 | size = ALIGN(size, 4); | 332 | size = ALIGN(size, 4); |
388 | 333 | ||
@@ -397,10 +342,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, | |||
397 | pr_debug(" unflattening %p...\n", mem); | 342 | pr_debug(" unflattening %p...\n", mem); |
398 | 343 | ||
399 | /* Second pass, do actual unflattening */ | 344 | /* Second pass, do actual unflattening */ |
400 | start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct); | 345 | start = 0; |
401 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); | 346 | unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0); |
402 | if (be32_to_cpup(start) != OF_DT_END) | ||
403 | pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start)); | ||
404 | if (be32_to_cpup(mem + size) != 0xdeadbeef) | 347 | if (be32_to_cpup(mem + size) != 0xdeadbeef) |
405 | pr_warning("End of tree marker overwritten: %08x\n", | 348 | pr_warning("End of tree marker overwritten: %08x\n", |
406 | be32_to_cpup(mem + size)); | 349 | be32_to_cpup(mem + size)); |
@@ -440,6 +383,129 @@ struct boot_param_header *initial_boot_params; | |||
440 | #ifdef CONFIG_OF_EARLY_FLATTREE | 383 | #ifdef CONFIG_OF_EARLY_FLATTREE |
441 | 384 | ||
442 | /** | 385 | /** |
386 | * res_mem_reserve_reg() - reserve all memory described in 'reg' property | ||
387 | */ | ||
388 | static int __init __reserved_mem_reserve_reg(unsigned long node, | ||
389 | const char *uname) | ||
390 | { | ||
391 | int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); | ||
392 | phys_addr_t base, size; | ||
393 | int len; | ||
394 | const __be32 *prop; | ||
395 | int nomap, first = 1; | ||
396 | |||
397 | prop = of_get_flat_dt_prop(node, "reg", &len); | ||
398 | if (!prop) | ||
399 | return -ENOENT; | ||
400 | |||
401 | if (len && len % t_len != 0) { | ||
402 | pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n", | ||
403 | uname); | ||
404 | return -EINVAL; | ||
405 | } | ||
406 | |||
407 | nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; | ||
408 | |||
409 | while (len >= t_len) { | ||
410 | base = dt_mem_next_cell(dt_root_addr_cells, &prop); | ||
411 | size = dt_mem_next_cell(dt_root_size_cells, &prop); | ||
412 | |||
413 | if (base && size && | ||
414 | early_init_dt_reserve_memory_arch(base, size, nomap) == 0) | ||
415 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", | ||
416 | uname, &base, (unsigned long)size / SZ_1M); | ||
417 | else | ||
418 | pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", | ||
419 | uname, &base, (unsigned long)size / SZ_1M); | ||
420 | |||
421 | len -= t_len; | ||
422 | if (first) { | ||
423 | fdt_reserved_mem_save_node(node, uname, base, size); | ||
424 | first = 0; | ||
425 | } | ||
426 | } | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * __reserved_mem_check_root() - check if #size-cells, #address-cells provided | ||
432 | * in /reserved-memory matches the values supported by the current implementation, | ||
433 | * also check if ranges property has been provided | ||
434 | */ | ||
435 | static int __init __reserved_mem_check_root(unsigned long node) | ||
436 | { | ||
437 | const __be32 *prop; | ||
438 | |||
439 | prop = of_get_flat_dt_prop(node, "#size-cells", NULL); | ||
440 | if (!prop || be32_to_cpup(prop) != dt_root_size_cells) | ||
441 | return -EINVAL; | ||
442 | |||
443 | prop = of_get_flat_dt_prop(node, "#address-cells", NULL); | ||
444 | if (!prop || be32_to_cpup(prop) != dt_root_addr_cells) | ||
445 | return -EINVAL; | ||
446 | |||
447 | prop = of_get_flat_dt_prop(node, "ranges", NULL); | ||
448 | if (!prop) | ||
449 | return -EINVAL; | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory | ||
455 | */ | ||
456 | static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, | ||
457 | int depth, void *data) | ||
458 | { | ||
459 | static int found; | ||
460 | const char *status; | ||
461 | int err; | ||
462 | |||
463 | if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { | ||
464 | if (__reserved_mem_check_root(node) != 0) { | ||
465 | pr_err("Reserved memory: unsupported node format, ignoring\n"); | ||
466 | /* break scan */ | ||
467 | return 1; | ||
468 | } | ||
469 | found = 1; | ||
470 | /* scan next node */ | ||
471 | return 0; | ||
472 | } else if (!found) { | ||
473 | /* scan next node */ | ||
474 | return 0; | ||
475 | } else if (found && depth < 2) { | ||
476 | /* scanning of /reserved-memory has been finished */ | ||
477 | return 1; | ||
478 | } | ||
479 | |||
480 | status = of_get_flat_dt_prop(node, "status", NULL); | ||
481 | if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) | ||
482 | return 0; | ||
483 | |||
484 | err = __reserved_mem_reserve_reg(node, uname); | ||
485 | if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL)) | ||
486 | fdt_reserved_mem_save_node(node, uname, 0, 0); | ||
487 | |||
488 | /* scan next node */ | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | /** | ||
493 | * early_init_fdt_scan_reserved_mem() - create reserved memory regions | ||
494 | * | ||
495 | * This function grabs memory from early allocator for device exclusive use | ||
496 | * defined in device tree structures. It should be called by arch specific code | ||
497 | * once the early allocator (i.e. memblock) has been fully activated. | ||
498 | */ | ||
499 | void __init early_init_fdt_scan_reserved_mem(void) | ||
500 | { | ||
501 | if (!initial_boot_params) | ||
502 | return; | ||
503 | |||
504 | of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); | ||
505 | fdt_init_reserved_mem(); | ||
506 | } | ||
507 | |||
508 | /** | ||
443 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. | 509 | * of_scan_flat_dt - scan flattened tree blob and call callback on each. |
444 | * @it: callback function | 510 | * @it: callback function |
445 | * @data: context data pointer | 511 | * @data: context data pointer |
@@ -453,47 +519,19 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, | |||
453 | void *data), | 519 | void *data), |
454 | void *data) | 520 | void *data) |
455 | { | 521 | { |
456 | unsigned long p = ((unsigned long)initial_boot_params) + | 522 | const void *blob = initial_boot_params; |
457 | be32_to_cpu(initial_boot_params->off_dt_struct); | 523 | const char *pathp; |
458 | int rc = 0; | 524 | int offset, rc = 0, depth = -1; |
459 | int depth = -1; | 525 | |
460 | 526 | for (offset = fdt_next_node(blob, -1, &depth); | |
461 | do { | 527 | offset >= 0 && depth >= 0 && !rc; |
462 | u32 tag = be32_to_cpup((__be32 *)p); | 528 | offset = fdt_next_node(blob, offset, &depth)) { |
463 | const char *pathp; | 529 | |
464 | 530 | pathp = fdt_get_name(blob, offset, NULL); | |
465 | p += 4; | ||
466 | if (tag == OF_DT_END_NODE) { | ||
467 | depth--; | ||
468 | continue; | ||
469 | } | ||
470 | if (tag == OF_DT_NOP) | ||
471 | continue; | ||
472 | if (tag == OF_DT_END) | ||
473 | break; | ||
474 | if (tag == OF_DT_PROP) { | ||
475 | u32 sz = be32_to_cpup((__be32 *)p); | ||
476 | p += 8; | ||
477 | if (be32_to_cpu(initial_boot_params->version) < 0x10) | ||
478 | p = ALIGN(p, sz >= 8 ? 8 : 4); | ||
479 | p += sz; | ||
480 | p = ALIGN(p, 4); | ||
481 | continue; | ||
482 | } | ||
483 | if (tag != OF_DT_BEGIN_NODE) { | ||
484 | pr_err("Invalid tag %x in flat device tree!\n", tag); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | depth++; | ||
488 | pathp = (char *)p; | ||
489 | p = ALIGN(p + strlen(pathp) + 1, 4); | ||
490 | if (*pathp == '/') | 531 | if (*pathp == '/') |
491 | pathp = kbasename(pathp); | 532 | pathp = kbasename(pathp); |
492 | rc = it(p, pathp, depth, data); | 533 | rc = it(offset, pathp, depth, data); |
493 | if (rc != 0) | 534 | } |
494 | break; | ||
495 | } while (1); | ||
496 | |||
497 | return rc; | 535 | return rc; |
498 | } | 536 | } |
499 | 537 | ||
@@ -502,14 +540,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, | |||
502 | */ | 540 | */ |
503 | unsigned long __init of_get_flat_dt_root(void) | 541 | unsigned long __init of_get_flat_dt_root(void) |
504 | { | 542 | { |
505 | unsigned long p = ((unsigned long)initial_boot_params) + | 543 | return 0; |
506 | be32_to_cpu(initial_boot_params->off_dt_struct); | ||
507 | |||
508 | while (be32_to_cpup((__be32 *)p) == OF_DT_NOP) | ||
509 | p += 4; | ||
510 | BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE); | ||
511 | p += 4; | ||
512 | return ALIGN(p + strlen((char *)p) + 1, 4); | ||
513 | } | 544 | } |
514 | 545 | ||
515 | /** | 546 | /** |
@@ -518,10 +549,10 @@ unsigned long __init of_get_flat_dt_root(void) | |||
518 | * This function can be used within scan_flattened_dt callback to get | 549 | * This function can be used within scan_flattened_dt callback to get |
519 | * access to properties | 550 | * access to properties |
520 | */ | 551 | */ |
521 | void *__init of_get_flat_dt_prop(unsigned long node, const char *name, | 552 | const void *__init of_get_flat_dt_prop(unsigned long node, const char *name, |
522 | unsigned long *size) | 553 | int *size) |
523 | { | 554 | { |
524 | return of_fdt_get_property(initial_boot_params, node, name, size); | 555 | return fdt_getprop(initial_boot_params, node, name, size); |
525 | } | 556 | } |
526 | 557 | ||
527 | /** | 558 | /** |
@@ -551,73 +582,6 @@ struct fdt_scan_status { | |||
551 | void *data; | 582 | void *data; |
552 | }; | 583 | }; |
553 | 584 | ||
554 | /** | ||
555 | * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function | ||
556 | */ | ||
557 | static int __init fdt_scan_node_by_path(unsigned long node, const char *uname, | ||
558 | int depth, void *data) | ||
559 | { | ||
560 | struct fdt_scan_status *st = data; | ||
561 | |||
562 | /* | ||
563 | * if scan at the requested fdt node has been completed, | ||
564 | * return -ENXIO to abort further scanning | ||
565 | */ | ||
566 | if (depth <= st->depth) | ||
567 | return -ENXIO; | ||
568 | |||
569 | /* requested fdt node has been found, so call iterator function */ | ||
570 | if (st->found) | ||
571 | return st->iterator(node, uname, depth, st->data); | ||
572 | |||
573 | /* check if scanning automata is entering next level of fdt nodes */ | ||
574 | if (depth == st->depth + 1 && | ||
575 | strncmp(st->name, uname, st->namelen) == 0 && | ||
576 | uname[st->namelen] == 0) { | ||
577 | st->depth += 1; | ||
578 | if (st->name[st->namelen] == 0) { | ||
579 | st->found = 1; | ||
580 | } else { | ||
581 | const char *next = st->name + st->namelen + 1; | ||
582 | st->name = next; | ||
583 | st->namelen = strcspn(next, "/"); | ||
584 | } | ||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | /* scan next fdt node */ | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | /** | ||
593 | * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each | ||
594 | * child of the given path. | ||
595 | * @path: path to start searching for children | ||
596 | * @it: callback function | ||
597 | * @data: context data pointer | ||
598 | * | ||
599 | * This function is used to scan the flattened device-tree starting from the | ||
600 | * node given by path. It is used to extract information (like reserved | ||
601 | * memory), which is required on ealy boot before we can unflatten the tree. | ||
602 | */ | ||
603 | int __init of_scan_flat_dt_by_path(const char *path, | ||
604 | int (*it)(unsigned long node, const char *name, int depth, void *data), | ||
605 | void *data) | ||
606 | { | ||
607 | struct fdt_scan_status st = {path, 0, -1, 0, it, data}; | ||
608 | int ret = 0; | ||
609 | |||
610 | if (initial_boot_params) | ||
611 | ret = of_scan_flat_dt(fdt_scan_node_by_path, &st); | ||
612 | |||
613 | if (!st.found) | ||
614 | return -ENOENT; | ||
615 | else if (ret == -ENXIO) /* scan has been completed */ | ||
616 | return 0; | ||
617 | else | ||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | const char * __init of_flat_dt_get_machine_name(void) | 585 | const char * __init of_flat_dt_get_machine_name(void) |
622 | { | 586 | { |
623 | const char *name; | 587 | const char *name; |
@@ -657,7 +621,7 @@ const void * __init of_flat_dt_match_machine(const void *default_match, | |||
657 | } | 621 | } |
658 | if (!best_data) { | 622 | if (!best_data) { |
659 | const char *prop; | 623 | const char *prop; |
660 | long size; | 624 | int size; |
661 | 625 | ||
662 | pr_err("\n unrecognized device tree list:\n[ "); | 626 | pr_err("\n unrecognized device tree list:\n[ "); |
663 | 627 | ||
@@ -686,8 +650,8 @@ const void * __init of_flat_dt_match_machine(const void *default_match, | |||
686 | static void __init early_init_dt_check_for_initrd(unsigned long node) | 650 | static void __init early_init_dt_check_for_initrd(unsigned long node) |
687 | { | 651 | { |
688 | u64 start, end; | 652 | u64 start, end; |
689 | unsigned long len; | 653 | int len; |
690 | __be32 *prop; | 654 | const __be32 *prop; |
691 | 655 | ||
692 | pr_debug("Looking for initrd properties... "); | 656 | pr_debug("Looking for initrd properties... "); |
693 | 657 | ||
@@ -720,7 +684,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) | |||
720 | int __init early_init_dt_scan_root(unsigned long node, const char *uname, | 684 | int __init early_init_dt_scan_root(unsigned long node, const char *uname, |
721 | int depth, void *data) | 685 | int depth, void *data) |
722 | { | 686 | { |
723 | __be32 *prop; | 687 | const __be32 *prop; |
724 | 688 | ||
725 | if (depth != 0) | 689 | if (depth != 0) |
726 | return 0; | 690 | return 0; |
@@ -742,9 +706,9 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname, | |||
742 | return 1; | 706 | return 1; |
743 | } | 707 | } |
744 | 708 | ||
745 | u64 __init dt_mem_next_cell(int s, __be32 **cellp) | 709 | u64 __init dt_mem_next_cell(int s, const __be32 **cellp) |
746 | { | 710 | { |
747 | __be32 *p = *cellp; | 711 | const __be32 *p = *cellp; |
748 | 712 | ||
749 | *cellp = p + s; | 713 | *cellp = p + s; |
750 | return of_read_number(p, s); | 714 | return of_read_number(p, s); |
@@ -756,9 +720,9 @@ u64 __init dt_mem_next_cell(int s, __be32 **cellp) | |||
756 | int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | 720 | int __init early_init_dt_scan_memory(unsigned long node, const char *uname, |
757 | int depth, void *data) | 721 | int depth, void *data) |
758 | { | 722 | { |
759 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 723 | const char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
760 | __be32 *reg, *endp; | 724 | const __be32 *reg, *endp; |
761 | unsigned long l; | 725 | int l; |
762 | 726 | ||
763 | /* We are scanning "memory" nodes only */ | 727 | /* We are scanning "memory" nodes only */ |
764 | if (type == NULL) { | 728 | if (type == NULL) { |
@@ -779,7 +743,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | |||
779 | 743 | ||
780 | endp = reg + (l / sizeof(__be32)); | 744 | endp = reg + (l / sizeof(__be32)); |
781 | 745 | ||
782 | pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", | 746 | pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n", |
783 | uname, l, reg[0], reg[1], reg[2], reg[3]); | 747 | uname, l, reg[0], reg[1], reg[2], reg[3]); |
784 | 748 | ||
785 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { | 749 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { |
@@ -802,8 +766,8 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | |||
802 | int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | 766 | int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, |
803 | int depth, void *data) | 767 | int depth, void *data) |
804 | { | 768 | { |
805 | unsigned long l; | 769 | int l; |
806 | char *p; | 770 | const char *p; |
807 | 771 | ||
808 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | 772 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
809 | 773 | ||
@@ -856,6 +820,16 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) | |||
856 | memblock_add(base, size); | 820 | memblock_add(base, size); |
857 | } | 821 | } |
858 | 822 | ||
823 | int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, | ||
824 | phys_addr_t size, bool nomap) | ||
825 | { | ||
826 | if (memblock_is_region_reserved(base, size)) | ||
827 | return -EBUSY; | ||
828 | if (nomap) | ||
829 | return memblock_remove(base, size); | ||
830 | return memblock_reserve(base, size); | ||
831 | } | ||
832 | |||
859 | /* | 833 | /* |
860 | * called from unflatten_device_tree() to bootstrap devicetree itself | 834 | * called from unflatten_device_tree() to bootstrap devicetree itself |
861 | * Architectures can override this definition if memblock isn't used | 835 | * Architectures can override this definition if memblock isn't used |
@@ -864,6 +838,14 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align) | |||
864 | { | 838 | { |
865 | return __va(memblock_alloc(size, align)); | 839 | return __va(memblock_alloc(size, align)); |
866 | } | 840 | } |
841 | #else | ||
842 | int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, | ||
843 | phys_addr_t size, bool nomap) | ||
844 | { | ||
845 | pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", | ||
846 | base, size, nomap ? " (nomap)" : ""); | ||
847 | return -ENOSYS; | ||
848 | } | ||
867 | #endif | 849 | #endif |
868 | 850 | ||
869 | bool __init early_init_dt_scan(void *params) | 851 | bool __init early_init_dt_scan(void *params) |
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c new file mode 100644 index 00000000000..e420eb52e5c --- /dev/null +++ b/drivers/of/of_reserved_mem.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * Device tree based initialization code for reserved memory. | ||
3 | * | ||
4 | * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. | ||
5 | * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. | ||
6 | * http://www.samsung.com | ||
7 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> | ||
8 | * Author: Josh Cartwright <joshc@codeaurora.org> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation; either version 2 of the | ||
13 | * License or (at your optional) any later version of the license. | ||
14 | */ | ||
15 | |||
16 | #include <linux/err.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_fdt.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/sizes.h> | ||
22 | #include <linux/of_reserved_mem.h> | ||
23 | |||
24 | #define MAX_RESERVED_REGIONS 16 | ||
25 | static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; | ||
26 | static int reserved_mem_count; | ||
27 | |||
28 | #if defined(CONFIG_HAVE_MEMBLOCK) | ||
29 | #include <linux/memblock.h> | ||
30 | int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, | ||
31 | phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, | ||
32 | phys_addr_t *res_base) | ||
33 | { | ||
34 | /* | ||
35 | * We use __memblock_alloc_base() because memblock_alloc_base() | ||
36 | * panic()s on allocation failure. | ||
37 | */ | ||
38 | phys_addr_t base = __memblock_alloc_base(size, align, end); | ||
39 | if (!base) | ||
40 | return -ENOMEM; | ||
41 | |||
42 | /* | ||
43 | * Check if the allocated region fits in to start..end window | ||
44 | */ | ||
45 | if (base < start) { | ||
46 | memblock_free(base, size); | ||
47 | return -ENOMEM; | ||
48 | } | ||
49 | |||
50 | *res_base = base; | ||
51 | if (nomap) | ||
52 | return memblock_remove(base, size); | ||
53 | return 0; | ||
54 | } | ||
55 | #else | ||
56 | int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, | ||
57 | phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, | ||
58 | phys_addr_t *res_base) | ||
59 | { | ||
60 | pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n", | ||
61 | size, nomap ? " (nomap)" : ""); | ||
62 | return -ENOSYS; | ||
63 | } | ||
64 | #endif | ||
65 | |||
66 | /** | ||
67 | * res_mem_save_node() - save fdt node for second pass initialization | ||
68 | */ | ||
69 | void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, | ||
70 | phys_addr_t base, phys_addr_t size) | ||
71 | { | ||
72 | struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; | ||
73 | |||
74 | if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { | ||
75 | pr_err("Reserved memory: not enough space all defined regions.\n"); | ||
76 | return; | ||
77 | } | ||
78 | |||
79 | rmem->fdt_node = node; | ||
80 | rmem->name = uname; | ||
81 | rmem->base = base; | ||
82 | rmem->size = size; | ||
83 | |||
84 | reserved_mem_count++; | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * res_mem_alloc_size() - allocate reserved memory described by 'size', 'align' | ||
90 | * and 'alloc-ranges' properties | ||
91 | */ | ||
92 | static int __init __reserved_mem_alloc_size(unsigned long node, | ||
93 | const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) | ||
94 | { | ||
95 | int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); | ||
96 | phys_addr_t start = 0, end = 0; | ||
97 | phys_addr_t base = 0, align = 0, size; | ||
98 | int len; | ||
99 | const __be32 *prop; | ||
100 | int nomap; | ||
101 | int ret; | ||
102 | |||
103 | prop = of_get_flat_dt_prop(node, "size", &len); | ||
104 | if (!prop) | ||
105 | return -EINVAL; | ||
106 | |||
107 | if (len != dt_root_size_cells * sizeof(__be32)) { | ||
108 | pr_err("Reserved memory: invalid size property in '%s' node.\n", | ||
109 | uname); | ||
110 | return -EINVAL; | ||
111 | } | ||
112 | size = dt_mem_next_cell(dt_root_size_cells, &prop); | ||
113 | |||
114 | nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; | ||
115 | |||
116 | prop = of_get_flat_dt_prop(node, "alignment", &len); | ||
117 | if (prop) { | ||
118 | if (len != dt_root_addr_cells * sizeof(__be32)) { | ||
119 | pr_err("Reserved memory: invalid alignment property in '%s' node.\n", | ||
120 | uname); | ||
121 | return -EINVAL; | ||
122 | } | ||
123 | align = dt_mem_next_cell(dt_root_addr_cells, &prop); | ||
124 | } | ||
125 | |||
126 | prop = of_get_flat_dt_prop(node, "alloc-ranges", &len); | ||
127 | if (prop) { | ||
128 | |||
129 | if (len % t_len != 0) { | ||
130 | pr_err("Reserved memory: invalid alloc-ranges property in '%s', skipping node.\n", | ||
131 | uname); | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | base = 0; | ||
136 | |||
137 | while (len > 0) { | ||
138 | start = dt_mem_next_cell(dt_root_addr_cells, &prop); | ||
139 | end = start + dt_mem_next_cell(dt_root_size_cells, | ||
140 | &prop); | ||
141 | |||
142 | ret = early_init_dt_alloc_reserved_memory_arch(size, | ||
143 | align, start, end, nomap, &base); | ||
144 | if (ret == 0) { | ||
145 | pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", | ||
146 | uname, &base, | ||
147 | (unsigned long)size / SZ_1M); | ||
148 | break; | ||
149 | } | ||
150 | len -= t_len; | ||
151 | } | ||
152 | |||
153 | } else { | ||
154 | ret = early_init_dt_alloc_reserved_memory_arch(size, align, | ||
155 | 0, 0, nomap, &base); | ||
156 | if (ret == 0) | ||
157 | pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", | ||
158 | uname, &base, (unsigned long)size / SZ_1M); | ||
159 | } | ||
160 | |||
161 | if (base == 0) { | ||
162 | pr_info("Reserved memory: failed to allocate memory for node '%s'\n", | ||
163 | uname); | ||
164 | return -ENOMEM; | ||
165 | } | ||
166 | |||
167 | *res_base = base; | ||
168 | *res_size = size; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static const struct of_device_id __rmem_of_table_sentinel | ||
174 | __used __section(__reservedmem_of_table_end); | ||
175 | |||
176 | /** | ||
177 | * res_mem_init_node() - call region specific reserved memory init code | ||
178 | */ | ||
179 | static int __init __reserved_mem_init_node(struct reserved_mem *rmem) | ||
180 | { | ||
181 | extern const struct of_device_id __reservedmem_of_table[]; | ||
182 | const struct of_device_id *i; | ||
183 | |||
184 | for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { | ||
185 | reservedmem_of_init_fn initfn = i->data; | ||
186 | const char *compat = i->compatible; | ||
187 | |||
188 | if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) | ||
189 | continue; | ||
190 | |||
191 | if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) { | ||
192 | pr_info("Reserved memory: initialized node %s, compatible id %s\n", | ||
193 | rmem->name, compat); | ||
194 | return 0; | ||
195 | } | ||
196 | } | ||
197 | return -ENOENT; | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * fdt_init_reserved_mem - allocate and init all saved reserved memory regions | ||
202 | */ | ||
203 | void __init fdt_init_reserved_mem(void) | ||
204 | { | ||
205 | int i; | ||
206 | for (i = 0; i < reserved_mem_count; i++) { | ||
207 | struct reserved_mem *rmem = &reserved_mem[i]; | ||
208 | unsigned long node = rmem->fdt_node; | ||
209 | int err = 0; | ||
210 | |||
211 | if (rmem->size == 0) | ||
212 | err = __reserved_mem_alloc_size(node, rmem->name, | ||
213 | &rmem->base, &rmem->size); | ||
214 | if (err == 0) | ||
215 | __reserved_mem_init_node(rmem); | ||
216 | } | ||
217 | } | ||
diff --git a/drivers/usb/host/ehci-h20ahb.c b/drivers/usb/host/ehci-h20ahb.c index 3ee3c7aa6e5..7724bab1828 100644 --- a/drivers/usb/host/ehci-h20ahb.c +++ b/drivers/usb/host/ehci-h20ahb.c | |||
@@ -58,12 +58,12 @@ struct h20ahb_hcd { | |||
58 | 58 | ||
59 | static inline void ehci_write(void __iomem *base, u32 reg, u32 val) | 59 | static inline void ehci_write(void __iomem *base, u32 reg, u32 val) |
60 | { | 60 | { |
61 | __raw_writel(val, base + reg); | 61 | writel_relaxed(val, base + reg); |
62 | } | 62 | } |
63 | 63 | ||
64 | static inline u32 ehci_read(void __iomem *base, u32 reg) | 64 | static inline u32 ehci_read(void __iomem *base, u32 reg) |
65 | { | 65 | { |
66 | return __raw_readl(base + reg); | 66 | return readl_relaxed(base + reg); |
67 | } | 67 | } |
68 | 68 | ||
69 | /* configure so an HC device and id are always provided */ | 69 | /* configure so an HC device and id are always provided */ |
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h new file mode 100644 index 00000000000..a5de55c04fb --- /dev/null +++ b/include/asm-generic/early_ioremap.h | |||
@@ -0,0 +1,42 @@ | |||
1 | #ifndef _ASM_EARLY_IOREMAP_H_ | ||
2 | #define _ASM_EARLY_IOREMAP_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | /* | ||
7 | * early_ioremap() and early_iounmap() are for temporary early boot-time | ||
8 | * mappings, before the real ioremap() is functional. | ||
9 | */ | ||
10 | extern void __iomem *early_ioremap(resource_size_t phys_addr, | ||
11 | unsigned long size); | ||
12 | extern void *early_memremap(resource_size_t phys_addr, | ||
13 | unsigned long size); | ||
14 | extern void early_iounmap(void __iomem *addr, unsigned long size); | ||
15 | extern void early_memunmap(void *addr, unsigned long size); | ||
16 | |||
17 | /* | ||
18 | * Weak function called by early_ioremap_reset(). It does nothing, but | ||
19 | * architectures may provide their own version to do any needed cleanups. | ||
20 | */ | ||
21 | extern void early_ioremap_shutdown(void); | ||
22 | |||
23 | #if defined(CONFIG_GENERIC_EARLY_IOREMAP) && defined(CONFIG_MMU) | ||
24 | /* Arch-specific initialization */ | ||
25 | extern void early_ioremap_init(void); | ||
26 | |||
27 | /* Generic initialization called by architecture code */ | ||
28 | extern void early_ioremap_setup(void); | ||
29 | |||
30 | /* | ||
31 | * Called as last step in paging_init() so library can act | ||
32 | * accordingly for subsequent map/unmap requests. | ||
33 | */ | ||
34 | extern void early_ioremap_reset(void); | ||
35 | |||
36 | #else | ||
37 | static inline void early_ioremap_init(void) { } | ||
38 | static inline void early_ioremap_setup(void) { } | ||
39 | static inline void early_ioremap_reset(void) { } | ||
40 | #endif | ||
41 | |||
42 | #endif /* _ASM_EARLY_IOREMAP_H_ */ | ||
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index bc2121fa913..f10f64fcc81 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -167,6 +167,16 @@ | |||
167 | #define CLK_OF_TABLES() | 167 | #define CLK_OF_TABLES() |
168 | #endif | 168 | #endif |
169 | 169 | ||
170 | #ifdef CONFIG_OF_RESERVED_MEM | ||
171 | #define RESERVEDMEM_OF_TABLES() \ | ||
172 | . = ALIGN(8); \ | ||
173 | VMLINUX_SYMBOL(__reservedmem_of_table) = .; \ | ||
174 | *(__reservedmem_of_table) \ | ||
175 | *(__reservedmem_of_table_end) | ||
176 | #else | ||
177 | #define RESERVEDMEM_OF_TABLES() | ||
178 | #endif | ||
179 | |||
170 | #define KERNEL_DTB() \ | 180 | #define KERNEL_DTB() \ |
171 | STRUCT_ALIGN(); \ | 181 | STRUCT_ALIGN(); \ |
172 | VMLINUX_SYMBOL(__dtb_start) = .; \ | 182 | VMLINUX_SYMBOL(__dtb_start) = .; \ |
@@ -490,6 +500,7 @@ | |||
490 | TRACE_SYSCALLS() \ | 500 | TRACE_SYSCALLS() \ |
491 | MEM_DISCARD(init.rodata) \ | 501 | MEM_DISCARD(init.rodata) \ |
492 | CLK_OF_TABLES() \ | 502 | CLK_OF_TABLES() \ |
503 | RESERVEDMEM_OF_TABLES() \ | ||
493 | CLKSRC_OF_TABLES() \ | 504 | CLKSRC_OF_TABLES() \ |
494 | KERNEL_DTB() \ | 505 | KERNEL_DTB() \ |
495 | IRQCHIP_OF_MATCH_TABLE() | 506 | IRQCHIP_OF_MATCH_TABLE() |
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 2b77058a733..5f5b83461a8 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h | |||
@@ -66,7 +66,7 @@ extern char *of_fdt_get_string(struct boot_param_header *blob, u32 offset); | |||
66 | extern void *of_fdt_get_property(struct boot_param_header *blob, | 66 | extern void *of_fdt_get_property(struct boot_param_header *blob, |
67 | unsigned long node, | 67 | unsigned long node, |
68 | const char *name, | 68 | const char *name, |
69 | unsigned long *size); | 69 | int *size); |
70 | extern int of_fdt_is_compatible(struct boot_param_header *blob, | 70 | extern int of_fdt_is_compatible(struct boot_param_header *blob, |
71 | unsigned long node, | 71 | unsigned long node, |
72 | const char *compat); | 72 | const char *compat); |
@@ -81,26 +81,25 @@ extern int __initdata dt_root_size_cells; | |||
81 | extern struct boot_param_header *initial_boot_params; | 81 | extern struct boot_param_header *initial_boot_params; |
82 | 82 | ||
83 | /* For scanning the flat device-tree at boot time */ | 83 | /* For scanning the flat device-tree at boot time */ |
84 | extern char *find_flat_dt_string(u32 offset); | ||
85 | extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, | 84 | extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, |
86 | int depth, void *data), | 85 | int depth, void *data), |
87 | void *data); | 86 | void *data); |
88 | extern void *of_get_flat_dt_prop(unsigned long node, const char *name, | 87 | extern const void *of_get_flat_dt_prop(unsigned long node, const char *name, |
89 | unsigned long *size); | 88 | int *size); |
90 | extern int of_flat_dt_is_compatible(unsigned long node, const char *name); | 89 | extern int of_flat_dt_is_compatible(unsigned long node, const char *name); |
91 | extern int of_flat_dt_match(unsigned long node, const char *const *matches); | 90 | extern int of_flat_dt_match(unsigned long node, const char *const *matches); |
92 | extern unsigned long of_get_flat_dt_root(void); | 91 | extern unsigned long of_get_flat_dt_root(void); |
93 | extern int of_scan_flat_dt_by_path(const char *path, | ||
94 | int (*it)(unsigned long node, const char *name, int depth, void *data), | ||
95 | void *data); | ||
96 | 92 | ||
97 | extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, | 93 | extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, |
98 | int depth, void *data); | 94 | int depth, void *data); |
99 | extern int early_init_dt_scan_memory(unsigned long node, const char *uname, | 95 | extern int early_init_dt_scan_memory(unsigned long node, const char *uname, |
100 | int depth, void *data); | 96 | int depth, void *data); |
97 | extern void early_init_fdt_scan_reserved_mem(void); | ||
101 | extern void early_init_dt_add_memory_arch(u64 base, u64 size); | 98 | extern void early_init_dt_add_memory_arch(u64 base, u64 size); |
99 | extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, | ||
100 | bool no_map); | ||
102 | extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); | 101 | extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); |
103 | extern u64 dt_mem_next_cell(int s, __be32 **cellp); | 102 | extern u64 dt_mem_next_cell(int s, const __be32 **cellp); |
104 | 103 | ||
105 | /* Early flat tree scan hooks */ | 104 | /* Early flat tree scan hooks */ |
106 | extern int early_init_dt_scan_root(unsigned long node, const char *uname, | 105 | extern int early_init_dt_scan_root(unsigned long node, const char *uname, |
@@ -118,6 +117,7 @@ extern void unflatten_and_copy_device_tree(void); | |||
118 | extern void early_init_devtree(void *); | 117 | extern void early_init_devtree(void *); |
119 | extern void early_get_first_memblock_info(void *, phys_addr_t *); | 118 | extern void early_get_first_memblock_info(void *, phys_addr_t *); |
120 | #else /* CONFIG_OF_FLATTREE */ | 119 | #else /* CONFIG_OF_FLATTREE */ |
120 | static inline void early_init_fdt_scan_reserved_mem(void) {} | ||
121 | static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } | 121 | static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } |
122 | static inline void unflatten_device_tree(void) {} | 122 | static inline void unflatten_device_tree(void) {} |
123 | static inline void unflatten_and_copy_device_tree(void) {} | 123 | static inline void unflatten_and_copy_device_tree(void) {} |
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h new file mode 100644 index 00000000000..9b1fbb7f29f --- /dev/null +++ b/include/linux/of_reserved_mem.h | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifndef __OF_RESERVED_MEM_H | ||
2 | #define __OF_RESERVED_MEM_H | ||
3 | |||
4 | struct device; | ||
5 | struct of_phandle_args; | ||
6 | struct reserved_mem_ops; | ||
7 | |||
8 | struct reserved_mem { | ||
9 | const char *name; | ||
10 | unsigned long fdt_node; | ||
11 | const struct reserved_mem_ops *ops; | ||
12 | phys_addr_t base; | ||
13 | phys_addr_t size; | ||
14 | void *priv; | ||
15 | }; | ||
16 | |||
17 | struct reserved_mem_ops { | ||
18 | void (*device_init)(struct reserved_mem *rmem, | ||
19 | struct device *dev); | ||
20 | void (*device_release)(struct reserved_mem *rmem, | ||
21 | struct device *dev); | ||
22 | }; | ||
23 | |||
24 | typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem, | ||
25 | unsigned long node, const char *uname); | ||
26 | |||
27 | #ifdef CONFIG_OF_RESERVED_MEM | ||
28 | void fdt_init_reserved_mem(void); | ||
29 | void fdt_reserved_mem_save_node(unsigned long node, const char *uname, | ||
30 | phys_addr_t base, phys_addr_t size); | ||
31 | |||
32 | #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ | ||
33 | static const struct of_device_id __reservedmem_of_table_##name \ | ||
34 | __used __section(__reservedmem_of_table) \ | ||
35 | = { .compatible = compat, \ | ||
36 | .data = (init == (reservedmem_of_init_fn)NULL) ? \ | ||
37 | init : init } | ||
38 | |||
39 | #else | ||
40 | static inline void fdt_init_reserved_mem(void) { } | ||
41 | static inline void fdt_reserved_mem_save_node(unsigned long node, | ||
42 | const char *uname, phys_addr_t base, phys_addr_t size) { } | ||
43 | |||
44 | #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ | ||
45 | static const struct of_device_id __reservedmem_of_table_##name \ | ||
46 | __attribute__((unused)) \ | ||
47 | = { .compatible = compat, \ | ||
48 | .data = (init == (reservedmem_of_init_fn)NULL) ? \ | ||
49 | init : init } | ||
50 | |||
51 | #endif | ||
52 | |||
53 | #endif /* __OF_RESERVED_MEM_H */ | ||
diff --git a/lib/Makefile b/lib/Makefile index 48140e3ba73..befe5554a34 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -147,7 +147,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o | |||
147 | 147 | ||
148 | obj-$(CONFIG_STMP_DEVICE) += stmp_device.o | 148 | obj-$(CONFIG_STMP_DEVICE) += stmp_device.o |
149 | 149 | ||
150 | libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o | 150 | libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ |
151 | fdt_empty_tree.o | ||
151 | $(foreach file, $(libfdt_files), \ | 152 | $(foreach file, $(libfdt_files), \ |
152 | $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) | 153 | $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) |
153 | lib-$(CONFIG_LIBFDT) += $(libfdt_files) | 154 | lib-$(CONFIG_LIBFDT) += $(libfdt_files) |
diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 00000000000..5d30c58150a --- /dev/null +++ b/lib/fdt_empty_tree.c | |||
@@ -0,0 +1,2 @@ | |||
1 | #include <linux/libfdt_env.h> | ||
2 | #include "../scripts/dtc/libfdt/fdt_empty_tree.c" | ||
diff --git a/linaro/configs/linaro-base.conf b/linaro/configs/linaro-base.conf index eb9fe266ca0..bbd0f160398 100644 --- a/linaro/configs/linaro-base.conf +++ b/linaro/configs/linaro-base.conf | |||
@@ -114,3 +114,5 @@ CONFIG_LSM_MMAP_MIN_ADDR=4096 | |||
114 | CONFIG_SECURITY_SELINUX=y | 114 | CONFIG_SECURITY_SELINUX=y |
115 | CONFIG_EXT4_FS_SECURITY=y | 115 | CONFIG_EXT4_FS_SECURITY=y |
116 | CONFIG_BLK_DEV_LOOP=y | 116 | CONFIG_BLK_DEV_LOOP=y |
117 | CONFIG_DEBUG_INFO=y | ||
118 | CONFIG_FANOTIFY=y | ||
diff --git a/mm/Kconfig b/mm/Kconfig index 0862816bb45..57c124ee411 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -595,3 +595,6 @@ config MAX_STACK_SIZE_MB | |||
595 | changed to a smaller value in which case that is used. | 595 | changed to a smaller value in which case that is used. |
596 | 596 | ||
597 | A sane initial value is 80 MB. | 597 | A sane initial value is 80 MB. |
598 | |||
599 | config GENERIC_EARLY_IOREMAP | ||
600 | bool | ||
diff --git a/mm/Makefile b/mm/Makefile index 310c90a0926..9d9c587620a 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
@@ -61,3 +61,4 @@ obj-$(CONFIG_CLEANCACHE) += cleancache.o | |||
61 | obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o | 61 | obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o |
62 | obj-$(CONFIG_ZBUD) += zbud.o | 62 | obj-$(CONFIG_ZBUD) += zbud.o |
63 | obj-$(CONFIG_ZSMALLOC) += zsmalloc.o | 63 | obj-$(CONFIG_ZSMALLOC) += zsmalloc.o |
64 | obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o | ||
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c new file mode 100644 index 00000000000..e10ccd299d6 --- /dev/null +++ b/mm/early_ioremap.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | * Provide common bits of early_ioremap() support for architectures needing | ||
3 | * temporary mappings during boot before ioremap() is available. | ||
4 | * | ||
5 | * This is mostly a direct copy of the x86 early_ioremap implementation. | ||
6 | * | ||
7 | * (C) Copyright 1995 1996, 2014 Linus Torvalds | ||
8 | * | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/vmalloc.h> | ||
17 | #include <asm/fixmap.h> | ||
18 | |||
19 | #ifdef CONFIG_MMU | ||
20 | static int early_ioremap_debug __initdata; | ||
21 | |||
22 | static int __init early_ioremap_debug_setup(char *str) | ||
23 | { | ||
24 | early_ioremap_debug = 1; | ||
25 | |||
26 | return 0; | ||
27 | } | ||
28 | early_param("early_ioremap_debug", early_ioremap_debug_setup); | ||
29 | |||
30 | static int after_paging_init __initdata; | ||
31 | |||
32 | void __init __weak early_ioremap_shutdown(void) | ||
33 | { | ||
34 | } | ||
35 | |||
36 | void __init early_ioremap_reset(void) | ||
37 | { | ||
38 | early_ioremap_shutdown(); | ||
39 | after_paging_init = 1; | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * Generally, ioremap() is available after paging_init() has been called. | ||
44 | * Architectures wanting to allow early_ioremap after paging_init() can | ||
45 | * define __late_set_fixmap and __late_clear_fixmap to do the right thing. | ||
46 | */ | ||
47 | #ifndef __late_set_fixmap | ||
48 | static inline void __init __late_set_fixmap(enum fixed_addresses idx, | ||
49 | phys_addr_t phys, pgprot_t prot) | ||
50 | { | ||
51 | BUG(); | ||
52 | } | ||
53 | #endif | ||
54 | |||
55 | #ifndef __late_clear_fixmap | ||
56 | static inline void __init __late_clear_fixmap(enum fixed_addresses idx) | ||
57 | { | ||
58 | BUG(); | ||
59 | } | ||
60 | #endif | ||
61 | |||
62 | static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata; | ||
63 | static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; | ||
64 | static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; | ||
65 | |||
66 | void __init early_ioremap_setup(void) | ||
67 | { | ||
68 | int i; | ||
69 | |||
70 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) | ||
71 | if (WARN_ON(prev_map[i])) | ||
72 | break; | ||
73 | |||
74 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) | ||
75 | slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); | ||
76 | } | ||
77 | |||
78 | static int __init check_early_ioremap_leak(void) | ||
79 | { | ||
80 | int count = 0; | ||
81 | int i; | ||
82 | |||
83 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) | ||
84 | if (prev_map[i]) | ||
85 | count++; | ||
86 | |||
87 | if (WARN(count, KERN_WARNING | ||
88 | "Debug warning: early ioremap leak of %d areas detected.\n" | ||
89 | "please boot with early_ioremap_debug and report the dmesg.\n", | ||
90 | count)) | ||
91 | return 1; | ||
92 | return 0; | ||
93 | } | ||
94 | late_initcall(check_early_ioremap_leak); | ||
95 | |||
96 | static void __init __iomem * | ||
97 | __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) | ||
98 | { | ||
99 | unsigned long offset; | ||
100 | resource_size_t last_addr; | ||
101 | unsigned int nrpages; | ||
102 | enum fixed_addresses idx; | ||
103 | int i, slot; | ||
104 | |||
105 | WARN_ON(system_state != SYSTEM_BOOTING); | ||
106 | |||
107 | slot = -1; | ||
108 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { | ||
109 | if (!prev_map[i]) { | ||
110 | slot = i; | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (WARN(slot < 0, "%s(%08llx, %08lx) not found slot\n", | ||
116 | __func__, (u64)phys_addr, size)) | ||
117 | return NULL; | ||
118 | |||
119 | /* Don't allow wraparound or zero size */ | ||
120 | last_addr = phys_addr + size - 1; | ||
121 | if (WARN_ON(!size || last_addr < phys_addr)) | ||
122 | return NULL; | ||
123 | |||
124 | prev_size[slot] = size; | ||
125 | /* | ||
126 | * Mappings have to be page-aligned | ||
127 | */ | ||
128 | offset = phys_addr & ~PAGE_MASK; | ||
129 | phys_addr &= PAGE_MASK; | ||
130 | size = PAGE_ALIGN(last_addr + 1) - phys_addr; | ||
131 | |||
132 | /* | ||
133 | * Mappings have to fit in the FIX_BTMAP area. | ||
134 | */ | ||
135 | nrpages = size >> PAGE_SHIFT; | ||
136 | if (WARN_ON(nrpages > NR_FIX_BTMAPS)) | ||
137 | return NULL; | ||
138 | |||
139 | /* | ||
140 | * Ok, go for it.. | ||
141 | */ | ||
142 | idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; | ||
143 | while (nrpages > 0) { | ||
144 | if (after_paging_init) | ||
145 | __late_set_fixmap(idx, phys_addr, prot); | ||
146 | else | ||
147 | __early_set_fixmap(idx, phys_addr, prot); | ||
148 | phys_addr += PAGE_SIZE; | ||
149 | --idx; | ||
150 | --nrpages; | ||
151 | } | ||
152 | WARN(early_ioremap_debug, "%s(%08llx, %08lx) [%d] => %08lx + %08lx\n", | ||
153 | __func__, (u64)phys_addr, size, slot, offset, slot_virt[slot]); | ||
154 | |||
155 | prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]); | ||
156 | return prev_map[slot]; | ||
157 | } | ||
158 | |||
159 | void __init early_iounmap(void __iomem *addr, unsigned long size) | ||
160 | { | ||
161 | unsigned long virt_addr; | ||
162 | unsigned long offset; | ||
163 | unsigned int nrpages; | ||
164 | enum fixed_addresses idx; | ||
165 | int i, slot; | ||
166 | |||
167 | slot = -1; | ||
168 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { | ||
169 | if (prev_map[i] == addr) { | ||
170 | slot = i; | ||
171 | break; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | if (WARN(slot < 0, "early_iounmap(%p, %08lx) not found slot\n", | ||
176 | addr, size)) | ||
177 | return; | ||
178 | |||
179 | if (WARN(prev_size[slot] != size, | ||
180 | "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n", | ||
181 | addr, size, slot, prev_size[slot])) | ||
182 | return; | ||
183 | |||
184 | WARN(early_ioremap_debug, "early_iounmap(%p, %08lx) [%d]\n", | ||
185 | addr, size, slot); | ||
186 | |||
187 | virt_addr = (unsigned long)addr; | ||
188 | if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))) | ||
189 | return; | ||
190 | |||
191 | offset = virt_addr & ~PAGE_MASK; | ||
192 | nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT; | ||
193 | |||
194 | idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; | ||
195 | while (nrpages > 0) { | ||
196 | if (after_paging_init) | ||
197 | __late_clear_fixmap(idx); | ||
198 | else | ||
199 | __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); | ||
200 | --idx; | ||
201 | --nrpages; | ||
202 | } | ||
203 | prev_map[slot] = NULL; | ||
204 | } | ||
205 | |||
206 | /* Remap an IO device */ | ||
207 | void __init __iomem * | ||
208 | early_ioremap(resource_size_t phys_addr, unsigned long size) | ||
209 | { | ||
210 | return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO); | ||
211 | } | ||
212 | |||
213 | /* Remap memory */ | ||
214 | void __init * | ||
215 | early_memremap(resource_size_t phys_addr, unsigned long size) | ||
216 | { | ||
217 | return (__force void *)__early_ioremap(phys_addr, size, | ||
218 | FIXMAP_PAGE_NORMAL); | ||
219 | } | ||
220 | #else /* CONFIG_MMU */ | ||
221 | |||
222 | void __init __iomem * | ||
223 | early_ioremap(resource_size_t phys_addr, unsigned long size) | ||
224 | { | ||
225 | return (__force void __iomem *)phys_addr; | ||
226 | } | ||
227 | |||
228 | /* Remap memory */ | ||
229 | void __init * | ||
230 | early_memremap(resource_size_t phys_addr, unsigned long size) | ||
231 | { | ||
232 | return (void *)phys_addr; | ||
233 | } | ||
234 | |||
235 | void __init early_iounmap(void __iomem *addr, unsigned long size) | ||
236 | { | ||
237 | } | ||
238 | |||
239 | #endif /* CONFIG_MMU */ | ||
240 | |||
241 | |||
242 | void __init early_memunmap(void *addr, unsigned long size) | ||
243 | { | ||
244 | early_iounmap((__force void __iomem *)addr, size); | ||
245 | } | ||