aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/Makefile35
-rw-r--r--arch/microblaze/include/asm/io.h1
-rw-r--r--arch/microblaze/include/asm/pgtable.h6
-rw-r--r--arch/microblaze/include/asm/prom.h23
-rw-r--r--arch/microblaze/include/asm/tlb.h2
-rw-r--r--arch/microblaze/include/asm/uaccess.h2
-rw-r--r--arch/microblaze/kernel/Makefile2
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c2
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-static.c2
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo.c2
-rw-r--r--arch/microblaze/kernel/head.S17
-rw-r--r--arch/microblaze/kernel/hw_exception_handler.S109
-rw-r--r--arch/microblaze/kernel/module.c19
-rw-r--r--arch/microblaze/kernel/setup.c8
-rw-r--r--arch/microblaze/kernel/sys_microblaze.c99
-rw-r--r--arch/microblaze/kernel/syscall_table.S2
-rw-r--r--arch/microblaze/mm/fault.c15
17 files changed, 126 insertions, 220 deletions
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile
index d0bcf80a1136..8439598d4655 100644
--- a/arch/microblaze/Makefile
+++ b/arch/microblaze/Makefile
@@ -6,14 +6,16 @@ endif
6 6
7# What CPU vesion are we building for, and crack it open 7# What CPU vesion are we building for, and crack it open
8# as major.minor.rev 8# as major.minor.rev
9CPU_VER=$(subst ",,$(CONFIG_XILINX_MICROBLAZE0_HW_VER) ) 9CPU_VER := $(shell echo $(CONFIG_XILINX_MICROBLAZE0_HW_VER))
10CPU_MAJOR=$(shell echo $(CPU_VER) | cut -d '.' -f 1) 10CPU_MAJOR := $(shell echo $(CPU_VER) | cut -d '.' -f 1)
11CPU_MINOR=$(shell echo $(CPU_VER) | cut -d '.' -f 2) 11CPU_MINOR := $(shell echo $(CPU_VER) | cut -d '.' -f 2)
12CPU_REV=$(shell echo $(CPU_VER) | cut -d '.' -f 3) 12CPU_REV := $(shell echo $(CPU_VER) | cut -d '.' -f 3)
13 13
14export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV 14export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV
15 15
16# Use cpu-related CONFIG_ vars to set compile options. 16# Use cpu-related CONFIG_ vars to set compile options.
17# The various CONFIG_XILINX cpu features options are integers 0/1/2...
18# rather than bools y/n
17 19
18# Work out HW multipler support. This is icky. 20# Work out HW multipler support. This is icky.
19# 1. Spartan2 has no HW multiplers. 21# 1. Spartan2 has no HW multiplers.
@@ -34,30 +36,29 @@ CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR) += -mxl-pattern-compare
34 36
35CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER)) 37CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER))
36 38
37# The various CONFIG_XILINX cpu features options are integers 0/1/2...
38# rather than bools y/n
39
40# r31 holds current when in kernel mode 39# r31 holds current when in kernel mode
41CFLAGS_KERNEL += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2) 40KBUILD_KERNEL += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
42 41
43LDFLAGS := 42LDFLAGS :=
44LDFLAGS_vmlinux := 43LDFLAGS_vmlinux :=
45LDFLAGS_BLOB := --format binary --oformat elf32-microblaze
46 44
47LIBGCC := $(shell $(CC) $(CFLAGS_KERNEL) -print-libgcc-file-name) 45LIBGCC := $(shell $(CC) $(KBUILD_KERNEL) -print-libgcc-file-name)
48 46
49head-y := arch/microblaze/kernel/head.o 47head-y := arch/microblaze/kernel/head.o
50libs-y += arch/microblaze/lib/ $(LIBGCC) 48libs-y += arch/microblaze/lib/
51core-y += arch/microblaze/kernel/ arch/microblaze/mm/ \ 49libs-y += $(LIBGCC)
52 arch/microblaze/platform/ 50core-y += arch/microblaze/kernel/
51core-y += arch/microblaze/mm/
52core-y += arch/microblaze/platform/
53 53
54boot := arch/$(ARCH)/boot 54boot := arch/microblaze/boot
55 55
56# defines filename extension depending memory management type 56# defines filename extension depending memory management type
57ifeq ($(CONFIG_MMU),) 57ifeq ($(CONFIG_MMU),)
58MMUEXT := -nommu 58MMU := -nommu
59endif 59endif
60export MMUEXT 60
61export MMU
61 62
62all: linux.bin 63all: linux.bin
63 64
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
index 5c173424d074..7c3ec13b44d8 100644
--- a/arch/microblaze/include/asm/io.h
+++ b/arch/microblaze/include/asm/io.h
@@ -14,7 +14,6 @@
14#include <asm/byteorder.h> 14#include <asm/byteorder.h>
15#include <asm/page.h> 15#include <asm/page.h>
16#include <linux/types.h> 16#include <linux/types.h>
17#include <asm/byteorder.h>
18#include <linux/mm.h> /* Get struct page {...} */ 17#include <linux/mm.h> /* Get struct page {...} */
19 18
20 19
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
index 4c57a586a989..cc3a4dfc3eaa 100644
--- a/arch/microblaze/include/asm/pgtable.h
+++ b/arch/microblaze/include/asm/pgtable.h
@@ -185,6 +185,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
185 185
186/* Definitions for MicroBlaze. */ 186/* Definitions for MicroBlaze. */
187#define _PAGE_GUARDED 0x001 /* G: page is guarded from prefetch */ 187#define _PAGE_GUARDED 0x001 /* G: page is guarded from prefetch */
188#define _PAGE_FILE 0x001 /* when !present: nonlinear file mapping */
188#define _PAGE_PRESENT 0x002 /* software: PTE contains a translation */ 189#define _PAGE_PRESENT 0x002 /* software: PTE contains a translation */
189#define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */ 190#define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */
190#define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */ 191#define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */
@@ -320,8 +321,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
320static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; } 321static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
321static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } 322static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
322static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } 323static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
323/* FIXME */ 324static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
324static inline int pte_file(pte_t pte) { return 0; }
325 325
326static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; } 326static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
327static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; } 327static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -488,7 +488,7 @@ static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
488/* Encode and decode a nonlinear file mapping entry */ 488/* Encode and decode a nonlinear file mapping entry */
489#define PTE_FILE_MAX_BITS 29 489#define PTE_FILE_MAX_BITS 29
490#define pte_to_pgoff(pte) (pte_val(pte) >> 3) 490#define pte_to_pgoff(pte) (pte_val(pte) >> 3)
491#define pgoff_to_pte(off) ((pte_t) { ((off) << 3) }) 491#define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE })
492 492
493extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; 493extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
494 494
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 20f7b3a926e8..37e6f305a68e 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -16,6 +16,18 @@
16#define _ASM_MICROBLAZE_PROM_H 16#define _ASM_MICROBLAZE_PROM_H
17#ifdef __KERNEL__ 17#ifdef __KERNEL__
18 18
19/* Definitions used by the flattened device tree */
20#define OF_DT_HEADER 0xd00dfeed /* marker */
21#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
22#define OF_DT_END_NODE 0x2 /* End node */
23#define OF_DT_PROP 0x3 /* Property: name off, size, content */
24#define OF_DT_NOP 0x4 /* nop */
25#define OF_DT_END 0x9
26
27#define OF_DT_VERSION 0x10
28
29#ifndef __ASSEMBLY__
30
19#include <linux/types.h> 31#include <linux/types.h>
20#include <linux/proc_fs.h> 32#include <linux/proc_fs.h>
21#include <linux/platform_device.h> 33#include <linux/platform_device.h>
@@ -29,16 +41,6 @@
29#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) 41#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
30#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) 42#define of_node_cmp(s1, s2) strcasecmp((s1), (s2))
31 43
32/* Definitions used by the flattened device tree */
33#define OF_DT_HEADER 0xd00dfeed /* marker */
34#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
35#define OF_DT_END_NODE 0x2 /* End node */
36#define OF_DT_PROP 0x3 /* Property: name off, size, content */
37#define OF_DT_NOP 0x4 /* nop */
38#define OF_DT_END 0x9
39
40#define OF_DT_VERSION 0x10
41
42/* 44/*
43 * This is what gets passed to the kernel by prom_init or kexec 45 * This is what gets passed to the kernel by prom_init or kexec
44 * 46 *
@@ -309,5 +311,6 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
309 */ 311 */
310#include <linux/of.h> 312#include <linux/of.h>
311 313
314#endif /* __ASSEMBLY__ */
312#endif /* __KERNEL__ */ 315#endif /* __KERNEL__ */
313#endif /* _ASM_MICROBLAZE_PROM_H */ 316#endif /* _ASM_MICROBLAZE_PROM_H */
diff --git a/arch/microblaze/include/asm/tlb.h b/arch/microblaze/include/asm/tlb.h
index c472d2801132..e8abd4a0349c 100644
--- a/arch/microblaze/include/asm/tlb.h
+++ b/arch/microblaze/include/asm/tlb.h
@@ -11,7 +11,7 @@
11#ifndef _ASM_MICROBLAZE_TLB_H 11#ifndef _ASM_MICROBLAZE_TLB_H
12#define _ASM_MICROBLAZE_TLB_H 12#define _ASM_MICROBLAZE_TLB_H
13 13
14#define tlb_flush(tlb) do {} while (0) 14#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
15 15
16#include <asm-generic/tlb.h> 16#include <asm-generic/tlb.h>
17 17
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index 65adad61e7e9..5431b4631a7a 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -189,7 +189,7 @@ extern long strnlen_user(const char *src, long count);
189 189
190#define __put_user(x, ptr) \ 190#define __put_user(x, ptr) \
191({ \ 191({ \
192 __typeof__(*(ptr)) __gu_val = x; \ 192 __typeof__(*(ptr)) volatile __gu_val = (x); \
193 long __gu_err = 0; \ 193 long __gu_err = 0; \
194 switch (sizeof(__gu_val)) { \ 194 switch (sizeof(__gu_val)) { \
195 case 1: \ 195 case 1: \
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index f4a5e19a20eb..d487729683de 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -17,4 +17,4 @@ obj-$(CONFIG_HEART_BEAT) += heartbeat.o
17obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o 17obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
18obj-$(CONFIG_MMU) += misc.o 18obj-$(CONFIG_MMU) += misc.o
19 19
20obj-y += entry$(MMUEXT).o 20obj-y += entry$(MMU).o
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
index 153f57c57b6d..c259786e7faa 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -22,7 +22,7 @@
22 22
23#define CI(c, p) { ci->c = PVR_##p(pvr); } 23#define CI(c, p) { ci->c = PVR_##p(pvr); }
24#define err_printk(x) \ 24#define err_printk(x) \
25 early_printk("ERROR: Microblaze " x " - different for PVR and DTS\n"); 25 early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
26 26
27void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) 27void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
28{ 28{
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
index 450ca6bb828d..adb448f93d5f 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -18,7 +18,7 @@ static const char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY;
18static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER; 18static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
19 19
20#define err_printk(x) \ 20#define err_printk(x) \
21 early_printk("ERROR: Microblaze " x "- different for kernel and DTS\n"); 21 early_printk("ERROR: Microblaze " x "-different for kernel and DTS\n");
22 22
23void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) 23void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
24{ 24{
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index a10bea119b94..c411c6757deb 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -26,6 +26,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
26 {"7.10.b", 0x09}, 26 {"7.10.b", 0x09},
27 {"7.10.c", 0x0a}, 27 {"7.10.c", 0x0a},
28 {"7.10.d", 0x0b}, 28 {"7.10.d", 0x0b},
29 {"7.20.a", 0x0c},
30 {"7.20.b", 0x0d},
29 /* FIXME There is no keycode defined in MBV for these versions */ 31 /* FIXME There is no keycode defined in MBV for these versions */
30 {"2.10.a", 0x10}, 32 {"2.10.a", 0x10},
31 {"3.00.a", 0x20}, 33 {"3.00.a", 0x20},
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
index e568d6ec621b..e41c6ce2a7be 100644
--- a/arch/microblaze/kernel/head.S
+++ b/arch/microblaze/kernel/head.S
@@ -31,6 +31,7 @@
31#include <linux/linkage.h> 31#include <linux/linkage.h>
32#include <asm/thread_info.h> 32#include <asm/thread_info.h>
33#include <asm/page.h> 33#include <asm/page.h>
34#include <asm/prom.h> /* for OF_DT_HEADER */
34 35
35#ifdef CONFIG_MMU 36#ifdef CONFIG_MMU
36#include <asm/setup.h> /* COMMAND_LINE_SIZE */ 37#include <asm/setup.h> /* COMMAND_LINE_SIZE */
@@ -54,11 +55,19 @@ ENTRY(_start)
54 andi r1, r1, ~2 55 andi r1, r1, ~2
55 mts rmsr, r1 56 mts rmsr, r1
56 57
57/* save fdt to kernel location */ 58/* r7 may point to an FDT, or there may be one linked in.
58/* r7 stores pointer to fdt blob */ 59 if it's in r7, we've got to save it away ASAP.
59 beqi r7, no_fdt_arg 60 We ensure r7 points to a valid FDT, just in case the bootloader
61 is broken or non-existent */
62 beqi r7, no_fdt_arg /* NULL pointer? don't copy */
63 lw r11, r0, r7 /* Does r7 point to a */
64 rsubi r11, r11, OF_DT_HEADER /* valid FDT? */
65 beqi r11, _prepare_copy_fdt
66 or r7, r0, r0 /* clear R7 when not valid DTB */
67 bnei r11, no_fdt_arg /* No - get out of here */
68_prepare_copy_fdt:
60 or r11, r0, r0 /* incremment */ 69 or r11, r0, r0 /* incremment */
61 ori r4, r0, TOPHYS(_fdt_start) /* save bram context */ 70 ori r4, r0, TOPHYS(_fdt_start)
62 ori r3, r0, (0x4000 - 4) 71 ori r3, r0, (0x4000 - 4)
63_copy_fdt: 72_copy_fdt:
64 lw r12, r7, r11 /* r12 = r7 + r11 */ 73 lw r12, r7, r11 /* r12 = r7 + r11 */
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S
index 9d591cd74fc2..3288c9737671 100644
--- a/arch/microblaze/kernel/hw_exception_handler.S
+++ b/arch/microblaze/kernel/hw_exception_handler.S
@@ -74,6 +74,7 @@
74 74
75#include <asm/mmu.h> 75#include <asm/mmu.h>
76#include <asm/pgtable.h> 76#include <asm/pgtable.h>
77#include <asm/signal.h>
77#include <asm/asm-offsets.h> 78#include <asm/asm-offsets.h>
78 79
79/* Helpful Macros */ 80/* Helpful Macros */
@@ -428,19 +429,9 @@ handle_unaligned_ex:
428 mfs r17, rbtr; /* ESR[DS] set - return address in BTR */ 429 mfs r17, rbtr; /* ESR[DS] set - return address in BTR */
429 nop 430 nop
430_no_delayslot: 431_no_delayslot:
431#endif 432 /* jump to high level unaligned handler */
432 433 RESTORE_STATE;
433#ifdef CONFIG_MMU 434 bri unaligned_data_trap
434 /* Check if unaligned address is last on a 4k page */
435 andi r5, r4, 0xffc
436 xori r5, r5, 0xffc
437 bnei r5, _unaligned_ex2
438 _unaligned_ex1:
439 RESTORE_STATE;
440/* Another page must be accessed or physical address not in page table */
441 bri unaligned_data_trap
442
443 _unaligned_ex2:
444#endif 435#endif
445 andi r6, r3, 0x3E0; /* Mask and extract the register operand */ 436 andi r6, r3, 0x3E0; /* Mask and extract the register operand */
446 srl r6, r6; /* r6 >> 5 */ 437 srl r6, r6; /* r6 >> 5 */
@@ -450,45 +441,6 @@ _no_delayslot:
450 srl r6, r6; 441 srl r6, r6;
451 /* Store the register operand in a temporary location */ 442 /* Store the register operand in a temporary location */
452 sbi r6, r0, TOPHYS(ex_reg_op); 443 sbi r6, r0, TOPHYS(ex_reg_op);
453#ifdef CONFIG_MMU
454 /* Get physical address */
455 /* If we are faulting a kernel address, we have to use the
456 * kernel page tables.
457 */
458 ori r5, r0, CONFIG_KERNEL_START
459 cmpu r5, r4, r5
460 bgti r5, _unaligned_ex3
461 ori r5, r0, swapper_pg_dir
462 bri _unaligned_ex4
463
464 /* Get the PGD for the current thread. */
465_unaligned_ex3: /* user thread */
466 addi r5 ,CURRENT_TASK, TOPHYS(0); /* get current task address */
467 lwi r5, r5, TASK_THREAD + PGDIR
468_unaligned_ex4:
469 tophys(r5,r5)
470 BSRLI(r6,r4,20) /* Create L1 (pgdir/pmd) address */
471 andi r6, r6, 0xffc
472/* Assume pgdir aligned on 4K boundary, no need for "andi r5,r5,0xfffff003" */
473 or r5, r5, r6
474 lwi r6, r5, 0 /* Get L1 entry */
475 andi r5, r6, 0xfffff000 /* Extract L2 (pte) base address. */
476 beqi r5, _unaligned_ex1 /* Bail if no table */
477
478 tophys(r5,r5)
479 BSRLI(r6,r4,10) /* Compute PTE address */
480 andi r6, r6, 0xffc
481 andi r5, r5, 0xfffff003
482 or r5, r5, r6
483 lwi r5, r5, 0 /* Get Linux PTE */
484
485 andi r6, r5, _PAGE_PRESENT
486 beqi r6, _unaligned_ex1 /* Bail if no page */
487
488 andi r5, r5, 0xfffff000 /* Extract RPN */
489 andi r4, r4, 0x00000fff /* Extract offset */
490 or r4, r4, r5 /* Create physical address */
491#endif /* CONFIG_MMU */
492 444
493 andi r6, r3, 0x400; /* Extract ESR[S] */ 445 andi r6, r3, 0x400; /* Extract ESR[S] */
494 bnei r6, ex_sw; 446 bnei r6, ex_sw;
@@ -959,15 +911,15 @@ _unaligned_data_exception:
959 andi r6, r3, 0x800; /* Extract ESR[W] - delay slot */ 911 andi r6, r3, 0x800; /* Extract ESR[W] - delay slot */
960ex_lw_vm: 912ex_lw_vm:
961 beqid r6, ex_lhw_vm; 913 beqid r6, ex_lhw_vm;
962 lbui r5, r4, 0; /* Exception address in r4 - delay slot */ 914load1: lbui r5, r4, 0; /* Exception address in r4 - delay slot */
963/* Load a word, byte-by-byte from destination address and save it in tmp space*/ 915/* Load a word, byte-by-byte from destination address and save it in tmp space*/
964 la r6, r0, ex_tmp_data_loc_0; 916 la r6, r0, ex_tmp_data_loc_0;
965 sbi r5, r6, 0; 917 sbi r5, r6, 0;
966 lbui r5, r4, 1; 918load2: lbui r5, r4, 1;
967 sbi r5, r6, 1; 919 sbi r5, r6, 1;
968 lbui r5, r4, 2; 920load3: lbui r5, r4, 2;
969 sbi r5, r6, 2; 921 sbi r5, r6, 2;
970 lbui r5, r4, 3; 922load4: lbui r5, r4, 3;
971 sbi r5, r6, 3; 923 sbi r5, r6, 3;
972 brid ex_lw_tail_vm; 924 brid ex_lw_tail_vm;
973/* Get the destination register value into r3 - delay slot */ 925/* Get the destination register value into r3 - delay slot */
@@ -977,7 +929,7 @@ ex_lhw_vm:
977 * save it in tmp space */ 929 * save it in tmp space */
978 la r6, r0, ex_tmp_data_loc_0; 930 la r6, r0, ex_tmp_data_loc_0;
979 sbi r5, r6, 0; 931 sbi r5, r6, 0;
980 lbui r5, r4, 1; 932load5: lbui r5, r4, 1;
981 sbi r5, r6, 1; 933 sbi r5, r6, 1;
982 lhui r3, r6, 0; /* Get the destination register value into r3 */ 934 lhui r3, r6, 0; /* Get the destination register value into r3 */
983ex_lw_tail_vm: 935ex_lw_tail_vm:
@@ -996,22 +948,53 @@ ex_sw_tail_vm:
996 swi r3, r5, 0; /* Get the word - delay slot */ 948 swi r3, r5, 0; /* Get the word - delay slot */
997 /* Store the word, byte-by-byte into destination address */ 949 /* Store the word, byte-by-byte into destination address */
998 lbui r3, r5, 0; 950 lbui r3, r5, 0;
999 sbi r3, r4, 0; 951store1: sbi r3, r4, 0;
1000 lbui r3, r5, 1; 952 lbui r3, r5, 1;
1001 sbi r3, r4, 1; 953store2: sbi r3, r4, 1;
1002 lbui r3, r5, 2; 954 lbui r3, r5, 2;
1003 sbi r3, r4, 2; 955store3: sbi r3, r4, 2;
1004 lbui r3, r5, 3; 956 lbui r3, r5, 3;
1005 brid ret_from_exc; 957 brid ret_from_exc;
1006 sbi r3, r4, 3; /* Delay slot */ 958store4: sbi r3, r4, 3; /* Delay slot */
1007ex_shw_vm: 959ex_shw_vm:
1008 /* Store the lower half-word, byte-by-byte into destination address */ 960 /* Store the lower half-word, byte-by-byte into destination address */
1009 lbui r3, r5, 2; 961 lbui r3, r5, 2;
1010 sbi r3, r4, 0; 962store5: sbi r3, r4, 0;
1011 lbui r3, r5, 3; 963 lbui r3, r5, 3;
1012 brid ret_from_exc; 964 brid ret_from_exc;
1013 sbi r3, r4, 1; /* Delay slot */ 965store6: sbi r3, r4, 1; /* Delay slot */
1014ex_sw_end_vm: /* Exception handling of store word, ends. */ 966ex_sw_end_vm: /* Exception handling of store word, ends. */
967
968/* We have to prevent cases that get/put_user macros get unaligned pointer
969 * to bad page area. We have to find out which origin instruction caused it
970 * and called fixup for that origin instruction not instruction in unaligned
971 * handler */
972ex_unaligned_fixup:
973 ori r5, r7, 0 /* setup pointer to pt_regs */
974 lwi r6, r7, PT_PC; /* faulting address is one instruction above */
975 addik r6, r6, -4 /* for finding proper fixup */
976 swi r6, r7, PT_PC; /* a save back it to PT_PC */
977 addik r7, r0, SIGSEGV
978 /* call bad_page_fault for finding aligned fixup, fixup address is saved
979 * in PT_PC which is used as return address from exception */
980 la r15, r0, ret_from_exc-8 /* setup return address */
981 brid bad_page_fault
982 nop
983
984/* We prevent all load/store because it could failed any attempt to access */
985.section __ex_table,"a";
986 .word load1,ex_unaligned_fixup;
987 .word load2,ex_unaligned_fixup;
988 .word load3,ex_unaligned_fixup;
989 .word load4,ex_unaligned_fixup;
990 .word load5,ex_unaligned_fixup;
991 .word store1,ex_unaligned_fixup;
992 .word store2,ex_unaligned_fixup;
993 .word store3,ex_unaligned_fixup;
994 .word store4,ex_unaligned_fixup;
995 .word store5,ex_unaligned_fixup;
996 .word store6,ex_unaligned_fixup;
997.previous;
1015.end _unaligned_data_exception 998.end _unaligned_data_exception
1016#endif /* CONFIG_MMU */ 999#endif /* CONFIG_MMU */
1017 1000
diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c
index 51414171326f..5a45b1adfef1 100644
--- a/arch/microblaze/kernel/module.c
+++ b/arch/microblaze/kernel/module.c
@@ -57,7 +57,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
57 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 57 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
58 Elf32_Sym *sym; 58 Elf32_Sym *sym;
59 unsigned long int *location; 59 unsigned long int *location;
60 unsigned long int locoffs;
61 unsigned long int value; 60 unsigned long int value;
62#if __GNUC__ < 4 61#if __GNUC__ < 4
63 unsigned long int old_value; 62 unsigned long int old_value;
@@ -113,10 +112,12 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
113 break; 112 break;
114 113
115 case R_MICROBLAZE_64_PCREL: 114 case R_MICROBLAZE_64_PCREL:
116 locoffs = (location[0] & 0xFFFF) << 16 | 115#if __GNUC__ < 4
116 old_value = (location[0] & 0xFFFF) << 16 |
117 (location[1] & 0xFFFF); 117 (location[1] & 0xFFFF);
118 value -= (unsigned long int)(location) + 4 + 118 value -= old_value;
119 locoffs; 119#endif
120 value -= (unsigned long int)(location) + 4;
120 location[0] = (location[0] & 0xFFFF0000) | 121 location[0] = (location[0] & 0xFFFF0000) |
121 (value >> 16); 122 (value >> 16);
122 location[1] = (location[1] & 0xFFFF0000) | 123 location[1] = (location[1] & 0xFFFF0000) |
@@ -125,6 +126,14 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
125 value); 126 value);
126 break; 127 break;
127 128
129 case R_MICROBLAZE_32_PCREL_LO:
130 pr_debug("R_MICROBLAZE_32_PCREL_LO\n");
131 break;
132
133 case R_MICROBLAZE_64_NONE:
134 pr_debug("R_MICROBLAZE_NONE\n");
135 break;
136
128 case R_MICROBLAZE_NONE: 137 case R_MICROBLAZE_NONE:
129 pr_debug("R_MICROBLAZE_NONE\n"); 138 pr_debug("R_MICROBLAZE_NONE\n");
130 break; 139 break;
@@ -133,7 +142,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
133 printk(KERN_ERR "module %s: " 142 printk(KERN_ERR "module %s: "
134 "Unknown relocation: %u\n", 143 "Unknown relocation: %u\n",
135 module->name, 144 module->name,
136 ELF32_R_TYPE(rela->r_info)); 145 ELF32_R_TYPE(rela[i].r_info));
137 return -ENOEXEC; 146 return -ENOEXEC;
138 } 147 }
139 } 148 }
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 8709bea09604..2a97bf513b64 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -138,8 +138,12 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
138 setup_early_printk(NULL); 138 setup_early_printk(NULL);
139#endif 139#endif
140 140
141 early_printk("Ramdisk addr 0x%08x, FDT 0x%08x\n", ram, fdt); 141 early_printk("Ramdisk addr 0x%08x, ", ram);
142 printk(KERN_NOTICE "Found FDT at 0x%08x\n", fdt); 142 if (fdt)
143 early_printk("FDT at 0x%08x\n", fdt);
144 else
145 early_printk("Compiled-in FDT at 0x%08x\n",
146 (unsigned int)_fdt_start);
143 147
144#ifdef CONFIG_MTD_UCLINUX 148#ifdef CONFIG_MTD_UCLINUX
145 early_printk("Found romfs @ 0x%08x (0x%08x)\n", 149 early_printk("Found romfs @ 0x%08x (0x%08x)\n",
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
index e000bce09b2b..b96f1682bb24 100644
--- a/arch/microblaze/kernel/sys_microblaze.c
+++ b/arch/microblaze/kernel/sys_microblaze.c
@@ -33,105 +33,6 @@
33#include <linux/unistd.h> 33#include <linux/unistd.h>
34 34
35#include <asm/syscalls.h> 35#include <asm/syscalls.h>
36/*
37 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
38 *
39 * This is really horribly ugly. This will be remove with new toolchain.
40 */
41asmlinkage long
42sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth)
43{
44 int version, ret;
45
46 version = call >> 16; /* hack for backward compatibility */
47 call &= 0xffff;
48
49 ret = -EINVAL;
50 switch (call) {
51 case SEMOP:
52 ret = sys_semop(first, (struct sembuf *)ptr, second);
53 break;
54 case SEMGET:
55 ret = sys_semget(first, second, third);
56 break;
57 case SEMCTL:
58 {
59 union semun fourth;
60
61 if (!ptr)
62 break;
63 ret = (access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
64 || (get_user(fourth.__pad, (void **)ptr)) ;
65 if (ret)
66 break;
67 ret = sys_semctl(first, second, third, fourth);
68 break;
69 }
70 case MSGSND:
71 ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third);
72 break;
73 case MSGRCV:
74 switch (version) {
75 case 0: {
76 struct ipc_kludge tmp;
77
78 if (!ptr)
79 break;
80 ret = (access_ok(VERIFY_READ, ptr, sizeof(tmp))
81 ? 0 : -EFAULT) || copy_from_user(&tmp,
82 (struct ipc_kludge *) ptr, sizeof(tmp));
83 if (ret)
84 break;
85 ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp,
86 third);
87 break;
88 }
89 default:
90 ret = sys_msgrcv(first, (struct msgbuf *) ptr,
91 second, fifth, third);
92 break;
93 }
94 break;
95 case MSGGET:
96 ret = sys_msgget((key_t) first, second);
97 break;
98 case MSGCTL:
99 ret = sys_msgctl(first, second, (struct msqid_ds *) ptr);
100 break;
101 case SHMAT:
102 switch (version) {
103 default: {
104 ulong raddr;
105 ret = access_ok(VERIFY_WRITE, (ulong *) third,
106 sizeof(ulong)) ? 0 : -EFAULT;
107 if (ret)
108 break;
109 ret = do_shmat(first, (char *) ptr, second, &raddr);
110 if (ret)
111 break;
112 ret = put_user(raddr, (ulong *) third);
113 break;
114 }
115 case 1: /* iBCS2 emulator entry point */
116 if (!segment_eq(get_fs(), get_ds()))
117 break;
118 ret = do_shmat(first, (char *) ptr, second,
119 (ulong *) third);
120 break;
121 }
122 break;
123 case SHMDT:
124 ret = sys_shmdt((char *)ptr);
125 break;
126 case SHMGET:
127 ret = sys_shmget(first, second, third);
128 break;
129 case SHMCTL:
130 ret = sys_shmctl(first, second, (struct shmid_ds *) ptr);
131 break;
132 }
133 return ret;
134}
135 36
136asmlinkage long microblaze_vfork(struct pt_regs *regs) 37asmlinkage long microblaze_vfork(struct pt_regs *regs)
137{ 38{
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index 31b32a6c5f4e..216db817beb6 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -121,7 +121,7 @@ ENTRY(sys_call_table)
121 .long sys_wait4 121 .long sys_wait4
122 .long sys_swapoff /* 115 */ 122 .long sys_swapoff /* 115 */
123 .long sys_sysinfo 123 .long sys_sysinfo
124 .long sys_ipc 124 .long sys_ni_syscall /* old sys_ipc */
125 .long sys_fsync 125 .long sys_fsync
126 .long sys_ni_syscall /* sys_sigreturn_wrapper */ 126 .long sys_ni_syscall /* sys_sigreturn_wrapper */
127 .long sys_clone /* 120 */ 127 .long sys_clone /* 120 */
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c
index 956607a63f4c..d9d249a66ff2 100644
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -69,7 +69,7 @@ static int store_updates_sp(struct pt_regs *regs)
69 * It is called from do_page_fault above and from some of the procedures 69 * It is called from do_page_fault above and from some of the procedures
70 * in traps.c. 70 * in traps.c.
71 */ 71 */
72static void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) 72void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
73{ 73{
74 const struct exception_table_entry *fixup; 74 const struct exception_table_entry *fixup;
75/* MS: no context */ 75/* MS: no context */
@@ -122,15 +122,10 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
122 } 122 }
123#endif /* CONFIG_KGDB */ 123#endif /* CONFIG_KGDB */
124 124
125 if (in_atomic() || mm == NULL) { 125 if (in_atomic() || !mm) {
126 /* FIXME */ 126 if (kernel_mode(regs))
127 if (kernel_mode(regs)) { 127 goto bad_area_nosemaphore;
128 printk(KERN_EMERG 128
129 "Page fault in kernel mode - Oooou!!! pid %d\n",
130 current->pid);
131 _exception(SIGSEGV, regs, code, address);
132 return;
133 }
134 /* in_atomic() in user mode is really bad, 129 /* in_atomic() in user mode is really bad,
135 as is current->mm == NULL. */ 130 as is current->mm == NULL. */
136 printk(KERN_EMERG "Page fault in user mode with " 131 printk(KERN_EMERG "Page fault in user mode with "