aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/Kconfig34
-rw-r--r--arch/microblaze/boot/Makefile12
-rw-r--r--arch/microblaze/include/asm/atomic.h1
-rw-r--r--arch/microblaze/include/asm/barrier.h27
-rw-r--r--arch/microblaze/include/asm/cmpxchg.h42
-rw-r--r--arch/microblaze/include/asm/exec.h14
-rw-r--r--arch/microblaze/include/asm/fixmap.h109
-rw-r--r--arch/microblaze/include/asm/futex.h2
-rw-r--r--arch/microblaze/include/asm/hardirq.h16
-rw-r--r--arch/microblaze/include/asm/highmem.h96
-rw-r--r--arch/microblaze/include/asm/irq.h42
-rw-r--r--arch/microblaze/include/asm/mmu.h12
-rw-r--r--arch/microblaze/include/asm/page.h4
-rw-r--r--arch/microblaze/include/asm/pci-bridge.h1
-rw-r--r--arch/microblaze/include/asm/pci.h8
-rw-r--r--arch/microblaze/include/asm/pgtable.h5
-rw-r--r--arch/microblaze/include/asm/processor.h11
-rw-r--r--arch/microblaze/include/asm/setup.h9
-rw-r--r--arch/microblaze/include/asm/switch_to.h24
-rw-r--r--arch/microblaze/include/asm/system.h97
-rw-r--r--arch/microblaze/include/asm/uaccess.h2
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo.c2
-rw-r--r--arch/microblaze/kernel/cpu/pvr.c1
-rw-r--r--arch/microblaze/kernel/early_printk.c18
-rw-r--r--arch/microblaze/kernel/head.S129
-rw-r--r--arch/microblaze/kernel/hw_exception_handler.S13
-rw-r--r--arch/microblaze/kernel/intc.c65
-rw-r--r--arch/microblaze/kernel/irq.c24
-rw-r--r--arch/microblaze/kernel/microblaze_ksyms.c1
-rw-r--r--arch/microblaze/kernel/misc.S13
-rw-r--r--arch/microblaze/kernel/process.c5
-rw-r--r--arch/microblaze/kernel/prom.c1
-rw-r--r--arch/microblaze/kernel/setup.c29
-rw-r--r--arch/microblaze/kernel/timer.c7
-rw-r--r--arch/microblaze/kernel/traps.c1
-rw-r--r--arch/microblaze/kernel/unwind.c1
-rw-r--r--arch/microblaze/kernel/vmlinux.lds.S2
-rw-r--r--arch/microblaze/lib/memcpy.c1
-rw-r--r--arch/microblaze/lib/uaccess_old.S98
-rw-r--r--arch/microblaze/mm/Makefile1
-rw-r--r--arch/microblaze/mm/fault.c1
-rw-r--r--arch/microblaze/mm/highmem.c88
-rw-r--r--arch/microblaze/mm/init.c224
-rw-r--r--arch/microblaze/mm/pgtable.c20
-rw-r--r--arch/microblaze/pci/pci-common.c117
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 @@
1config MICROBLAZE 1config 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
27config RWSEM_GENERIC_SPINLOCK 29config RWSEM_GENERIC_SPINLOCK
28 def_bool y 30 def_bool y
29 31
32config ZONE_DMA
33 def_bool y
34
35config ARCH_POPULATES_NODE_MAP
36 def_bool y
37
30config RWSEM_XCHGADD_ALGORITHM 38config 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
155config HIGHMEM_START_BOOL 163config 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
165config HIGHMEM_START
166 hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
167 depends on MMU
168 default "0xfe000000"
169 175
170config LOWMEM_SIZE_BOOL 176config 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
255endchoice 261endchoice
256 262
263config KERNEL_PAD
264 hex "Kernel PAD for unpacking" if ADVANCED_OPTIONS
265 default "0x80000" if MMU
266
257endmenu 267endmenu
258 268
259source "mm/Kconfig" 269source "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
5MKIMAGE := $(srctree)/scripts/mkuboot.sh
6
7obj-y += linked_dtb.o 5obj-y += linked_dtb.o
8 6
9targets := linux.bin linux.bin.gz simpleImage.% 7targets := linux.bin linux.bin.gz simpleImage.%
10 8
11OBJCOPYFLAGS := -O binary 9OBJCOPYFLAGS := -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
38quiet_cmd_uimage = UIMAGE $@.ub 36UIMAGE_IN = $@
39 cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A microblaze -O linux -T kernel \ 37UIMAGE_OUT = $@.ub
40 -C none -n 'Linux-$(KERNELRELEASE)' \ 38UIMAGE_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
6void __bad_xchg(volatile void *ptr, int size);
7
8static 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 */
49enum 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
58extern 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
78extern 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 */
85static __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
102static 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 */
13extern 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
27extern pte_t *kmap_pte;
28extern pgprot_t kmap_prot;
29extern 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
53extern void *kmap_high(struct page *page);
54extern void kunmap_high(struct page *page);
55extern void *kmap_atomic_prot(struct page *page, pgprot_t prot);
56extern void __kunmap_atomic(void *kvaddr);
57
58static 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
66static inline void kunmap(struct page *page)
67{
68 BUG_ON(in_interrupt());
69 if (!PageHighMem(page))
70 return;
71 kunmap_high(page);
72}
73
74static inline void *__kmap_atomic(struct page *page)
75{
76 return kmap_atomic_prot(page, kmap_prot);
77}
78
79static 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 */
26typedef unsigned long irq_hw_number_t;
27
28extern unsigned int nr_irq;
29
30struct pt_regs; 15struct pt_regs;
31extern void do_IRQ(struct pt_regs *regs); 16extern 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 19extern unsigned int get_irq(void);
35 * @virq: linux virq number of the interrupt to unmap
36 */
37static inline void irq_dispose_mapping(unsigned int virq)
38{
39 return;
40}
41
42struct 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 */
54extern 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
57extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ 57extern void _tlbie(unsigned long va); /* invalidate a TLB entry */
58extern void _tlbia(void); /* invalidate all TLB entries */ 58extern 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 */
64extern 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;
135extern unsigned long max_pfn; 135extern unsigned long max_pfn;
136 136
137extern unsigned long memory_start; 137extern unsigned long memory_start;
138extern unsigned long memory_end;
139extern unsigned long memory_size; 138extern unsigned long memory_size;
139extern unsigned long lowmem_size;
140
141extern unsigned long kernel_tlb;
140 142
141extern int page_is_ram(unsigned long pfn); 143extern 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
15struct device_node; 14struct 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
97extern void pcibios_resource_to_bus(struct pci_dev *dev,
98 struct pci_bus_region *region,
99 struct resource *res);
100
101extern void pcibios_bus_to_resource(struct pci_dev *dev,
102 struct resource *res,
103 struct pci_bus_region *region);
104
105static inline struct resource *pcibios_select_root(struct pci_dev *pdev, 97static 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. */
32void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); 32void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);
33 33
34extern 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. */
130extern inline void release_thread(struct task_struct *dead_task) 131extern 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
170void disable_hlt(void);
171void enable_hlt(void);
172void default_idle(void);
173
174#ifdef CONFIG_DEBUG_FS
175extern 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
21extern char cmd_line[COMMAND_LINE_SIZE]; 21extern char cmd_line[COMMAND_LINE_SIZE];
22 22
23extern char *klimit;
24
23void early_printk(const char *fmt, ...); 25void early_printk(const char *fmt, ...);
24 26
25int setup_early_printk(char *opt); 27int setup_early_printk(char *opt);
@@ -39,13 +41,18 @@ extern void of_platform_reset_gpio_probe(void);
39void time_init(void); 41void time_init(void);
40void init_IRQ(void); 42void init_IRQ(void);
41void machine_early_init(const char *cmdline, unsigned int ram, 43void 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
44void machine_restart(char *cmd); 47void machine_restart(char *cmd);
45void machine_shutdown(void); 48void machine_shutdown(void);
46void machine_halt(void); 49void machine_halt(void);
47void machine_power_off(void); 50void machine_power_off(void);
48 51
52void free_init_pages(char *what, unsigned long begin, unsigned long end);
53extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
54extern 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
12struct task_struct;
13struct thread_info;
14
15extern 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
20struct task_struct;
21struct thread_info;
22
23extern 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
46void __bad_xchg(volatile void *ptr, int size);
47
48static 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
76void disable_hlt(void);
77void enable_hlt(void);
78void default_idle(void);
79
80#define xchg(ptr, x) \
81 ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
82
83void free_init_pages(char *what, unsigned long begin, unsigned long end);
84void free_initmem(void);
85extern char *klimit;
86extern void ret_from_fork(void);
87
88extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
89extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
90
91#ifdef CONFIG_DEBUG_FS
92extern 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);
80static inline int ___range_ok(unsigned long addr, unsigned long size) 80static 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
180void __init disable_early_printk(void) 196void __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)
63real_start: 63real_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
194GT4: /* r11 contains the rest - will be either 1 or 4 */
195 ori r9, r0, 0x400000 /* TLB0 is 4MB */
196 bri TLB1
197GT16: /* TLB0 is 16MB */
198 addik r9, r0, 0x1000000 /* means TLB0 is 16MB */
199TLB1:
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 */
207GT1:
208 addik r10, r0, 0x0100000 /* means TLB1 is 1MB */
209 bri tlb_end
210GT2: /* TLB0 is 0 and TLB1 will be 4MB */
211GT17: /* TLB1 is 4MB - kernel size <20MB */
212 addik r10, r0, 0x0400000 /* means TLB1 is 4MB */
213 bri tlb_end
214GT8: /* TLB0 is still zero that's why I can use only TLB1 */
215GT20: /* TLB1 is 16MB - kernel size >20MB */
216 addik r10, r0, 0x1000000 /* means TLB1 is 16MB */
217tlb_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
235tlb0_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
2481:
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
2781:
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
296jump_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 */
270kernel_load_context: 370kernel_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
28unsigned 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
87unsigned int get_irq(struct pt_regs *regs) 86static struct irq_domain *root_domain;
87
88unsigned 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
101int 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
117static const struct irq_domain_ops xintc_irq_domain_ops = {
118 .xlate = irq_domain_xlate_onetwocell,
119 .map = xintc_map,
120};
121
102void __init init_IRQ(void) 122void __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();
35next_irq: 35next_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 */
54unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
55{
56 return hwirq + IRQ_OFFSET;
57}
58EXPORT_SYMBOL_GPL(irq_create_mapping);
59
60unsigned int irq_create_of_mapping(struct device_node *controller,
61 const u32 *intspec, unsigned int intsize)
62{
63 return intspec[0] + IRQ_OFFSET;
64}
65EXPORT_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
97unsigned long kernel_tlb;
98
100void __init machine_early_init(const char *cmdline, unsigned int ram, 99void __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}
201arch_initcall(microblaze_debugfs_init); 207arch_initcall(microblaze_debugfs_init);
208
209# ifdef CONFIG_MMU
210static 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}
221device_initcall(debugfs_tlb);
222# endif
202#endif 223#endif
203 224
204static int dflt_bus_notify(struct notifier_block *nb, 225static 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
21void trap_init(void) 20void 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
28struct stack_trace; 29struct 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:
12215: swi r24, r5, 0x0018 + offset; \ 12215: swi r24, r5, 0x0018 + offset; \
12316: swi r25, r5, 0x001C + offset; \ 12316: 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 */
192page: /* Create room on stack and save registers for storign values */ 192page: /* 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
201loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */ 204loop: /* 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 */
23433:
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 @@
5obj-y := consistent.o init.o 5obj-y := consistent.o init.o
6 6
7obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o 7obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o
8obj-$(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
34void *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}
57EXPORT_SYMBOL(kmap_atomic_prot);
58
59void __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}
88EXPORT_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 */
29int mem_init_done; 30int mem_init_done;
@@ -44,9 +45,56 @@ char *klimit = _end;
44 */ 45 */
45unsigned long memory_start; 46unsigned long memory_start;
46EXPORT_SYMBOL(memory_start); 47EXPORT_SYMBOL(memory_start);
47unsigned long memory_end; /* due to mm/nommu.c */
48unsigned long memory_size; 48unsigned long memory_size;
49EXPORT_SYMBOL(memory_size); 49EXPORT_SYMBOL(memory_size);
50unsigned long lowmem_size;
51
52#ifdef CONFIG_HIGHMEM
53pte_t *kmap_pte;
54EXPORT_SYMBOL(kmap_pte);
55pgprot_t kmap_prot;
56EXPORT_SYMBOL(kmap_prot);
57
58static 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
64static 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
74static 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);
54static void __init paging_init(void) 102static 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
70void __init setup_memory(void) 129void __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
191void __init mem_init(void) 275void __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;
44unsigned long ioremap_bot; 45unsigned long ioremap_bot;
45EXPORT_SYMBOL(ioremap_bot); 46EXPORT_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
53struct pgtable_cache_struct quicklists; 49struct 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
254void __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 */
47resource_size_t isa_mem_base; 47resource_size_t isa_mem_base;
48 48
49/* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
50unsigned int pci_flags;
51
52static struct dma_map_ops *pci_dma_ops = &dma_direct_ops; 49static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
53 50
54unsigned long isa_io_base; 51unsigned 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
843void 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}
860EXPORT_SYMBOL(pcibios_resource_to_bus);
861
862void 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}
878EXPORT_SYMBOL(pcibios_bus_to_resource);
879
880/* Fixup a bus resource into a linux resource */
881static 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}
946DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); 873DECLARE_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
1108static int skip_isa_ioresource_align(struct pci_dev *dev) 1028static 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,