diff options
Diffstat (limited to 'arch/microblaze')
45 files changed, 964 insertions, 466 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index c8d6efb99dbf..ac22dc7f4cab 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config MICROBLAZE | 1 | config MICROBLAZE |
2 | def_bool y | 2 | def_bool y |
3 | select HAVE_MEMBLOCK | 3 | select HAVE_MEMBLOCK |
4 | select HAVE_MEMBLOCK_NODE_MAP | ||
4 | select HAVE_FUNCTION_TRACER | 5 | select HAVE_FUNCTION_TRACER |
5 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | 6 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST |
6 | select HAVE_FUNCTION_GRAPH_TRACER | 7 | select HAVE_FUNCTION_GRAPH_TRACER |
@@ -14,6 +15,7 @@ config MICROBLAZE | |||
14 | select TRACING_SUPPORT | 15 | select TRACING_SUPPORT |
15 | select OF | 16 | select OF |
16 | select OF_EARLY_FLATTREE | 17 | select OF_EARLY_FLATTREE |
18 | select IRQ_DOMAIN | ||
17 | select HAVE_GENERIC_HARDIRQS | 19 | select HAVE_GENERIC_HARDIRQS |
18 | select GENERIC_IRQ_PROBE | 20 | select GENERIC_IRQ_PROBE |
19 | select GENERIC_IRQ_SHOW | 21 | select GENERIC_IRQ_SHOW |
@@ -27,6 +29,12 @@ config SWAP | |||
27 | config RWSEM_GENERIC_SPINLOCK | 29 | config RWSEM_GENERIC_SPINLOCK |
28 | def_bool y | 30 | def_bool y |
29 | 31 | ||
32 | config ZONE_DMA | ||
33 | def_bool y | ||
34 | |||
35 | config ARCH_POPULATES_NODE_MAP | ||
36 | def_bool y | ||
37 | |||
30 | config RWSEM_XCHGADD_ALGORITHM | 38 | config RWSEM_XCHGADD_ALGORITHM |
31 | bool | 39 | bool |
32 | 40 | ||
@@ -152,20 +160,18 @@ config XILINX_UNCACHED_SHADOW | |||
152 | The feature requires the design to define the RAM memory controller | 160 | The feature requires the design to define the RAM memory controller |
153 | window to be twice as large as the actual physical memory. | 161 | window to be twice as large as the actual physical memory. |
154 | 162 | ||
155 | config HIGHMEM_START_BOOL | 163 | config HIGHMEM |
156 | bool "Set high memory pool address" | 164 | bool "High memory support" |
157 | depends on ADVANCED_OPTIONS && HIGHMEM | 165 | depends on MMU |
158 | help | 166 | help |
159 | This option allows you to set the base address of the kernel virtual | 167 | The address space of Microblaze processors is only 4 Gigabytes large |
160 | area used to map high memory pages. This can be useful in | 168 | and it has to accommodate user address space, kernel address |
161 | optimizing the layout of kernel virtual memory. | 169 | space as well as some memory mapped IO. That means that, if you |
170 | have a large amount of physical memory and/or IO, not all of the | ||
171 | memory can be "permanently mapped" by the kernel. The physical | ||
172 | memory that is not permanently mapped is called "high memory". | ||
162 | 173 | ||
163 | Say N here unless you know what you are doing. | 174 | If unsure, say n. |
164 | |||
165 | config HIGHMEM_START | ||
166 | hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL | ||
167 | depends on MMU | ||
168 | default "0xfe000000" | ||
169 | 175 | ||
170 | config LOWMEM_SIZE_BOOL | 176 | config LOWMEM_SIZE_BOOL |
171 | bool "Set maximum low memory" | 177 | bool "Set maximum low memory" |
@@ -254,6 +260,10 @@ config MICROBLAZE_32K_PAGES | |||
254 | 260 | ||
255 | endchoice | 261 | endchoice |
256 | 262 | ||
263 | config KERNEL_PAD | ||
264 | hex "Kernel PAD for unpacking" if ADVANCED_OPTIONS | ||
265 | default "0x80000" if MMU | ||
266 | |||
257 | endmenu | 267 | endmenu |
258 | 268 | ||
259 | source "mm/Kconfig" | 269 | source "mm/Kconfig" |
diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile index 0c796cf81586..fa83ea497db7 100644 --- a/arch/microblaze/boot/Makefile +++ b/arch/microblaze/boot/Makefile | |||
@@ -2,13 +2,11 @@ | |||
2 | # arch/microblaze/boot/Makefile | 2 | # arch/microblaze/boot/Makefile |
3 | # | 3 | # |
4 | 4 | ||
5 | MKIMAGE := $(srctree)/scripts/mkuboot.sh | ||
6 | |||
7 | obj-y += linked_dtb.o | 5 | obj-y += linked_dtb.o |
8 | 6 | ||
9 | targets := linux.bin linux.bin.gz simpleImage.% | 7 | targets := linux.bin linux.bin.gz simpleImage.% |
10 | 8 | ||
11 | OBJCOPYFLAGS := -O binary | 9 | OBJCOPYFLAGS := -R .note -R .comment -R .note.gnu.build-id -O binary |
12 | 10 | ||
13 | # Ensure system.dtb exists | 11 | # Ensure system.dtb exists |
14 | $(obj)/linked_dtb.o: $(obj)/system.dtb | 12 | $(obj)/linked_dtb.o: $(obj)/system.dtb |
@@ -35,11 +33,9 @@ quiet_cmd_strip = STRIP $@ | |||
35 | cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \ | 33 | cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \ |
36 | -K _fdt_start vmlinux -o $@ | 34 | -K _fdt_start vmlinux -o $@ |
37 | 35 | ||
38 | quiet_cmd_uimage = UIMAGE $@.ub | 36 | UIMAGE_IN = $@ |
39 | cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A microblaze -O linux -T kernel \ | 37 | UIMAGE_OUT = $@.ub |
40 | -C none -n 'Linux-$(KERNELRELEASE)' \ | 38 | UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR) |
41 | -a $(CONFIG_KERNEL_BASE_ADDR) -e $(CONFIG_KERNEL_BASE_ADDR) \ | ||
42 | -d $@ $@.ub | ||
43 | 39 | ||
44 | $(obj)/simpleImage.%: vmlinux FORCE | 40 | $(obj)/simpleImage.%: vmlinux FORCE |
45 | $(call if_changed,cp,.unstrip) | 41 | $(call if_changed,cp,.unstrip) |
diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h index 615f53992c65..472d8bf726df 100644 --- a/arch/microblaze/include/asm/atomic.h +++ b/arch/microblaze/include/asm/atomic.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _ASM_MICROBLAZE_ATOMIC_H | 1 | #ifndef _ASM_MICROBLAZE_ATOMIC_H |
2 | #define _ASM_MICROBLAZE_ATOMIC_H | 2 | #define _ASM_MICROBLAZE_ATOMIC_H |
3 | 3 | ||
4 | #include <asm/cmpxchg.h> | ||
4 | #include <asm-generic/atomic.h> | 5 | #include <asm-generic/atomic.h> |
5 | #include <asm-generic/atomic64.h> | 6 | #include <asm-generic/atomic64.h> |
6 | 7 | ||
diff --git a/arch/microblaze/include/asm/barrier.h b/arch/microblaze/include/asm/barrier.h new file mode 100644 index 000000000000..df5be3e87044 --- /dev/null +++ b/arch/microblaze/include/asm/barrier.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
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 | |||
9 | #ifndef _ASM_MICROBLAZE_BARRIER_H | ||
10 | #define _ASM_MICROBLAZE_BARRIER_H | ||
11 | |||
12 | #define nop() asm volatile ("nop") | ||
13 | |||
14 | #define smp_read_barrier_depends() do {} while (0) | ||
15 | #define read_barrier_depends() do {} while (0) | ||
16 | |||
17 | #define mb() barrier() | ||
18 | #define rmb() mb() | ||
19 | #define wmb() mb() | ||
20 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
21 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
22 | |||
23 | #define smp_mb() mb() | ||
24 | #define smp_rmb() rmb() | ||
25 | #define smp_wmb() wmb() | ||
26 | |||
27 | #endif /* _ASM_MICROBLAZE_BARRIER_H */ | ||
diff --git a/arch/microblaze/include/asm/cmpxchg.h b/arch/microblaze/include/asm/cmpxchg.h new file mode 100644 index 000000000000..538afc0ab9f3 --- /dev/null +++ b/arch/microblaze/include/asm/cmpxchg.h | |||
@@ -0,0 +1,42 @@ | |||
1 | #ifndef _ASM_MICROBLAZE_CMPXCHG_H | ||
2 | #define _ASM_MICROBLAZE_CMPXCHG_H | ||
3 | |||
4 | #include <linux/irqflags.h> | ||
5 | |||
6 | void __bad_xchg(volatile void *ptr, int size); | ||
7 | |||
8 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | ||
9 | int size) | ||
10 | { | ||
11 | unsigned long ret; | ||
12 | unsigned long flags; | ||
13 | |||
14 | switch (size) { | ||
15 | case 1: | ||
16 | local_irq_save(flags); | ||
17 | ret = *(volatile unsigned char *)ptr; | ||
18 | *(volatile unsigned char *)ptr = x; | ||
19 | local_irq_restore(flags); | ||
20 | break; | ||
21 | |||
22 | case 4: | ||
23 | local_irq_save(flags); | ||
24 | ret = *(volatile unsigned long *)ptr; | ||
25 | *(volatile unsigned long *)ptr = x; | ||
26 | local_irq_restore(flags); | ||
27 | break; | ||
28 | default: | ||
29 | __bad_xchg(ptr, size), ret = 0; | ||
30 | break; | ||
31 | } | ||
32 | |||
33 | return ret; | ||
34 | } | ||
35 | |||
36 | #define xchg(ptr, x) \ | ||
37 | ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) | ||
38 | |||
39 | #include <asm-generic/cmpxchg.h> | ||
40 | #include <asm-generic/cmpxchg-local.h> | ||
41 | |||
42 | #endif /* _ASM_MICROBLAZE_CMPXCHG_H */ | ||
diff --git a/arch/microblaze/include/asm/exec.h b/arch/microblaze/include/asm/exec.h new file mode 100644 index 000000000000..e750de1fe8fb --- /dev/null +++ b/arch/microblaze/include/asm/exec.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
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 | |||
9 | #ifndef _ASM_MICROBLAZE_EXEC_H | ||
10 | #define _ASM_MICROBLAZE_EXEC_H | ||
11 | |||
12 | #define arch_align_stack(x) (x) | ||
13 | |||
14 | #endif /* _ASM_MICROBLAZE_EXEC_H */ | ||
diff --git a/arch/microblaze/include/asm/fixmap.h b/arch/microblaze/include/asm/fixmap.h new file mode 100644 index 000000000000..f2b312e10b10 --- /dev/null +++ b/arch/microblaze/include/asm/fixmap.h | |||
@@ -0,0 +1,109 @@ | |||
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 | * Copyright 2008 Freescale Semiconductor Inc. | ||
11 | * Port to powerpc added by Kumar Gala | ||
12 | * | ||
13 | * Copyright 2011 Michal Simek <monstr@monstr.eu> | ||
14 | * Copyright 2011 PetaLogix Qld Pty Ltd | ||
15 | * Port to Microblaze | ||
16 | */ | ||
17 | |||
18 | #ifndef _ASM_FIXMAP_H | ||
19 | #define _ASM_FIXMAP_H | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <asm/page.h> | ||
24 | #ifdef CONFIG_HIGHMEM | ||
25 | #include <linux/threads.h> | ||
26 | #include <asm/kmap_types.h> | ||
27 | #endif | ||
28 | |||
29 | #define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE)) | ||
30 | |||
31 | /* | ||
32 | * Here we define all the compile-time 'special' virtual | ||
33 | * addresses. The point is to have a constant address at | ||
34 | * compile time, but to set the physical address only | ||
35 | * in the boot process. We allocate these special addresses | ||
36 | * from the end of virtual memory (0xfffff000) backwards. | ||
37 | * Also this lets us do fail-safe vmalloc(), we | ||
38 | * can guarantee that these special addresses and | ||
39 | * vmalloc()-ed addresses never overlap. | ||
40 | * | ||
41 | * these 'compile-time allocated' memory buffers are | ||
42 | * fixed-size 4k pages. (or larger if used with an increment | ||
43 | * highger than 1) use fixmap_set(idx,phys) to associate | ||
44 | * physical memory with fixmap indices. | ||
45 | * | ||
46 | * TLB entries of such buffers will not be flushed across | ||
47 | * task switches. | ||
48 | */ | ||
49 | enum fixed_addresses { | ||
50 | FIX_HOLE, | ||
51 | #ifdef CONFIG_HIGHMEM | ||
52 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ | ||
53 | FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * num_possible_cpus()) - 1, | ||
54 | #endif | ||
55 | __end_of_fixed_addresses | ||
56 | }; | ||
57 | |||
58 | extern void __set_fixmap(enum fixed_addresses idx, | ||
59 | phys_addr_t phys, pgprot_t flags); | ||
60 | |||
61 | #define set_fixmap(idx, phys) \ | ||
62 | __set_fixmap(idx, phys, PAGE_KERNEL) | ||
63 | /* | ||
64 | * Some hardware wants to get fixmapped without caching. | ||
65 | */ | ||
66 | #define set_fixmap_nocache(idx, phys) \ | ||
67 | __set_fixmap(idx, phys, PAGE_KERNEL_CI) | ||
68 | |||
69 | #define clear_fixmap(idx) \ | ||
70 | __set_fixmap(idx, 0, __pgprot(0)) | ||
71 | |||
72 | #define __FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | ||
73 | #define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE) | ||
74 | |||
75 | #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) | ||
76 | #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) | ||
77 | |||
78 | extern void __this_fixmap_does_not_exist(void); | ||
79 | |||
80 | /* | ||
81 | * 'index to address' translation. If anyone tries to use the idx | ||
82 | * directly without tranlation, we catch the bug with a NULL-deference | ||
83 | * kernel oops. Illegal ranges of incoming indices are caught too. | ||
84 | */ | ||
85 | static __always_inline unsigned long fix_to_virt(const unsigned int idx) | ||
86 | { | ||
87 | /* | ||
88 | * this branch gets completely eliminated after inlining, | ||
89 | * except when someone tries to use fixaddr indices in an | ||
90 | * illegal way. (such as mixing up address types or using | ||
91 | * out-of-range indices). | ||
92 | * | ||
93 | * If it doesn't get removed, the linker will complain | ||
94 | * loudly with a reasonably clear error message.. | ||
95 | */ | ||
96 | if (idx >= __end_of_fixed_addresses) | ||
97 | __this_fixmap_does_not_exist(); | ||
98 | |||
99 | return __fix_to_virt(idx); | ||
100 | } | ||
101 | |||
102 | static inline unsigned long virt_to_fix(const unsigned long vaddr) | ||
103 | { | ||
104 | BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); | ||
105 | return __virt_to_fix(vaddr); | ||
106 | } | ||
107 | |||
108 | #endif /* !__ASSEMBLY__ */ | ||
109 | #endif | ||
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h index b0526d2716fa..ff8cde159d9a 100644 --- a/arch/microblaze/include/asm/futex.h +++ b/arch/microblaze/include/asm/futex.h | |||
@@ -24,7 +24,7 @@ | |||
24 | .word 1b,4b,2b,4b; \ | 24 | .word 1b,4b,2b,4b; \ |
25 | .previous;" \ | 25 | .previous;" \ |
26 | : "=&r" (oldval), "=&r" (ret) \ | 26 | : "=&r" (oldval), "=&r" (ret) \ |
27 | : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ | 27 | : "r" (uaddr), "i" (-EFAULT), "r" (oparg) \ |
28 | ); \ | 28 | ); \ |
29 | }) | 29 | }) |
30 | 30 | ||
diff --git a/arch/microblaze/include/asm/hardirq.h b/arch/microblaze/include/asm/hardirq.h index cd1ac9aad56c..fb3c05a0cbbf 100644 --- a/arch/microblaze/include/asm/hardirq.h +++ b/arch/microblaze/include/asm/hardirq.h | |||
@@ -1,17 +1 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
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 | |||
9 | #ifndef _ASM_MICROBLAZE_HARDIRQ_H | ||
10 | #define _ASM_MICROBLAZE_HARDIRQ_H | ||
11 | |||
12 | /* should be defined in each interrupt controller driver */ | ||
13 | extern unsigned int get_irq(struct pt_regs *regs); | ||
14 | |||
15 | #include <asm-generic/hardirq.h> | #include <asm-generic/hardirq.h> | |
16 | |||
17 | #endif /* _ASM_MICROBLAZE_HARDIRQ_H */ | ||
diff --git a/arch/microblaze/include/asm/highmem.h b/arch/microblaze/include/asm/highmem.h new file mode 100644 index 000000000000..2446a73140ac --- /dev/null +++ b/arch/microblaze/include/asm/highmem.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * highmem.h: virtual kernel memory mappings for high memory | ||
3 | * | ||
4 | * Used in CONFIG_HIGHMEM systems for memory pages which | ||
5 | * are not addressable by direct kernel virtual addresses. | ||
6 | * | ||
7 | * Copyright (C) 1999 Gerhard Wichert, Siemens AG | ||
8 | * Gerhard.Wichert@pdb.siemens.de | ||
9 | * | ||
10 | * | ||
11 | * Redesigned the x86 32-bit VM architecture to deal with | ||
12 | * up to 16 Terabyte physical memory. With current x86 CPUs | ||
13 | * we now support up to 64 Gigabytes physical RAM. | ||
14 | * | ||
15 | * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> | ||
16 | */ | ||
17 | #ifndef _ASM_HIGHMEM_H | ||
18 | #define _ASM_HIGHMEM_H | ||
19 | |||
20 | #ifdef __KERNEL__ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <asm/fixmap.h> | ||
26 | |||
27 | extern pte_t *kmap_pte; | ||
28 | extern pgprot_t kmap_prot; | ||
29 | extern pte_t *pkmap_page_table; | ||
30 | |||
31 | /* | ||
32 | * Right now we initialize only a single pte table. It can be extended | ||
33 | * easily, subsequent pte tables have to be allocated in one physical | ||
34 | * chunk of RAM. | ||
35 | */ | ||
36 | /* | ||
37 | * We use one full pte table with 4K pages. And with 16K/64K/256K pages pte | ||
38 | * table covers enough memory (32MB/512MB/2GB resp.), so that both FIXMAP | ||
39 | * and PKMAP can be placed in a single pte table. We use 512 pages for PKMAP | ||
40 | * in case of 16K/64K/256K page sizes. | ||
41 | */ | ||
42 | |||
43 | #define PKMAP_ORDER PTE_SHIFT | ||
44 | #define LAST_PKMAP (1 << PKMAP_ORDER) | ||
45 | |||
46 | #define PKMAP_BASE ((FIXADDR_START - PAGE_SIZE * (LAST_PKMAP + 1)) \ | ||
47 | & PMD_MASK) | ||
48 | |||
49 | #define LAST_PKMAP_MASK (LAST_PKMAP - 1) | ||
50 | #define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT) | ||
51 | #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) | ||
52 | |||
53 | extern void *kmap_high(struct page *page); | ||
54 | extern void kunmap_high(struct page *page); | ||
55 | extern void *kmap_atomic_prot(struct page *page, pgprot_t prot); | ||
56 | extern void __kunmap_atomic(void *kvaddr); | ||
57 | |||
58 | static inline void *kmap(struct page *page) | ||
59 | { | ||
60 | might_sleep(); | ||
61 | if (!PageHighMem(page)) | ||
62 | return page_address(page); | ||
63 | return kmap_high(page); | ||
64 | } | ||
65 | |||
66 | static inline void kunmap(struct page *page) | ||
67 | { | ||
68 | BUG_ON(in_interrupt()); | ||
69 | if (!PageHighMem(page)) | ||
70 | return; | ||
71 | kunmap_high(page); | ||
72 | } | ||
73 | |||
74 | static inline void *__kmap_atomic(struct page *page) | ||
75 | { | ||
76 | return kmap_atomic_prot(page, kmap_prot); | ||
77 | } | ||
78 | |||
79 | static inline struct page *kmap_atomic_to_page(void *ptr) | ||
80 | { | ||
81 | unsigned long idx, vaddr = (unsigned long) ptr; | ||
82 | pte_t *pte; | ||
83 | |||
84 | if (vaddr < FIXADDR_START) | ||
85 | return virt_to_page(ptr); | ||
86 | |||
87 | idx = virt_to_fix(vaddr); | ||
88 | pte = kmap_pte - (idx - FIX_KMAP_BEGIN); | ||
89 | return pte_page(*pte); | ||
90 | } | ||
91 | |||
92 | #define flush_cache_kmaps() { flush_icache(); flush_dcache(); } | ||
93 | |||
94 | #endif /* __KERNEL__ */ | ||
95 | |||
96 | #endif /* _ASM_HIGHMEM_H */ | ||
diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h index a175132e4496..bab3b1393ad4 100644 --- a/arch/microblaze/include/asm/irq.h +++ b/arch/microblaze/include/asm/irq.h | |||
@@ -9,49 +9,13 @@ | |||
9 | #ifndef _ASM_MICROBLAZE_IRQ_H | 9 | #ifndef _ASM_MICROBLAZE_IRQ_H |
10 | #define _ASM_MICROBLAZE_IRQ_H | 10 | #define _ASM_MICROBLAZE_IRQ_H |
11 | 11 | ||
12 | 12 | #define NR_IRQS (32 + 1) | |
13 | /* | ||
14 | * Linux IRQ# is currently offset by one to map to the hardware | ||
15 | * irq number. So hardware IRQ0 maps to Linux irq 1. | ||
16 | */ | ||
17 | #define NO_IRQ_OFFSET 1 | ||
18 | #define IRQ_OFFSET NO_IRQ_OFFSET | ||
19 | #define NR_IRQS (32 + IRQ_OFFSET) | ||
20 | #include <asm-generic/irq.h> | 13 | #include <asm-generic/irq.h> |
21 | 14 | ||
22 | /* This type is the placeholder for a hardware interrupt number. It has to | ||
23 | * be big enough to enclose whatever representation is used by a given | ||
24 | * platform. | ||
25 | */ | ||
26 | typedef unsigned long irq_hw_number_t; | ||
27 | |||
28 | extern unsigned int nr_irq; | ||
29 | |||
30 | struct pt_regs; | 15 | struct pt_regs; |
31 | extern void do_IRQ(struct pt_regs *regs); | 16 | extern void do_IRQ(struct pt_regs *regs); |
32 | 17 | ||
33 | /** FIXME - not implement | 18 | /* should be defined in each interrupt controller driver */ |
34 | * irq_dispose_mapping - Unmap an interrupt | 19 | extern unsigned int get_irq(void); |
35 | * @virq: linux virq number of the interrupt to unmap | ||
36 | */ | ||
37 | static inline void irq_dispose_mapping(unsigned int virq) | ||
38 | { | ||
39 | return; | ||
40 | } | ||
41 | |||
42 | struct irq_host; | ||
43 | |||
44 | /** | ||
45 | * irq_create_mapping - Map a hardware interrupt into linux virq space | ||
46 | * @host: host owning this hardware interrupt or NULL for default host | ||
47 | * @hwirq: hardware irq number in that host space | ||
48 | * | ||
49 | * Only one mapping per hardware interrupt is permitted. Returns a linux | ||
50 | * virq number. | ||
51 | * If the sense/trigger is to be specified, set_irq_type() should be called | ||
52 | * on the number returned from that call. | ||
53 | */ | ||
54 | extern unsigned int irq_create_mapping(struct irq_host *host, | ||
55 | irq_hw_number_t hwirq); | ||
56 | 20 | ||
57 | #endif /* _ASM_MICROBLAZE_IRQ_H */ | 21 | #endif /* _ASM_MICROBLAZE_IRQ_H */ |
diff --git a/arch/microblaze/include/asm/mmu.h b/arch/microblaze/include/asm/mmu.h index 8d6a654ceffb..1f9edddf7f4b 100644 --- a/arch/microblaze/include/asm/mmu.h +++ b/arch/microblaze/include/asm/mmu.h | |||
@@ -56,6 +56,12 @@ typedef struct _SEGREG { | |||
56 | 56 | ||
57 | extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ | 57 | extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ |
58 | extern void _tlbia(void); /* invalidate all TLB entries */ | 58 | extern void _tlbia(void); /* invalidate all TLB entries */ |
59 | |||
60 | /* | ||
61 | * tlb_skip size stores actual number skipped TLBs from TLB0 - every directy TLB | ||
62 | * mapping has to increase tlb_skip size. | ||
63 | */ | ||
64 | extern u32 tlb_skip; | ||
59 | # endif /* __ASSEMBLY__ */ | 65 | # endif /* __ASSEMBLY__ */ |
60 | 66 | ||
61 | /* | 67 | /* |
@@ -69,6 +75,12 @@ extern void _tlbia(void); /* invalidate all TLB entries */ | |||
69 | 75 | ||
70 | # define MICROBLAZE_TLB_SIZE 64 | 76 | # define MICROBLAZE_TLB_SIZE 64 |
71 | 77 | ||
78 | /* For cases when you want to skip some TLB entries */ | ||
79 | # define MICROBLAZE_TLB_SKIP 0 | ||
80 | |||
81 | /* Use the last TLB for temporary access to LMB */ | ||
82 | # define MICROBLAZE_LMB_TLB_ID 63 | ||
83 | |||
72 | /* | 84 | /* |
73 | * TLB entries are defined by a "high" tag portion and a "low" data | 85 | * TLB entries are defined by a "high" tag portion and a "low" data |
74 | * portion. The data portion is 32-bits. | 86 | * portion. The data portion is 32-bits. |
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index a25e6b5e2ad4..287c5485d286 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h | |||
@@ -135,8 +135,10 @@ extern unsigned long min_low_pfn; | |||
135 | extern unsigned long max_pfn; | 135 | extern unsigned long max_pfn; |
136 | 136 | ||
137 | extern unsigned long memory_start; | 137 | extern unsigned long memory_start; |
138 | extern unsigned long memory_end; | ||
139 | extern unsigned long memory_size; | 138 | extern unsigned long memory_size; |
139 | extern unsigned long lowmem_size; | ||
140 | |||
141 | extern unsigned long kernel_tlb; | ||
140 | 142 | ||
141 | extern int page_is_ram(unsigned long pfn); | 143 | extern int page_is_ram(unsigned long pfn); |
142 | 144 | ||
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h index e9834b2991d0..cb5d39794800 100644 --- a/arch/microblaze/include/asm/pci-bridge.h +++ b/arch/microblaze/include/asm/pci-bridge.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/pci.h> | 10 | #include <linux/pci.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include <linux/ioport.h> | 12 | #include <linux/ioport.h> |
13 | #include <asm-generic/pci-bridge.h> | ||
14 | 13 | ||
15 | struct device_node; | 14 | struct device_node; |
16 | 15 | ||
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index 033137628e8a..a0da88bf70c5 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h | |||
@@ -94,14 +94,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus, | |||
94 | */ | 94 | */ |
95 | #define PCI_DMA_BUS_IS_PHYS (1) | 95 | #define PCI_DMA_BUS_IS_PHYS (1) |
96 | 96 | ||
97 | extern void pcibios_resource_to_bus(struct pci_dev *dev, | ||
98 | struct pci_bus_region *region, | ||
99 | struct resource *res); | ||
100 | |||
101 | extern void pcibios_bus_to_resource(struct pci_dev *dev, | ||
102 | struct resource *res, | ||
103 | struct pci_bus_region *region); | ||
104 | |||
105 | static inline struct resource *pcibios_select_root(struct pci_dev *pdev, | 97 | static inline struct resource *pcibios_select_root(struct pci_dev *pdev, |
106 | struct resource *res) | 98 | struct resource *res) |
107 | { | 99 | { |
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h index b2af42311a12..3ef7b9cafeca 100644 --- a/arch/microblaze/include/asm/pgtable.h +++ b/arch/microblaze/include/asm/pgtable.h | |||
@@ -94,8 +94,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; } | |||
94 | /* Start and end of the vmalloc area. */ | 94 | /* Start and end of the vmalloc area. */ |
95 | /* Make sure to map the vmalloc area above the pinned kernel memory area | 95 | /* Make sure to map the vmalloc area above the pinned kernel memory area |
96 | of 32Mb. */ | 96 | of 32Mb. */ |
97 | #define VMALLOC_START (CONFIG_KERNEL_START + \ | 97 | #define VMALLOC_START (CONFIG_KERNEL_START + CONFIG_LOWMEM_SIZE) |
98 | max(32 * 1024 * 1024UL, memory_size)) | ||
99 | #define VMALLOC_END ioremap_bot | 98 | #define VMALLOC_END ioremap_bot |
100 | 99 | ||
101 | #endif /* __ASSEMBLY__ */ | 100 | #endif /* __ASSEMBLY__ */ |
@@ -543,8 +542,6 @@ extern unsigned long iopa(unsigned long addr); | |||
543 | /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ | 542 | /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ |
544 | #define kern_addr_valid(addr) (1) | 543 | #define kern_addr_valid(addr) (1) |
545 | 544 | ||
546 | #define io_remap_page_range remap_page_range | ||
547 | |||
548 | /* | 545 | /* |
549 | * No page table caches to initialise | 546 | * No page table caches to initialise |
550 | */ | 547 | */ |
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index 7283bfb2f7e4..bffb54527299 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h | |||
@@ -31,6 +31,8 @@ extern const struct seq_operations cpuinfo_op; | |||
31 | /* Do necessary setup to start up a newly executed thread. */ | 31 | /* Do necessary setup to start up a newly executed thread. */ |
32 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); | 32 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); |
33 | 33 | ||
34 | extern void ret_from_fork(void); | ||
35 | |||
34 | # endif /* __ASSEMBLY__ */ | 36 | # endif /* __ASSEMBLY__ */ |
35 | 37 | ||
36 | # ifndef CONFIG_MMU | 38 | # ifndef CONFIG_MMU |
@@ -125,7 +127,6 @@ struct thread_struct { | |||
125 | .pgdir = swapper_pg_dir, \ | 127 | .pgdir = swapper_pg_dir, \ |
126 | } | 128 | } |
127 | 129 | ||
128 | |||
129 | /* Free all resources held by a thread. */ | 130 | /* Free all resources held by a thread. */ |
130 | extern inline void release_thread(struct task_struct *dead_task) | 131 | extern inline void release_thread(struct task_struct *dead_task) |
131 | { | 132 | { |
@@ -166,6 +167,14 @@ unsigned long get_wchan(struct task_struct *p); | |||
166 | # define STACK_TOP TASK_SIZE | 167 | # define STACK_TOP TASK_SIZE |
167 | # define STACK_TOP_MAX STACK_TOP | 168 | # define STACK_TOP_MAX STACK_TOP |
168 | 169 | ||
170 | void disable_hlt(void); | ||
171 | void enable_hlt(void); | ||
172 | void default_idle(void); | ||
173 | |||
174 | #ifdef CONFIG_DEBUG_FS | ||
175 | extern struct dentry *of_debugfs_root; | ||
176 | #endif | ||
177 | |||
169 | # endif /* __ASSEMBLY__ */ | 178 | # endif /* __ASSEMBLY__ */ |
170 | # endif /* CONFIG_MMU */ | 179 | # endif /* CONFIG_MMU */ |
171 | #endif /* _ASM_MICROBLAZE_PROCESSOR_H */ | 180 | #endif /* _ASM_MICROBLAZE_PROCESSOR_H */ |
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index 6c72ed7eba98..0061aa13a340 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h | |||
@@ -20,6 +20,8 @@ extern unsigned int boot_cpuid; /* move to smp.h */ | |||
20 | 20 | ||
21 | extern char cmd_line[COMMAND_LINE_SIZE]; | 21 | extern char cmd_line[COMMAND_LINE_SIZE]; |
22 | 22 | ||
23 | extern char *klimit; | ||
24 | |||
23 | void early_printk(const char *fmt, ...); | 25 | void early_printk(const char *fmt, ...); |
24 | 26 | ||
25 | int setup_early_printk(char *opt); | 27 | int setup_early_printk(char *opt); |
@@ -39,13 +41,18 @@ extern void of_platform_reset_gpio_probe(void); | |||
39 | void time_init(void); | 41 | void time_init(void); |
40 | void init_IRQ(void); | 42 | void init_IRQ(void); |
41 | void machine_early_init(const char *cmdline, unsigned int ram, | 43 | void machine_early_init(const char *cmdline, unsigned int ram, |
42 | unsigned int fdt, unsigned int msr); | 44 | unsigned int fdt, unsigned int msr, unsigned int tlb0, |
45 | unsigned int tlb1); | ||
43 | 46 | ||
44 | void machine_restart(char *cmd); | 47 | void machine_restart(char *cmd); |
45 | void machine_shutdown(void); | 48 | void machine_shutdown(void); |
46 | void machine_halt(void); | 49 | void machine_halt(void); |
47 | void machine_power_off(void); | 50 | void machine_power_off(void); |
48 | 51 | ||
52 | void free_init_pages(char *what, unsigned long begin, unsigned long end); | ||
53 | extern void *alloc_maybe_bootmem(size_t size, gfp_t mask); | ||
54 | extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); | ||
55 | |||
49 | # endif/* __KERNEL__ */ | 56 | # endif/* __KERNEL__ */ |
50 | # endif /* __ASSEMBLY__ */ | 57 | # endif /* __ASSEMBLY__ */ |
51 | #endif /* _ASM_MICROBLAZE_SETUP_H */ | 58 | #endif /* _ASM_MICROBLAZE_SETUP_H */ |
diff --git a/arch/microblaze/include/asm/switch_to.h b/arch/microblaze/include/asm/switch_to.h new file mode 100644 index 000000000000..f45baa2c5e09 --- /dev/null +++ b/arch/microblaze/include/asm/switch_to.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
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 | |||
9 | #ifndef _ASM_MICROBLAZE_SWITCH_TO_H | ||
10 | #define _ASM_MICROBLAZE_SWITCH_TO_H | ||
11 | |||
12 | struct task_struct; | ||
13 | struct thread_info; | ||
14 | |||
15 | extern struct task_struct *_switch_to(struct thread_info *prev, | ||
16 | struct thread_info *next); | ||
17 | |||
18 | #define switch_to(prev, next, last) \ | ||
19 | do { \ | ||
20 | (last) = _switch_to(task_thread_info(prev), \ | ||
21 | task_thread_info(next)); \ | ||
22 | } while (0) | ||
23 | |||
24 | #endif /* _ASM_MICROBLAZE_SWITCH_TO_H */ | ||
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h deleted file mode 100644 index 5a433cbaafb3..000000000000 --- a/arch/microblaze/include/asm/system.h +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
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 | |||
9 | #ifndef _ASM_MICROBLAZE_SYSTEM_H | ||
10 | #define _ASM_MICROBLAZE_SYSTEM_H | ||
11 | |||
12 | #include <asm/registers.h> | ||
13 | #include <asm/setup.h> | ||
14 | #include <asm/irqflags.h> | ||
15 | #include <asm/cache.h> | ||
16 | |||
17 | #include <asm-generic/cmpxchg.h> | ||
18 | #include <asm-generic/cmpxchg-local.h> | ||
19 | |||
20 | struct task_struct; | ||
21 | struct thread_info; | ||
22 | |||
23 | extern struct task_struct *_switch_to(struct thread_info *prev, | ||
24 | struct thread_info *next); | ||
25 | |||
26 | #define switch_to(prev, next, last) \ | ||
27 | do { \ | ||
28 | (last) = _switch_to(task_thread_info(prev), \ | ||
29 | task_thread_info(next)); \ | ||
30 | } while (0) | ||
31 | |||
32 | #define smp_read_barrier_depends() do {} while (0) | ||
33 | #define read_barrier_depends() do {} while (0) | ||
34 | |||
35 | #define nop() asm volatile ("nop") | ||
36 | #define mb() barrier() | ||
37 | #define rmb() mb() | ||
38 | #define wmb() mb() | ||
39 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
40 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
41 | |||
42 | #define smp_mb() mb() | ||
43 | #define smp_rmb() rmb() | ||
44 | #define smp_wmb() wmb() | ||
45 | |||
46 | void __bad_xchg(volatile void *ptr, int size); | ||
47 | |||
48 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | ||
49 | int size) | ||
50 | { | ||
51 | unsigned long ret; | ||
52 | unsigned long flags; | ||
53 | |||
54 | switch (size) { | ||
55 | case 1: | ||
56 | local_irq_save(flags); | ||
57 | ret = *(volatile unsigned char *)ptr; | ||
58 | *(volatile unsigned char *)ptr = x; | ||
59 | local_irq_restore(flags); | ||
60 | break; | ||
61 | |||
62 | case 4: | ||
63 | local_irq_save(flags); | ||
64 | ret = *(volatile unsigned long *)ptr; | ||
65 | *(volatile unsigned long *)ptr = x; | ||
66 | local_irq_restore(flags); | ||
67 | break; | ||
68 | default: | ||
69 | __bad_xchg(ptr, size), ret = 0; | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | void disable_hlt(void); | ||
77 | void enable_hlt(void); | ||
78 | void default_idle(void); | ||
79 | |||
80 | #define xchg(ptr, x) \ | ||
81 | ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) | ||
82 | |||
83 | void free_init_pages(char *what, unsigned long begin, unsigned long end); | ||
84 | void free_initmem(void); | ||
85 | extern char *klimit; | ||
86 | extern void ret_from_fork(void); | ||
87 | |||
88 | extern void *alloc_maybe_bootmem(size_t size, gfp_t mask); | ||
89 | extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); | ||
90 | |||
91 | #ifdef CONFIG_DEBUG_FS | ||
92 | extern struct dentry *of_debugfs_root; | ||
93 | #endif | ||
94 | |||
95 | #define arch_align_stack(x) (x) | ||
96 | |||
97 | #endif /* _ASM_MICROBLAZE_SYSTEM_H */ | ||
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 072b0077abf9..ef25f7538d4a 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
@@ -80,7 +80,7 @@ extern unsigned long search_exception_table(unsigned long); | |||
80 | static inline int ___range_ok(unsigned long addr, unsigned long size) | 80 | static inline int ___range_ok(unsigned long addr, unsigned long size) |
81 | { | 81 | { |
82 | return ((addr < memory_start) || | 82 | return ((addr < memory_start) || |
83 | ((addr + size) > memory_end)); | 83 | ((addr + size - 1) > (memory_start + memory_size - 1))); |
84 | } | 84 | } |
85 | 85 | ||
86 | #define __range_ok(addr, size) \ | 86 | #define __range_ok(addr, size) \ |
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 54194b28574a..eab6abf5652e 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c | |||
@@ -35,6 +35,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = { | |||
35 | {"8.00.b", 0x13}, | 35 | {"8.00.b", 0x13}, |
36 | {"8.10.a", 0x14}, | 36 | {"8.10.a", 0x14}, |
37 | {"8.20.a", 0x15}, | 37 | {"8.20.a", 0x15}, |
38 | {"8.20.b", 0x16}, | ||
39 | {"8.30.a", 0x17}, | ||
38 | {NULL, 0}, | 40 | {NULL, 0}, |
39 | }; | 41 | }; |
40 | 42 | ||
diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c index 488c1ed24e38..3a749d5e71fd 100644 --- a/arch/microblaze/kernel/cpu/pvr.c +++ b/arch/microblaze/kernel/cpu/pvr.c | |||
@@ -12,7 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/compiler.h> | 14 | #include <linux/compiler.h> |
15 | #include <asm/system.h> | ||
16 | #include <asm/exceptions.h> | 15 | #include <asm/exceptions.h> |
17 | #include <asm/pvr.h> | 16 | #include <asm/pvr.h> |
18 | 17 | ||
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c index 8356e47631c4..aba1f9a97d5d 100644 --- a/arch/microblaze/kernel/early_printk.c +++ b/arch/microblaze/kernel/early_printk.c | |||
@@ -171,10 +171,26 @@ void __init remap_early_printk(void) | |||
171 | { | 171 | { |
172 | if (!early_console_initialized || !early_console) | 172 | if (!early_console_initialized || !early_console) |
173 | return; | 173 | return; |
174 | printk(KERN_INFO "early_printk_console remaping from 0x%x to ", | 174 | printk(KERN_INFO "early_printk_console remapping from 0x%x to ", |
175 | base_addr); | 175 | base_addr); |
176 | base_addr = (u32) ioremap(base_addr, PAGE_SIZE); | 176 | base_addr = (u32) ioremap(base_addr, PAGE_SIZE); |
177 | printk(KERN_CONT "0x%x\n", base_addr); | 177 | printk(KERN_CONT "0x%x\n", base_addr); |
178 | |||
179 | #ifdef CONFIG_MMU | ||
180 | /* | ||
181 | * Early console is on the top of skipped TLB entries | ||
182 | * decrease tlb_skip size ensure that hardcoded TLB entry will be | ||
183 | * used by generic algorithm | ||
184 | * FIXME check if early console mapping is on the top by rereading | ||
185 | * TLB entry and compare baseaddr | ||
186 | * mts rtlbx, (tlb_skip - 1) | ||
187 | * nop | ||
188 | * mfs rX, rtlblo | ||
189 | * nop | ||
190 | * cmp rX, orig_base_addr | ||
191 | */ | ||
192 | tlb_skip -= 1; | ||
193 | #endif | ||
178 | } | 194 | } |
179 | 195 | ||
180 | void __init disable_early_printk(void) | 196 | void __init disable_early_printk(void) |
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index 77320b8fc16a..98b17f9f904b 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S | |||
@@ -63,9 +63,7 @@ ENTRY(_start) | |||
63 | real_start: | 63 | real_start: |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | mfs r1, rmsr | 66 | mts rmsr, r0 |
67 | andi r1, r1, ~2 | ||
68 | mts rmsr, r1 | ||
69 | /* | 67 | /* |
70 | * According to Xilinx, msrclr instruction behaves like 'mfs rX,rpc' | 68 | * According to Xilinx, msrclr instruction behaves like 'mfs rX,rpc' |
71 | * if the msrclr instruction is not enabled. We use this to detect | 69 | * if the msrclr instruction is not enabled. We use this to detect |
@@ -73,6 +71,7 @@ real_start: | |||
73 | * r8 == 0 - msr instructions are implemented | 71 | * r8 == 0 - msr instructions are implemented |
74 | * r8 != 0 - msr instructions are not implemented | 72 | * r8 != 0 - msr instructions are not implemented |
75 | */ | 73 | */ |
74 | mfs r1, rmsr | ||
76 | msrclr r8, 0 /* clear nothing - just read msr for test */ | 75 | msrclr r8, 0 /* clear nothing - just read msr for test */ |
77 | cmpu r8, r8, r1 /* r1 must contain msr reg content */ | 76 | cmpu r8, r8, r1 /* r1 must contain msr reg content */ |
78 | 77 | ||
@@ -96,7 +95,7 @@ big_endian: | |||
96 | _prepare_copy_fdt: | 95 | _prepare_copy_fdt: |
97 | or r11, r0, r0 /* incremment */ | 96 | or r11, r0, r0 /* incremment */ |
98 | ori r4, r0, TOPHYS(_fdt_start) | 97 | ori r4, r0, TOPHYS(_fdt_start) |
99 | ori r3, r0, (0x4000 - 4) | 98 | ori r3, r0, (0x8000 - 4) |
100 | _copy_fdt: | 99 | _copy_fdt: |
101 | lw r12, r7, r11 /* r12 = r7 + r11 */ | 100 | lw r12, r7, r11 /* r12 = r7 + r11 */ |
102 | sw r12, r4, r11 /* addr[r4 + r11] = r12 */ | 101 | sw r12, r4, r11 /* addr[r4 + r11] = r12 */ |
@@ -150,6 +149,7 @@ _copy_bram: | |||
150 | _invalidate: | 149 | _invalidate: |
151 | mts rtlbx, r3 | 150 | mts rtlbx, r3 |
152 | mts rtlbhi, r0 /* flush: ensure V is clear */ | 151 | mts rtlbhi, r0 /* flush: ensure V is clear */ |
152 | mts rtlblo, r0 | ||
153 | bgtid r3, _invalidate /* loop for all entries */ | 153 | bgtid r3, _invalidate /* loop for all entries */ |
154 | addik r3, r3, -1 | 154 | addik r3, r3, -1 |
155 | /* sync */ | 155 | /* sync */ |
@@ -169,6 +169,53 @@ _invalidate: | |||
169 | addik r3,r0, CONFIG_KERNEL_START /* Load the kernel virtual address */ | 169 | addik r3,r0, CONFIG_KERNEL_START /* Load the kernel virtual address */ |
170 | tophys(r4,r3) /* Load the kernel physical address */ | 170 | tophys(r4,r3) /* Load the kernel physical address */ |
171 | 171 | ||
172 | /* start to do TLB calculation */ | ||
173 | addik r12, r0, _end | ||
174 | rsub r12, r3, r12 | ||
175 | addik r12, r12, CONFIG_KERNEL_PAD /* that's the pad */ | ||
176 | |||
177 | or r9, r0, r0 /* TLB0 = 0 */ | ||
178 | or r10, r0, r0 /* TLB1 = 0 */ | ||
179 | |||
180 | addik r11, r12, -0x1000000 | ||
181 | bgei r11, GT16 /* size is greater than 16MB */ | ||
182 | addik r11, r12, -0x0800000 | ||
183 | bgei r11, GT8 /* size is greater than 8MB */ | ||
184 | addik r11, r12, -0x0400000 | ||
185 | bgei r11, GT4 /* size is greater than 4MB */ | ||
186 | /* size is less than 4MB */ | ||
187 | addik r11, r12, -0x0200000 | ||
188 | bgei r11, GT2 /* size is greater than 2MB */ | ||
189 | addik r9, r0, 0x0100000 /* TLB0 must be 1MB */ | ||
190 | addik r11, r12, -0x0100000 | ||
191 | bgei r11, GT1 /* size is greater than 1MB */ | ||
192 | /* TLB1 is 0 which is setup above */ | ||
193 | bri tlb_end | ||
194 | GT4: /* r11 contains the rest - will be either 1 or 4 */ | ||
195 | ori r9, r0, 0x400000 /* TLB0 is 4MB */ | ||
196 | bri TLB1 | ||
197 | GT16: /* TLB0 is 16MB */ | ||
198 | addik r9, r0, 0x1000000 /* means TLB0 is 16MB */ | ||
199 | TLB1: | ||
200 | /* must be used r2 because of substract if failed */ | ||
201 | addik r2, r11, -0x0400000 | ||
202 | bgei r2, GT20 /* size is greater than 16MB */ | ||
203 | /* size is >16MB and <20MB */ | ||
204 | addik r11, r11, -0x0100000 | ||
205 | bgei r11, GT17 /* size is greater than 17MB */ | ||
206 | /* kernel is >16MB and < 17MB */ | ||
207 | GT1: | ||
208 | addik r10, r0, 0x0100000 /* means TLB1 is 1MB */ | ||
209 | bri tlb_end | ||
210 | GT2: /* TLB0 is 0 and TLB1 will be 4MB */ | ||
211 | GT17: /* TLB1 is 4MB - kernel size <20MB */ | ||
212 | addik r10, r0, 0x0400000 /* means TLB1 is 4MB */ | ||
213 | bri tlb_end | ||
214 | GT8: /* TLB0 is still zero that's why I can use only TLB1 */ | ||
215 | GT20: /* TLB1 is 16MB - kernel size >20MB */ | ||
216 | addik r10, r0, 0x1000000 /* means TLB1 is 16MB */ | ||
217 | tlb_end: | ||
218 | |||
172 | /* | 219 | /* |
173 | * Configure and load two entries into TLB slots 0 and 1. | 220 | * Configure and load two entries into TLB slots 0 and 1. |
174 | * In case we are pinning TLBs, these are reserved in by the | 221 | * In case we are pinning TLBs, these are reserved in by the |
@@ -178,28 +225,81 @@ _invalidate: | |||
178 | andi r4,r4,0xfffffc00 /* Mask off the real page number */ | 225 | andi r4,r4,0xfffffc00 /* Mask off the real page number */ |
179 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ | 226 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ |
180 | 227 | ||
228 | /* | ||
229 | * TLB0 is always used - check if is not zero (r9 stores TLB0 value) | ||
230 | * if is use TLB1 value and clear it (r10 stores TLB1 value) | ||
231 | */ | ||
232 | bnei r9, tlb0_not_zero | ||
233 | add r9, r10, r0 | ||
234 | add r10, r0, r0 | ||
235 | tlb0_not_zero: | ||
236 | |||
237 | /* look at the code below */ | ||
238 | ori r30, r0, 0x200 | ||
239 | andi r29, r9, 0x100000 | ||
240 | bneid r29, 1f | ||
241 | addik r30, r30, 0x80 | ||
242 | andi r29, r9, 0x400000 | ||
243 | bneid r29, 1f | ||
244 | addik r30, r30, 0x80 | ||
245 | andi r29, r9, 0x1000000 | ||
246 | bneid r29, 1f | ||
247 | addik r30, r30, 0x80 | ||
248 | 1: | ||
181 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ | 249 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ |
182 | ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M)) | 250 | ori r3,r3,(TLB_VALID) |
251 | or r3, r3, r30 | ||
183 | 252 | ||
184 | mts rtlbx,r0 /* TLB slow 0 */ | 253 | /* Load tlb_skip size value which is index to first unused TLB entry */ |
254 | lwi r11, r0, TOPHYS(tlb_skip) | ||
255 | mts rtlbx,r11 /* TLB slow 0 */ | ||
185 | 256 | ||
186 | mts rtlblo,r4 /* Load the data portion of the entry */ | 257 | mts rtlblo,r4 /* Load the data portion of the entry */ |
187 | mts rtlbhi,r3 /* Load the tag portion of the entry */ | 258 | mts rtlbhi,r3 /* Load the tag portion of the entry */ |
188 | 259 | ||
189 | addik r4, r4, 0x01000000 /* Map next 16 M entries */ | 260 | /* Increase tlb_skip size */ |
190 | addik r3, r3, 0x01000000 | 261 | addik r11, r11, 1 |
262 | swi r11, r0, TOPHYS(tlb_skip) | ||
263 | |||
264 | /* TLB1 can be zeroes that's why we not setup it */ | ||
265 | beqi r10, jump_over2 | ||
266 | |||
267 | /* look at the code below */ | ||
268 | ori r30, r0, 0x200 | ||
269 | andi r29, r10, 0x100000 | ||
270 | bneid r29, 1f | ||
271 | addik r30, r30, 0x80 | ||
272 | andi r29, r10, 0x400000 | ||
273 | bneid r29, 1f | ||
274 | addik r30, r30, 0x80 | ||
275 | andi r29, r10, 0x1000000 | ||
276 | bneid r29, 1f | ||
277 | addik r30, r30, 0x80 | ||
278 | 1: | ||
279 | addk r4, r4, r9 /* previous addr + TLB0 size */ | ||
280 | addk r3, r3, r9 | ||
191 | 281 | ||
192 | ori r6,r0,1 /* TLB slot 1 */ | 282 | andi r3,r3,0xfffffc00 /* Mask off the effective page number */ |
193 | mts rtlbx,r6 | 283 | ori r3,r3,(TLB_VALID) |
284 | or r3, r3, r30 | ||
285 | |||
286 | lwi r11, r0, TOPHYS(tlb_skip) | ||
287 | mts rtlbx, r11 /* r11 is used from TLB0 */ | ||
194 | 288 | ||
195 | mts rtlblo,r4 /* Load the data portion of the entry */ | 289 | mts rtlblo,r4 /* Load the data portion of the entry */ |
196 | mts rtlbhi,r3 /* Load the tag portion of the entry */ | 290 | mts rtlbhi,r3 /* Load the tag portion of the entry */ |
197 | 291 | ||
292 | /* Increase tlb_skip size */ | ||
293 | addik r11, r11, 1 | ||
294 | swi r11, r0, TOPHYS(tlb_skip) | ||
295 | |||
296 | jump_over2: | ||
198 | /* | 297 | /* |
199 | * Load a TLB entry for LMB, since we need access to | 298 | * Load a TLB entry for LMB, since we need access to |
200 | * the exception vectors, using a 4k real==virtual mapping. | 299 | * the exception vectors, using a 4k real==virtual mapping. |
201 | */ | 300 | */ |
202 | ori r6,r0,3 /* TLB slot 3 */ | 301 | /* Use temporary TLB_ID for LMB - clear this temporary mapping later */ |
302 | ori r6, r0, MICROBLAZE_LMB_TLB_ID | ||
203 | mts rtlbx,r6 | 303 | mts rtlbx,r6 |
204 | 304 | ||
205 | ori r4,r0,(TLB_WR | TLB_EX) | 305 | ori r4,r0,(TLB_WR | TLB_EX) |
@@ -238,8 +338,8 @@ start_here: | |||
238 | * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for | 338 | * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for |
239 | * the function. | 339 | * the function. |
240 | */ | 340 | */ |
241 | addik r9, r0, machine_early_init | 341 | addik r11, r0, machine_early_init |
242 | brald r15, r9 | 342 | brald r15, r11 |
243 | nop | 343 | nop |
244 | 344 | ||
245 | #ifndef CONFIG_MMU | 345 | #ifndef CONFIG_MMU |
@@ -268,8 +368,7 @@ start_here: | |||
268 | 368 | ||
269 | /* Load up the kernel context */ | 369 | /* Load up the kernel context */ |
270 | kernel_load_context: | 370 | kernel_load_context: |
271 | # Keep entry 0 and 1 valid. Entry 3 mapped to LMB can go away. | 371 | ori r5, r0, MICROBLAZE_LMB_TLB_ID |
272 | ori r5,r0,3 | ||
273 | mts rtlbx,r5 | 372 | mts rtlbx,r5 |
274 | nop | 373 | nop |
275 | mts rtlbhi,r0 | 374 | mts rtlbhi,r0 |
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S index e62be8379604..aa510f450ac6 100644 --- a/arch/microblaze/kernel/hw_exception_handler.S +++ b/arch/microblaze/kernel/hw_exception_handler.S | |||
@@ -820,19 +820,26 @@ ex_handler_done: | |||
820 | * Upon exit, we reload everything and RFI. | 820 | * Upon exit, we reload everything and RFI. |
821 | * A common place to load the TLB. | 821 | * A common place to load the TLB. |
822 | */ | 822 | */ |
823 | .section .data | ||
824 | .align 4 | ||
825 | .global tlb_skip | ||
826 | tlb_skip: | ||
827 | .long MICROBLAZE_TLB_SKIP | ||
823 | tlb_index: | 828 | tlb_index: |
824 | .long 1 /* MS: storing last used tlb index */ | 829 | /* MS: storing last used tlb index */ |
830 | .long MICROBLAZE_TLB_SIZE/2 | ||
831 | .previous | ||
825 | finish_tlb_load: | 832 | finish_tlb_load: |
826 | /* MS: load the last used TLB index. */ | 833 | /* MS: load the last used TLB index. */ |
827 | lwi r5, r0, TOPHYS(tlb_index) | 834 | lwi r5, r0, TOPHYS(tlb_index) |
828 | addik r5, r5, 1 /* MS: inc tlb_index -> use next one */ | 835 | addik r5, r5, 1 /* MS: inc tlb_index -> use next one */ |
829 | 836 | ||
830 | /* MS: FIXME this is potential fault, because this is mask not count */ | 837 | /* MS: FIXME this is potential fault, because this is mask not count */ |
831 | andi r5, r5, (MICROBLAZE_TLB_SIZE-1) | 838 | andi r5, r5, MICROBLAZE_TLB_SIZE - 1 |
832 | ori r6, r0, 1 | 839 | ori r6, r0, 1 |
833 | cmp r31, r5, r6 | 840 | cmp r31, r5, r6 |
834 | blti r31, ex12 | 841 | blti r31, ex12 |
835 | addik r5, r6, 1 | 842 | lwi r5, r0, TOPHYS(tlb_skip) |
836 | ex12: | 843 | ex12: |
837 | /* MS: save back current TLB index */ | 844 | /* MS: save back current TLB index */ |
838 | swi r5, r0, TOPHYS(tlb_index) | 845 | swi r5, r0, TOPHYS(tlb_index) |
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 44b177e2ab12..6c54d4dcdec3 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/irqdomain.h> | ||
12 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
13 | #include <asm/page.h> | 14 | #include <asm/page.h> |
14 | #include <linux/io.h> | 15 | #include <linux/io.h> |
@@ -25,8 +26,6 @@ static unsigned int intc_baseaddr; | |||
25 | #define INTC_BASE intc_baseaddr | 26 | #define INTC_BASE intc_baseaddr |
26 | #endif | 27 | #endif |
27 | 28 | ||
28 | unsigned int nr_irq; | ||
29 | |||
30 | /* No one else should require these constants, so define them locally here. */ | 29 | /* No one else should require these constants, so define them locally here. */ |
31 | #define ISR 0x00 /* Interrupt Status Register */ | 30 | #define ISR 0x00 /* Interrupt Status Register */ |
32 | #define IPR 0x04 /* Interrupt Pending Register */ | 31 | #define IPR 0x04 /* Interrupt Pending Register */ |
@@ -84,24 +83,45 @@ static struct irq_chip intc_dev = { | |||
84 | .irq_mask_ack = intc_mask_ack, | 83 | .irq_mask_ack = intc_mask_ack, |
85 | }; | 84 | }; |
86 | 85 | ||
87 | unsigned int get_irq(struct pt_regs *regs) | 86 | static struct irq_domain *root_domain; |
87 | |||
88 | unsigned int get_irq(void) | ||
88 | { | 89 | { |
89 | int irq; | 90 | unsigned int hwirq, irq = -1; |
90 | 91 | ||
91 | /* | 92 | hwirq = in_be32(INTC_BASE + IVR); |
92 | * NOTE: This function is the one that needs to be improved in | 93 | if (hwirq != -1U) |
93 | * order to handle multiple interrupt controllers. It currently | 94 | irq = irq_find_mapping(root_domain, hwirq); |
94 | * is hardcoded to check for interrupts only on the first INTC. | 95 | |
95 | */ | 96 | pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq); |
96 | irq = in_be32(INTC_BASE + IVR) + NO_IRQ_OFFSET; | ||
97 | pr_debug("get_irq: %d\n", irq); | ||
98 | 97 | ||
99 | return irq; | 98 | return irq; |
100 | } | 99 | } |
101 | 100 | ||
101 | int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | ||
102 | { | ||
103 | u32 intr_mask = (u32)d->host_data; | ||
104 | |||
105 | if (intr_mask & (1 << hw)) { | ||
106 | irq_set_chip_and_handler_name(irq, &intc_dev, | ||
107 | handle_edge_irq, "edge"); | ||
108 | irq_clear_status_flags(irq, IRQ_LEVEL); | ||
109 | } else { | ||
110 | irq_set_chip_and_handler_name(irq, &intc_dev, | ||
111 | handle_level_irq, "level"); | ||
112 | irq_set_status_flags(irq, IRQ_LEVEL); | ||
113 | } | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static const struct irq_domain_ops xintc_irq_domain_ops = { | ||
118 | .xlate = irq_domain_xlate_onetwocell, | ||
119 | .map = xintc_map, | ||
120 | }; | ||
121 | |||
102 | void __init init_IRQ(void) | 122 | void __init init_IRQ(void) |
103 | { | 123 | { |
104 | u32 i, intr_mask; | 124 | u32 nr_irq, intr_mask; |
105 | struct device_node *intc = NULL; | 125 | struct device_node *intc = NULL; |
106 | #ifdef CONFIG_SELFMOD_INTC | 126 | #ifdef CONFIG_SELFMOD_INTC |
107 | unsigned int intc_baseaddr = 0; | 127 | unsigned int intc_baseaddr = 0; |
@@ -131,8 +151,8 @@ void __init init_IRQ(void) | |||
131 | #ifdef CONFIG_SELFMOD_INTC | 151 | #ifdef CONFIG_SELFMOD_INTC |
132 | selfmod_function((int *) arr_func, intc_baseaddr); | 152 | selfmod_function((int *) arr_func, intc_baseaddr); |
133 | #endif | 153 | #endif |
134 | printk(KERN_INFO "XPS intc #0 at 0x%08x, num_irq=%d, edge=0x%x\n", | 154 | printk(KERN_INFO "%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n", |
135 | intc_baseaddr, nr_irq, intr_mask); | 155 | intc->name, intc_baseaddr, nr_irq, intr_mask); |
136 | 156 | ||
137 | /* | 157 | /* |
138 | * Disable all external interrupts until they are | 158 | * Disable all external interrupts until they are |
@@ -146,16 +166,9 @@ void __init init_IRQ(void) | |||
146 | /* Turn on the Master Enable. */ | 166 | /* Turn on the Master Enable. */ |
147 | out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); | 167 | out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); |
148 | 168 | ||
149 | for (i = IRQ_OFFSET; i < (nr_irq + IRQ_OFFSET); ++i) { | 169 | /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm |
150 | if (intr_mask & (0x00000001 << (i - IRQ_OFFSET))) { | 170 | * lazy and Michal can clean it up to something nicer when he tests |
151 | irq_set_chip_and_handler_name(i, &intc_dev, | 171 | * and commits this patch. ~~gcl */ |
152 | handle_edge_irq, "edge"); | 172 | root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, |
153 | irq_clear_status_flags(i, IRQ_LEVEL); | 173 | (void *)intr_mask); |
154 | } else { | ||
155 | irq_set_chip_and_handler_name(i, &intc_dev, | ||
156 | handle_level_irq, "level"); | ||
157 | irq_set_status_flags(i, IRQ_LEVEL); | ||
158 | } | ||
159 | irq_get_irq_data(i)->hwirq = i - IRQ_OFFSET; | ||
160 | } | ||
161 | } | 174 | } |
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index bbebcae72c02..ace700afbfdf 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c | |||
@@ -31,14 +31,13 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
31 | trace_hardirqs_off(); | 31 | trace_hardirqs_off(); |
32 | 32 | ||
33 | irq_enter(); | 33 | irq_enter(); |
34 | irq = get_irq(regs); | 34 | irq = get_irq(); |
35 | next_irq: | 35 | next_irq: |
36 | BUG_ON(!irq); | 36 | BUG_ON(!irq); |
37 | /* Substract 1 because of get_irq */ | 37 | generic_handle_irq(irq); |
38 | generic_handle_irq(irq + IRQ_OFFSET - NO_IRQ_OFFSET); | ||
39 | 38 | ||
40 | irq = get_irq(regs); | 39 | irq = get_irq(); |
41 | if (irq) { | 40 | if (irq != -1U) { |
42 | pr_debug("next irq: %d\n", irq); | 41 | pr_debug("next irq: %d\n", irq); |
43 | ++concurrent_irq; | 42 | ++concurrent_irq; |
44 | goto next_irq; | 43 | goto next_irq; |
@@ -48,18 +47,3 @@ next_irq: | |||
48 | set_irq_regs(old_regs); | 47 | set_irq_regs(old_regs); |
49 | trace_hardirqs_on(); | 48 | trace_hardirqs_on(); |
50 | } | 49 | } |
51 | |||
52 | /* MS: There is no any advance mapping mechanism. We are using simple 32bit | ||
53 | intc without any cascades or any connection that's why mapping is 1:1 */ | ||
54 | unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) | ||
55 | { | ||
56 | return hwirq + IRQ_OFFSET; | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(irq_create_mapping); | ||
59 | |||
60 | unsigned int irq_create_of_mapping(struct device_node *controller, | ||
61 | const u32 *intspec, unsigned int intsize) | ||
62 | { | ||
63 | return intspec[0] + IRQ_OFFSET; | ||
64 | } | ||
65 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | ||
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index 49faeb429599..bb4907c828dc 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <asm/page.h> | 20 | #include <asm/page.h> |
21 | #include <asm/system.h> | ||
22 | #include <linux/ftrace.h> | 21 | #include <linux/ftrace.h> |
23 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
24 | 23 | ||
diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S index 206da3da361f..1dafddeb8a0b 100644 --- a/arch/microblaze/kernel/misc.S +++ b/arch/microblaze/kernel/misc.S | |||
@@ -29,16 +29,16 @@ | |||
29 | .type _tlbia, @function | 29 | .type _tlbia, @function |
30 | .align 4; | 30 | .align 4; |
31 | _tlbia: | 31 | _tlbia: |
32 | addik r12, r0, MICROBLAZE_TLB_SIZE - 1 /* flush all entries (63 - 3) */ | 32 | lwi r12, r0, tlb_skip; |
33 | /* isync */ | 33 | /* isync */ |
34 | _tlbia_1: | 34 | _tlbia_1: |
35 | mts rtlbx, r12 | 35 | mts rtlbx, r12 |
36 | nop | 36 | nop |
37 | mts rtlbhi, r0 /* flush: ensure V is clear */ | 37 | mts rtlbhi, r0 /* flush: ensure V is clear */ |
38 | nop | 38 | nop |
39 | addik r11, r12, -2 | 39 | rsubi r11, r12, MICROBLAZE_TLB_SIZE - 1 |
40 | bneid r11, _tlbia_1 /* loop for all entries */ | 40 | bneid r11, _tlbia_1 /* loop for all entries */ |
41 | addik r12, r12, -1 | 41 | addik r12, r12, 1 |
42 | /* sync */ | 42 | /* sync */ |
43 | rtsd r15, 8 | 43 | rtsd r15, 8 |
44 | nop | 44 | nop |
@@ -75,7 +75,7 @@ early_console_reg_tlb_alloc: | |||
75 | * Load a TLB entry for the UART, so that microblaze_progress() can use | 75 | * Load a TLB entry for the UART, so that microblaze_progress() can use |
76 | * the UARTs nice and early. We use a 4k real==virtual mapping. | 76 | * the UARTs nice and early. We use a 4k real==virtual mapping. |
77 | */ | 77 | */ |
78 | ori r4, r0, MICROBLAZE_TLB_SIZE - 1 | 78 | lwi r4, r0, tlb_skip |
79 | mts rtlbx, r4 /* TLB slot 63 */ | 79 | mts rtlbx, r4 /* TLB slot 63 */ |
80 | 80 | ||
81 | or r4,r5,r0 | 81 | or r4,r5,r0 |
@@ -89,6 +89,11 @@ early_console_reg_tlb_alloc: | |||
89 | nop | 89 | nop |
90 | mts rtlbhi,r5 /* Load the tag portion of the entry */ | 90 | mts rtlbhi,r5 /* Load the tag portion of the entry */ |
91 | nop | 91 | nop |
92 | |||
93 | lwi r5, r0, tlb_skip | ||
94 | addik r5, r5, 1 | ||
95 | swi r5, r0, tlb_skip | ||
96 | |||
92 | rtsd r15, 8 | 97 | rtsd r15, 8 |
93 | nop | 98 | nop |
94 | 99 | ||
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 7dcb5bfffb75..883b92789cdf 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/pm.h> | 13 | #include <linux/pm.h> |
14 | #include <linux/tick.h> | 14 | #include <linux/tick.h> |
15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
16 | #include <asm/system.h> | ||
17 | #include <asm/pgalloc.h> | 16 | #include <asm/pgalloc.h> |
18 | #include <asm/uaccess.h> /* for USER_DS macros */ | 17 | #include <asm/uaccess.h> /* for USER_DS macros */ |
19 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
@@ -110,9 +109,7 @@ void cpu_idle(void) | |||
110 | rcu_idle_exit(); | 109 | rcu_idle_exit(); |
111 | tick_nohz_idle_exit(); | 110 | tick_nohz_idle_exit(); |
112 | 111 | ||
113 | preempt_enable_no_resched(); | 112 | schedule_preempt_disabled(); |
114 | schedule(); | ||
115 | preempt_disable(); | ||
116 | check_pgt_cache(); | 113 | check_pgt_cache(); |
117 | } | 114 | } |
118 | } | 115 | } |
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index 80d314e81901..4a764ccb9f26 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <asm/processor.h> | 36 | #include <asm/processor.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <linux/io.h> | 38 | #include <linux/io.h> |
39 | #include <asm/system.h> | ||
40 | #include <asm/mmu.h> | 39 | #include <asm/mmu.h> |
41 | #include <asm/pgtable.h> | 40 | #include <asm/pgtable.h> |
42 | #include <asm/sections.h> | 41 | #include <asm/sections.h> |
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 604cd9dd1333..16d8dfd9094b 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/entry.h> | 30 | #include <asm/entry.h> |
31 | #include <asm/cpuinfo.h> | 31 | #include <asm/cpuinfo.h> |
32 | 32 | ||
33 | #include <asm/system.h> | ||
34 | #include <asm/prom.h> | 33 | #include <asm/prom.h> |
35 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
36 | 35 | ||
@@ -51,8 +50,6 @@ void __init setup_arch(char **cmdline_p) | |||
51 | 50 | ||
52 | unflatten_device_tree(); | 51 | unflatten_device_tree(); |
53 | 52 | ||
54 | /* NOTE I think that this function is not necessary to call */ | ||
55 | /* irq_early_init(); */ | ||
56 | setup_cpuinfo(); | 53 | setup_cpuinfo(); |
57 | 54 | ||
58 | microblaze_cache_init(); | 55 | microblaze_cache_init(); |
@@ -97,8 +94,11 @@ inline unsigned get_romfs_len(unsigned *addr) | |||
97 | } | 94 | } |
98 | #endif /* CONFIG_MTD_UCLINUX_EBSS */ | 95 | #endif /* CONFIG_MTD_UCLINUX_EBSS */ |
99 | 96 | ||
97 | unsigned long kernel_tlb; | ||
98 | |||
100 | void __init machine_early_init(const char *cmdline, unsigned int ram, | 99 | void __init machine_early_init(const char *cmdline, unsigned int ram, |
101 | unsigned int fdt, unsigned int msr) | 100 | unsigned int fdt, unsigned int msr, unsigned int tlb0, |
101 | unsigned int tlb1) | ||
102 | { | 102 | { |
103 | unsigned long *src, *dst; | 103 | unsigned long *src, *dst; |
104 | unsigned int offset = 0; | 104 | unsigned int offset = 0; |
@@ -145,6 +145,12 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, | |||
145 | setup_early_printk(NULL); | 145 | setup_early_printk(NULL); |
146 | #endif | 146 | #endif |
147 | 147 | ||
148 | /* setup kernel_tlb after BSS cleaning | ||
149 | * Maybe worth to move to asm code */ | ||
150 | kernel_tlb = tlb0 + tlb1; | ||
151 | /* printk("TLB1 0x%08x, TLB0 0x%08x, tlb 0x%x\n", tlb0, | ||
152 | tlb1, kernel_tlb); */ | ||
153 | |||
148 | printk("Ramdisk addr 0x%08x, ", ram); | 154 | printk("Ramdisk addr 0x%08x, ", ram); |
149 | if (fdt) | 155 | if (fdt) |
150 | printk("FDT at 0x%08x\n", fdt); | 156 | printk("FDT at 0x%08x\n", fdt); |
@@ -199,6 +205,21 @@ static int microblaze_debugfs_init(void) | |||
199 | return of_debugfs_root == NULL; | 205 | return of_debugfs_root == NULL; |
200 | } | 206 | } |
201 | arch_initcall(microblaze_debugfs_init); | 207 | arch_initcall(microblaze_debugfs_init); |
208 | |||
209 | # ifdef CONFIG_MMU | ||
210 | static int __init debugfs_tlb(void) | ||
211 | { | ||
212 | struct dentry *d; | ||
213 | |||
214 | if (!of_debugfs_root) | ||
215 | return -ENODEV; | ||
216 | |||
217 | d = debugfs_create_u32("tlb_skip", S_IRUGO, of_debugfs_root, &tlb_skip); | ||
218 | if (!d) | ||
219 | return -ENOMEM; | ||
220 | } | ||
221 | device_initcall(debugfs_tlb); | ||
222 | # endif | ||
202 | #endif | 223 | #endif |
203 | 224 | ||
204 | static int dflt_bus_notify(struct notifier_block *nb, | 225 | static int dflt_bus_notify(struct notifier_block *nb, |
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 3cb0bf640135..522defa7d41f 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
28 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
29 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
30 | #include <asm/system.h> | ||
31 | #include <linux/cnt32_to_63.h> | 30 | #include <linux/cnt32_to_63.h> |
32 | 31 | ||
33 | #ifdef CONFIG_SELFMOD_TIMER | 32 | #ifdef CONFIG_SELFMOD_TIMER |
@@ -79,7 +78,7 @@ static inline void microblaze_timer0_start_periodic(unsigned long load_val) | |||
79 | * !PWMA - disable pwm | 78 | * !PWMA - disable pwm |
80 | * TINT - clear interrupt status | 79 | * TINT - clear interrupt status |
81 | * ENT- enable timer itself | 80 | * ENT- enable timer itself |
82 | * EINT - enable interrupt | 81 | * ENIT - enable interrupt |
83 | * !LOAD - clear the bit to let go | 82 | * !LOAD - clear the bit to let go |
84 | * ARHT - auto reload | 83 | * ARHT - auto reload |
85 | * !CAPT - no external trigger | 84 | * !CAPT - no external trigger |
@@ -274,8 +273,8 @@ void __init time_init(void) | |||
274 | #ifdef CONFIG_SELFMOD_TIMER | 273 | #ifdef CONFIG_SELFMOD_TIMER |
275 | selfmod_function((int *) arr_func, timer_baseaddr); | 274 | selfmod_function((int *) arr_func, timer_baseaddr); |
276 | #endif | 275 | #endif |
277 | printk(KERN_INFO "XPS timer #0 at 0x%08x, irq=%d\n", | 276 | printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n", |
278 | timer_baseaddr, irq); | 277 | timer->name, timer_baseaddr, irq); |
279 | 278 | ||
280 | /* If there is clock-frequency property than use it */ | 279 | /* If there is clock-frequency property than use it */ |
281 | prop = of_get_property(timer, "clock-frequency", NULL); | 280 | prop = of_get_property(timer, "clock-frequency", NULL); |
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c index ba034d421ec2..5541ac559593 100644 --- a/arch/microblaze/kernel/traps.c +++ b/arch/microblaze/kernel/traps.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/debug_locks.h> | 15 | #include <linux/debug_locks.h> |
16 | 16 | ||
17 | #include <asm/exceptions.h> | 17 | #include <asm/exceptions.h> |
18 | #include <asm/system.h> | ||
19 | #include <asm/unwind.h> | 18 | #include <asm/unwind.h> |
20 | 19 | ||
21 | void trap_init(void) | 20 | void trap_init(void) |
diff --git a/arch/microblaze/kernel/unwind.c b/arch/microblaze/kernel/unwind.c index 9781a528cfc9..6be4ae3c3351 100644 --- a/arch/microblaze/kernel/unwind.c +++ b/arch/microblaze/kernel/unwind.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/sections.h> | 24 | #include <asm/sections.h> |
25 | #include <asm/exceptions.h> | 25 | #include <asm/exceptions.h> |
26 | #include <asm/unwind.h> | 26 | #include <asm/unwind.h> |
27 | #include <asm/switch_to.h> | ||
27 | 28 | ||
28 | struct stack_trace; | 29 | struct stack_trace; |
29 | 30 | ||
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index ac0e1a5d4782..109e9d86ade4 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S | |||
@@ -44,7 +44,7 @@ SECTIONS { | |||
44 | __fdt_blob : AT(ADDR(__fdt_blob) - LOAD_OFFSET) { | 44 | __fdt_blob : AT(ADDR(__fdt_blob) - LOAD_OFFSET) { |
45 | _fdt_start = . ; /* place for fdt blob */ | 45 | _fdt_start = . ; /* place for fdt blob */ |
46 | *(__fdt_blob) ; /* Any link-placed DTB */ | 46 | *(__fdt_blob) ; /* Any link-placed DTB */ |
47 | . = _fdt_start + 0x4000; /* Pad up to 16kbyte */ | 47 | . = _fdt_start + 0x8000; /* Pad up to 32kbyte */ |
48 | _fdt_end = . ; | 48 | _fdt_end = . ; |
49 | } | 49 | } |
50 | 50 | ||
diff --git a/arch/microblaze/lib/memcpy.c b/arch/microblaze/lib/memcpy.c index 52746e718dfa..fe9c53fafdea 100644 --- a/arch/microblaze/lib/memcpy.c +++ b/arch/microblaze/lib/memcpy.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | 31 | ||
32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
33 | #include <asm/system.h> | ||
34 | 33 | ||
35 | #ifdef __HAVE_ARCH_MEMCPY | 34 | #ifdef __HAVE_ARCH_MEMCPY |
36 | #ifndef CONFIG_OPT_LIB_FUNCTION | 35 | #ifndef CONFIG_OPT_LIB_FUNCTION |
diff --git a/arch/microblaze/lib/uaccess_old.S b/arch/microblaze/lib/uaccess_old.S index f037266cdaf3..f085995ee848 100644 --- a/arch/microblaze/lib/uaccess_old.S +++ b/arch/microblaze/lib/uaccess_old.S | |||
@@ -122,22 +122,22 @@ __strnlen_user: | |||
122 | 15: swi r24, r5, 0x0018 + offset; \ | 122 | 15: swi r24, r5, 0x0018 + offset; \ |
123 | 16: swi r25, r5, 0x001C + offset; \ | 123 | 16: swi r25, r5, 0x001C + offset; \ |
124 | .section __ex_table,"a"; \ | 124 | .section __ex_table,"a"; \ |
125 | .word 1b, 0f; \ | 125 | .word 1b, 33f; \ |
126 | .word 2b, 0f; \ | 126 | .word 2b, 33f; \ |
127 | .word 3b, 0f; \ | 127 | .word 3b, 33f; \ |
128 | .word 4b, 0f; \ | 128 | .word 4b, 33f; \ |
129 | .word 5b, 0f; \ | 129 | .word 5b, 33f; \ |
130 | .word 6b, 0f; \ | 130 | .word 6b, 33f; \ |
131 | .word 7b, 0f; \ | 131 | .word 7b, 33f; \ |
132 | .word 8b, 0f; \ | 132 | .word 8b, 33f; \ |
133 | .word 9b, 0f; \ | 133 | .word 9b, 33f; \ |
134 | .word 10b, 0f; \ | 134 | .word 10b, 33f; \ |
135 | .word 11b, 0f; \ | 135 | .word 11b, 33f; \ |
136 | .word 12b, 0f; \ | 136 | .word 12b, 33f; \ |
137 | .word 13b, 0f; \ | 137 | .word 13b, 33f; \ |
138 | .word 14b, 0f; \ | 138 | .word 14b, 33f; \ |
139 | .word 15b, 0f; \ | 139 | .word 15b, 33f; \ |
140 | .word 16b, 0f; \ | 140 | .word 16b, 33f; \ |
141 | .text | 141 | .text |
142 | 142 | ||
143 | #define COPY_80(offset) \ | 143 | #define COPY_80(offset) \ |
@@ -190,14 +190,17 @@ w2: sw r4, r5, r3 | |||
190 | 190 | ||
191 | .align 4 /* Alignment is important to keep icache happy */ | 191 | .align 4 /* Alignment is important to keep icache happy */ |
192 | page: /* Create room on stack and save registers for storign values */ | 192 | page: /* Create room on stack and save registers for storign values */ |
193 | addik r1, r1, -32 | 193 | addik r1, r1, -40 |
194 | swi r19, r1, 4 | 194 | swi r5, r1, 0 |
195 | swi r20, r1, 8 | 195 | swi r6, r1, 4 |
196 | swi r21, r1, 12 | 196 | swi r7, r1, 8 |
197 | swi r22, r1, 16 | 197 | swi r19, r1, 12 |
198 | swi r23, r1, 20 | 198 | swi r20, r1, 16 |
199 | swi r24, r1, 24 | 199 | swi r21, r1, 20 |
200 | swi r25, r1, 28 | 200 | swi r22, r1, 24 |
201 | swi r23, r1, 28 | ||
202 | swi r24, r1, 32 | ||
203 | swi r25, r1, 36 | ||
201 | loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */ | 204 | loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */ |
202 | /* Loop unrolling to get performance boost */ | 205 | /* Loop unrolling to get performance boost */ |
203 | COPY_80(0x000); | 206 | COPY_80(0x000); |
@@ -205,21 +208,44 @@ loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */ | |||
205 | COPY_80(0x100); | 208 | COPY_80(0x100); |
206 | COPY_80(0x180); | 209 | COPY_80(0x180); |
207 | /* copy loop */ | 210 | /* copy loop */ |
208 | addik r6, r6, 0x200 | 211 | addik r6, r6, 0x200 |
209 | addik r7, r7, -0x200 | 212 | addik r7, r7, -0x200 |
210 | bneid r7, loop | 213 | bneid r7, loop |
211 | addik r5, r5, 0x200 | 214 | addik r5, r5, 0x200 |
215 | |||
212 | /* Restore register content */ | 216 | /* Restore register content */ |
213 | lwi r19, r1, 4 | 217 | lwi r5, r1, 0 |
214 | lwi r20, r1, 8 | 218 | lwi r6, r1, 4 |
215 | lwi r21, r1, 12 | 219 | lwi r7, r1, 8 |
216 | lwi r22, r1, 16 | 220 | lwi r19, r1, 12 |
217 | lwi r23, r1, 20 | 221 | lwi r20, r1, 16 |
218 | lwi r24, r1, 24 | 222 | lwi r21, r1, 20 |
219 | lwi r25, r1, 28 | 223 | lwi r22, r1, 24 |
220 | addik r1, r1, 32 | 224 | lwi r23, r1, 28 |
225 | lwi r24, r1, 32 | ||
226 | lwi r25, r1, 36 | ||
227 | addik r1, r1, 40 | ||
221 | /* return back */ | 228 | /* return back */ |
229 | addik r3, r0, 0 | ||
230 | rtsd r15, 8 | ||
231 | nop | ||
232 | |||
233 | /* Fault case - return temp count */ | ||
234 | 33: | ||
222 | addik r3, r7, 0 | 235 | addik r3, r7, 0 |
236 | /* Restore register content */ | ||
237 | lwi r5, r1, 0 | ||
238 | lwi r6, r1, 4 | ||
239 | lwi r7, r1, 8 | ||
240 | lwi r19, r1, 12 | ||
241 | lwi r20, r1, 16 | ||
242 | lwi r21, r1, 20 | ||
243 | lwi r22, r1, 24 | ||
244 | lwi r23, r1, 28 | ||
245 | lwi r24, r1, 32 | ||
246 | lwi r25, r1, 36 | ||
247 | addik r1, r1, 40 | ||
248 | /* return back */ | ||
223 | rtsd r15, 8 | 249 | rtsd r15, 8 |
224 | nop | 250 | nop |
225 | 251 | ||
diff --git a/arch/microblaze/mm/Makefile b/arch/microblaze/mm/Makefile index 09c49ed87235..7313bd8acbb7 100644 --- a/arch/microblaze/mm/Makefile +++ b/arch/microblaze/mm/Makefile | |||
@@ -5,3 +5,4 @@ | |||
5 | obj-y := consistent.o init.o | 5 | obj-y := consistent.o init.o |
6 | 6 | ||
7 | obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o | 7 | obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o |
8 | obj-$(CONFIG_HIGHMEM) += highmem.o | ||
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c index ae97d2ccdc22..c38a265846de 100644 --- a/arch/microblaze/mm/fault.c +++ b/arch/microblaze/mm/fault.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
34 | #include <asm/mmu.h> | 34 | #include <asm/mmu.h> |
35 | #include <asm/mmu_context.h> | 35 | #include <asm/mmu_context.h> |
36 | #include <asm/system.h> | ||
37 | #include <linux/uaccess.h> | 36 | #include <linux/uaccess.h> |
38 | #include <asm/exceptions.h> | 37 | #include <asm/exceptions.h> |
39 | 38 | ||
diff --git a/arch/microblaze/mm/highmem.c b/arch/microblaze/mm/highmem.c new file mode 100644 index 000000000000..7d78838e8bfa --- /dev/null +++ b/arch/microblaze/mm/highmem.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * highmem.c: virtual kernel memory mappings for high memory | ||
3 | * | ||
4 | * PowerPC version, stolen from the i386 version. | ||
5 | * | ||
6 | * Used in CONFIG_HIGHMEM systems for memory pages which | ||
7 | * are not addressable by direct kernel virtual addresses. | ||
8 | * | ||
9 | * Copyright (C) 1999 Gerhard Wichert, Siemens AG | ||
10 | * Gerhard.Wichert@pdb.siemens.de | ||
11 | * | ||
12 | * | ||
13 | * Redesigned the x86 32-bit VM architecture to deal with | ||
14 | * up to 16 Terrabyte physical memory. With current x86 CPUs | ||
15 | * we now support up to 64 Gigabytes physical RAM. | ||
16 | * | ||
17 | * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> | ||
18 | * | ||
19 | * Reworked for PowerPC by various contributors. Moved from | ||
20 | * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp. | ||
21 | */ | ||
22 | |||
23 | #include <linux/highmem.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | /* | ||
27 | * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap | ||
28 | * gives a more generic (and caching) interface. But kmap_atomic can | ||
29 | * be used in IRQ contexts, so in some (very limited) cases we need | ||
30 | * it. | ||
31 | */ | ||
32 | #include <asm/tlbflush.h> | ||
33 | |||
34 | void *kmap_atomic_prot(struct page *page, pgprot_t prot) | ||
35 | { | ||
36 | |||
37 | unsigned long vaddr; | ||
38 | int idx, type; | ||
39 | |||
40 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | ||
41 | pagefault_disable(); | ||
42 | if (!PageHighMem(page)) | ||
43 | return page_address(page); | ||
44 | |||
45 | |||
46 | type = kmap_atomic_idx_push(); | ||
47 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
48 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
49 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
50 | BUG_ON(!pte_none(*(kmap_pte-idx))); | ||
51 | #endif | ||
52 | set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot)); | ||
53 | local_flush_tlb_page(NULL, vaddr); | ||
54 | |||
55 | return (void *) vaddr; | ||
56 | } | ||
57 | EXPORT_SYMBOL(kmap_atomic_prot); | ||
58 | |||
59 | void __kunmap_atomic(void *kvaddr) | ||
60 | { | ||
61 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | ||
62 | int type; | ||
63 | |||
64 | if (vaddr < __fix_to_virt(FIX_KMAP_END)) { | ||
65 | pagefault_enable(); | ||
66 | return; | ||
67 | } | ||
68 | |||
69 | type = kmap_atomic_idx(); | ||
70 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
71 | { | ||
72 | unsigned int idx; | ||
73 | |||
74 | idx = type + KM_TYPE_NR * smp_processor_id(); | ||
75 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | ||
76 | |||
77 | /* | ||
78 | * force other mappings to Oops if they'll try to access | ||
79 | * this pte without first remap it | ||
80 | */ | ||
81 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | ||
82 | local_flush_tlb_page(NULL, vaddr); | ||
83 | } | ||
84 | #endif | ||
85 | kmap_atomic_idx_pop(); | ||
86 | pagefault_enable(); | ||
87 | } | ||
88 | EXPORT_SYMBOL(__kunmap_atomic); | ||
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 565d193c7ebf..ce80823051ba 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/pgalloc.h> | 24 | #include <asm/pgalloc.h> |
25 | #include <asm/sections.h> | 25 | #include <asm/sections.h> |
26 | #include <asm/tlb.h> | 26 | #include <asm/tlb.h> |
27 | #include <asm/fixmap.h> | ||
27 | 28 | ||
28 | /* Use for MMU and noMMU because of PCI generic code */ | 29 | /* Use for MMU and noMMU because of PCI generic code */ |
29 | int mem_init_done; | 30 | int mem_init_done; |
@@ -44,9 +45,56 @@ char *klimit = _end; | |||
44 | */ | 45 | */ |
45 | unsigned long memory_start; | 46 | unsigned long memory_start; |
46 | EXPORT_SYMBOL(memory_start); | 47 | EXPORT_SYMBOL(memory_start); |
47 | unsigned long memory_end; /* due to mm/nommu.c */ | ||
48 | unsigned long memory_size; | 48 | unsigned long memory_size; |
49 | EXPORT_SYMBOL(memory_size); | 49 | EXPORT_SYMBOL(memory_size); |
50 | unsigned long lowmem_size; | ||
51 | |||
52 | #ifdef CONFIG_HIGHMEM | ||
53 | pte_t *kmap_pte; | ||
54 | EXPORT_SYMBOL(kmap_pte); | ||
55 | pgprot_t kmap_prot; | ||
56 | EXPORT_SYMBOL(kmap_prot); | ||
57 | |||
58 | static inline pte_t *virt_to_kpte(unsigned long vaddr) | ||
59 | { | ||
60 | return pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), | ||
61 | vaddr), vaddr); | ||
62 | } | ||
63 | |||
64 | static void __init highmem_init(void) | ||
65 | { | ||
66 | pr_debug("%x\n", (u32)PKMAP_BASE); | ||
67 | map_page(PKMAP_BASE, 0, 0); /* XXX gross */ | ||
68 | pkmap_page_table = virt_to_kpte(PKMAP_BASE); | ||
69 | |||
70 | kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); | ||
71 | kmap_prot = PAGE_KERNEL; | ||
72 | } | ||
73 | |||
74 | static unsigned long highmem_setup(void) | ||
75 | { | ||
76 | unsigned long pfn; | ||
77 | unsigned long reservedpages = 0; | ||
78 | |||
79 | for (pfn = max_low_pfn; pfn < max_pfn; ++pfn) { | ||
80 | struct page *page = pfn_to_page(pfn); | ||
81 | |||
82 | /* FIXME not sure about */ | ||
83 | if (memblock_is_reserved(pfn << PAGE_SHIFT)) | ||
84 | continue; | ||
85 | ClearPageReserved(page); | ||
86 | init_page_count(page); | ||
87 | __free_page(page); | ||
88 | totalhigh_pages++; | ||
89 | reservedpages++; | ||
90 | } | ||
91 | totalram_pages += totalhigh_pages; | ||
92 | printk(KERN_INFO "High memory: %luk\n", | ||
93 | totalhigh_pages << (PAGE_SHIFT-10)); | ||
94 | |||
95 | return reservedpages; | ||
96 | } | ||
97 | #endif /* CONFIG_HIGHMEM */ | ||
50 | 98 | ||
51 | /* | 99 | /* |
52 | * paging_init() sets up the page tables - in fact we've already done this. | 100 | * paging_init() sets up the page tables - in fact we've already done this. |
@@ -54,17 +102,28 @@ EXPORT_SYMBOL(memory_size); | |||
54 | static void __init paging_init(void) | 102 | static void __init paging_init(void) |
55 | { | 103 | { |
56 | unsigned long zones_size[MAX_NR_ZONES]; | 104 | unsigned long zones_size[MAX_NR_ZONES]; |
105 | #ifdef CONFIG_MMU | ||
106 | int idx; | ||
107 | |||
108 | /* Setup fixmaps */ | ||
109 | for (idx = 0; idx < __end_of_fixed_addresses; idx++) | ||
110 | clear_fixmap(idx); | ||
111 | #endif | ||
57 | 112 | ||
58 | /* Clean every zones */ | 113 | /* Clean every zones */ |
59 | memset(zones_size, 0, sizeof(zones_size)); | 114 | memset(zones_size, 0, sizeof(zones_size)); |
60 | 115 | ||
61 | /* | 116 | #ifdef CONFIG_HIGHMEM |
62 | * old: we can DMA to/from any address.put all page into ZONE_DMA | 117 | highmem_init(); |
63 | * We use only ZONE_NORMAL | ||
64 | */ | ||
65 | zones_size[ZONE_NORMAL] = max_mapnr; | ||
66 | 118 | ||
67 | free_area_init(zones_size); | 119 | zones_size[ZONE_DMA] = max_low_pfn; |
120 | zones_size[ZONE_HIGHMEM] = max_pfn; | ||
121 | #else | ||
122 | zones_size[ZONE_DMA] = max_pfn; | ||
123 | #endif | ||
124 | |||
125 | /* We don't have holes in memory map */ | ||
126 | free_area_init_nodes(zones_size); | ||
68 | } | 127 | } |
69 | 128 | ||
70 | void __init setup_memory(void) | 129 | void __init setup_memory(void) |
@@ -78,32 +137,31 @@ void __init setup_memory(void) | |||
78 | /* Find main memory where is the kernel */ | 137 | /* Find main memory where is the kernel */ |
79 | for_each_memblock(memory, reg) { | 138 | for_each_memblock(memory, reg) { |
80 | memory_start = (u32)reg->base; | 139 | memory_start = (u32)reg->base; |
81 | memory_end = (u32) reg->base + reg->size; | 140 | lowmem_size = reg->size; |
82 | if ((memory_start <= (u32)_text) && | 141 | if ((memory_start <= (u32)_text) && |
83 | ((u32)_text <= memory_end)) { | 142 | ((u32)_text <= (memory_start + lowmem_size - 1))) { |
84 | memory_size = memory_end - memory_start; | 143 | memory_size = lowmem_size; |
85 | PAGE_OFFSET = memory_start; | 144 | PAGE_OFFSET = memory_start; |
86 | printk(KERN_INFO "%s: Main mem: 0x%x-0x%x, " | 145 | printk(KERN_INFO "%s: Main mem: 0x%x, " |
87 | "size 0x%08x\n", __func__, (u32) memory_start, | 146 | "size 0x%08x\n", __func__, (u32) memory_start, |
88 | (u32) memory_end, (u32) memory_size); | 147 | (u32) memory_size); |
89 | break; | 148 | break; |
90 | } | 149 | } |
91 | } | 150 | } |
92 | 151 | ||
93 | if (!memory_start || !memory_end) { | 152 | if (!memory_start || !memory_size) { |
94 | panic("%s: Missing memory setting 0x%08x-0x%08x\n", | 153 | panic("%s: Missing memory setting 0x%08x, size=0x%08x\n", |
95 | __func__, (u32) memory_start, (u32) memory_end); | 154 | __func__, (u32) memory_start, (u32) memory_size); |
96 | } | 155 | } |
97 | 156 | ||
98 | /* reservation of region where is the kernel */ | 157 | /* reservation of region where is the kernel */ |
99 | kernel_align_start = PAGE_DOWN((u32)_text); | 158 | kernel_align_start = PAGE_DOWN((u32)_text); |
100 | /* ALIGN can be remove because _end in vmlinux.lds.S is align */ | 159 | /* ALIGN can be remove because _end in vmlinux.lds.S is align */ |
101 | kernel_align_size = PAGE_UP((u32)klimit) - kernel_align_start; | 160 | kernel_align_size = PAGE_UP((u32)klimit) - kernel_align_start; |
102 | memblock_reserve(kernel_align_start, kernel_align_size); | 161 | printk(KERN_INFO "%s: kernel addr:0x%08x-0x%08x size=0x%08x\n", |
103 | printk(KERN_INFO "%s: kernel addr=0x%08x-0x%08x size=0x%08x\n", | ||
104 | __func__, kernel_align_start, kernel_align_start | 162 | __func__, kernel_align_start, kernel_align_start |
105 | + kernel_align_size, kernel_align_size); | 163 | + kernel_align_size, kernel_align_size); |
106 | 164 | memblock_reserve(kernel_align_start, kernel_align_size); | |
107 | #endif | 165 | #endif |
108 | /* | 166 | /* |
109 | * Kernel: | 167 | * Kernel: |
@@ -120,11 +178,13 @@ void __init setup_memory(void) | |||
120 | min_low_pfn = memory_start >> PAGE_SHIFT; /* minimum for allocation */ | 178 | min_low_pfn = memory_start >> PAGE_SHIFT; /* minimum for allocation */ |
121 | /* RAM is assumed contiguous */ | 179 | /* RAM is assumed contiguous */ |
122 | num_physpages = max_mapnr = memory_size >> PAGE_SHIFT; | 180 | num_physpages = max_mapnr = memory_size >> PAGE_SHIFT; |
123 | max_pfn = max_low_pfn = memory_end >> PAGE_SHIFT; | 181 | max_low_pfn = ((u64)memory_start + (u64)lowmem_size) >> PAGE_SHIFT; |
182 | max_pfn = ((u64)memory_start + (u64)memory_size) >> PAGE_SHIFT; | ||
124 | 183 | ||
125 | printk(KERN_INFO "%s: max_mapnr: %#lx\n", __func__, max_mapnr); | 184 | printk(KERN_INFO "%s: max_mapnr: %#lx\n", __func__, max_mapnr); |
126 | printk(KERN_INFO "%s: min_low_pfn: %#lx\n", __func__, min_low_pfn); | 185 | printk(KERN_INFO "%s: min_low_pfn: %#lx\n", __func__, min_low_pfn); |
127 | printk(KERN_INFO "%s: max_low_pfn: %#lx\n", __func__, max_low_pfn); | 186 | printk(KERN_INFO "%s: max_low_pfn: %#lx\n", __func__, max_low_pfn); |
187 | printk(KERN_INFO "%s: max_pfn: %#lx\n", __func__, max_pfn); | ||
128 | 188 | ||
129 | /* | 189 | /* |
130 | * Find an area to use for the bootmem bitmap. | 190 | * Find an area to use for the bootmem bitmap. |
@@ -137,15 +197,39 @@ void __init setup_memory(void) | |||
137 | PFN_UP(TOPHYS((u32)klimit)), min_low_pfn, max_low_pfn); | 197 | PFN_UP(TOPHYS((u32)klimit)), min_low_pfn, max_low_pfn); |
138 | memblock_reserve(PFN_UP(TOPHYS((u32)klimit)) << PAGE_SHIFT, map_size); | 198 | memblock_reserve(PFN_UP(TOPHYS((u32)klimit)) << PAGE_SHIFT, map_size); |
139 | 199 | ||
200 | /* Add active regions with valid PFNs */ | ||
201 | for_each_memblock(memory, reg) { | ||
202 | unsigned long start_pfn, end_pfn; | ||
203 | |||
204 | start_pfn = memblock_region_memory_base_pfn(reg); | ||
205 | end_pfn = memblock_region_memory_end_pfn(reg); | ||
206 | memblock_set_node(start_pfn << PAGE_SHIFT, | ||
207 | (end_pfn - start_pfn) << PAGE_SHIFT, 0); | ||
208 | } | ||
209 | |||
140 | /* free bootmem is whole main memory */ | 210 | /* free bootmem is whole main memory */ |
141 | free_bootmem(memory_start, memory_size); | 211 | free_bootmem_with_active_regions(0, max_low_pfn); |
142 | 212 | ||
143 | /* reserve allocate blocks */ | 213 | /* reserve allocate blocks */ |
144 | for_each_memblock(reserved, reg) { | 214 | for_each_memblock(reserved, reg) { |
145 | pr_debug("reserved - 0x%08x-0x%08x\n", | 215 | unsigned long top = reg->base + reg->size - 1; |
146 | (u32) reg->base, (u32) reg->size); | 216 | |
147 | reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); | 217 | pr_debug("reserved - 0x%08x-0x%08x, %lx, %lx\n", |
218 | (u32) reg->base, (u32) reg->size, top, | ||
219 | memory_start + lowmem_size - 1); | ||
220 | |||
221 | if (top <= (memory_start + lowmem_size - 1)) { | ||
222 | reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); | ||
223 | } else if (reg->base < (memory_start + lowmem_size - 1)) { | ||
224 | unsigned long trunc_size = memory_start + lowmem_size - | ||
225 | reg->base; | ||
226 | reserve_bootmem(reg->base, trunc_size, BOOTMEM_DEFAULT); | ||
227 | } | ||
148 | } | 228 | } |
229 | |||
230 | /* XXX need to clip this if using highmem? */ | ||
231 | sparse_memory_present_with_active_regions(0); | ||
232 | |||
149 | #ifdef CONFIG_MMU | 233 | #ifdef CONFIG_MMU |
150 | init_bootmem_done = 1; | 234 | init_bootmem_done = 1; |
151 | #endif | 235 | #endif |
@@ -190,13 +274,58 @@ void free_initmem(void) | |||
190 | 274 | ||
191 | void __init mem_init(void) | 275 | void __init mem_init(void) |
192 | { | 276 | { |
193 | high_memory = (void *)__va(memory_end); | 277 | pg_data_t *pgdat; |
278 | unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize; | ||
279 | |||
280 | high_memory = (void *)__va(memory_start + lowmem_size - 1); | ||
281 | |||
194 | /* this will put all memory onto the freelists */ | 282 | /* this will put all memory onto the freelists */ |
195 | totalram_pages += free_all_bootmem(); | 283 | totalram_pages += free_all_bootmem(); |
196 | 284 | ||
197 | printk(KERN_INFO "Memory: %luk/%luk available\n", | 285 | for_each_online_pgdat(pgdat) { |
198 | nr_free_pages() << (PAGE_SHIFT-10), | 286 | unsigned long i; |
199 | num_physpages << (PAGE_SHIFT-10)); | 287 | struct page *page; |
288 | |||
289 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | ||
290 | if (!pfn_valid(pgdat->node_start_pfn + i)) | ||
291 | continue; | ||
292 | page = pgdat_page_nr(pgdat, i); | ||
293 | if (PageReserved(page)) | ||
294 | reservedpages++; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | #ifdef CONFIG_HIGHMEM | ||
299 | reservedpages -= highmem_setup(); | ||
300 | #endif | ||
301 | |||
302 | codesize = (unsigned long)&_sdata - (unsigned long)&_stext; | ||
303 | datasize = (unsigned long)&_edata - (unsigned long)&_sdata; | ||
304 | initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin; | ||
305 | bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start; | ||
306 | |||
307 | pr_info("Memory: %luk/%luk available (%luk kernel code, " | ||
308 | "%luk reserved, %luk data, %luk bss, %luk init)\n", | ||
309 | nr_free_pages() << (PAGE_SHIFT-10), | ||
310 | num_physpages << (PAGE_SHIFT-10), | ||
311 | codesize >> 10, | ||
312 | reservedpages << (PAGE_SHIFT-10), | ||
313 | datasize >> 10, | ||
314 | bsssize >> 10, | ||
315 | initsize >> 10); | ||
316 | |||
317 | #ifdef CONFIG_MMU | ||
318 | pr_info("Kernel virtual memory layout:\n"); | ||
319 | pr_info(" * 0x%08lx..0x%08lx : fixmap\n", FIXADDR_START, FIXADDR_TOP); | ||
320 | #ifdef CONFIG_HIGHMEM | ||
321 | pr_info(" * 0x%08lx..0x%08lx : highmem PTEs\n", | ||
322 | PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP)); | ||
323 | #endif /* CONFIG_HIGHMEM */ | ||
324 | pr_info(" * 0x%08lx..0x%08lx : early ioremap\n", | ||
325 | ioremap_bot, ioremap_base); | ||
326 | pr_info(" * 0x%08lx..0x%08lx : vmalloc & ioremap\n", | ||
327 | (unsigned long)VMALLOC_START, VMALLOC_END); | ||
328 | #endif | ||
200 | mem_init_done = 1; | 329 | mem_init_done = 1; |
201 | } | 330 | } |
202 | 331 | ||
@@ -226,7 +355,6 @@ static void mm_cmdline_setup(void) | |||
226 | maxmem = memparse(p, &p); | 355 | maxmem = memparse(p, &p); |
227 | if (maxmem && memory_size > maxmem) { | 356 | if (maxmem && memory_size > maxmem) { |
228 | memory_size = maxmem; | 357 | memory_size = maxmem; |
229 | memory_end = memory_start + memory_size; | ||
230 | memblock.memory.regions[0].size = memory_size; | 358 | memblock.memory.regions[0].size = memory_size; |
231 | } | 359 | } |
232 | } | 360 | } |
@@ -270,15 +398,26 @@ asmlinkage void __init mmu_init(void) | |||
270 | machine_restart(NULL); | 398 | machine_restart(NULL); |
271 | } | 399 | } |
272 | 400 | ||
273 | if ((u32) memblock.memory.regions[0].size < 0x1000000) { | 401 | if ((u32) memblock.memory.regions[0].size < 0x400000) { |
274 | printk(KERN_EMERG "Memory must be greater than 16MB\n"); | 402 | printk(KERN_EMERG "Memory must be greater than 4MB\n"); |
403 | machine_restart(NULL); | ||
404 | } | ||
405 | |||
406 | if ((u32) memblock.memory.regions[0].size < kernel_tlb) { | ||
407 | printk(KERN_EMERG "Kernel size is greater than memory node\n"); | ||
275 | machine_restart(NULL); | 408 | machine_restart(NULL); |
276 | } | 409 | } |
410 | |||
277 | /* Find main memory where the kernel is */ | 411 | /* Find main memory where the kernel is */ |
278 | memory_start = (u32) memblock.memory.regions[0].base; | 412 | memory_start = (u32) memblock.memory.regions[0].base; |
279 | memory_end = (u32) memblock.memory.regions[0].base + | 413 | lowmem_size = memory_size = (u32) memblock.memory.regions[0].size; |
280 | (u32) memblock.memory.regions[0].size; | 414 | |
281 | memory_size = memory_end - memory_start; | 415 | if (lowmem_size > CONFIG_LOWMEM_SIZE) { |
416 | lowmem_size = CONFIG_LOWMEM_SIZE; | ||
417 | #ifndef CONFIG_HIGHMEM | ||
418 | memory_size = lowmem_size; | ||
419 | #endif | ||
420 | } | ||
282 | 421 | ||
283 | mm_cmdline_setup(); /* FIXME parse args from command line - not used */ | 422 | mm_cmdline_setup(); /* FIXME parse args from command line - not used */ |
284 | 423 | ||
@@ -305,15 +444,20 @@ asmlinkage void __init mmu_init(void) | |||
305 | /* Map in all of RAM starting at CONFIG_KERNEL_START */ | 444 | /* Map in all of RAM starting at CONFIG_KERNEL_START */ |
306 | mapin_ram(); | 445 | mapin_ram(); |
307 | 446 | ||
308 | #ifdef CONFIG_HIGHMEM_START_BOOL | 447 | /* Extend vmalloc and ioremap area as big as possible */ |
309 | ioremap_base = CONFIG_HIGHMEM_START; | 448 | #ifdef CONFIG_HIGHMEM |
449 | ioremap_base = ioremap_bot = PKMAP_BASE; | ||
310 | #else | 450 | #else |
311 | ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */ | 451 | ioremap_base = ioremap_bot = FIXADDR_START; |
312 | #endif /* CONFIG_HIGHMEM_START_BOOL */ | 452 | #endif |
313 | ioremap_bot = ioremap_base; | ||
314 | 453 | ||
315 | /* Initialize the context management stuff */ | 454 | /* Initialize the context management stuff */ |
316 | mmu_context_init(); | 455 | mmu_context_init(); |
456 | |||
457 | /* Shortly after that, the entire linear mapping will be available */ | ||
458 | /* This will also cause that unflatten device tree will be allocated | ||
459 | * inside 768MB limit */ | ||
460 | memblock_set_current_limit(memory_start + lowmem_size - 1); | ||
317 | } | 461 | } |
318 | 462 | ||
319 | /* This is only called until mem_init is done. */ | 463 | /* This is only called until mem_init is done. */ |
@@ -324,11 +468,11 @@ void __init *early_get_page(void) | |||
324 | p = alloc_bootmem_pages(PAGE_SIZE); | 468 | p = alloc_bootmem_pages(PAGE_SIZE); |
325 | } else { | 469 | } else { |
326 | /* | 470 | /* |
327 | * Mem start + 32MB -> here is limit | 471 | * Mem start + kernel_tlb -> here is limit |
328 | * because of mem mapping from head.S | 472 | * because of mem mapping from head.S |
329 | */ | 473 | */ |
330 | p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, | 474 | p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, |
331 | memory_start + 0x2000000)); | 475 | memory_start + kernel_tlb)); |
332 | } | 476 | } |
333 | return p; | 477 | return p; |
334 | } | 478 | } |
diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c index 59bf2335a4ce..d1c06d07fed8 100644 --- a/arch/microblaze/mm/pgtable.c +++ b/arch/microblaze/mm/pgtable.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <asm/mmu.h> | 38 | #include <asm/mmu.h> |
39 | #include <asm/sections.h> | 39 | #include <asm/sections.h> |
40 | #include <asm/fixmap.h> | ||
40 | 41 | ||
41 | #define flush_HPTE(X, va, pg) _tlbie(va) | 42 | #define flush_HPTE(X, va, pg) _tlbie(va) |
42 | 43 | ||
@@ -44,11 +45,6 @@ unsigned long ioremap_base; | |||
44 | unsigned long ioremap_bot; | 45 | unsigned long ioremap_bot; |
45 | EXPORT_SYMBOL(ioremap_bot); | 46 | EXPORT_SYMBOL(ioremap_bot); |
46 | 47 | ||
47 | /* The maximum lowmem defaults to 768Mb, but this can be configured to | ||
48 | * another value. | ||
49 | */ | ||
50 | #define MAX_LOW_MEM CONFIG_LOWMEM_SIZE | ||
51 | |||
52 | #ifndef CONFIG_SMP | 48 | #ifndef CONFIG_SMP |
53 | struct pgtable_cache_struct quicklists; | 49 | struct pgtable_cache_struct quicklists; |
54 | #endif | 50 | #endif |
@@ -80,7 +76,7 @@ static void __iomem *__ioremap(phys_addr_t addr, unsigned long size, | |||
80 | !(p >= virt_to_phys((unsigned long)&__bss_stop) && | 76 | !(p >= virt_to_phys((unsigned long)&__bss_stop) && |
81 | p < virt_to_phys((unsigned long)__bss_stop))) { | 77 | p < virt_to_phys((unsigned long)__bss_stop))) { |
82 | printk(KERN_WARNING "__ioremap(): phys addr "PTE_FMT | 78 | printk(KERN_WARNING "__ioremap(): phys addr "PTE_FMT |
83 | " is RAM lr %p\n", (unsigned long)p, | 79 | " is RAM lr %pf\n", (unsigned long)p, |
84 | __builtin_return_address(0)); | 80 | __builtin_return_address(0)); |
85 | return NULL; | 81 | return NULL; |
86 | } | 82 | } |
@@ -171,7 +167,7 @@ void __init mapin_ram(void) | |||
171 | 167 | ||
172 | v = CONFIG_KERNEL_START; | 168 | v = CONFIG_KERNEL_START; |
173 | p = memory_start; | 169 | p = memory_start; |
174 | for (s = 0; s < memory_size; s += PAGE_SIZE) { | 170 | for (s = 0; s < lowmem_size; s += PAGE_SIZE) { |
175 | f = _PAGE_PRESENT | _PAGE_ACCESSED | | 171 | f = _PAGE_PRESENT | _PAGE_ACCESSED | |
176 | _PAGE_SHARED | _PAGE_HWEXEC; | 172 | _PAGE_SHARED | _PAGE_HWEXEC; |
177 | if ((char *) v < _stext || (char *) v >= _etext) | 173 | if ((char *) v < _stext || (char *) v >= _etext) |
@@ -254,3 +250,13 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | |||
254 | } | 250 | } |
255 | return pte; | 251 | return pte; |
256 | } | 252 | } |
253 | |||
254 | void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags) | ||
255 | { | ||
256 | unsigned long address = __fix_to_virt(idx); | ||
257 | |||
258 | if (idx >= __end_of_fixed_addresses) | ||
259 | BUG(); | ||
260 | |||
261 | map_page(address, phys, pgprot_val(flags)); | ||
262 | } | ||
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 85f2ac1230a8..d10403dadd2b 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c | |||
@@ -46,9 +46,6 @@ static int global_phb_number; /* Global phb counter */ | |||
46 | /* ISA Memory physical address */ | 46 | /* ISA Memory physical address */ |
47 | resource_size_t isa_mem_base; | 47 | resource_size_t isa_mem_base; |
48 | 48 | ||
49 | /* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */ | ||
50 | unsigned int pci_flags; | ||
51 | |||
52 | static struct dma_map_ops *pci_dma_ops = &dma_direct_ops; | 49 | static struct dma_map_ops *pci_dma_ops = &dma_direct_ops; |
53 | 50 | ||
54 | unsigned long isa_io_base; | 51 | unsigned long isa_io_base; |
@@ -833,64 +830,7 @@ int pci_proc_domain(struct pci_bus *bus) | |||
833 | { | 830 | { |
834 | struct pci_controller *hose = pci_bus_to_host(bus); | 831 | struct pci_controller *hose = pci_bus_to_host(bus); |
835 | 832 | ||
836 | if (!(pci_flags & PCI_ENABLE_PROC_DOMAINS)) | 833 | return 0; |
837 | return 0; | ||
838 | if (pci_flags & PCI_COMPAT_DOMAIN_0) | ||
839 | return hose->global_number != 0; | ||
840 | return 1; | ||
841 | } | ||
842 | |||
843 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
844 | struct resource *res) | ||
845 | { | ||
846 | resource_size_t offset = 0, mask = (resource_size_t)-1; | ||
847 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
848 | |||
849 | if (!hose) | ||
850 | return; | ||
851 | if (res->flags & IORESOURCE_IO) { | ||
852 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
853 | mask = 0xffffffffu; | ||
854 | } else if (res->flags & IORESOURCE_MEM) | ||
855 | offset = hose->pci_mem_offset; | ||
856 | |||
857 | region->start = (res->start - offset) & mask; | ||
858 | region->end = (res->end - offset) & mask; | ||
859 | } | ||
860 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
861 | |||
862 | void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
863 | struct pci_bus_region *region) | ||
864 | { | ||
865 | resource_size_t offset = 0, mask = (resource_size_t)-1; | ||
866 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
867 | |||
868 | if (!hose) | ||
869 | return; | ||
870 | if (res->flags & IORESOURCE_IO) { | ||
871 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
872 | mask = 0xffffffffu; | ||
873 | } else if (res->flags & IORESOURCE_MEM) | ||
874 | offset = hose->pci_mem_offset; | ||
875 | res->start = (region->start + offset) & mask; | ||
876 | res->end = (region->end + offset) & mask; | ||
877 | } | ||
878 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
879 | |||
880 | /* Fixup a bus resource into a linux resource */ | ||
881 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | ||
882 | { | ||
883 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
884 | resource_size_t offset = 0, mask = (resource_size_t)-1; | ||
885 | |||
886 | if (res->flags & IORESOURCE_IO) { | ||
887 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
888 | mask = 0xffffffffu; | ||
889 | } else if (res->flags & IORESOURCE_MEM) | ||
890 | offset = hose->pci_mem_offset; | ||
891 | |||
892 | res->start = (res->start + offset) & mask; | ||
893 | res->end = (res->end + offset) & mask; | ||
894 | } | 834 | } |
895 | 835 | ||
896 | /* This header fixup will do the resource fixup for all devices as they are | 836 | /* This header fixup will do the resource fixup for all devices as they are |
@@ -910,13 +850,7 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev) | |||
910 | struct resource *res = dev->resource + i; | 850 | struct resource *res = dev->resource + i; |
911 | if (!res->flags) | 851 | if (!res->flags) |
912 | continue; | 852 | continue; |
913 | /* On platforms that have PCI_PROBE_ONLY set, we don't | 853 | if (res->start == 0) { |
914 | * consider 0 as an unassigned BAR value. It's technically | ||
915 | * a valid value, but linux doesn't like it... so when we can | ||
916 | * re-assign things, we do so, but if we can't, we keep it | ||
917 | * around and hope for the best... | ||
918 | */ | ||
919 | if (res->start == 0 && !(pci_flags & PCI_PROBE_ONLY)) { | ||
920 | pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]" \ | 854 | pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]" \ |
921 | "is unassigned\n", | 855 | "is unassigned\n", |
922 | pci_name(dev), i, | 856 | pci_name(dev), i, |
@@ -929,18 +863,11 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev) | |||
929 | continue; | 863 | continue; |
930 | } | 864 | } |
931 | 865 | ||
932 | pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] fixup...\n", | 866 | pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]\n", |
933 | pci_name(dev), i, | 867 | pci_name(dev), i, |
934 | (unsigned long long)res->start,\ | 868 | (unsigned long long)res->start,\ |
935 | (unsigned long long)res->end, | 869 | (unsigned long long)res->end, |
936 | (unsigned int)res->flags); | 870 | (unsigned int)res->flags); |
937 | |||
938 | fixup_resource(res, dev); | ||
939 | |||
940 | pr_debug("PCI:%s %016llx-%016llx\n", | ||
941 | pci_name(dev), | ||
942 | (unsigned long long)res->start, | ||
943 | (unsigned long long)res->end); | ||
944 | } | 871 | } |
945 | } | 872 | } |
946 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); | 873 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); |
@@ -959,10 +886,6 @@ static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus, | |||
959 | u16 command; | 886 | u16 command; |
960 | int i; | 887 | int i; |
961 | 888 | ||
962 | /* We don't do anything if PCI_PROBE_ONLY is set */ | ||
963 | if (pci_flags & PCI_PROBE_ONLY) | ||
964 | return 0; | ||
965 | |||
966 | /* Job is a bit different between memory and IO */ | 889 | /* Job is a bit different between memory and IO */ |
967 | if (res->flags & IORESOURCE_MEM) { | 890 | if (res->flags & IORESOURCE_MEM) { |
968 | /* If the BAR is non-0 (res != pci_mem_offset) then it's | 891 | /* If the BAR is non-0 (res != pci_mem_offset) then it's |
@@ -1037,9 +960,6 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) | |||
1037 | (unsigned long long)res->end, | 960 | (unsigned long long)res->end, |
1038 | (unsigned int)res->flags); | 961 | (unsigned int)res->flags); |
1039 | 962 | ||
1040 | /* Perform fixup */ | ||
1041 | fixup_resource(res, dev); | ||
1042 | |||
1043 | /* Try to detect uninitialized P2P bridge resources, | 963 | /* Try to detect uninitialized P2P bridge resources, |
1044 | * and clear them out so they get re-assigned later | 964 | * and clear them out so they get re-assigned later |
1045 | */ | 965 | */ |
@@ -1107,9 +1027,6 @@ EXPORT_SYMBOL(pcibios_fixup_bus); | |||
1107 | 1027 | ||
1108 | static int skip_isa_ioresource_align(struct pci_dev *dev) | 1028 | static int skip_isa_ioresource_align(struct pci_dev *dev) |
1109 | { | 1029 | { |
1110 | if ((pci_flags & PCI_CAN_SKIP_ISA_ALIGN) && | ||
1111 | !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA)) | ||
1112 | return 1; | ||
1113 | return 0; | 1030 | return 0; |
1114 | } | 1031 | } |
1115 | 1032 | ||
@@ -1236,8 +1153,6 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) | |||
1236 | * and as such ensure proper re-allocation | 1153 | * and as such ensure proper re-allocation |
1237 | * later. | 1154 | * later. |
1238 | */ | 1155 | */ |
1239 | if (pci_flags & PCI_REASSIGN_ALL_RSRC) | ||
1240 | goto clear_resource; | ||
1241 | pr = pci_find_parent_resource(bus->self, res); | 1156 | pr = pci_find_parent_resource(bus->self, res); |
1242 | if (pr == res) { | 1157 | if (pr == res) { |
1243 | /* this happens when the generic PCI | 1158 | /* this happens when the generic PCI |
@@ -1422,27 +1337,19 @@ void __init pcibios_resource_survey(void) | |||
1422 | list_for_each_entry(b, &pci_root_buses, node) | 1337 | list_for_each_entry(b, &pci_root_buses, node) |
1423 | pcibios_allocate_bus_resources(b); | 1338 | pcibios_allocate_bus_resources(b); |
1424 | 1339 | ||
1425 | if (!(pci_flags & PCI_REASSIGN_ALL_RSRC)) { | 1340 | pcibios_allocate_resources(0); |
1426 | pcibios_allocate_resources(0); | 1341 | pcibios_allocate_resources(1); |
1427 | pcibios_allocate_resources(1); | ||
1428 | } | ||
1429 | 1342 | ||
1430 | /* Before we start assigning unassigned resource, we try to reserve | 1343 | /* Before we start assigning unassigned resource, we try to reserve |
1431 | * the low IO area and the VGA memory area if they intersect the | 1344 | * the low IO area and the VGA memory area if they intersect the |
1432 | * bus available resources to avoid allocating things on top of them | 1345 | * bus available resources to avoid allocating things on top of them |
1433 | */ | 1346 | */ |
1434 | if (!(pci_flags & PCI_PROBE_ONLY)) { | 1347 | list_for_each_entry(b, &pci_root_buses, node) |
1435 | list_for_each_entry(b, &pci_root_buses, node) | 1348 | pcibios_reserve_legacy_regions(b); |
1436 | pcibios_reserve_legacy_regions(b); | ||
1437 | } | ||
1438 | 1349 | ||
1439 | /* Now, if the platform didn't decide to blindly trust the firmware, | 1350 | /* Now proceed to assigning things that were left unassigned */ |
1440 | * we proceed to assigning things that were left unassigned | 1351 | pr_debug("PCI: Assigning unassigned resources...\n"); |
1441 | */ | 1352 | pci_assign_unassigned_resources(); |
1442 | if (!(pci_flags & PCI_PROBE_ONLY)) { | ||
1443 | pr_debug("PCI: Assigning unassigned resources...\n"); | ||
1444 | pci_assign_unassigned_resources(); | ||
1445 | } | ||
1446 | } | 1353 | } |
1447 | 1354 | ||
1448 | #ifdef CONFIG_HOTPLUG | 1355 | #ifdef CONFIG_HOTPLUG |
@@ -1535,7 +1442,7 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s | |||
1535 | res->end = res->start + IO_SPACE_LIMIT; | 1442 | res->end = res->start + IO_SPACE_LIMIT; |
1536 | res->flags = IORESOURCE_IO; | 1443 | res->flags = IORESOURCE_IO; |
1537 | } | 1444 | } |
1538 | pci_add_resource(resources, res); | 1445 | pci_add_resource_offset(resources, res, hose->io_base_virt - _IO_BASE); |
1539 | 1446 | ||
1540 | pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", | 1447 | pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", |
1541 | (unsigned long long)res->start, | 1448 | (unsigned long long)res->start, |
@@ -1558,7 +1465,7 @@ static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, s | |||
1558 | res->flags = IORESOURCE_MEM; | 1465 | res->flags = IORESOURCE_MEM; |
1559 | 1466 | ||
1560 | } | 1467 | } |
1561 | pci_add_resource(resources, res); | 1468 | pci_add_resource_offset(resources, res, hose->pci_mem_offset); |
1562 | 1469 | ||
1563 | pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", | 1470 | pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", |
1564 | i, (unsigned long long)res->start, | 1471 | i, (unsigned long long)res->start, |