aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPraneeth Bajjuri2014-08-20 17:29:32 -0500
committerPraneeth Bajjuri2014-08-20 17:29:32 -0500
commit1bac0d75dddea95fed777f36b793b13745432fa2 (patch)
tree8d64f81acf2074b6e215d3f7cfcd4f1323e963dc
parenta9c8e3d8d78dab930e133884a7c887e5c97c114b (diff)
parent4811ec8cfa2f8d959cee6c7bd99f58f4b6d82a48 (diff)
downloadkernel-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>
-rw-r--r--Documentation/arm64/memory.txt12
-rw-r--r--arch/arc/kernel/devtree.c2
-rw-r--r--arch/arm/kernel/devtree.c2
-rw-r--r--arch/arm/mach-exynos/common.c2
-rw-r--r--arch/arm/mach-vexpress/platsmp.c2
-rw-r--r--arch/arm/plat-samsung/s5p-dev-mfc.c16
-rw-r--r--arch/arm64/Kconfig4
-rw-r--r--arch/arm64/boot/dts/apm-storm.dtsi52
-rw-r--r--arch/arm64/include/asm/Kbuild1
-rw-r--r--arch/arm64/include/asm/atomic.h2
-rw-r--r--arch/arm64/include/asm/barrier.h2
-rw-r--r--arch/arm64/include/asm/cacheflush.h13
-rw-r--r--arch/arm64/include/asm/cmpxchg.h7
-rw-r--r--arch/arm64/include/asm/fixmap.h67
-rw-r--r--arch/arm64/include/asm/io.h9
-rw-r--r--arch/arm64/include/asm/memory.h3
-rw-r--r--arch/arm64/include/asm/mmu.h6
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h2
-rw-r--r--arch/arm64/include/asm/pgtable.h120
-rw-r--r--arch/arm64/include/asm/sigcontext.h31
-rw-r--r--arch/arm64/include/asm/tlbflush.h49
-rw-r--r--arch/arm64/kernel/early_printk.c8
-rw-r--r--arch/arm64/kernel/head.S15
-rw-r--r--arch/arm64/kernel/process.c2
-rw-r--r--arch/arm64/kernel/setup.c3
-rw-r--r--arch/arm64/kernel/signal.c27
-rw-r--r--arch/arm64/kernel/smp_spin_table.c39
-rw-r--r--arch/arm64/kvm/sys_regs.c4
-rw-r--r--arch/arm64/mm/Makefile2
-rw-r--r--arch/arm64/mm/dma-mapping.c6
-rw-r--r--arch/arm64/mm/ioremap.c85
-rw-r--r--arch/arm64/mm/mmu.c134
-rw-r--r--arch/arm64/mm/tlb.S71
-rw-r--r--arch/microblaze/kernel/prom.c8
-rw-r--r--arch/powerpc/kernel/epapr_paravirt.c2
-rw-r--r--arch/powerpc/kernel/fadump.c4
-rw-r--r--arch/powerpc/kernel/prom.c24
-rw-r--r--arch/powerpc/kernel/rtas.c2
-rw-r--r--arch/powerpc/mm/hash_utils_64.c22
-rw-r--r--arch/powerpc/platforms/52xx/efika.c4
-rw-r--r--arch/powerpc/platforms/chrp/setup.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal.c72
-rw-r--r--arch/powerpc/platforms/pseries/setup.c4
-rw-r--r--arch/xtensa/kernel/setup.c2
-rw-r--r--drivers/of/Kconfig7
-rw-r--r--drivers/of/Makefile3
-rw-r--r--drivers/of/fdt.c450
-rw-r--r--drivers/of/of_reserved_mem.c217
-rw-r--r--drivers/usb/host/ehci-h20ahb.c4
-rw-r--r--include/asm-generic/early_ioremap.h42
-rw-r--r--include/asm-generic/vmlinux.lds.h11
-rw-r--r--include/linux/of_fdt.h16
-rw-r--r--include/linux/of_reserved_mem.h53
-rw-r--r--lib/Makefile3
-rw-r--r--lib/fdt_empty_tree.c2
-rw-r--r--linaro/configs/linaro-base.conf2
-rw-r--r--mm/Kconfig3
-rw-r--r--mm/Makefile1
-rw-r--r--mm/early_ioremap.c245
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
36ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] 36ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap]
37 37
38ffffffbffbc00000 ffffffbffbdfffff 2MB earlyprintk device 38ffffffbffa000000 ffffffbffaffffff 16MB PCI I/O space
39
40ffffffbffb000000 ffffffbffbbfffff 12MB [guard]
41
42ffffffbffbc00000 ffffffbffbdfffff 2MB fixed mappings
39 43
40ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space 44ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space
41 45
@@ -60,7 +64,11 @@ fffffdfc00000000 fffffdfdffffffff 8GB vmemmap
60 64
61fffffdfe00000000 fffffdfffbbfffff ~8GB [guard, future vmmemap] 65fffffdfe00000000 fffffdfffbbfffff ~8GB [guard, future vmmemap]
62 66
63fffffdfffbc00000 fffffdfffbdfffff 2MB earlyprintk device 67fffffdfffa000000 fffffdfffaffffff 16MB PCI I/O space
68
69fffffdfffb000000 fffffdfffbbfffff 12MB [guard]
70
71fffffdfffbc00000 fffffdfffbdfffff 2MB fixed mappings
64 72
65fffffdfffbe00000 fffffdfffbe0ffff 64KB PCI I/O space 73fffffdfffbe00000 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);
125int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname, 125int __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
118config KERNEL_MODE_NEON 119config KERNEL_MODE_NEON
119 def_bool y 120 def_bool y
120 121
122config FIX_EARLYCON_MEM
123 def_bool y
124
121source "init/Kconfig" 125source "init/Kconfig"
122 126
123source "kernel/Kconfig.freezer" 127source "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
10generic-y += div64.h 10generic-y += div64.h
11generic-y += dma.h 11generic-y += dma.h
12generic-y += emergency-restart.h 12generic-y += emergency-restart.h
13generic-y += early_ioremap.h
13generic-y += errno.h 14generic-y += errno.h
14generic-y += ftrace.h 15generic-y += ftrace.h
15generic-y += hw_irq.h 16generic-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
168static inline void atomic64_add(u64 i, atomic64_t *v) 168static 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 *);
123static inline void __flush_icache_all(void) 123static 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 */
147static inline void flush_cache_vmap(unsigned long start, unsigned long end) 143static 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
156static inline void flush_cache_vunmap(unsigned long start, unsigned long end) 147static 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
77static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, 82static 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 */
33enum 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
59extern 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
229extern void __iounmap(volatile void __iomem *addr); 230extern void __iounmap(volatile void __iomem *addr);
230extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); 231extern 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
27extern void paging_init(void); 30extern void paging_init(void);
28extern void setup_mm_for_reboot(void); 31extern void setup_mm_for_reboot(void);
29extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); 32extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
33extern void init_mem_pgprot(void);
34/* create an identity mapping for memory (or io if map_io is true) */
35extern 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
63extern 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
149static inline pte_t pte_wrprotect(pte_t pte) 145static inline pte_t pte_wrprotect(pte_t pte)
150{ 146{
@@ -191,6 +187,15 @@ static inline pte_t pte_mkspecial(pte_t pte)
191static inline void set_pte(pte_t *ptep, pte_t pte) 187static 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
196extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); 201extern 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
271static inline int has_transparent_hugepage(void) 276static 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
286struct file; 292struct file;
287extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 293extern 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,
301static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) 307static 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
307static inline void pmd_clear(pmd_t *pmdp) 314static inline void pmd_clear(pmd_t *pmdp)
@@ -331,7 +338,8 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
331static inline void set_pud(pud_t *pudp, pud_t pud) 338static 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
337static inline void pud_clear(pud_t *pudp) 345static 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 */
26struct 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 */
73static inline void flush_tlb_all(void) 73static 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
90static inline void flush_tlb_page(struct vm_area_struct *vma, 90static 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/* 101static 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
115static 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
29static void __iomem *early_base; 31static void __iomem *early_base;
30static void (*printch)(char ch); 32static 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
2211: dc cvac, x1 // Clean potentially dirty cache line 2211: 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
227ENDPROC(set_cpu_boot_mode_flag) 223ENDPROC(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
4711: 4671:
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(&regs->user_regs); 121 err |= !valid_user_regs(&regs->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);
30volatile unsigned long secondary_holding_pen_release = INVALID_HWID; 30volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
31 31
32static phys_addr_t cpu_release_addr[NR_CPUS]; 32static phys_addr_t cpu_release_addr[NR_CPUS];
33static 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
95static int smp_spin_table_cpu_boot(unsigned int cpu) 94static 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
131void 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
145const struct cpu_operations smp_spin_table_ops = { 109const 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)
70static void do_dc_cisw(u32 val) 70static 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
76static void do_dc_csw(u32 val) 76static 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 @@
1obj-y := dma-mapping.o extable.o fault.o init.o \ 1obj-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
5obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 5obj-$(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);
36static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot, 36static 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
28static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, 32static 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}
100EXPORT_SYMBOL(ioremap_cache); 104EXPORT_SYMBOL(ioremap_cache);
105
106#ifndef CONFIG_ARM64_64K_PAGES
107static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
108#endif
109
110static 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
124static 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
133void __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
166void __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 @@
43struct page *empty_zero_page; 43struct page *empty_zero_page;
44EXPORT_SYMBOL(empty_zero_page); 44EXPORT_SYMBOL(empty_zero_page);
45 45
46pgprot_t pgprot_default;
47EXPORT_SYMBOL(pgprot_default);
48
49static pmdval_t prot_sect_kernel;
50
51struct cachepolicy { 46struct 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}
123early_param("cachepolicy", early_cachepolicy); 118early_param("cachepolicy", early_cachepolicy);
124 119
125/*
126 * Adjust the PMD section entries according to the CPU in use.
127 */
128static 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
152pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 120pgprot_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
170static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, 138static 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
188static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, 157static 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
222static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, 204static 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 */
239static void __init create_mapping(phys_addr_t phys, unsigned long virt, 222static 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 239static 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 */
269void __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)); 250void __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
304static void __init map_mem(void) 260static 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 */
36ENTRY(__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
441: 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
50ENDPROC(__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 */
60ENTRY(__cpu_flush_kern_tlb_range)
61 dsb sy
62 lsr x0, x0, #12 // align address
63 lsr x1, x1, #12
641: 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
71ENDPROC(__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
46static char *stdout; 46static const char *stdout;
47 47
48static int __init early_init_dt_scan_chosen_serial(unsigned long node, 48static 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;
55int __init early_init_dt_scan_fw_dump(unsigned long node, 55int __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
165static void __init scan_features(unsigned long node, unsigned char *ftrs, 165static 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
202static void __init check_cpu_pa_features(unsigned long node) 202static 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
216static void __init check_cpu_slb_size(unsigned long node) 216static 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 {
256static inline void identical_pvr_fixup(unsigned long node) 256static 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,
391int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname, 391int __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 */
443static int __init early_init_dt_scan_drconf_memory(unsigned long node) 443static 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
564static void __init early_reserve_mem_dt(void) 565static 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)
1135int __init early_init_dt_scan_rtas(unsigned long node, 1135int __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,
402static int __init htab_dt_scan_hugepage_blocks(unsigned long node, 402static 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
200static int __init efika_probe(void) 200static 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
575static int __init chrp_probe(void) 575static 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=======
89int __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
87static int __init opal_register_exception_handlers(void) 149static 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,
704static int __init pSeries_probe(void) 704static 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
28config OF_FLATTREE 28config OF_FLATTREE
29 bool 29 bool
30 select DTC 30 select DTC
31 select LIBFDT
31 32
32config OF_EARLY_FLATTREE 33config 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
79config OF_RESERVED_MEM
80 depends on OF_EARLY_FLATTREE
81 bool
82 help
83 Helpers to allow for reservation of memory regions
84
78endmenu # OF 85endmenu # 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
9obj-$(CONFIG_OF_PCI) += of_pci.o 9obj-$(CONFIG_OF_PCI) += of_pci.o
10obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o 10obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
11obj-$(CONFIG_OF_MTD) += of_mtd.o 11obj-$(CONFIG_OF_MTD) += of_mtd.o
12obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
13
14CFLAGS_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
29char *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 */
39void *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 */
150static void * unflatten_dt_node(struct boot_param_header *blob, 106static 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 */
388static 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 */
435static 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 */
456static 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 */
499void __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 */
503unsigned long __init of_get_flat_dt_root(void) 541unsigned 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 */
521void *__init of_get_flat_dt_prop(unsigned long node, const char *name, 552const 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 */
557static 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 */
603int __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
621const char * __init of_flat_dt_get_machine_name(void) 585const 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,
686static void __init early_init_dt_check_for_initrd(unsigned long node) 650static 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)
720int __init early_init_dt_scan_root(unsigned long node, const char *uname, 684int __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
745u64 __init dt_mem_next_cell(int s, __be32 **cellp) 709u64 __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)
756int __init early_init_dt_scan_memory(unsigned long node, const char *uname, 720int __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,
802int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, 766int __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
823int __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
842int __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
869bool __init early_init_dt_scan(void *params) 851bool __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
25static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
26static int reserved_mem_count;
27
28#if defined(CONFIG_HAVE_MEMBLOCK)
29#include <linux/memblock.h>
30int __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
56int __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 */
69void __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 */
92static 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
173static 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 */
179static 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 */
203void __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
59static inline void ehci_write(void __iomem *base, u32 reg, u32 val) 59static 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
64static inline u32 ehci_read(void __iomem *base, u32 reg) 64static 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 */
10extern void __iomem *early_ioremap(resource_size_t phys_addr,
11 unsigned long size);
12extern void *early_memremap(resource_size_t phys_addr,
13 unsigned long size);
14extern void early_iounmap(void __iomem *addr, unsigned long size);
15extern 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 */
21extern void early_ioremap_shutdown(void);
22
23#if defined(CONFIG_GENERIC_EARLY_IOREMAP) && defined(CONFIG_MMU)
24/* Arch-specific initialization */
25extern void early_ioremap_init(void);
26
27/* Generic initialization called by architecture code */
28extern 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 */
34extern void early_ioremap_reset(void);
35
36#else
37static inline void early_ioremap_init(void) { }
38static inline void early_ioremap_setup(void) { }
39static 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);
66extern void *of_fdt_get_property(struct boot_param_header *blob, 66extern 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);
70extern int of_fdt_is_compatible(struct boot_param_header *blob, 70extern 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;
81extern struct boot_param_header *initial_boot_params; 81extern 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 */
84extern char *find_flat_dt_string(u32 offset);
85extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, 84extern 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);
88extern void *of_get_flat_dt_prop(unsigned long node, const char *name, 87extern const void *of_get_flat_dt_prop(unsigned long node, const char *name,
89 unsigned long *size); 88 int *size);
90extern int of_flat_dt_is_compatible(unsigned long node, const char *name); 89extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
91extern int of_flat_dt_match(unsigned long node, const char *const *matches); 90extern int of_flat_dt_match(unsigned long node, const char *const *matches);
92extern unsigned long of_get_flat_dt_root(void); 91extern unsigned long of_get_flat_dt_root(void);
93extern 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
97extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, 93extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
98 int depth, void *data); 94 int depth, void *data);
99extern int early_init_dt_scan_memory(unsigned long node, const char *uname, 95extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
100 int depth, void *data); 96 int depth, void *data);
97extern void early_init_fdt_scan_reserved_mem(void);
101extern void early_init_dt_add_memory_arch(u64 base, u64 size); 98extern void early_init_dt_add_memory_arch(u64 base, u64 size);
99extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size,
100 bool no_map);
102extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); 101extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
103extern u64 dt_mem_next_cell(int s, __be32 **cellp); 102extern u64 dt_mem_next_cell(int s, const __be32 **cellp);
104 103
105/* Early flat tree scan hooks */ 104/* Early flat tree scan hooks */
106extern int early_init_dt_scan_root(unsigned long node, const char *uname, 105extern int early_init_dt_scan_root(unsigned long node, const char *uname,
@@ -118,6 +117,7 @@ extern void unflatten_and_copy_device_tree(void);
118extern void early_init_devtree(void *); 117extern void early_init_devtree(void *);
119extern void early_get_first_memblock_info(void *, phys_addr_t *); 118extern void early_get_first_memblock_info(void *, phys_addr_t *);
120#else /* CONFIG_OF_FLATTREE */ 119#else /* CONFIG_OF_FLATTREE */
120static inline void early_init_fdt_scan_reserved_mem(void) {}
121static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } 121static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
122static inline void unflatten_device_tree(void) {} 122static inline void unflatten_device_tree(void) {}
123static inline void unflatten_and_copy_device_tree(void) {} 123static 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
4struct device;
5struct of_phandle_args;
6struct reserved_mem_ops;
7
8struct 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
17struct 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
24typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem,
25 unsigned long node, const char *uname);
26
27#ifdef CONFIG_OF_RESERVED_MEM
28void fdt_init_reserved_mem(void);
29void 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
40static inline void fdt_init_reserved_mem(void) { }
41static 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
148obj-$(CONFIG_STMP_DEVICE) += stmp_device.o 148obj-$(CONFIG_STMP_DEVICE) += stmp_device.o
149 149
150libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o 150libfdt_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))
153lib-$(CONFIG_LIBFDT) += $(libfdt_files) 154lib-$(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
114CONFIG_SECURITY_SELINUX=y 114CONFIG_SECURITY_SELINUX=y
115CONFIG_EXT4_FS_SECURITY=y 115CONFIG_EXT4_FS_SECURITY=y
116CONFIG_BLK_DEV_LOOP=y 116CONFIG_BLK_DEV_LOOP=y
117CONFIG_DEBUG_INFO=y
118CONFIG_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
599config 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
61obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o 61obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o
62obj-$(CONFIG_ZBUD) += zbud.o 62obj-$(CONFIG_ZBUD) += zbud.o
63obj-$(CONFIG_ZSMALLOC) += zsmalloc.o 63obj-$(CONFIG_ZSMALLOC) += zsmalloc.o
64obj-$(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
20static int early_ioremap_debug __initdata;
21
22static int __init early_ioremap_debug_setup(char *str)
23{
24 early_ioremap_debug = 1;
25
26 return 0;
27}
28early_param("early_ioremap_debug", early_ioremap_debug_setup);
29
30static int after_paging_init __initdata;
31
32void __init __weak early_ioremap_shutdown(void)
33{
34}
35
36void __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
48static 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
56static inline void __init __late_clear_fixmap(enum fixed_addresses idx)
57{
58 BUG();
59}
60#endif
61
62static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
63static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
64static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
65
66void __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
78static 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}
94late_initcall(check_early_ioremap_leak);
95
96static 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
159void __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 */
207void __init __iomem *
208early_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 */
214void __init *
215early_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
222void __init __iomem *
223early_ioremap(resource_size_t phys_addr, unsigned long size)
224{
225 return (__force void __iomem *)phys_addr;
226}
227
228/* Remap memory */
229void __init *
230early_memremap(resource_size_t phys_addr, unsigned long size)
231{
232 return (void *)phys_addr;
233}
234
235void __init early_iounmap(void __iomem *addr, unsigned long size)
236{
237}
238
239#endif /* CONFIG_MMU */
240
241
242void __init early_memunmap(void *addr, unsigned long size)
243{
244 early_iounmap((__force void __iomem *)addr, size);
245}