Commit 03787ff6f9156e43019f3f4b69cb6212b3a47f65
Exists in
ti-lsk-linux-4.1.y
and in
12 other branches
Merge tag 'xtensa-next-20140503' of git://github.com/czankel/xtensa-linux
Pull Xtensa fixes from Chris Zankel: - Fixes allmodconfig, allnoconfig builds - Adds highmem support - Enables build-time exception table sorting. * tag 'xtensa-next-20140503' of git://github.com/czankel/xtensa-linux: xtensa: ISS: don't depend on CONFIG_TTY xtensa: xt2000: drop redundant sysmem initialization xtensa: add support for KC705 xtensa: xtfpga: introduce SoC I/O bus xtensa: add HIGHMEM support xtensa: optimize local_flush_tlb_kernel_range xtensa: dump sysmem from the bootmem_init xtensa: handle memmap kernel option xtensa: keep sysmem banks ordered in mem_reserve xtensa: keep sysmem banks ordered in add_sysmem_bank xtensa: split bootparam and kernel meminfo xtensa: enable sorting extable at build time xtensa: export __{invalidate,flush}_dcache_range xtensa: Export __invalidate_icache_range
Showing 24 changed files Side-by-side Diff
- arch/xtensa/Kconfig
- arch/xtensa/boot/dts/kc705.dts
- arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
- arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
- arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
- arch/xtensa/boot/dts/xtfpga.dtsi
- arch/xtensa/include/asm/bootparam.h
- arch/xtensa/include/asm/fixmap.h
- arch/xtensa/include/asm/highmem.h
- arch/xtensa/include/asm/pgtable.h
- arch/xtensa/include/asm/sysmem.h
- arch/xtensa/include/asm/tlbflush.h
- arch/xtensa/kernel/setup.c
- arch/xtensa/kernel/smp.c
- arch/xtensa/kernel/xtensa_ksyms.c
- arch/xtensa/mm/Makefile
- arch/xtensa/mm/cache.c
- arch/xtensa/mm/highmem.c
- arch/xtensa/mm/init.c
- arch/xtensa/mm/mmu.c
- arch/xtensa/mm/tlb.c
- arch/xtensa/platforms/iss/Makefile
- arch/xtensa/platforms/xt2000/setup.c
- scripts/sortextable.c
arch/xtensa/Kconfig
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | select GENERIC_PCI_IOMAP |
15 | 15 | select ARCH_WANT_IPC_PARSE_VERSION |
16 | 16 | select ARCH_WANT_OPTIONAL_GPIOLIB |
17 | + select BUILDTIME_EXTABLE_SORT | |
17 | 18 | select CLONE_BACKWARDS |
18 | 19 | select IRQ_DOMAIN |
19 | 20 | select HAVE_OPROFILE |
... | ... | @@ -189,6 +190,24 @@ |
189 | 190 | |
190 | 191 | If in doubt, say Y. |
191 | 192 | |
193 | +config HIGHMEM | |
194 | + bool "High Memory Support" | |
195 | + help | |
196 | + Linux can use the full amount of RAM in the system by | |
197 | + default. However, the default MMUv2 setup only maps the | |
198 | + lowermost 128 MB of memory linearly to the areas starting | |
199 | + at 0xd0000000 (cached) and 0xd8000000 (uncached). | |
200 | + When there are more than 128 MB memory in the system not | |
201 | + all of it can be "permanently mapped" by the kernel. | |
202 | + The physical memory that's not permanently mapped is called | |
203 | + "high memory". | |
204 | + | |
205 | + If you are compiling a kernel which will never run on a | |
206 | + machine with more than 128 MB total physical RAM, answer | |
207 | + N here. | |
208 | + | |
209 | + If unsure, say Y. | |
210 | + | |
192 | 211 | endmenu |
193 | 212 | |
194 | 213 | config XTENSA_CALIBRATE_CCOUNT |
... | ... | @@ -224,7 +243,6 @@ |
224 | 243 | |
225 | 244 | config XTENSA_PLATFORM_ISS |
226 | 245 | bool "ISS" |
227 | - depends on TTY | |
228 | 246 | select XTENSA_CALIBRATE_CCOUNT |
229 | 247 | select SERIAL_CONSOLE |
230 | 248 | help |
arch/xtensa/boot/dts/kc705.dts
arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
1 | +/ { | |
2 | + soc { | |
3 | + flash: flash@00000000 { | |
4 | + #address-cells = <1>; | |
5 | + #size-cells = <1>; | |
6 | + compatible = "cfi-flash"; | |
7 | + reg = <0x00000000 0x08000000>; | |
8 | + bank-width = <2>; | |
9 | + device-width = <2>; | |
10 | + partition@0x0 { | |
11 | + label = "data"; | |
12 | + reg = <0x00000000 0x06000000>; | |
13 | + }; | |
14 | + partition@0x6000000 { | |
15 | + label = "boot loader area"; | |
16 | + reg = <0x06000000 0x00800000>; | |
17 | + }; | |
18 | + partition@0x6800000 { | |
19 | + label = "kernel image"; | |
20 | + reg = <0x06800000 0x017e0000>; | |
21 | + }; | |
22 | + partition@0x7fe0000 { | |
23 | + label = "boot environment"; | |
24 | + reg = <0x07fe0000 0x00020000>; | |
25 | + }; | |
26 | + }; | |
27 | + }; | |
28 | +}; |
arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
1 | 1 | / { |
2 | - flash: flash@f8000000 { | |
3 | - #address-cells = <1>; | |
4 | - #size-cells = <1>; | |
5 | - compatible = "cfi-flash"; | |
6 | - reg = <0xf8000000 0x01000000>; | |
7 | - bank-width = <2>; | |
8 | - device-width = <2>; | |
9 | - partition@0x0 { | |
10 | - label = "boot loader area"; | |
11 | - reg = <0x00000000 0x00400000>; | |
2 | + soc { | |
3 | + flash: flash@08000000 { | |
4 | + #address-cells = <1>; | |
5 | + #size-cells = <1>; | |
6 | + compatible = "cfi-flash"; | |
7 | + reg = <0x08000000 0x01000000>; | |
8 | + bank-width = <2>; | |
9 | + device-width = <2>; | |
10 | + partition@0x0 { | |
11 | + label = "boot loader area"; | |
12 | + reg = <0x00000000 0x00400000>; | |
13 | + }; | |
14 | + partition@0x400000 { | |
15 | + label = "kernel image"; | |
16 | + reg = <0x00400000 0x00600000>; | |
17 | + }; | |
18 | + partition@0xa00000 { | |
19 | + label = "data"; | |
20 | + reg = <0x00a00000 0x005e0000>; | |
21 | + }; | |
22 | + partition@0xfe0000 { | |
23 | + label = "boot environment"; | |
24 | + reg = <0x00fe0000 0x00020000>; | |
25 | + }; | |
12 | 26 | }; |
13 | - partition@0x400000 { | |
14 | - label = "kernel image"; | |
15 | - reg = <0x00400000 0x00600000>; | |
16 | - }; | |
17 | - partition@0xa00000 { | |
18 | - label = "data"; | |
19 | - reg = <0x00a00000 0x005e0000>; | |
20 | - }; | |
21 | - partition@0xfe0000 { | |
22 | - label = "boot environment"; | |
23 | - reg = <0x00fe0000 0x00020000>; | |
24 | - }; | |
25 | - }; | |
27 | + }; | |
26 | 28 | }; |
arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
1 | 1 | / { |
2 | - flash: flash@f8000000 { | |
3 | - #address-cells = <1>; | |
4 | - #size-cells = <1>; | |
5 | - compatible = "cfi-flash"; | |
6 | - reg = <0xf8000000 0x00400000>; | |
7 | - bank-width = <2>; | |
8 | - device-width = <2>; | |
9 | - partition@0x0 { | |
10 | - label = "boot loader area"; | |
11 | - reg = <0x00000000 0x003f0000>; | |
2 | + soc { | |
3 | + flash: flash@08000000 { | |
4 | + #address-cells = <1>; | |
5 | + #size-cells = <1>; | |
6 | + compatible = "cfi-flash"; | |
7 | + reg = <0x08000000 0x00400000>; | |
8 | + bank-width = <2>; | |
9 | + device-width = <2>; | |
10 | + partition@0x0 { | |
11 | + label = "boot loader area"; | |
12 | + reg = <0x00000000 0x003f0000>; | |
13 | + }; | |
14 | + partition@0x3f0000 { | |
15 | + label = "boot environment"; | |
16 | + reg = <0x003f0000 0x00010000>; | |
17 | + }; | |
12 | 18 | }; |
13 | - partition@0x3f0000 { | |
14 | - label = "boot environment"; | |
15 | - reg = <0x003f0000 0x00010000>; | |
16 | - }; | |
17 | - }; | |
19 | + }; | |
18 | 20 | }; |
arch/xtensa/boot/dts/xtfpga.dtsi
... | ... | @@ -42,22 +42,29 @@ |
42 | 42 | }; |
43 | 43 | }; |
44 | 44 | |
45 | - serial0: serial@fd050020 { | |
46 | - device_type = "serial"; | |
47 | - compatible = "ns16550a"; | |
48 | - no-loopback-test; | |
49 | - reg = <0xfd050020 0x20>; | |
50 | - reg-shift = <2>; | |
51 | - interrupts = <0 1>; /* external irq 0 */ | |
52 | - clocks = <&osc>; | |
53 | - }; | |
45 | + soc { | |
46 | + #address-cells = <1>; | |
47 | + #size-cells = <1>; | |
48 | + compatible = "simple-bus"; | |
49 | + ranges = <0x00000000 0xf0000000 0x10000000>; | |
54 | 50 | |
55 | - enet0: ethoc@fd030000 { | |
56 | - compatible = "opencores,ethoc"; | |
57 | - reg = <0xfd030000 0x4000 0xfd800000 0x4000>; | |
58 | - interrupts = <1 1>; /* external irq 1 */ | |
59 | - local-mac-address = [00 50 c2 13 6f 00]; | |
60 | - clocks = <&osc>; | |
51 | + serial0: serial@0d050020 { | |
52 | + device_type = "serial"; | |
53 | + compatible = "ns16550a"; | |
54 | + no-loopback-test; | |
55 | + reg = <0x0d050020 0x20>; | |
56 | + reg-shift = <2>; | |
57 | + interrupts = <0 1>; /* external irq 0 */ | |
58 | + clocks = <&osc>; | |
59 | + }; | |
60 | + | |
61 | + enet0: ethoc@0d030000 { | |
62 | + compatible = "opencores,ethoc"; | |
63 | + reg = <0x0d030000 0x4000 0x0d800000 0x4000>; | |
64 | + interrupts = <1 1>; /* external irq 1 */ | |
65 | + local-mac-address = [00 50 c2 13 6f 00]; | |
66 | + clocks = <&osc>; | |
67 | + }; | |
61 | 68 | }; |
62 | 69 | }; |
arch/xtensa/include/asm/bootparam.h
... | ... | @@ -37,23 +37,14 @@ |
37 | 37 | unsigned long data[0]; /* data */ |
38 | 38 | } bp_tag_t; |
39 | 39 | |
40 | -typedef struct meminfo { | |
40 | +struct bp_meminfo { | |
41 | 41 | unsigned long type; |
42 | 42 | unsigned long start; |
43 | 43 | unsigned long end; |
44 | -} meminfo_t; | |
44 | +}; | |
45 | 45 | |
46 | -#define SYSMEM_BANKS_MAX 5 | |
47 | - | |
48 | 46 | #define MEMORY_TYPE_CONVENTIONAL 0x1000 |
49 | 47 | #define MEMORY_TYPE_NONE 0x2000 |
50 | - | |
51 | -typedef struct sysmem_info { | |
52 | - int nr_banks; | |
53 | - meminfo_t bank[SYSMEM_BANKS_MAX]; | |
54 | -} sysmem_info_t; | |
55 | - | |
56 | -extern sysmem_info_t sysmem; | |
57 | 48 | |
58 | 49 | #endif |
59 | 50 | #endif |
arch/xtensa/include/asm/fixmap.h
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 | + * | |
10 | + * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 | |
11 | + */ | |
12 | + | |
13 | +#ifndef _ASM_FIXMAP_H | |
14 | +#define _ASM_FIXMAP_H | |
15 | + | |
16 | +#include <asm/pgtable.h> | |
17 | +#ifdef CONFIG_HIGHMEM | |
18 | +#include <linux/threads.h> | |
19 | +#include <asm/kmap_types.h> | |
20 | +#endif | |
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. We allocate these special addresses | |
27 | + * from the end of the consistent memory region backwards. | |
28 | + * Also this lets us do fail-safe vmalloc(), we | |
29 | + * can guarantee that these special addresses and | |
30 | + * vmalloc()-ed addresses never overlap. | |
31 | + * | |
32 | + * these 'compile-time allocated' memory buffers are | |
33 | + * fixed-size 4k pages. (or larger if used with an increment | |
34 | + * higher than 1) use fixmap_set(idx,phys) to associate | |
35 | + * physical memory with fixmap indices. | |
36 | + */ | |
37 | +enum fixed_addresses { | |
38 | +#ifdef CONFIG_HIGHMEM | |
39 | + /* reserved pte's for temporary kernel mappings */ | |
40 | + FIX_KMAP_BEGIN, | |
41 | + FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, | |
42 | +#endif | |
43 | + __end_of_fixed_addresses | |
44 | +}; | |
45 | + | |
46 | +#define FIXADDR_TOP (VMALLOC_START - PAGE_SIZE) | |
47 | +#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | |
48 | +#define FIXADDR_START ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK) | |
49 | + | |
50 | +#include <asm-generic/fixmap.h> | |
51 | + | |
52 | +#define kmap_get_fixmap_pte(vaddr) \ | |
53 | + pte_offset_kernel( \ | |
54 | + pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), \ | |
55 | + (vaddr) \ | |
56 | + ) | |
57 | + | |
58 | +#endif |
arch/xtensa/include/asm/highmem.h
... | ... | @@ -6,12 +6,55 @@ |
6 | 6 | * this archive for more details. |
7 | 7 | * |
8 | 8 | * Copyright (C) 2003 - 2005 Tensilica Inc. |
9 | + * Copyright (C) 2014 Cadence Design Systems Inc. | |
9 | 10 | */ |
10 | 11 | |
11 | 12 | #ifndef _XTENSA_HIGHMEM_H |
12 | 13 | #define _XTENSA_HIGHMEM_H |
13 | 14 | |
14 | -extern void flush_cache_kmaps(void); | |
15 | +#include <asm/cacheflush.h> | |
16 | +#include <asm/fixmap.h> | |
17 | +#include <asm/kmap_types.h> | |
18 | +#include <asm/pgtable.h> | |
19 | + | |
20 | +#define PKMAP_BASE (FIXADDR_START - PMD_SIZE) | |
21 | +#define LAST_PKMAP PTRS_PER_PTE | |
22 | +#define LAST_PKMAP_MASK (LAST_PKMAP - 1) | |
23 | +#define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) | |
24 | +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) | |
25 | + | |
26 | +#define kmap_prot PAGE_KERNEL | |
27 | + | |
28 | +extern pte_t *pkmap_page_table; | |
29 | + | |
30 | +void *kmap_high(struct page *page); | |
31 | +void kunmap_high(struct page *page); | |
32 | + | |
33 | +static inline void *kmap(struct page *page) | |
34 | +{ | |
35 | + BUG_ON(in_interrupt()); | |
36 | + if (!PageHighMem(page)) | |
37 | + return page_address(page); | |
38 | + return kmap_high(page); | |
39 | +} | |
40 | + | |
41 | +static inline void kunmap(struct page *page) | |
42 | +{ | |
43 | + BUG_ON(in_interrupt()); | |
44 | + if (!PageHighMem(page)) | |
45 | + return; | |
46 | + kunmap_high(page); | |
47 | +} | |
48 | + | |
49 | +static inline void flush_cache_kmaps(void) | |
50 | +{ | |
51 | + flush_cache_all(); | |
52 | +} | |
53 | + | |
54 | +void *kmap_atomic(struct page *page); | |
55 | +void __kunmap_atomic(void *kvaddr); | |
56 | + | |
57 | +void kmap_init(void); | |
15 | 58 | |
16 | 59 | #endif |
arch/xtensa/include/asm/pgtable.h
arch/xtensa/include/asm/sysmem.h
1 | +/* | |
2 | + * sysmem-related prototypes. | |
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) 2014 Cadence Design Systems Inc. | |
9 | + */ | |
10 | + | |
11 | +#ifndef _XTENSA_SYSMEM_H | |
12 | +#define _XTENSA_SYSMEM_H | |
13 | + | |
14 | +#define SYSMEM_BANKS_MAX 31 | |
15 | + | |
16 | +struct meminfo { | |
17 | + unsigned long start; | |
18 | + unsigned long end; | |
19 | +}; | |
20 | + | |
21 | +/* | |
22 | + * Bank array is sorted by .start. | |
23 | + * Banks don't overlap and there's at least one page gap | |
24 | + * between adjacent bank entries. | |
25 | + */ | |
26 | +struct sysmem_info { | |
27 | + int nr_banks; | |
28 | + struct meminfo bank[SYSMEM_BANKS_MAX]; | |
29 | +}; | |
30 | + | |
31 | +extern struct sysmem_info sysmem; | |
32 | + | |
33 | +int add_sysmem_bank(unsigned long start, unsigned long end); | |
34 | +int mem_reserve(unsigned long, unsigned long, int); | |
35 | +void bootmem_init(void); | |
36 | +void zones_init(void); | |
37 | + | |
38 | +#endif /* _XTENSA_SYSMEM_H */ |
arch/xtensa/include/asm/tlbflush.h
... | ... | @@ -36,6 +36,7 @@ |
36 | 36 | unsigned long page); |
37 | 37 | void local_flush_tlb_range(struct vm_area_struct *vma, |
38 | 38 | unsigned long start, unsigned long end); |
39 | +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); | |
39 | 40 | |
40 | 41 | #ifdef CONFIG_SMP |
41 | 42 | |
42 | 43 | |
... | ... | @@ -44,13 +45,8 @@ |
44 | 45 | void flush_tlb_page(struct vm_area_struct *, unsigned long); |
45 | 46 | void flush_tlb_range(struct vm_area_struct *, unsigned long, |
46 | 47 | unsigned long); |
48 | +void flush_tlb_kernel_range(unsigned long start, unsigned long end); | |
47 | 49 | |
48 | -static inline void flush_tlb_kernel_range(unsigned long start, | |
49 | - unsigned long end) | |
50 | -{ | |
51 | - flush_tlb_all(); | |
52 | -} | |
53 | - | |
54 | 50 | #else /* !CONFIG_SMP */ |
55 | 51 | |
56 | 52 | #define flush_tlb_all() local_flush_tlb_all() |
... | ... | @@ -58,7 +54,8 @@ |
58 | 54 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) |
59 | 55 | #define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ |
60 | 56 | end) |
61 | -#define flush_tlb_kernel_range(start, end) local_flush_tlb_all() | |
57 | +#define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \ | |
58 | + end) | |
62 | 59 | |
63 | 60 | #endif /* CONFIG_SMP */ |
64 | 61 |
arch/xtensa/kernel/setup.c
... | ... | @@ -50,6 +50,7 @@ |
50 | 50 | #include <asm/param.h> |
51 | 51 | #include <asm/traps.h> |
52 | 52 | #include <asm/smp.h> |
53 | +#include <asm/sysmem.h> | |
53 | 54 | |
54 | 55 | #include <platform/hardware.h> |
55 | 56 | |
... | ... | @@ -88,12 +89,6 @@ |
88 | 89 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; |
89 | 90 | #endif |
90 | 91 | |
91 | -sysmem_info_t __initdata sysmem; | |
92 | - | |
93 | -extern int mem_reserve(unsigned long, unsigned long, int); | |
94 | -extern void bootmem_init(void); | |
95 | -extern void zones_init(void); | |
96 | - | |
97 | 92 | /* |
98 | 93 | * Boot parameter parsing. |
99 | 94 | * |
100 | 95 | |
101 | 96 | |
... | ... | @@ -113,31 +108,14 @@ |
113 | 108 | |
114 | 109 | /* parse current tag */ |
115 | 110 | |
116 | -static int __init add_sysmem_bank(unsigned long type, unsigned long start, | |
117 | - unsigned long end) | |
118 | -{ | |
119 | - if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) { | |
120 | - printk(KERN_WARNING | |
121 | - "Ignoring memory bank 0x%08lx size %ldKB\n", | |
122 | - start, end - start); | |
123 | - return -EINVAL; | |
124 | - } | |
125 | - sysmem.bank[sysmem.nr_banks].type = type; | |
126 | - sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(start); | |
127 | - sysmem.bank[sysmem.nr_banks].end = end & PAGE_MASK; | |
128 | - sysmem.nr_banks++; | |
129 | - | |
130 | - return 0; | |
131 | -} | |
132 | - | |
133 | 111 | static int __init parse_tag_mem(const bp_tag_t *tag) |
134 | 112 | { |
135 | - meminfo_t *mi = (meminfo_t *)(tag->data); | |
113 | + struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data); | |
136 | 114 | |
137 | 115 | if (mi->type != MEMORY_TYPE_CONVENTIONAL) |
138 | 116 | return -1; |
139 | 117 | |
140 | - return add_sysmem_bank(mi->type, mi->start, mi->end); | |
118 | + return add_sysmem_bank(mi->start, mi->end); | |
141 | 119 | } |
142 | 120 | |
143 | 121 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); |
... | ... | @@ -146,8 +124,8 @@ |
146 | 124 | |
147 | 125 | static int __init parse_tag_initrd(const bp_tag_t* tag) |
148 | 126 | { |
149 | - meminfo_t* mi; | |
150 | - mi = (meminfo_t*)(tag->data); | |
127 | + struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data); | |
128 | + | |
151 | 129 | initrd_start = (unsigned long)__va(mi->start); |
152 | 130 | initrd_end = (unsigned long)__va(mi->end); |
153 | 131 | |
... | ... | @@ -255,7 +233,7 @@ |
255 | 233 | return; |
256 | 234 | |
257 | 235 | size &= PAGE_MASK; |
258 | - add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size); | |
236 | + add_sysmem_bank(base, base + size); | |
259 | 237 | } |
260 | 238 | |
261 | 239 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) |
... | ... | @@ -292,8 +270,6 @@ |
292 | 270 | |
293 | 271 | void __init init_arch(bp_tag_t *bp_start) |
294 | 272 | { |
295 | - sysmem.nr_banks = 0; | |
296 | - | |
297 | 273 | /* Parse boot parameters */ |
298 | 274 | |
299 | 275 | if (bp_start) |
... | ... | @@ -304,10 +280,9 @@ |
304 | 280 | #endif |
305 | 281 | |
306 | 282 | if (sysmem.nr_banks == 0) { |
307 | - sysmem.nr_banks = 1; | |
308 | - sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START; | |
309 | - sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START | |
310 | - + PLATFORM_DEFAULT_MEM_SIZE; | |
283 | + add_sysmem_bank(PLATFORM_DEFAULT_MEM_START, | |
284 | + PLATFORM_DEFAULT_MEM_START + | |
285 | + PLATFORM_DEFAULT_MEM_SIZE); | |
311 | 286 | } |
312 | 287 | |
313 | 288 | #ifdef CONFIG_CMDLINE_BOOL |
... | ... | @@ -487,7 +462,7 @@ |
487 | 462 | #ifdef CONFIG_BLK_DEV_INITRD |
488 | 463 | if (initrd_start < initrd_end) { |
489 | 464 | initrd_is_mapped = mem_reserve(__pa(initrd_start), |
490 | - __pa(initrd_end), 0); | |
465 | + __pa(initrd_end), 0) == 0; | |
491 | 466 | initrd_below_start_ok = 1; |
492 | 467 | } else { |
493 | 468 | initrd_start = 0; |
... | ... | @@ -532,6 +507,7 @@ |
532 | 507 | __pa(&_Level6InterruptVector_text_end), 0); |
533 | 508 | #endif |
534 | 509 | |
510 | + parse_early_param(); | |
535 | 511 | bootmem_init(); |
536 | 512 | |
537 | 513 | unflatten_and_copy_device_tree(); |
arch/xtensa/kernel/smp.c
... | ... | @@ -496,6 +496,21 @@ |
496 | 496 | on_each_cpu(ipi_flush_tlb_range, &fd, 1); |
497 | 497 | } |
498 | 498 | |
499 | +static void ipi_flush_tlb_kernel_range(void *arg) | |
500 | +{ | |
501 | + struct flush_data *fd = arg; | |
502 | + local_flush_tlb_kernel_range(fd->addr1, fd->addr2); | |
503 | +} | |
504 | + | |
505 | +void flush_tlb_kernel_range(unsigned long start, unsigned long end) | |
506 | +{ | |
507 | + struct flush_data fd = { | |
508 | + .addr1 = start, | |
509 | + .addr2 = end, | |
510 | + }; | |
511 | + on_each_cpu(ipi_flush_tlb_kernel_range, &fd, 1); | |
512 | +} | |
513 | + | |
499 | 514 | /* Cache flush functions */ |
500 | 515 | |
501 | 516 | static void ipi_flush_cache_all(void *arg) |
arch/xtensa/kernel/xtensa_ksyms.c
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | #include <linux/in6.h> |
21 | 21 | |
22 | 22 | #include <asm/uaccess.h> |
23 | +#include <asm/cacheflush.h> | |
23 | 24 | #include <asm/checksum.h> |
24 | 25 | #include <asm/dma.h> |
25 | 26 | #include <asm/io.h> |
... | ... | @@ -105,6 +106,7 @@ |
105 | 106 | * Architecture-specific symbols |
106 | 107 | */ |
107 | 108 | EXPORT_SYMBOL(__xtensa_copy_user); |
109 | +EXPORT_SYMBOL(__invalidate_icache_range); | |
108 | 110 | |
109 | 111 | /* |
110 | 112 | * Kernel hacking ... |
... | ... | @@ -126,5 +128,10 @@ |
126 | 128 | |
127 | 129 | #ifdef CONFIG_FUNCTION_TRACER |
128 | 130 | EXPORT_SYMBOL(_mcount); |
131 | +#endif | |
132 | + | |
133 | +EXPORT_SYMBOL(__invalidate_dcache_range); | |
134 | +#if XCHAL_DCACHE_IS_WRITEBACK | |
135 | +EXPORT_SYMBOL(__flush_dcache_range); | |
129 | 136 | #endif |
arch/xtensa/mm/Makefile
arch/xtensa/mm/cache.c
... | ... | @@ -59,6 +59,10 @@ |
59 | 59 | * |
60 | 60 | */ |
61 | 61 | |
62 | +#if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM) | |
63 | +#error "HIGHMEM is not supported on cores with aliasing cache." | |
64 | +#endif | |
65 | + | |
62 | 66 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK |
63 | 67 | |
64 | 68 | /* |
65 | 69 | |
... | ... | @@ -179,10 +183,11 @@ |
179 | 183 | #else |
180 | 184 | if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags) |
181 | 185 | && (vma->vm_flags & VM_EXEC) != 0) { |
182 | - unsigned long paddr = (unsigned long) page_address(page); | |
186 | + unsigned long paddr = (unsigned long)kmap_atomic(page); | |
183 | 187 | __flush_dcache_page(paddr); |
184 | 188 | __invalidate_icache_page(paddr); |
185 | 189 | set_bit(PG_arch_1, &page->flags); |
190 | + kunmap_atomic((void *)paddr); | |
186 | 191 | } |
187 | 192 | #endif |
188 | 193 | } |
arch/xtensa/mm/highmem.c
1 | +/* | |
2 | + * High memory support for Xtensa architecture | |
3 | + * | |
4 | + * This file is subject to the terms and conditions of the GNU General | |
5 | + * Public License. See the file "COPYING" in the main directory of | |
6 | + * this archive for more details. | |
7 | + * | |
8 | + * Copyright (C) 2014 Cadence Design Systems Inc. | |
9 | + */ | |
10 | + | |
11 | +#include <linux/export.h> | |
12 | +#include <linux/highmem.h> | |
13 | +#include <asm/tlbflush.h> | |
14 | + | |
15 | +static pte_t *kmap_pte; | |
16 | + | |
17 | +void *kmap_atomic(struct page *page) | |
18 | +{ | |
19 | + enum fixed_addresses idx; | |
20 | + unsigned long vaddr; | |
21 | + int type; | |
22 | + | |
23 | + pagefault_disable(); | |
24 | + if (!PageHighMem(page)) | |
25 | + return page_address(page); | |
26 | + | |
27 | + type = kmap_atomic_idx_push(); | |
28 | + idx = type + KM_TYPE_NR * smp_processor_id(); | |
29 | + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | |
30 | +#ifdef CONFIG_DEBUG_HIGHMEM | |
31 | + BUG_ON(!pte_none(*(kmap_pte - idx))); | |
32 | +#endif | |
33 | + set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC)); | |
34 | + | |
35 | + return (void *)vaddr; | |
36 | +} | |
37 | +EXPORT_SYMBOL(kmap_atomic); | |
38 | + | |
39 | +void __kunmap_atomic(void *kvaddr) | |
40 | +{ | |
41 | + int idx, type; | |
42 | + | |
43 | + if (kvaddr >= (void *)FIXADDR_START && | |
44 | + kvaddr < (void *)FIXADDR_TOP) { | |
45 | + type = kmap_atomic_idx(); | |
46 | + idx = type + KM_TYPE_NR * smp_processor_id(); | |
47 | + | |
48 | + /* | |
49 | + * Force other mappings to Oops if they'll try to access this | |
50 | + * pte without first remap it. Keeping stale mappings around | |
51 | + * is a bad idea also, in case the page changes cacheability | |
52 | + * attributes or becomes a protected page in a hypervisor. | |
53 | + */ | |
54 | + pte_clear(&init_mm, kvaddr, kmap_pte - idx); | |
55 | + local_flush_tlb_kernel_range((unsigned long)kvaddr, | |
56 | + (unsigned long)kvaddr + PAGE_SIZE); | |
57 | + | |
58 | + kmap_atomic_idx_pop(); | |
59 | + } | |
60 | + | |
61 | + pagefault_enable(); | |
62 | +} | |
63 | +EXPORT_SYMBOL(__kunmap_atomic); | |
64 | + | |
65 | +void __init kmap_init(void) | |
66 | +{ | |
67 | + unsigned long kmap_vstart; | |
68 | + | |
69 | + /* cache the first kmap pte */ | |
70 | + kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); | |
71 | + kmap_pte = kmap_get_fixmap_pte(kmap_vstart); | |
72 | +} |
arch/xtensa/mm/init.c
... | ... | @@ -8,6 +8,7 @@ |
8 | 8 | * for more details. |
9 | 9 | * |
10 | 10 | * Copyright (C) 2001 - 2005 Tensilica Inc. |
11 | + * Copyright (C) 2014 Cadence Design Systems Inc. | |
11 | 12 | * |
12 | 13 | * Chris Zankel <chris@zankel.net> |
13 | 14 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> |
... | ... | @@ -19,6 +20,7 @@ |
19 | 20 | #include <linux/errno.h> |
20 | 21 | #include <linux/bootmem.h> |
21 | 22 | #include <linux/gfp.h> |
23 | +#include <linux/highmem.h> | |
22 | 24 | #include <linux/swap.h> |
23 | 25 | #include <linux/mman.h> |
24 | 26 | #include <linux/nodemask.h> |
25 | 27 | |
26 | 28 | |
27 | 29 | |
... | ... | @@ -27,11 +29,133 @@ |
27 | 29 | #include <asm/bootparam.h> |
28 | 30 | #include <asm/page.h> |
29 | 31 | #include <asm/sections.h> |
32 | +#include <asm/sysmem.h> | |
30 | 33 | |
34 | +struct sysmem_info sysmem __initdata; | |
35 | + | |
36 | +static void __init sysmem_dump(void) | |
37 | +{ | |
38 | + unsigned i; | |
39 | + | |
40 | + pr_debug("Sysmem:\n"); | |
41 | + for (i = 0; i < sysmem.nr_banks; ++i) | |
42 | + pr_debug(" 0x%08lx - 0x%08lx (%ldK)\n", | |
43 | + sysmem.bank[i].start, sysmem.bank[i].end, | |
44 | + (sysmem.bank[i].end - sysmem.bank[i].start) >> 10); | |
45 | +} | |
46 | + | |
31 | 47 | /* |
48 | + * Find bank with maximal .start such that bank.start <= start | |
49 | + */ | |
50 | +static inline struct meminfo * __init find_bank(unsigned long start) | |
51 | +{ | |
52 | + unsigned i; | |
53 | + struct meminfo *it = NULL; | |
54 | + | |
55 | + for (i = 0; i < sysmem.nr_banks; ++i) | |
56 | + if (sysmem.bank[i].start <= start) | |
57 | + it = sysmem.bank + i; | |
58 | + else | |
59 | + break; | |
60 | + return it; | |
61 | +} | |
62 | + | |
63 | +/* | |
64 | + * Move all memory banks starting at 'from' to a new place at 'to', | |
65 | + * adjust nr_banks accordingly. | |
66 | + * Both 'from' and 'to' must be inside the sysmem.bank. | |
67 | + * | |
68 | + * Returns: 0 (success), -ENOMEM (not enough space in the sysmem.bank). | |
69 | + */ | |
70 | +static int __init move_banks(struct meminfo *to, struct meminfo *from) | |
71 | +{ | |
72 | + unsigned n = sysmem.nr_banks - (from - sysmem.bank); | |
73 | + | |
74 | + if (to > from && to - from + sysmem.nr_banks > SYSMEM_BANKS_MAX) | |
75 | + return -ENOMEM; | |
76 | + if (to != from) | |
77 | + memmove(to, from, n * sizeof(struct meminfo)); | |
78 | + sysmem.nr_banks += to - from; | |
79 | + return 0; | |
80 | +} | |
81 | + | |
82 | +/* | |
83 | + * Add new bank to sysmem. Resulting sysmem is the union of bytes of the | |
84 | + * original sysmem and the new bank. | |
85 | + * | |
86 | + * Returns: 0 (success), < 0 (error) | |
87 | + */ | |
88 | +int __init add_sysmem_bank(unsigned long start, unsigned long end) | |
89 | +{ | |
90 | + unsigned i; | |
91 | + struct meminfo *it = NULL; | |
92 | + unsigned long sz; | |
93 | + unsigned long bank_sz = 0; | |
94 | + | |
95 | + if (start == end || | |
96 | + (start < end) != (PAGE_ALIGN(start) < (end & PAGE_MASK))) { | |
97 | + pr_warn("Ignoring small memory bank 0x%08lx size: %ld bytes\n", | |
98 | + start, end - start); | |
99 | + return -EINVAL; | |
100 | + } | |
101 | + | |
102 | + start = PAGE_ALIGN(start); | |
103 | + end &= PAGE_MASK; | |
104 | + sz = end - start; | |
105 | + | |
106 | + it = find_bank(start); | |
107 | + | |
108 | + if (it) | |
109 | + bank_sz = it->end - it->start; | |
110 | + | |
111 | + if (it && bank_sz >= start - it->start) { | |
112 | + if (end - it->start > bank_sz) | |
113 | + it->end = end; | |
114 | + else | |
115 | + return 0; | |
116 | + } else { | |
117 | + if (!it) | |
118 | + it = sysmem.bank; | |
119 | + else | |
120 | + ++it; | |
121 | + | |
122 | + if (it - sysmem.bank < sysmem.nr_banks && | |
123 | + it->start - start <= sz) { | |
124 | + it->start = start; | |
125 | + if (it->end - it->start < sz) | |
126 | + it->end = end; | |
127 | + else | |
128 | + return 0; | |
129 | + } else { | |
130 | + if (move_banks(it + 1, it) < 0) { | |
131 | + pr_warn("Ignoring memory bank 0x%08lx size %ld bytes\n", | |
132 | + start, end - start); | |
133 | + return -EINVAL; | |
134 | + } | |
135 | + it->start = start; | |
136 | + it->end = end; | |
137 | + return 0; | |
138 | + } | |
139 | + } | |
140 | + sz = it->end - it->start; | |
141 | + for (i = it + 1 - sysmem.bank; i < sysmem.nr_banks; ++i) | |
142 | + if (sysmem.bank[i].start - it->start <= sz) { | |
143 | + if (sz < sysmem.bank[i].end - it->start) | |
144 | + it->end = sysmem.bank[i].end; | |
145 | + } else { | |
146 | + break; | |
147 | + } | |
148 | + | |
149 | + move_banks(it + 1, sysmem.bank + i); | |
150 | + return 0; | |
151 | +} | |
152 | + | |
153 | +/* | |
32 | 154 | * mem_reserve(start, end, must_exist) |
33 | 155 | * |
34 | 156 | * Reserve some memory from the memory pool. |
157 | + * If must_exist is set and a part of the region being reserved does not exist | |
158 | + * memory map is not altered. | |
35 | 159 | * |
36 | 160 | * Parameters: |
37 | 161 | * start Start of region, |
38 | 162 | |
39 | 163 | |
40 | 164 | |
41 | 165 | |
42 | 166 | |
43 | 167 | |
44 | 168 | |
45 | 169 | |
46 | 170 | |
47 | 171 | |
... | ... | @@ -39,53 +163,69 @@ |
39 | 163 | * must_exist Must exist in memory pool. |
40 | 164 | * |
41 | 165 | * Returns: |
42 | - * 0 (memory area couldn't be mapped) | |
43 | - * -1 (success) | |
166 | + * 0 (success) | |
167 | + * < 0 (error) | |
44 | 168 | */ |
45 | 169 | |
46 | 170 | int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) |
47 | 171 | { |
48 | - int i; | |
172 | + struct meminfo *it; | |
173 | + struct meminfo *rm = NULL; | |
174 | + unsigned long sz; | |
175 | + unsigned long bank_sz = 0; | |
49 | 176 | |
50 | - if (start == end) | |
51 | - return 0; | |
52 | - | |
53 | 177 | start = start & PAGE_MASK; |
54 | 178 | end = PAGE_ALIGN(end); |
179 | + sz = end - start; | |
180 | + if (!sz) | |
181 | + return -EINVAL; | |
55 | 182 | |
56 | - for (i = 0; i < sysmem.nr_banks; i++) | |
57 | - if (start < sysmem.bank[i].end | |
58 | - && end >= sysmem.bank[i].start) | |
59 | - break; | |
183 | + it = find_bank(start); | |
60 | 184 | |
61 | - if (i == sysmem.nr_banks) { | |
62 | - if (must_exist) | |
63 | - printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) " | |
64 | - "not in any region!\n", start, end); | |
65 | - return 0; | |
185 | + if (it) | |
186 | + bank_sz = it->end - it->start; | |
187 | + | |
188 | + if ((!it || end - it->start > bank_sz) && must_exist) { | |
189 | + pr_warn("mem_reserve: [0x%0lx, 0x%0lx) not in any region!\n", | |
190 | + start, end); | |
191 | + return -EINVAL; | |
66 | 192 | } |
67 | 193 | |
68 | - if (start > sysmem.bank[i].start) { | |
69 | - if (end < sysmem.bank[i].end) { | |
70 | - /* split entry */ | |
71 | - if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) | |
72 | - panic("meminfo overflow\n"); | |
73 | - sysmem.bank[sysmem.nr_banks].start = end; | |
74 | - sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end; | |
75 | - sysmem.nr_banks++; | |
194 | + if (it && start - it->start < bank_sz) { | |
195 | + if (start == it->start) { | |
196 | + if (end - it->start < bank_sz) { | |
197 | + it->start = end; | |
198 | + return 0; | |
199 | + } else { | |
200 | + rm = it; | |
201 | + } | |
202 | + } else { | |
203 | + it->end = start; | |
204 | + if (end - it->start < bank_sz) | |
205 | + return add_sysmem_bank(end, | |
206 | + it->start + bank_sz); | |
207 | + ++it; | |
76 | 208 | } |
77 | - sysmem.bank[i].end = start; | |
209 | + } | |
78 | 210 | |
79 | - } else if (end < sysmem.bank[i].end) { | |
80 | - sysmem.bank[i].start = end; | |
211 | + if (!it) | |
212 | + it = sysmem.bank; | |
81 | 213 | |
82 | - } else { | |
83 | - /* remove entry */ | |
84 | - sysmem.nr_banks--; | |
85 | - sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start; | |
86 | - sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end; | |
214 | + for (; it < sysmem.bank + sysmem.nr_banks; ++it) { | |
215 | + if (it->end - start <= sz) { | |
216 | + if (!rm) | |
217 | + rm = it; | |
218 | + } else { | |
219 | + if (it->start - start < sz) | |
220 | + it->start = end; | |
221 | + break; | |
222 | + } | |
87 | 223 | } |
88 | - return -1; | |
224 | + | |
225 | + if (rm) | |
226 | + move_banks(rm, it); | |
227 | + | |
228 | + return 0; | |
89 | 229 | } |
90 | 230 | |
91 | 231 | |
... | ... | @@ -99,6 +239,7 @@ |
99 | 239 | unsigned long bootmap_start, bootmap_size; |
100 | 240 | int i; |
101 | 241 | |
242 | + sysmem_dump(); | |
102 | 243 | max_low_pfn = max_pfn = 0; |
103 | 244 | min_low_pfn = ~0; |
104 | 245 | |
105 | 246 | |
106 | 247 | |
107 | 248 | |
... | ... | @@ -156,19 +297,13 @@ |
156 | 297 | |
157 | 298 | void __init zones_init(void) |
158 | 299 | { |
159 | - unsigned long zones_size[MAX_NR_ZONES]; | |
160 | - int i; | |
161 | - | |
162 | 300 | /* All pages are DMA-able, so we put them all in the DMA zone. */ |
163 | - | |
164 | - zones_size[ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET; | |
165 | - for (i = 1; i < MAX_NR_ZONES; i++) | |
166 | - zones_size[i] = 0; | |
167 | - | |
301 | + unsigned long zones_size[MAX_NR_ZONES] = { | |
302 | + [ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET, | |
168 | 303 | #ifdef CONFIG_HIGHMEM |
169 | - zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn; | |
304 | + [ZONE_HIGHMEM] = max_pfn - max_low_pfn, | |
170 | 305 | #endif |
171 | - | |
306 | + }; | |
172 | 307 | free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL); |
173 | 308 | } |
174 | 309 | |
175 | 310 | |
176 | 311 | |
177 | 312 | |
... | ... | @@ -178,16 +313,38 @@ |
178 | 313 | |
179 | 314 | void __init mem_init(void) |
180 | 315 | { |
181 | - max_mapnr = max_low_pfn - ARCH_PFN_OFFSET; | |
182 | - high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); | |
183 | - | |
184 | 316 | #ifdef CONFIG_HIGHMEM |
185 | -#error HIGHGMEM not implemented in init.c | |
317 | + unsigned long tmp; | |
318 | + | |
319 | + reset_all_zones_managed_pages(); | |
320 | + for (tmp = max_low_pfn; tmp < max_pfn; tmp++) | |
321 | + free_highmem_page(pfn_to_page(tmp)); | |
186 | 322 | #endif |
187 | 323 | |
324 | + max_mapnr = max_pfn - ARCH_PFN_OFFSET; | |
325 | + high_memory = (void *)__va(max_low_pfn << PAGE_SHIFT); | |
326 | + | |
188 | 327 | free_all_bootmem(); |
189 | 328 | |
190 | 329 | mem_init_print_info(NULL); |
330 | + pr_info("virtual kernel memory layout:\n" | |
331 | +#ifdef CONFIG_HIGHMEM | |
332 | + " pkmap : 0x%08lx - 0x%08lx (%5lu kB)\n" | |
333 | + " fixmap : 0x%08lx - 0x%08lx (%5lu kB)\n" | |
334 | +#endif | |
335 | + " vmalloc : 0x%08x - 0x%08x (%5u MB)\n" | |
336 | + " lowmem : 0x%08x - 0x%08lx (%5lu MB)\n", | |
337 | +#ifdef CONFIG_HIGHMEM | |
338 | + PKMAP_BASE, PKMAP_BASE + LAST_PKMAP * PAGE_SIZE, | |
339 | + (LAST_PKMAP*PAGE_SIZE) >> 10, | |
340 | + FIXADDR_START, FIXADDR_TOP, | |
341 | + (FIXADDR_TOP - FIXADDR_START) >> 10, | |
342 | +#endif | |
343 | + VMALLOC_START, VMALLOC_END, | |
344 | + (VMALLOC_END - VMALLOC_START) >> 20, | |
345 | + PAGE_OFFSET, PAGE_OFFSET + | |
346 | + (max_low_pfn - min_low_pfn) * PAGE_SIZE, | |
347 | + ((max_low_pfn - min_low_pfn) * PAGE_SIZE) >> 20); | |
191 | 348 | } |
192 | 349 | |
193 | 350 | #ifdef CONFIG_BLK_DEV_INITRD |
... | ... | @@ -204,4 +361,54 @@ |
204 | 361 | { |
205 | 362 | free_initmem_default(-1); |
206 | 363 | } |
364 | + | |
365 | +static void __init parse_memmap_one(char *p) | |
366 | +{ | |
367 | + char *oldp; | |
368 | + unsigned long start_at, mem_size; | |
369 | + | |
370 | + if (!p) | |
371 | + return; | |
372 | + | |
373 | + oldp = p; | |
374 | + mem_size = memparse(p, &p); | |
375 | + if (p == oldp) | |
376 | + return; | |
377 | + | |
378 | + switch (*p) { | |
379 | + case '@': | |
380 | + start_at = memparse(p + 1, &p); | |
381 | + add_sysmem_bank(start_at, start_at + mem_size); | |
382 | + break; | |
383 | + | |
384 | + case '$': | |
385 | + start_at = memparse(p + 1, &p); | |
386 | + mem_reserve(start_at, start_at + mem_size, 0); | |
387 | + break; | |
388 | + | |
389 | + case 0: | |
390 | + mem_reserve(mem_size, 0, 0); | |
391 | + break; | |
392 | + | |
393 | + default: | |
394 | + pr_warn("Unrecognized memmap syntax: %s\n", p); | |
395 | + break; | |
396 | + } | |
397 | +} | |
398 | + | |
399 | +static int __init parse_memmap_opt(char *str) | |
400 | +{ | |
401 | + while (str) { | |
402 | + char *k = strchr(str, ','); | |
403 | + | |
404 | + if (k) | |
405 | + *k++ = 0; | |
406 | + | |
407 | + parse_memmap_one(str); | |
408 | + str = k; | |
409 | + } | |
410 | + | |
411 | + return 0; | |
412 | +} | |
413 | +early_param("memmap", parse_memmap_opt); |
arch/xtensa/mm/mmu.c
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | * |
4 | 4 | * Extracted from init.c |
5 | 5 | */ |
6 | +#include <linux/bootmem.h> | |
6 | 7 | #include <linux/percpu.h> |
7 | 8 | #include <linux/init.h> |
8 | 9 | #include <linux/string.h> |
9 | 10 | |
... | ... | @@ -16,9 +17,44 @@ |
16 | 17 | #include <asm/initialize_mmu.h> |
17 | 18 | #include <asm/io.h> |
18 | 19 | |
20 | +#if defined(CONFIG_HIGHMEM) | |
21 | +static void * __init init_pmd(unsigned long vaddr) | |
22 | +{ | |
23 | + pgd_t *pgd = pgd_offset_k(vaddr); | |
24 | + pmd_t *pmd = pmd_offset(pgd, vaddr); | |
25 | + | |
26 | + if (pmd_none(*pmd)) { | |
27 | + unsigned i; | |
28 | + pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE); | |
29 | + | |
30 | + for (i = 0; i < 1024; i++) | |
31 | + pte_clear(NULL, 0, pte + i); | |
32 | + | |
33 | + set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK)); | |
34 | + BUG_ON(pte != pte_offset_kernel(pmd, 0)); | |
35 | + pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n", | |
36 | + __func__, vaddr, pmd, pte); | |
37 | + return pte; | |
38 | + } else { | |
39 | + return pte_offset_kernel(pmd, 0); | |
40 | + } | |
41 | +} | |
42 | + | |
43 | +static void __init fixedrange_init(void) | |
44 | +{ | |
45 | + BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE); | |
46 | + init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK); | |
47 | +} | |
48 | +#endif | |
49 | + | |
19 | 50 | void __init paging_init(void) |
20 | 51 | { |
21 | 52 | memset(swapper_pg_dir, 0, PAGE_SIZE); |
53 | +#ifdef CONFIG_HIGHMEM | |
54 | + fixedrange_init(); | |
55 | + pkmap_page_table = init_pmd(PKMAP_BASE); | |
56 | + kmap_init(); | |
57 | +#endif | |
22 | 58 | } |
23 | 59 | |
24 | 60 | /* |
arch/xtensa/mm/tlb.c
... | ... | @@ -149,6 +149,21 @@ |
149 | 149 | local_irq_restore(flags); |
150 | 150 | } |
151 | 151 | |
152 | +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | |
153 | +{ | |
154 | + if (end > start && start >= TASK_SIZE && end <= PAGE_OFFSET && | |
155 | + end - start < _TLB_ENTRIES << PAGE_SHIFT) { | |
156 | + start &= PAGE_MASK; | |
157 | + while (start < end) { | |
158 | + invalidate_itlb_mapping(start); | |
159 | + invalidate_dtlb_mapping(start); | |
160 | + start += PAGE_SIZE; | |
161 | + } | |
162 | + } else { | |
163 | + local_flush_tlb_all(); | |
164 | + } | |
165 | +} | |
166 | + | |
152 | 167 | #ifdef CONFIG_DEBUG_TLB_SANITY |
153 | 168 | |
154 | 169 | static unsigned get_pte_for_vaddr(unsigned vaddr) |
arch/xtensa/platforms/iss/Makefile
arch/xtensa/platforms/xt2000/setup.c
... | ... | @@ -92,18 +92,8 @@ |
92 | 92 | |
93 | 93 | /* early initialization */ |
94 | 94 | |
95 | -extern sysmem_info_t __initdata sysmem; | |
96 | - | |
97 | -void platform_init(bp_tag_t* first) | |
95 | +void __init platform_init(bp_tag_t *first) | |
98 | 96 | { |
99 | - /* Set default memory block if not provided by the bootloader. */ | |
100 | - | |
101 | - if (sysmem.nr_banks == 0) { | |
102 | - sysmem.nr_banks = 1; | |
103 | - sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START; | |
104 | - sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START | |
105 | - + PLATFORM_DEFAULT_MEM_SIZE; | |
106 | - } | |
107 | 97 | } |
108 | 98 | |
109 | 99 | /* Heartbeat. Let the LED blink. */ |
scripts/sortextable.c
... | ... | @@ -35,6 +35,10 @@ |
35 | 35 | #define EM_ARCOMPACT 93 |
36 | 36 | #endif |
37 | 37 | |
38 | +#ifndef EM_XTENSA | |
39 | +#define EM_XTENSA 94 | |
40 | +#endif | |
41 | + | |
38 | 42 | #ifndef EM_AARCH64 |
39 | 43 | #define EM_AARCH64 183 |
40 | 44 | #endif |
... | ... | @@ -281,6 +285,7 @@ |
281 | 285 | case EM_AARCH64: |
282 | 286 | case EM_MICROBLAZE: |
283 | 287 | case EM_MIPS: |
288 | + case EM_XTENSA: | |
284 | 289 | break; |
285 | 290 | } /* end switch */ |
286 | 291 |