diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-05-05 18:36:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-05-05 18:36:59 -0400 |
commit | 03787ff6f9156e43019f3f4b69cb6212b3a47f65 (patch) | |
tree | 05dd4b8de6de3313f1afdaaa7636a4052ad4e634 /arch | |
parent | 5575eeb7b9f687ca4899e2d8721a9b17265d0060 (diff) | |
parent | 55b441be5cd600bf645a01b14900880a09941d4c (diff) |
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
Diffstat (limited to 'arch')
-rw-r--r-- | arch/xtensa/Kconfig | 20 | ||||
-rw-r--r-- | arch/xtensa/boot/dts/kc705.dts | 11 | ||||
-rw-r--r-- | arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi | 28 | ||||
-rw-r--r-- | arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi | 48 | ||||
-rw-r--r-- | arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi | 32 | ||||
-rw-r--r-- | arch/xtensa/boot/dts/xtfpga.dtsi | 37 | ||||
-rw-r--r-- | arch/xtensa/include/asm/bootparam.h | 13 | ||||
-rw-r--r-- | arch/xtensa/include/asm/fixmap.h | 58 | ||||
-rw-r--r-- | arch/xtensa/include/asm/highmem.h | 45 | ||||
-rw-r--r-- | arch/xtensa/include/asm/pgtable.h | 4 | ||||
-rw-r--r-- | arch/xtensa/include/asm/sysmem.h | 38 | ||||
-rw-r--r-- | arch/xtensa/include/asm/tlbflush.h | 11 | ||||
-rw-r--r-- | arch/xtensa/kernel/setup.c | 46 | ||||
-rw-r--r-- | arch/xtensa/kernel/smp.c | 15 | ||||
-rw-r--r-- | arch/xtensa/kernel/xtensa_ksyms.c | 7 | ||||
-rw-r--r-- | arch/xtensa/mm/Makefile | 1 | ||||
-rw-r--r-- | arch/xtensa/mm/cache.c | 7 | ||||
-rw-r--r-- | arch/xtensa/mm/highmem.c | 72 | ||||
-rw-r--r-- | arch/xtensa/mm/init.c | 299 | ||||
-rw-r--r-- | arch/xtensa/mm/mmu.c | 36 | ||||
-rw-r--r-- | arch/xtensa/mm/tlb.c | 15 | ||||
-rw-r--r-- | arch/xtensa/platforms/iss/Makefile | 3 | ||||
-rw-r--r-- | arch/xtensa/platforms/xt2000/setup.c | 12 |
23 files changed, 691 insertions, 167 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 02d6d29a63c1..3a617af60d46 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
@@ -14,6 +14,7 @@ config XTENSA | |||
14 | select GENERIC_PCI_IOMAP | 14 | select GENERIC_PCI_IOMAP |
15 | select ARCH_WANT_IPC_PARSE_VERSION | 15 | select ARCH_WANT_IPC_PARSE_VERSION |
16 | select ARCH_WANT_OPTIONAL_GPIOLIB | 16 | select ARCH_WANT_OPTIONAL_GPIOLIB |
17 | select BUILDTIME_EXTABLE_SORT | ||
17 | select CLONE_BACKWARDS | 18 | select CLONE_BACKWARDS |
18 | select IRQ_DOMAIN | 19 | select IRQ_DOMAIN |
19 | select HAVE_OPROFILE | 20 | select HAVE_OPROFILE |
@@ -189,6 +190,24 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX | |||
189 | 190 | ||
190 | If in doubt, say Y. | 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 | endmenu | 211 | endmenu |
193 | 212 | ||
194 | config XTENSA_CALIBRATE_CCOUNT | 213 | config XTENSA_CALIBRATE_CCOUNT |
@@ -224,7 +243,6 @@ choice | |||
224 | 243 | ||
225 | config XTENSA_PLATFORM_ISS | 244 | config XTENSA_PLATFORM_ISS |
226 | bool "ISS" | 245 | bool "ISS" |
227 | depends on TTY | ||
228 | select XTENSA_CALIBRATE_CCOUNT | 246 | select XTENSA_CALIBRATE_CCOUNT |
229 | select SERIAL_CONSOLE | 247 | select SERIAL_CONSOLE |
230 | help | 248 | help |
diff --git a/arch/xtensa/boot/dts/kc705.dts b/arch/xtensa/boot/dts/kc705.dts new file mode 100644 index 000000000000..742a347be67a --- /dev/null +++ b/arch/xtensa/boot/dts/kc705.dts | |||
@@ -0,0 +1,11 @@ | |||
1 | /dts-v1/; | ||
2 | /include/ "xtfpga.dtsi" | ||
3 | /include/ "xtfpga-flash-128m.dtsi" | ||
4 | |||
5 | / { | ||
6 | compatible = "cdns,xtensa-kc705"; | ||
7 | memory@0 { | ||
8 | device_type = "memory"; | ||
9 | reg = <0x00000000 0x08000000>; | ||
10 | }; | ||
11 | }; | ||
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi new file mode 100644 index 000000000000..d3a88e029873 --- /dev/null +++ b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi | |||
@@ -0,0 +1,28 @@ | |||
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 | }; | ||
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi index e5703c7beeb6..1d97203c18e7 100644 --- a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi +++ b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi | |||
@@ -1,26 +1,28 @@ | |||
1 | / { | 1 | / { |
2 | flash: flash@f8000000 { | 2 | soc { |
3 | #address-cells = <1>; | 3 | flash: flash@08000000 { |
4 | #size-cells = <1>; | 4 | #address-cells = <1>; |
5 | compatible = "cfi-flash"; | 5 | #size-cells = <1>; |
6 | reg = <0xf8000000 0x01000000>; | 6 | compatible = "cfi-flash"; |
7 | bank-width = <2>; | 7 | reg = <0x08000000 0x01000000>; |
8 | device-width = <2>; | 8 | bank-width = <2>; |
9 | partition@0x0 { | 9 | device-width = <2>; |
10 | label = "boot loader area"; | 10 | partition@0x0 { |
11 | reg = <0x00000000 0x00400000>; | 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 { | 27 | }; |
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 | }; | ||
26 | }; | 28 | }; |
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi index 6f9c10d6b689..d1c621ca8be1 100644 --- a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi +++ b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi | |||
@@ -1,18 +1,20 @@ | |||
1 | / { | 1 | / { |
2 | flash: flash@f8000000 { | 2 | soc { |
3 | #address-cells = <1>; | 3 | flash: flash@08000000 { |
4 | #size-cells = <1>; | 4 | #address-cells = <1>; |
5 | compatible = "cfi-flash"; | 5 | #size-cells = <1>; |
6 | reg = <0xf8000000 0x00400000>; | 6 | compatible = "cfi-flash"; |
7 | bank-width = <2>; | 7 | reg = <0x08000000 0x00400000>; |
8 | device-width = <2>; | 8 | bank-width = <2>; |
9 | partition@0x0 { | 9 | device-width = <2>; |
10 | label = "boot loader area"; | 10 | partition@0x0 { |
11 | reg = <0x00000000 0x003f0000>; | 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 { | 19 | }; |
14 | label = "boot environment"; | ||
15 | reg = <0x003f0000 0x00010000>; | ||
16 | }; | ||
17 | }; | ||
18 | }; | 20 | }; |
diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi index e7370b11348e..dec9178840f6 100644 --- a/arch/xtensa/boot/dts/xtfpga.dtsi +++ b/arch/xtensa/boot/dts/xtfpga.dtsi | |||
@@ -42,21 +42,28 @@ | |||
42 | }; | 42 | }; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | serial0: serial@fd050020 { | 45 | soc { |
46 | device_type = "serial"; | 46 | #address-cells = <1>; |
47 | compatible = "ns16550a"; | 47 | #size-cells = <1>; |
48 | no-loopback-test; | 48 | compatible = "simple-bus"; |
49 | reg = <0xfd050020 0x20>; | 49 | ranges = <0x00000000 0xf0000000 0x10000000>; |
50 | reg-shift = <2>; | ||
51 | interrupts = <0 1>; /* external irq 0 */ | ||
52 | clocks = <&osc>; | ||
53 | }; | ||
54 | 50 | ||
55 | enet0: ethoc@fd030000 { | 51 | serial0: serial@0d050020 { |
56 | compatible = "opencores,ethoc"; | 52 | device_type = "serial"; |
57 | reg = <0xfd030000 0x4000 0xfd800000 0x4000>; | 53 | compatible = "ns16550a"; |
58 | interrupts = <1 1>; /* external irq 1 */ | 54 | no-loopback-test; |
59 | local-mac-address = [00 50 c2 13 6f 00]; | 55 | reg = <0x0d050020 0x20>; |
60 | clocks = <&osc>; | 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 | }; |
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h index 23392c5630ce..892aab399ac8 100644 --- a/arch/xtensa/include/asm/bootparam.h +++ b/arch/xtensa/include/asm/bootparam.h | |||
@@ -37,23 +37,14 @@ typedef struct bp_tag { | |||
37 | unsigned long data[0]; /* data */ | 37 | unsigned long data[0]; /* data */ |
38 | } bp_tag_t; | 38 | } bp_tag_t; |
39 | 39 | ||
40 | typedef struct meminfo { | 40 | struct bp_meminfo { |
41 | unsigned long type; | 41 | unsigned long type; |
42 | unsigned long start; | 42 | unsigned long start; |
43 | unsigned long end; | 43 | unsigned long end; |
44 | } meminfo_t; | 44 | }; |
45 | |||
46 | #define SYSMEM_BANKS_MAX 5 | ||
47 | 45 | ||
48 | #define MEMORY_TYPE_CONVENTIONAL 0x1000 | 46 | #define MEMORY_TYPE_CONVENTIONAL 0x1000 |
49 | #define MEMORY_TYPE_NONE 0x2000 | 47 | #define MEMORY_TYPE_NONE 0x2000 |
50 | 48 | ||
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 | |||
58 | #endif | 49 | #endif |
59 | #endif | 50 | #endif |
diff --git a/arch/xtensa/include/asm/fixmap.h b/arch/xtensa/include/asm/fixmap.h new file mode 100644 index 000000000000..9f6c33d0428a --- /dev/null +++ b/arch/xtensa/include/asm/fixmap.h | |||
@@ -0,0 +1,58 @@ | |||
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 | ||
diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h index 80be15124697..2653ef5d55f1 100644 --- a/arch/xtensa/include/asm/highmem.h +++ b/arch/xtensa/include/asm/highmem.h | |||
@@ -6,11 +6,54 @@ | |||
6 | * this archive for more details. | 6 | * this archive for more details. |
7 | * | 7 | * |
8 | * Copyright (C) 2003 - 2005 Tensilica Inc. | 8 | * Copyright (C) 2003 - 2005 Tensilica Inc. |
9 | * Copyright (C) 2014 Cadence Design Systems Inc. | ||
9 | */ | 10 | */ |
10 | 11 | ||
11 | #ifndef _XTENSA_HIGHMEM_H | 12 | #ifndef _XTENSA_HIGHMEM_H |
12 | #define _XTENSA_HIGHMEM_H | 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 | #endif | 59 | #endif |
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index 216446295ada..4b0ca35a93b1 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h | |||
@@ -310,6 +310,10 @@ set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) | |||
310 | update_pte(ptep, pteval); | 310 | update_pte(ptep, pteval); |
311 | } | 311 | } |
312 | 312 | ||
313 | static inline void set_pte(pte_t *ptep, pte_t pteval) | ||
314 | { | ||
315 | update_pte(ptep, pteval); | ||
316 | } | ||
313 | 317 | ||
314 | static inline void | 318 | static inline void |
315 | set_pmd(pmd_t *pmdp, pmd_t pmdval) | 319 | set_pmd(pmd_t *pmdp, pmd_t pmdval) |
diff --git a/arch/xtensa/include/asm/sysmem.h b/arch/xtensa/include/asm/sysmem.h new file mode 100644 index 000000000000..c015c5c8e3f7 --- /dev/null +++ b/arch/xtensa/include/asm/sysmem.h | |||
@@ -0,0 +1,38 @@ | |||
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 */ | ||
diff --git a/arch/xtensa/include/asm/tlbflush.h b/arch/xtensa/include/asm/tlbflush.h index fc34274ce41b..06875feb27c2 100644 --- a/arch/xtensa/include/asm/tlbflush.h +++ b/arch/xtensa/include/asm/tlbflush.h | |||
@@ -36,6 +36,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, | |||
36 | unsigned long page); | 36 | unsigned long page); |
37 | void local_flush_tlb_range(struct vm_area_struct *vma, | 37 | void local_flush_tlb_range(struct vm_area_struct *vma, |
38 | unsigned long start, unsigned long end); | 38 | unsigned long start, unsigned long end); |
39 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); | ||
39 | 40 | ||
40 | #ifdef CONFIG_SMP | 41 | #ifdef CONFIG_SMP |
41 | 42 | ||
@@ -44,12 +45,7 @@ void flush_tlb_mm(struct mm_struct *); | |||
44 | void flush_tlb_page(struct vm_area_struct *, unsigned long); | 45 | void flush_tlb_page(struct vm_area_struct *, unsigned long); |
45 | void flush_tlb_range(struct vm_area_struct *, unsigned long, | 46 | void flush_tlb_range(struct vm_area_struct *, unsigned long, |
46 | unsigned long); | 47 | unsigned long); |
47 | 48 | void flush_tlb_kernel_range(unsigned long start, unsigned long end); | |
48 | static inline void flush_tlb_kernel_range(unsigned long start, | ||
49 | unsigned long end) | ||
50 | { | ||
51 | flush_tlb_all(); | ||
52 | } | ||
53 | 49 | ||
54 | #else /* !CONFIG_SMP */ | 50 | #else /* !CONFIG_SMP */ |
55 | 51 | ||
@@ -58,7 +54,8 @@ static inline void flush_tlb_kernel_range(unsigned long start, | |||
58 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) | 54 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) |
59 | #define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ | 55 | #define flush_tlb_range(vma, vmaddr, end) local_flush_tlb_range(vma, vmaddr, \ |
60 | end) | 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 | #endif /* CONFIG_SMP */ | 60 | #endif /* CONFIG_SMP */ |
64 | 61 | ||
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 84fe931bb60e..9757bb74e532 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <asm/param.h> | 50 | #include <asm/param.h> |
51 | #include <asm/traps.h> | 51 | #include <asm/traps.h> |
52 | #include <asm/smp.h> | 52 | #include <asm/smp.h> |
53 | #include <asm/sysmem.h> | ||
53 | 54 | ||
54 | #include <platform/hardware.h> | 55 | #include <platform/hardware.h> |
55 | 56 | ||
@@ -88,12 +89,6 @@ static char __initdata command_line[COMMAND_LINE_SIZE]; | |||
88 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | 89 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; |
89 | #endif | 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 | * Boot parameter parsing. | 93 | * Boot parameter parsing. |
99 | * | 94 | * |
@@ -113,31 +108,14 @@ typedef struct tagtable { | |||
113 | 108 | ||
114 | /* parse current tag */ | 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 | static int __init parse_tag_mem(const bp_tag_t *tag) | 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 | if (mi->type != MEMORY_TYPE_CONVENTIONAL) | 115 | if (mi->type != MEMORY_TYPE_CONVENTIONAL) |
138 | return -1; | 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 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); | 121 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); |
@@ -146,8 +124,8 @@ __tagtable(BP_TAG_MEMORY, parse_tag_mem); | |||
146 | 124 | ||
147 | static int __init parse_tag_initrd(const bp_tag_t* tag) | 125 | static int __init parse_tag_initrd(const bp_tag_t* tag) |
148 | { | 126 | { |
149 | meminfo_t* mi; | 127 | struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data); |
150 | mi = (meminfo_t*)(tag->data); | 128 | |
151 | initrd_start = (unsigned long)__va(mi->start); | 129 | initrd_start = (unsigned long)__va(mi->start); |
152 | initrd_end = (unsigned long)__va(mi->end); | 130 | initrd_end = (unsigned long)__va(mi->end); |
153 | 131 | ||
@@ -255,7 +233,7 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) | |||
255 | return; | 233 | return; |
256 | 234 | ||
257 | size &= PAGE_MASK; | 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 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | 239 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) |
@@ -292,8 +270,6 @@ device_initcall(xtensa_device_probe); | |||
292 | 270 | ||
293 | void __init init_arch(bp_tag_t *bp_start) | 271 | void __init init_arch(bp_tag_t *bp_start) |
294 | { | 272 | { |
295 | sysmem.nr_banks = 0; | ||
296 | |||
297 | /* Parse boot parameters */ | 273 | /* Parse boot parameters */ |
298 | 274 | ||
299 | if (bp_start) | 275 | if (bp_start) |
@@ -304,10 +280,9 @@ void __init init_arch(bp_tag_t *bp_start) | |||
304 | #endif | 280 | #endif |
305 | 281 | ||
306 | if (sysmem.nr_banks == 0) { | 282 | if (sysmem.nr_banks == 0) { |
307 | sysmem.nr_banks = 1; | 283 | add_sysmem_bank(PLATFORM_DEFAULT_MEM_START, |
308 | sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START; | 284 | PLATFORM_DEFAULT_MEM_START + |
309 | sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START | 285 | PLATFORM_DEFAULT_MEM_SIZE); |
310 | + PLATFORM_DEFAULT_MEM_SIZE; | ||
311 | } | 286 | } |
312 | 287 | ||
313 | #ifdef CONFIG_CMDLINE_BOOL | 288 | #ifdef CONFIG_CMDLINE_BOOL |
@@ -487,7 +462,7 @@ void __init setup_arch(char **cmdline_p) | |||
487 | #ifdef CONFIG_BLK_DEV_INITRD | 462 | #ifdef CONFIG_BLK_DEV_INITRD |
488 | if (initrd_start < initrd_end) { | 463 | if (initrd_start < initrd_end) { |
489 | initrd_is_mapped = mem_reserve(__pa(initrd_start), | 464 | initrd_is_mapped = mem_reserve(__pa(initrd_start), |
490 | __pa(initrd_end), 0); | 465 | __pa(initrd_end), 0) == 0; |
491 | initrd_below_start_ok = 1; | 466 | initrd_below_start_ok = 1; |
492 | } else { | 467 | } else { |
493 | initrd_start = 0; | 468 | initrd_start = 0; |
@@ -532,6 +507,7 @@ void __init setup_arch(char **cmdline_p) | |||
532 | __pa(&_Level6InterruptVector_text_end), 0); | 507 | __pa(&_Level6InterruptVector_text_end), 0); |
533 | #endif | 508 | #endif |
534 | 509 | ||
510 | parse_early_param(); | ||
535 | bootmem_init(); | 511 | bootmem_init(); |
536 | 512 | ||
537 | unflatten_and_copy_device_tree(); | 513 | unflatten_and_copy_device_tree(); |
diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c index aa8bd8717927..40b5a3771fb0 100644 --- a/arch/xtensa/kernel/smp.c +++ b/arch/xtensa/kernel/smp.c | |||
@@ -496,6 +496,21 @@ void flush_tlb_range(struct vm_area_struct *vma, | |||
496 | on_each_cpu(ipi_flush_tlb_range, &fd, 1); | 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 | /* Cache flush functions */ | 514 | /* Cache flush functions */ |
500 | 515 | ||
501 | static void ipi_flush_cache_all(void *arg) | 516 | static void ipi_flush_cache_all(void *arg) |
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 80b33ed51f31..4d2872fd9bb5 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/in6.h> | 20 | #include <linux/in6.h> |
21 | 21 | ||
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | #include <asm/cacheflush.h> | ||
23 | #include <asm/checksum.h> | 24 | #include <asm/checksum.h> |
24 | #include <asm/dma.h> | 25 | #include <asm/dma.h> |
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
@@ -105,6 +106,7 @@ EXPORT_SYMBOL(csum_partial_copy_generic); | |||
105 | * Architecture-specific symbols | 106 | * Architecture-specific symbols |
106 | */ | 107 | */ |
107 | EXPORT_SYMBOL(__xtensa_copy_user); | 108 | EXPORT_SYMBOL(__xtensa_copy_user); |
109 | EXPORT_SYMBOL(__invalidate_icache_range); | ||
108 | 110 | ||
109 | /* | 111 | /* |
110 | * Kernel hacking ... | 112 | * Kernel hacking ... |
@@ -127,3 +129,8 @@ EXPORT_SYMBOL(common_exception_return); | |||
127 | #ifdef CONFIG_FUNCTION_TRACER | 129 | #ifdef CONFIG_FUNCTION_TRACER |
128 | EXPORT_SYMBOL(_mcount); | 130 | EXPORT_SYMBOL(_mcount); |
129 | #endif | 131 | #endif |
132 | |||
133 | EXPORT_SYMBOL(__invalidate_dcache_range); | ||
134 | #if XCHAL_DCACHE_IS_WRITEBACK | ||
135 | EXPORT_SYMBOL(__flush_dcache_range); | ||
136 | #endif | ||
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile index f0b646d2f843..f54f78e24d7b 100644 --- a/arch/xtensa/mm/Makefile +++ b/arch/xtensa/mm/Makefile | |||
@@ -4,3 +4,4 @@ | |||
4 | 4 | ||
5 | obj-y := init.o cache.o misc.o | 5 | obj-y := init.o cache.o misc.o |
6 | obj-$(CONFIG_MMU) += fault.o mmu.o tlb.o | 6 | obj-$(CONFIG_MMU) += fault.o mmu.o tlb.o |
7 | obj-$(CONFIG_HIGHMEM) += highmem.o | ||
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index ba4c47f291b1..63cbb867dadd 100644 --- a/arch/xtensa/mm/cache.c +++ b/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 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK | 66 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK |
63 | 67 | ||
64 | /* | 68 | /* |
@@ -179,10 +183,11 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep) | |||
179 | #else | 183 | #else |
180 | if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags) | 184 | if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags) |
181 | && (vma->vm_flags & VM_EXEC) != 0) { | 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 | __flush_dcache_page(paddr); | 187 | __flush_dcache_page(paddr); |
184 | __invalidate_icache_page(paddr); | 188 | __invalidate_icache_page(paddr); |
185 | set_bit(PG_arch_1, &page->flags); | 189 | set_bit(PG_arch_1, &page->flags); |
190 | kunmap_atomic((void *)paddr); | ||
186 | } | 191 | } |
187 | #endif | 192 | #endif |
188 | } | 193 | } |
diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c new file mode 100644 index 000000000000..17a8c0d6fd17 --- /dev/null +++ b/arch/xtensa/mm/highmem.c | |||
@@ -0,0 +1,72 @@ | |||
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 | } | ||
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index aff108df92d3..4224256bb215 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * for more details. | 8 | * for more details. |
9 | * | 9 | * |
10 | * Copyright (C) 2001 - 2005 Tensilica Inc. | 10 | * Copyright (C) 2001 - 2005 Tensilica Inc. |
11 | * Copyright (C) 2014 Cadence Design Systems Inc. | ||
11 | * | 12 | * |
12 | * Chris Zankel <chris@zankel.net> | 13 | * Chris Zankel <chris@zankel.net> |
13 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> | 14 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> |
@@ -19,6 +20,7 @@ | |||
19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
20 | #include <linux/bootmem.h> | 21 | #include <linux/bootmem.h> |
21 | #include <linux/gfp.h> | 22 | #include <linux/gfp.h> |
23 | #include <linux/highmem.h> | ||
22 | #include <linux/swap.h> | 24 | #include <linux/swap.h> |
23 | #include <linux/mman.h> | 25 | #include <linux/mman.h> |
24 | #include <linux/nodemask.h> | 26 | #include <linux/nodemask.h> |
@@ -27,11 +29,133 @@ | |||
27 | #include <asm/bootparam.h> | 29 | #include <asm/bootparam.h> |
28 | #include <asm/page.h> | 30 | #include <asm/page.h> |
29 | #include <asm/sections.h> | 31 | #include <asm/sections.h> |
32 | #include <asm/sysmem.h> | ||
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 | |||
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 | } | ||
30 | 152 | ||
31 | /* | 153 | /* |
32 | * mem_reserve(start, end, must_exist) | 154 | * mem_reserve(start, end, must_exist) |
33 | * | 155 | * |
34 | * Reserve some memory from the memory pool. | 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 | * Parameters: | 160 | * Parameters: |
37 | * start Start of region, | 161 | * start Start of region, |
@@ -39,53 +163,69 @@ | |||
39 | * must_exist Must exist in memory pool. | 163 | * must_exist Must exist in memory pool. |
40 | * | 164 | * |
41 | * Returns: | 165 | * Returns: |
42 | * 0 (memory area couldn't be mapped) | 166 | * 0 (success) |
43 | * -1 (success) | 167 | * < 0 (error) |
44 | */ | 168 | */ |
45 | 169 | ||
46 | int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) | 170 | int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) |
47 | { | 171 | { |
48 | int i; | 172 | struct meminfo *it; |
49 | 173 | struct meminfo *rm = NULL; | |
50 | if (start == end) | 174 | unsigned long sz; |
51 | return 0; | 175 | unsigned long bank_sz = 0; |
52 | 176 | ||
53 | start = start & PAGE_MASK; | 177 | start = start & PAGE_MASK; |
54 | end = PAGE_ALIGN(end); | 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++) | 183 | it = find_bank(start); |
57 | if (start < sysmem.bank[i].end | 184 | |
58 | && end >= sysmem.bank[i].start) | 185 | if (it) |
59 | break; | 186 | bank_sz = it->end - it->start; |
60 | 187 | ||
61 | if (i == sysmem.nr_banks) { | 188 | if ((!it || end - it->start > bank_sz) && must_exist) { |
62 | if (must_exist) | 189 | pr_warn("mem_reserve: [0x%0lx, 0x%0lx) not in any region!\n", |
63 | printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) " | 190 | start, end); |
64 | "not in any region!\n", start, end); | 191 | return -EINVAL; |
65 | return 0; | ||
66 | } | 192 | } |
67 | 193 | ||
68 | if (start > sysmem.bank[i].start) { | 194 | if (it && start - it->start < bank_sz) { |
69 | if (end < sysmem.bank[i].end) { | 195 | if (start == it->start) { |
70 | /* split entry */ | 196 | if (end - it->start < bank_sz) { |
71 | if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) | 197 | it->start = end; |
72 | panic("meminfo overflow\n"); | 198 | return 0; |
73 | sysmem.bank[sysmem.nr_banks].start = end; | 199 | } else { |
74 | sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end; | 200 | rm = it; |
75 | sysmem.nr_banks++; | 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) { | 211 | if (!it) |
80 | sysmem.bank[i].start = end; | 212 | it = sysmem.bank; |
81 | 213 | ||
82 | } else { | 214 | for (; it < sysmem.bank + sysmem.nr_banks; ++it) { |
83 | /* remove entry */ | 215 | if (it->end - start <= sz) { |
84 | sysmem.nr_banks--; | 216 | if (!rm) |
85 | sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start; | 217 | rm = it; |
86 | sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end; | 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 @@ void __init bootmem_init(void) | |||
99 | unsigned long bootmap_start, bootmap_size; | 239 | unsigned long bootmap_start, bootmap_size; |
100 | int i; | 240 | int i; |
101 | 241 | ||
242 | sysmem_dump(); | ||
102 | max_low_pfn = max_pfn = 0; | 243 | max_low_pfn = max_pfn = 0; |
103 | min_low_pfn = ~0; | 244 | min_low_pfn = ~0; |
104 | 245 | ||
@@ -156,19 +297,13 @@ void __init bootmem_init(void) | |||
156 | 297 | ||
157 | void __init zones_init(void) | 298 | void __init zones_init(void) |
158 | { | 299 | { |
159 | unsigned long zones_size[MAX_NR_ZONES]; | ||
160 | int i; | ||
161 | |||
162 | /* All pages are DMA-able, so we put them all in the DMA zone. */ | 300 | /* All pages are DMA-able, so we put them all in the DMA zone. */ |
163 | 301 | unsigned long zones_size[MAX_NR_ZONES] = { | |
164 | zones_size[ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET; | 302 | [ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET, |
165 | for (i = 1; i < MAX_NR_ZONES; i++) | ||
166 | zones_size[i] = 0; | ||
167 | |||
168 | #ifdef CONFIG_HIGHMEM | 303 | #ifdef CONFIG_HIGHMEM |
169 | zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn; | 304 | [ZONE_HIGHMEM] = max_pfn - max_low_pfn, |
170 | #endif | 305 | #endif |
171 | 306 | }; | |
172 | free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL); | 307 | free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL); |
173 | } | 308 | } |
174 | 309 | ||
@@ -178,16 +313,38 @@ void __init zones_init(void) | |||
178 | 313 | ||
179 | void __init mem_init(void) | 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 | #ifdef CONFIG_HIGHMEM | 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 | #endif | 322 | #endif |
187 | 323 | ||
324 | max_mapnr = max_pfn - ARCH_PFN_OFFSET; | ||
325 | high_memory = (void *)__va(max_low_pfn << PAGE_SHIFT); | ||
326 | |||
188 | free_all_bootmem(); | 327 | free_all_bootmem(); |
189 | 328 | ||
190 | mem_init_print_info(NULL); | 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 | #ifdef CONFIG_BLK_DEV_INITRD | 350 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -204,3 +361,53 @@ void free_initmem(void) | |||
204 | { | 361 | { |
205 | free_initmem_default(-1); | 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); | ||
diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index 861203e958da..3429b483d9f8 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Extracted from init.c | 4 | * Extracted from init.c |
5 | */ | 5 | */ |
6 | #include <linux/bootmem.h> | ||
6 | #include <linux/percpu.h> | 7 | #include <linux/percpu.h> |
7 | #include <linux/init.h> | 8 | #include <linux/init.h> |
8 | #include <linux/string.h> | 9 | #include <linux/string.h> |
@@ -16,9 +17,44 @@ | |||
16 | #include <asm/initialize_mmu.h> | 17 | #include <asm/initialize_mmu.h> |
17 | #include <asm/io.h> | 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 | void __init paging_init(void) | 50 | void __init paging_init(void) |
20 | { | 51 | { |
21 | memset(swapper_pg_dir, 0, PAGE_SIZE); | 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 | /* |
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index ade623826788..5ece856c5725 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c | |||
@@ -149,6 +149,21 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
149 | local_irq_restore(flags); | 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 | #ifdef CONFIG_DEBUG_TLB_SANITY | 167 | #ifdef CONFIG_DEBUG_TLB_SANITY |
153 | 168 | ||
154 | static unsigned get_pte_for_vaddr(unsigned vaddr) | 169 | static unsigned get_pte_for_vaddr(unsigned vaddr) |
diff --git a/arch/xtensa/platforms/iss/Makefile b/arch/xtensa/platforms/iss/Makefile index d2369b799c50..b3e89291cfba 100644 --- a/arch/xtensa/platforms/iss/Makefile +++ b/arch/xtensa/platforms/iss/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | # "prom monitor" library routines under Linux. | 4 | # "prom monitor" library routines under Linux. |
5 | # | 5 | # |
6 | 6 | ||
7 | obj-y = console.o setup.o | 7 | obj-y = setup.o |
8 | obj-$(CONFIG_TTY) += console.o | ||
8 | obj-$(CONFIG_NET) += network.o | 9 | obj-$(CONFIG_NET) += network.o |
9 | obj-$(CONFIG_BLK_DEV_SIMDISK) += simdisk.o | 10 | obj-$(CONFIG_BLK_DEV_SIMDISK) += simdisk.o |
diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index f9bc87966290..b90555cb8089 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c | |||
@@ -92,18 +92,8 @@ void __init platform_setup(char** cmdline) | |||
92 | 92 | ||
93 | /* early initialization */ | 93 | /* early initialization */ |
94 | 94 | ||
95 | extern sysmem_info_t __initdata sysmem; | 95 | void __init platform_init(bp_tag_t *first) |
96 | |||
97 | void 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 | /* Heartbeat. Let the LED blink. */ | 99 | /* Heartbeat. Let the LED blink. */ |