aboutsummaryrefslogtreecommitdiffstats
path: root/arch/openrisc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/openrisc')
-rw-r--r--arch/openrisc/Kconfig207
-rw-r--r--arch/openrisc/Makefile55
-rw-r--r--arch/openrisc/README.openrisc99
-rw-r--r--arch/openrisc/TODO.openrisc16
-rw-r--r--arch/openrisc/boot/Makefile15
-rw-r--r--arch/openrisc/boot/dts/or1ksim.dts50
-rw-r--r--arch/openrisc/configs/or1ksim_defconfig65
-rw-r--r--arch/openrisc/include/asm/Kbuild64
-rw-r--r--arch/openrisc/include/asm/asm-offsets.h1
-rw-r--r--arch/openrisc/include/asm/bitops.h59
-rw-r--r--arch/openrisc/include/asm/bitops/__ffs.h33
-rw-r--r--arch/openrisc/include/asm/bitops/__fls.h33
-rw-r--r--arch/openrisc/include/asm/bitops/ffs.h32
-rw-r--r--arch/openrisc/include/asm/bitops/fls.h33
-rw-r--r--arch/openrisc/include/asm/byteorder.h1
-rw-r--r--arch/openrisc/include/asm/cache.h29
-rw-r--r--arch/openrisc/include/asm/cpuinfo.h34
-rw-r--r--arch/openrisc/include/asm/delay.h24
-rw-r--r--arch/openrisc/include/asm/dma-mapping.h189
-rw-r--r--arch/openrisc/include/asm/elf.h108
-rw-r--r--arch/openrisc/include/asm/fixmap.h87
-rw-r--r--arch/openrisc/include/asm/gpio.h65
-rw-r--r--arch/openrisc/include/asm/io.h51
-rw-r--r--arch/openrisc/include/asm/irq.h27
-rw-r--r--arch/openrisc/include/asm/irqflags.h29
-rw-r--r--arch/openrisc/include/asm/linkage.h25
-rw-r--r--arch/openrisc/include/asm/memblock.h24
-rw-r--r--arch/openrisc/include/asm/mmu.h26
-rw-r--r--arch/openrisc/include/asm/mmu_context.h43
-rw-r--r--arch/openrisc/include/asm/mutex.h27
-rw-r--r--arch/openrisc/include/asm/page.h110
-rw-r--r--arch/openrisc/include/asm/param.h26
-rw-r--r--arch/openrisc/include/asm/pgalloc.h102
-rw-r--r--arch/openrisc/include/asm/pgtable.h463
-rw-r--r--arch/openrisc/include/asm/processor.h113
-rw-r--r--arch/openrisc/include/asm/prom.h77
-rw-r--r--arch/openrisc/include/asm/ptrace.h131
-rw-r--r--arch/openrisc/include/asm/serial.h36
-rw-r--r--arch/openrisc/include/asm/sigcontext.h33
-rw-r--r--arch/openrisc/include/asm/spinlock.h24
-rw-r--r--arch/openrisc/include/asm/spr.h42
-rw-r--r--arch/openrisc/include/asm/spr_defs.h604
-rw-r--r--arch/openrisc/include/asm/syscall.h77
-rw-r--r--arch/openrisc/include/asm/syscalls.h27
-rw-r--r--arch/openrisc/include/asm/system.h35
-rw-r--r--arch/openrisc/include/asm/thread_info.h134
-rw-r--r--arch/openrisc/include/asm/timex.h36
-rw-r--r--arch/openrisc/include/asm/tlb.h34
-rw-r--r--arch/openrisc/include/asm/tlbflush.h55
-rw-r--r--arch/openrisc/include/asm/uaccess.h355
-rw-r--r--arch/openrisc/include/asm/unaligned.h51
-rw-r--r--arch/openrisc/include/asm/unistd.h31
-rw-r--r--arch/openrisc/kernel/Makefile14
-rw-r--r--arch/openrisc/kernel/asm-offsets.c70
-rw-r--r--arch/openrisc/kernel/dma.c217
-rw-r--r--arch/openrisc/kernel/entry.S1128
-rw-r--r--arch/openrisc/kernel/head.S1607
-rw-r--r--arch/openrisc/kernel/idle.c77
-rw-r--r--arch/openrisc/kernel/init_task.c41
-rw-r--r--arch/openrisc/kernel/irq.c172
-rw-r--r--arch/openrisc/kernel/module.c72
-rw-r--r--arch/openrisc/kernel/or32_ksyms.c46
-rw-r--r--arch/openrisc/kernel/process.c311
-rw-r--r--arch/openrisc/kernel/prom.c108
-rw-r--r--arch/openrisc/kernel/ptrace.c211
-rw-r--r--arch/openrisc/kernel/setup.c381
-rw-r--r--arch/openrisc/kernel/signal.c389
-rw-r--r--arch/openrisc/kernel/sys_call_table.c28
-rw-r--r--arch/openrisc/kernel/sys_or32.c57
-rw-r--r--arch/openrisc/kernel/time.c181
-rw-r--r--arch/openrisc/kernel/traps.c366
-rw-r--r--arch/openrisc/kernel/vmlinux.h12
-rw-r--r--arch/openrisc/kernel/vmlinux.lds.S115
-rw-r--r--arch/openrisc/lib/Makefile5
-rw-r--r--arch/openrisc/lib/delay.c60
-rw-r--r--arch/openrisc/lib/string.S204
-rw-r--r--arch/openrisc/mm/Makefile5
-rw-r--r--arch/openrisc/mm/fault.c338
-rw-r--r--arch/openrisc/mm/init.c283
-rw-r--r--arch/openrisc/mm/ioremap.c137
-rw-r--r--arch/openrisc/mm/tlb.c193
81 files changed, 10975 insertions, 0 deletions
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
new file mode 100644
index 00000000000..4558bafbd1a
--- /dev/null
+++ b/arch/openrisc/Kconfig
@@ -0,0 +1,207 @@
1#
2# For a description of the syntax of this configuration file,
3# see Documentation/kbuild/config-language.txt.
4#
5
6config OPENRISC
7 def_bool y
8 select OF
9 select OF_EARLY_FLATTREE
10 select HAVE_MEMBLOCK
11 select ARCH_WANT_OPTIONAL_GPIOLIB
12 select HAVE_ARCH_TRACEHOOK
13 select HAVE_GENERIC_HARDIRQS
14 select GENERIC_IRQ_CHIP
15 select GENERIC_IRQ_PROBE
16 select GENERIC_IRQ_SHOW
17 select GENERIC_IOMAP
18
19config MMU
20 def_bool y
21
22config WISHBONE_BUS_BIG_ENDIAN
23 def_bool y
24
25config SYMBOL_PREFIX
26 string
27 default ""
28
29config HAVE_DMA_ATTRS
30 def_bool y
31
32config UID16
33 def_bool y
34
35config RWSEM_GENERIC_SPINLOCK
36 def_bool y
37
38config RWSEM_XCHGADD_ALGORITHM
39 def_bool n
40
41config GENERIC_HWEIGHT
42 def_bool y
43
44config GENERIC_IOMAP
45 def_bool y
46
47config NO_IOPORT
48 def_bool y
49
50config GENERIC_GPIO
51 def_bool y
52
53config GENERIC_CLOCKEVENTS
54 def_bool y
55
56config TRACE_IRQFLAGS_SUPPORT
57 def_bool y
58
59# For now, use generic checksum functions
60#These can be reimplemented in assembly later if so inclined
61config GENERIC_CSUM
62 def_bool y
63
64config GENERIC_FIND_NEXT_BIT
65 def_bool y
66
67source "init/Kconfig"
68
69
70menu "Processor type and features"
71
72choice
73 prompt "Subarchitecture"
74 default OR1K_1200
75
76config OR1K_1200
77 bool "OR1200"
78 help
79 Generic OpenRISC 1200 architecture
80
81endchoice
82
83config OPENRISC_BUILTIN_DTB
84 string "Builtin DTB"
85 default ""
86
87menu "Class II Instructions"
88
89config OPENRISC_HAVE_INST_FF1
90 bool "Have instruction l.ff1"
91 default y
92 help
93 Select this if your implementation has the Class II instruction l.ff1
94
95config OPENRISC_HAVE_INST_FL1
96 bool "Have instruction l.fl1"
97 default y
98 help
99 Select this if your implementation has the Class II instruction l.fl1
100
101config OPENRISC_HAVE_INST_MUL
102 bool "Have instruction l.mul for hardware multiply"
103 default y
104 help
105 Select this if your implementation has a hardware multiply instruction
106
107config OPENRISC_HAVE_INST_DIV
108 bool "Have instruction l.div for hardware divide"
109 default y
110 help
111 Select this if your implementation has a hardware divide instruction
112endmenu
113
114
115source "kernel/time/Kconfig"
116source kernel/Kconfig.hz
117source kernel/Kconfig.preempt
118source "mm/Kconfig"
119
120config OPENRISC_NO_SPR_SR_DSX
121 bool "use SPR_SR_DSX software emulation" if OR1K_1200
122 default y
123 help
124 SPR_SR_DSX bit is status register bit indicating whether
125 the last exception has happened in delay slot.
126
127 OpenRISC architecture makes it optional to have it implemented
128 in hardware and the OR1200 does not have it.
129
130 Say N here if you know that your OpenRISC processor has
131 SPR_SR_DSX bit implemented. Say Y if you are unsure.
132
133config CMDLINE
134 string "Default kernel command string"
135 default ""
136 help
137 On some architectures there is currently no way for the boot loader
138 to pass arguments to the kernel. For these architectures, you should
139 supply some command-line options at build time by entering them
140 here.
141
142menu "Debugging options"
143
144config DEBUG_STACKOVERFLOW
145 bool "Check for kernel stack overflow"
146 default y
147 help
148 Make extra checks for space avaliable on stack in some
149 critical functions. This will cause kernel to run a bit slower,
150 but will catch most of kernel stack overruns and exit gracefuly.
151
152 Say Y if you are unsure.
153
154config JUMP_UPON_UNHANDLED_EXCEPTION
155 bool "Try to die gracefully"
156 default y
157 help
158 Now this puts kernel into infinite loop after first oops. Till
159 your kernel crashes this doesn't have any influence.
160
161 Say Y if you are unsure.
162
163config OPENRISC_EXCEPTION_DEBUG
164 bool "Print processor state at each exception"
165 default n
166 help
167 This option will make your kernel unusable for all but kernel
168 debugging.
169
170 Say N if you are unsure.
171
172config OPENRISC_ESR_EXCEPTION_BUG_CHECK
173 bool "Check for possible ESR exception bug"
174 default n
175 help
176 This option enables some checks that might expose some problems
177 in kernel.
178
179 Say N if you are unsure.
180
181endmenu
182
183endmenu
184
185menu "Executable file formats"
186
187source "fs/Kconfig.binfmt"
188
189endmenu
190
191source "net/Kconfig"
192
193source "drivers/Kconfig"
194
195source "fs/Kconfig"
196
197source "security/Kconfig"
198
199source "crypto/Kconfig"
200
201source "lib/Kconfig"
202
203menu "Kernel hacking"
204
205source "lib/Kconfig.debug"
206
207endmenu
diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile
new file mode 100644
index 00000000000..158ae4c0dc6
--- /dev/null
+++ b/arch/openrisc/Makefile
@@ -0,0 +1,55 @@
1# BK Id: %F% %I% %G% %U% %#%
2#
3# This file is included by the global makefile so that you can add your own
4# architecture-specific flags and dependencies. Remember to do have actions
5# for "archclean" and "archdep" for cleaning up and making dependencies for
6# this architecture
7#
8# This file is subject to the terms and conditions of the GNU General Public
9# License. See the file "COPYING" in the main directory of this archive
10# for more details.
11#
12# Copyright (C) 1994 by Linus Torvalds
13# Modifications for the OpenRISC architecture:
14# Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
15# Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
16#
17# Based on:
18# arch/i386/Makefile
19
20KBUILD_DEFCONFIG := or1ksim_defconfig
21
22LDFLAGS :=
23OBJCOPYFLAGS := -O binary -R .note -R .comment -S
24LDFLAGS_vmlinux :=
25LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
26
27KBUILD_CFLAGS += -pipe -ffixed-r10
28
29ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y)
30 KBUILD_CFLAGS += $(call cc-option,-mhard-mul)
31else
32 KBUILD_CFLAGS += $(call cc-option,-msoft-mul)
33endif
34
35ifeq ($(CONFIG_OPENRISC_HAVE_INST_DIV),y)
36 KBUILD_CFLAGS += $(call cc-option,-mhard-div)
37else
38 KBUILD_CFLAGS += $(call cc-option,-msoft-div)
39endif
40
41head-y := arch/openrisc/kernel/head.o arch/openrisc/kernel/init_task.o
42
43core-y += arch/openrisc/lib/ \
44 arch/openrisc/kernel/ \
45 arch/openrisc/mm/
46libs-y += $(LIBGCC)
47
48ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
49BUILTIN_DTB := y
50else
51BUILTIN_DTB := n
52endif
53core-$(BUILTIN_DTB) += arch/openrisc/boot/
54
55all: vmlinux
diff --git a/arch/openrisc/README.openrisc b/arch/openrisc/README.openrisc
new file mode 100644
index 00000000000..c9f7edf2b9a
--- /dev/null
+++ b/arch/openrisc/README.openrisc
@@ -0,0 +1,99 @@
1OpenRISC Linux
2==============
3
4This is a port of Linux to the OpenRISC class of microprocessors; the initial
5target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
6
7For information about OpenRISC processors and ongoing development:
8
9 website http://openrisc.net
10
11For more information about Linux on OpenRISC, please contact South Pole AB.
12
13 email: info@southpole.se
14
15 website: http://southpole.se
16 http://southpoleconsulting.com
17
18---------------------------------------------------------------------
19
20Build instructions for OpenRISC toolchain and Linux
21===================================================
22
23In order to build and run Linux for OpenRISC, you'll need at least a basic
24toolchain and, perhaps, the architectural simulator. Steps to get these bits
25in place are outlined here.
26
271) The toolchain can be obtained from openrisc.net. Instructions for building
28a toolchain can be found at:
29
30http://openrisc.net/toolchain-build.html
31
322) or1ksim (optional)
33
34or1ksim is the architectural simulator which will allow you to actually run
35your OpenRISC Linux kernel if you don't have an OpenRISC processor at hand.
36
37 git clone git://openrisc.net/jonas/or1ksim-svn
38
39 cd or1ksim
40 ./configure --prefix=$OPENRISC_PREFIX
41 make
42 make install
43
443) Linux kernel
45
46Build the kernel as usual
47
48 make ARCH=openrisc defconfig
49 make ARCH=openrisc
50
514) Run in architectural simulator
52
53Grab the or1ksim platform configuration file (from the or1ksim source) and
54together with your freshly built vmlinux, run your kernel with the following
55incantation:
56
57 sim -f arch/openrisc/or1ksim.cfg vmlinux
58
59---------------------------------------------------------------------
60
61Terminology
62===========
63
64In the code, the following particles are used on symbols to limit the scope
65to more or less specific processor implementations:
66
67openrisc: the OpenRISC class of processors
68or1k: the OpenRISC 1000 family of processors
69or1200: the OpenRISC 1200 processor
70
71---------------------------------------------------------------------
72
73History
74========
75
7618. 11. 2003 Matjaz Breskvar (phoenix@bsemi.com)
77 initial port of linux to OpenRISC/or32 architecture.
78 all the core stuff is implemented and seams usable.
79
8008. 12. 2003 Matjaz Breskvar (phoenix@bsemi.com)
81 complete change of TLB miss handling.
82 rewrite of exceptions handling.
83 fully functional sash-3.6 in default initrd.
84 a much improved version with changes all around.
85
8610. 04. 2004 Matjaz Breskvar (phoenix@bsemi.com)
87 alot of bugfixes all over.
88 ethernet support, functional http and telnet servers.
89 running many standard linux apps.
90
9126. 06. 2004 Matjaz Breskvar (phoenix@bsemi.com)
92 port to 2.6.x
93
9430. 11. 2004 Matjaz Breskvar (phoenix@bsemi.com)
95 lots of bugfixes and enhancments.
96 added opencores framebuffer driver.
97
9809. 10. 2010 Jonas Bonn (jonas@southpole.se)
99 major rewrite to bring up to par with upstream Linux 2.6.36
diff --git a/arch/openrisc/TODO.openrisc b/arch/openrisc/TODO.openrisc
new file mode 100644
index 00000000000..acfeef9c58e
--- /dev/null
+++ b/arch/openrisc/TODO.openrisc
@@ -0,0 +1,16 @@
1The OpenRISC Linux port is fully functional and has been tracking upstream
2since 2.6.35. There are, however, remaining items to be completed within
3the coming months. Here's a list of known-to-be-less-than-stellar items
4that are due for investigation shortly, i.e. our TODO list:
5
6-- Implement the rest of the DMA API... dma_map_sg, etc.
7
8-- Consolidate usage of memblock and bootmem... move everything over to
9 memblock.
10
11-- Finish the renaming cleanup... there are references to or32 in the code
12 which was an older name for the architecture. The name we've settled on is
13 or1k and this change is slowly trickling through the stack. For the time
14 being, or32 is equivalent to or1k.
15
16-- Implement optimized version of memcpy and memset
diff --git a/arch/openrisc/boot/Makefile b/arch/openrisc/boot/Makefile
new file mode 100644
index 00000000000..98ca185097a
--- /dev/null
+++ b/arch/openrisc/boot/Makefile
@@ -0,0 +1,15 @@
1
2
3ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
4BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_OPENRISC_BUILTIN_DTB)).dtb.o
5else
6BUILTIN_DTB :=
7endif
8obj-y += $(BUILTIN_DTB)
9
10clean-files := *.dtb.S
11
12#DTC_FLAGS ?= -p 1024
13
14$(obj)/%.dtb: $(src)/dts/%.dts
15 $(call cmd,dtc)
diff --git a/arch/openrisc/boot/dts/or1ksim.dts b/arch/openrisc/boot/dts/or1ksim.dts
new file mode 100644
index 00000000000..5d4f9027afa
--- /dev/null
+++ b/arch/openrisc/boot/dts/or1ksim.dts
@@ -0,0 +1,50 @@
1/dts-v1/;
2/ {
3 compatible = "opencores,or1ksim";
4 #address-cells = <1>;
5 #size-cells = <1>;
6 interrupt-parent = <&pic>;
7
8 chosen {
9 bootargs = "console=uart,mmio,0x90000000,115200";
10 };
11
12 memory@0 {
13 device_type = "memory";
14 reg = <0x00000000 0x02000000>;
15 };
16
17 cpus {
18 #address-cells = <1>;
19 #size-cells = <0>;
20 cpu@0 {
21 compatible = "opencores,or1200-rtlsvn481";
22 reg = <0>;
23 clock-frequency = <20000000>;
24 };
25 };
26
27 /*
28 * OR1K PIC is built into CPU and accessed via special purpose
29 * registers. It is not addressable and, hence, has no 'reg'
30 * property.
31 */
32 pic: pic {
33 compatible = "opencores,or1k-pic";
34 #interrupt-cells = <1>;
35 interrupt-controller;
36 };
37
38 serial0: serial@90000000 {
39 compatible = "opencores,uart16550-rtlsvn105", "ns16550a";
40 reg = <0x90000000 0x100>;
41 interrupts = <2>;
42 clock-frequency = <20000000>;
43 };
44
45 enet0: ethoc@92000000 {
46 compatible = "opencores,ethmac-rtlsvn338";
47 reg = <0x92000000 0x100>;
48 interrupts = <4>;
49 };
50};
diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig
new file mode 100644
index 00000000000..ea172bdfa36
--- /dev/null
+++ b/arch/openrisc/configs/or1ksim_defconfig
@@ -0,0 +1,65 @@
1CONFIG_CROSS_COMPILE="or32-linux-"
2CONFIG_LOG_BUF_SHIFT=14
3CONFIG_BLK_DEV_INITRD=y
4# CONFIG_RD_GZIP is not set
5CONFIG_EXPERT=y
6# CONFIG_SYSCTL_SYSCALL is not set
7# CONFIG_KALLSYMS is not set
8# CONFIG_EPOLL is not set
9# CONFIG_TIMERFD is not set
10# CONFIG_EVENTFD is not set
11# CONFIG_AIO is not set
12# CONFIG_VM_EVENT_COUNTERS is not set
13# CONFIG_COMPAT_BRK is not set
14CONFIG_SLOB=y
15CONFIG_MODULES=y
16# CONFIG_BLOCK is not set
17CONFIG_OPENRISC_BUILTIN_DTB="or1ksim"
18CONFIG_NO_HZ=y
19CONFIG_HZ_100=y
20CONFIG_NET=y
21CONFIG_PACKET=y
22CONFIG_UNIX=y
23CONFIG_INET=y
24# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
25# CONFIG_INET_XFRM_MODE_TUNNEL is not set
26# CONFIG_INET_XFRM_MODE_BEET is not set
27# CONFIG_INET_LRO is not set
28# CONFIG_INET_DIAG is not set
29CONFIG_TCP_CONG_ADVANCED=y
30# CONFIG_TCP_CONG_BIC is not set
31# CONFIG_TCP_CONG_CUBIC is not set
32# CONFIG_TCP_CONG_WESTWOOD is not set
33# CONFIG_TCP_CONG_HTCP is not set
34# CONFIG_IPV6 is not set
35# CONFIG_WIRELESS is not set
36CONFIG_DEVTMPFS=y
37CONFIG_DEVTMPFS_MOUNT=y
38# CONFIG_PREVENT_FIRMWARE_BUILD is not set
39# CONFIG_FW_LOADER is not set
40CONFIG_PROC_DEVICETREE=y
41CONFIG_NETDEVICES=y
42CONFIG_MICREL_PHY=y
43CONFIG_NET_ETHERNET=y
44CONFIG_ETHOC=y
45# CONFIG_NETDEV_1000 is not set
46# CONFIG_NETDEV_10000 is not set
47# CONFIG_WLAN is not set
48# CONFIG_INPUT is not set
49# CONFIG_SERIO is not set
50# CONFIG_VT is not set
51# CONFIG_LEGACY_PTYS is not set
52# CONFIG_DEVKMEM is not set
53CONFIG_SERIAL_8250=y
54CONFIG_SERIAL_8250_CONSOLE=y
55CONFIG_SERIAL_OF_PLATFORM=y
56# CONFIG_HW_RANDOM is not set
57# CONFIG_HWMON is not set
58# CONFIG_MFD_SUPPORT is not set
59# CONFIG_USB_SUPPORT is not set
60# CONFIG_DNOTIFY is not set
61CONFIG_TMPFS=y
62CONFIG_NFS_FS=y
63CONFIG_NFS_V3=y
64# CONFIG_ENABLE_WARN_DEPRECATED is not set
65# CONFIG_ENABLE_MUST_CHECK is not set
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
new file mode 100644
index 00000000000..11162e6c878
--- /dev/null
+++ b/arch/openrisc/include/asm/Kbuild
@@ -0,0 +1,64 @@
1include include/asm-generic/Kbuild.asm
2
3header-y += spr_defs.h
4
5generic-y += atomic.h
6generic-y += auxvec.h
7generic-y += bitsperlong.h
8generic-y += bug.h
9generic-y += bugs.h
10generic-y += cacheflush.h
11generic-y += checksum.h
12generic-y += cmpxchg.h
13generic-y += cmpxchg-local.h
14generic-y += cpumask.h
15generic-y += cputime.h
16generic-y += current.h
17generic-y += device.h
18generic-y += div64.h
19generic-y += dma.h
20generic-y += emergency-restart.h
21generic-y += errno.h
22generic-y += fb.h
23generic-y += fcntl.h
24generic-y += ftrace.h
25generic-y += futex.h
26generic-y += hardirq.h
27generic-y += hw_irq.h
28generic-y += ioctl.h
29generic-y += ioctls.h
30generic-y += ipcbuf.h
31generic-y += irq_regs.h
32generic-y += kdebug.h
33generic-y += kmap_types.h
34generic-y += local.h
35generic-y += mman.h
36generic-y += module.h
37generic-y += msgbuf.h
38generic-y += pci.h
39generic-y += percpu.h
40generic-y += poll.h
41generic-y += posix_types.h
42generic-y += resource.h
43generic-y += rmap.h
44generic-y += scatterlist.h
45generic-y += sections.h
46generic-y += segment.h
47generic-y += sembuf.h
48generic-y += setup.h
49generic-y += shmbuf.h
50generic-y += shmparam.h
51generic-y += siginfo.h
52generic-y += signal.h
53generic-y += socket.h
54generic-y += sockios.h
55generic-y += statfs.h
56generic-y += stat.h
57generic-y += string.h
58generic-y += swab.h
59generic-y += termbits.h
60generic-y += termios.h
61generic-y += topology.h
62generic-y += types.h
63generic-y += ucontext.h
64generic-y += user.h
diff --git a/arch/openrisc/include/asm/asm-offsets.h b/arch/openrisc/include/asm/asm-offsets.h
new file mode 100644
index 00000000000..d370ee36a18
--- /dev/null
+++ b/arch/openrisc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
#include <generated/asm-offsets.h>
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
new file mode 100644
index 00000000000..a9e11efae14
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops.h
@@ -0,0 +1,59 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_BITOPS_H
20#define __ASM_OPENRISC_BITOPS_H
21
22/*
23 * Where we haven't written assembly versions yet, we fall back to the
24 * generic implementations. Otherwise, we pull in our (hopefully)
25 * optimized versions.
26 */
27
28#include <linux/irqflags.h>
29#include <linux/compiler.h>
30
31/*
32 * clear_bit may not imply a memory barrier
33 */
34#ifndef smp_mb__before_clear_bit
35#define smp_mb__before_clear_bit() smp_mb()
36#define smp_mb__after_clear_bit() smp_mb()
37#endif
38
39#include <asm/bitops/__ffs.h>
40#include <asm-generic/bitops/ffz.h>
41#include <asm/bitops/fls.h>
42#include <asm/bitops/__fls.h>
43#include <asm-generic/bitops/fls64.h>
44#include <asm-generic/bitops/find.h>
45
46#ifndef _LINUX_BITOPS_H
47#error only <linux/bitops.h> can be included directly
48#endif
49
50#include <asm-generic/bitops/sched.h>
51#include <asm/bitops/ffs.h>
52#include <asm-generic/bitops/hweight.h>
53#include <asm-generic/bitops/lock.h>
54
55#include <asm-generic/bitops/atomic.h>
56#include <asm-generic/bitops/non-atomic.h>
57#include <asm-generic/bitops/ext2-atomic.h>
58
59#endif /* __ASM_GENERIC_BITOPS_H */
diff --git a/arch/openrisc/include/asm/bitops/__ffs.h b/arch/openrisc/include/asm/bitops/__ffs.h
new file mode 100644
index 00000000000..6c8368a3405
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/__ffs.h
@@ -0,0 +1,33 @@
1/*
2 * OpenRISC Linux
3 *
4 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __ASM_OPENRISC___FFS_H
13#define __ASM_OPENRISC___FFS_H
14
15
16#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
17
18static inline unsigned long __ffs(unsigned long x)
19{
20 int ret;
21
22 __asm__ ("l.ff1 %0,%1"
23 : "=r" (ret)
24 : "r" (x));
25
26 return ret-1;
27}
28
29#else
30#include <asm-generic/bitops/__ffs.h>
31#endif
32
33#endif /* __ASM_OPENRISC___FFS_H */
diff --git a/arch/openrisc/include/asm/bitops/__fls.h b/arch/openrisc/include/asm/bitops/__fls.h
new file mode 100644
index 00000000000..c4ecdb4c523
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/__fls.h
@@ -0,0 +1,33 @@
1/*
2 * OpenRISC Linux
3 *
4 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __ASM_OPENRISC___FLS_H
13#define __ASM_OPENRISC___FLS_H
14
15
16#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
17
18static inline unsigned long __fls(unsigned long x)
19{
20 int ret;
21
22 __asm__ ("l.fl1 %0,%1"
23 : "=r" (ret)
24 : "r" (x));
25
26 return ret-1;
27}
28
29#else
30#include <asm-generic/bitops/__fls.h>
31#endif
32
33#endif /* __ASM_OPENRISC___FLS_H */
diff --git a/arch/openrisc/include/asm/bitops/ffs.h b/arch/openrisc/include/asm/bitops/ffs.h
new file mode 100644
index 00000000000..9de46246ebc
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/ffs.h
@@ -0,0 +1,32 @@
1/*
2 * OpenRISC Linux
3 *
4 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __ASM_OPENRISC_FFS_H
13#define __ASM_OPENRISC_FFS_H
14
15#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
16
17static inline int ffs(int x)
18{
19 int ret;
20
21 __asm__ ("l.ff1 %0,%1"
22 : "=r" (ret)
23 : "r" (x));
24
25 return ret;
26}
27
28#else
29#include <asm-generic/bitops/ffs.h>
30#endif
31
32#endif /* __ASM_OPENRISC_FFS_H */
diff --git a/arch/openrisc/include/asm/bitops/fls.h b/arch/openrisc/include/asm/bitops/fls.h
new file mode 100644
index 00000000000..9efbf9ad86c
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/fls.h
@@ -0,0 +1,33 @@
1/*
2 * OpenRISC Linux
3 *
4 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __ASM_OPENRISC_FLS_H
13#define __ASM_OPENRISC_FLS_H
14
15
16#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
17
18static inline int fls(int x)
19{
20 int ret;
21
22 __asm__ ("l.fl1 %0,%1"
23 : "=r" (ret)
24 : "r" (x));
25
26 return ret;
27}
28
29#else
30#include <asm-generic/bitops/fls.h>
31#endif
32
33#endif /* __ASM_OPENRISC_FLS_H */
diff --git a/arch/openrisc/include/asm/byteorder.h b/arch/openrisc/include/asm/byteorder.h
new file mode 100644
index 00000000000..60d14f7e14e
--- /dev/null
+++ b/arch/openrisc/include/asm/byteorder.h
@@ -0,0 +1 @@
#include <linux/byteorder/big_endian.h>
diff --git a/arch/openrisc/include/asm/cache.h b/arch/openrisc/include/asm/cache.h
new file mode 100644
index 00000000000..4ce7a01a252
--- /dev/null
+++ b/arch/openrisc/include/asm/cache.h
@@ -0,0 +1,29 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_CACHE_H
20#define __ASM_OPENRISC_CACHE_H
21
22/* FIXME: How can we replace these with values from the CPU...
23 * they shouldn't be hard-coded!
24 */
25
26#define L1_CACHE_BYTES 16
27#define L1_CACHE_SHIFT 4
28
29#endif /* __ASM_OPENRISC_CACHE_H */
diff --git a/arch/openrisc/include/asm/cpuinfo.h b/arch/openrisc/include/asm/cpuinfo.h
new file mode 100644
index 00000000000..917318b6a97
--- /dev/null
+++ b/arch/openrisc/include/asm/cpuinfo.h
@@ -0,0 +1,34 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_CPUINFO_H
20#define __ASM_OPENRISC_CPUINFO_H
21
22struct cpuinfo {
23 u32 clock_frequency;
24
25 u32 icache_size;
26 u32 icache_block_size;
27
28 u32 dcache_size;
29 u32 dcache_block_size;
30};
31
32extern struct cpuinfo cpuinfo;
33
34#endif /* __ASM_OPENRISC_CPUINFO_H */
diff --git a/arch/openrisc/include/asm/delay.h b/arch/openrisc/include/asm/delay.h
new file mode 100644
index 00000000000..17f8bf5a5ac
--- /dev/null
+++ b/arch/openrisc/include/asm/delay.h
@@ -0,0 +1,24 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#ifndef __ASM_OPENRISC_DELAY_H
18#define __ASM_OPENRISC_DELAY_H
19
20#include <asm-generic/delay.h>
21
22extern unsigned long loops_per_jiffy;
23
24#endif
diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h
new file mode 100644
index 00000000000..60b47223390
--- /dev/null
+++ b/arch/openrisc/include/asm/dma-mapping.h
@@ -0,0 +1,189 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#ifndef __ASM_OPENRISC_DMA_MAPPING_H
18#define __ASM_OPENRISC_DMA_MAPPING_H
19
20/*
21 * See Documentation/PCI/PCI-DMA-mapping.txt and
22 * Documentation/DMA-API.txt for documentation.
23 *
24 * This file is written with the intention of eventually moving over
25 * to largely using asm-generic/dma-mapping-common.h in its place.
26 */
27
28#include <linux/dma-debug.h>
29#include <asm-generic/dma-coherent.h>
30#include <linux/kmemcheck.h>
31
32#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
33
34
35#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
36#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
37
38void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
39 dma_addr_t *dma_handle, gfp_t flag);
40void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
41 dma_addr_t dma_handle);
42dma_addr_t or1k_map_page(struct device *dev, struct page *page,
43 unsigned long offset, size_t size,
44 enum dma_data_direction dir,
45 struct dma_attrs *attrs);
46void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
47 size_t size, enum dma_data_direction dir,
48 struct dma_attrs *attrs);
49int or1k_map_sg(struct device *dev, struct scatterlist *sg,
50 int nents, enum dma_data_direction dir,
51 struct dma_attrs *attrs);
52void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
53 int nents, enum dma_data_direction dir,
54 struct dma_attrs *attrs);
55void or1k_sync_single_for_cpu(struct device *dev,
56 dma_addr_t dma_handle, size_t size,
57 enum dma_data_direction dir);
58void or1k_sync_single_for_device(struct device *dev,
59 dma_addr_t dma_handle, size_t size,
60 enum dma_data_direction dir);
61
62static inline void *dma_alloc_coherent(struct device *dev, size_t size,
63 dma_addr_t *dma_handle, gfp_t flag)
64{
65 void *memory;
66
67 memory = or1k_dma_alloc_coherent(dev, size, dma_handle, flag);
68
69 debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
70 return memory;
71}
72
73static inline void dma_free_coherent(struct device *dev, size_t size,
74 void *cpu_addr, dma_addr_t dma_handle)
75{
76 debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
77 or1k_dma_free_coherent(dev, size, cpu_addr, dma_handle);
78}
79
80static inline dma_addr_t dma_map_single(struct device *dev, void *ptr,
81 size_t size,
82 enum dma_data_direction dir)
83{
84 dma_addr_t addr;
85
86 kmemcheck_mark_initialized(ptr, size);
87 BUG_ON(!valid_dma_direction(dir));
88 addr = or1k_map_page(dev, virt_to_page(ptr),
89 (unsigned long)ptr & ~PAGE_MASK, size,
90 dir, NULL);
91 debug_dma_map_page(dev, virt_to_page(ptr),
92 (unsigned long)ptr & ~PAGE_MASK, size,
93 dir, addr, true);
94 return addr;
95}
96
97static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
98 size_t size,
99 enum dma_data_direction dir)
100{
101 BUG_ON(!valid_dma_direction(dir));
102 or1k_unmap_page(dev, addr, size, dir, NULL);
103 debug_dma_unmap_page(dev, addr, size, dir, true);
104}
105
106static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
107 int nents, enum dma_data_direction dir)
108{
109 int i, ents;
110 struct scatterlist *s;
111
112 for_each_sg(sg, s, nents, i)
113 kmemcheck_mark_initialized(sg_virt(s), s->length);
114 BUG_ON(!valid_dma_direction(dir));
115 ents = or1k_map_sg(dev, sg, nents, dir, NULL);
116 debug_dma_map_sg(dev, sg, nents, ents, dir);
117
118 return ents;
119}
120
121static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
122 int nents, enum dma_data_direction dir)
123{
124 BUG_ON(!valid_dma_direction(dir));
125 debug_dma_unmap_sg(dev, sg, nents, dir);
126 or1k_unmap_sg(dev, sg, nents, dir, NULL);
127}
128
129static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
130 size_t offset, size_t size,
131 enum dma_data_direction dir)
132{
133 dma_addr_t addr;
134
135 kmemcheck_mark_initialized(page_address(page) + offset, size);
136 BUG_ON(!valid_dma_direction(dir));
137 addr = or1k_map_page(dev, page, offset, size, dir, NULL);
138 debug_dma_map_page(dev, page, offset, size, dir, addr, false);
139
140 return addr;
141}
142
143static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
144 size_t size, enum dma_data_direction dir)
145{
146 BUG_ON(!valid_dma_direction(dir));
147 or1k_unmap_page(dev, addr, size, dir, NULL);
148 debug_dma_unmap_page(dev, addr, size, dir, true);
149}
150
151static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
152 size_t size,
153 enum dma_data_direction dir)
154{
155 BUG_ON(!valid_dma_direction(dir));
156 or1k_sync_single_for_cpu(dev, addr, size, dir);
157 debug_dma_sync_single_for_cpu(dev, addr, size, dir);
158}
159
160static inline void dma_sync_single_for_device(struct device *dev,
161 dma_addr_t addr, size_t size,
162 enum dma_data_direction dir)
163{
164 BUG_ON(!valid_dma_direction(dir));
165 or1k_sync_single_for_device(dev, addr, size, dir);
166 debug_dma_sync_single_for_device(dev, addr, size, dir);
167}
168
169static inline int dma_supported(struct device *dev, u64 dma_mask)
170{
171 /* Support 32 bit DMA mask exclusively */
172 return dma_mask == DMA_BIT_MASK(32);
173}
174
175static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
176{
177 return 0;
178}
179
180static inline int dma_set_mask(struct device *dev, u64 dma_mask)
181{
182 if (!dev->dma_mask || !dma_supported(dev, dma_mask))
183 return -EIO;
184
185 *dev->dma_mask = dma_mask;
186
187 return 0;
188}
189#endif /* __ASM_OPENRISC_DMA_MAPPING_H */
diff --git a/arch/openrisc/include/asm/elf.h b/arch/openrisc/include/asm/elf.h
new file mode 100644
index 00000000000..2ce603bbfdd
--- /dev/null
+++ b/arch/openrisc/include/asm/elf.h
@@ -0,0 +1,108 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_ELF_H
20#define __ASM_OPENRISC_ELF_H
21
22/*
23 * ELF register definitions..
24 */
25#include <linux/types.h>
26#include <linux/ptrace.h>
27
28
29/* The OR1K relocation types... not all relevant for module loader */
30#define R_OR32_NONE 0
31#define R_OR32_32 1
32#define R_OR32_16 2
33#define R_OR32_8 3
34#define R_OR32_CONST 4
35#define R_OR32_CONSTH 5
36#define R_OR32_JUMPTARG 6
37#define R_OR32_VTINHERIT 7
38#define R_OR32_VTENTRY 8
39
40typedef unsigned long elf_greg_t;
41
42/*
43 * Note that NGREG is defined to ELF_NGREG in include/linux/elfcore.h, and is
44 * thus exposed to user-space.
45 */
46#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
47typedef elf_greg_t elf_gregset_t[ELF_NGREG];
48
49/* A placeholder; OR32 does not have fp support yes, so no fp regs for now. */
50typedef unsigned long elf_fpregset_t;
51
52/* This should be moved to include/linux/elf.h */
53#define EM_OR32 0x8472
54#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
55
56/*
57 * These are used to set parameters in the core dumps.
58 */
59#define ELF_ARCH EM_OR32
60#define ELF_CLASS ELFCLASS32
61#define ELF_DATA ELFDATA2MSB
62
63#ifdef __KERNEL__
64
65/*
66 * This is used to ensure we don't load something for the wrong architecture.
67 */
68
69#define elf_check_arch(x) \
70 (((x)->e_machine == EM_OR32) || ((x)->e_machine == EM_OPENRISC))
71
72/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
73 use of this is to invoke "./ld.so someprog" to test out a new version of
74 the loader. We need to make sure that it is out of the way of the program
75 that it will "exec", and that there is sufficient room for the brk. */
76
77#define ELF_ET_DYN_BASE (0x08000000)
78
79/*
80 * Enable dump using regset.
81 * This covers all of general/DSP/FPU regs.
82 */
83#define CORE_DUMP_USE_REGSET
84
85#define ELF_EXEC_PAGESIZE 8192
86
87extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt);
88#define ELF_CORE_COPY_REGS(dest, regs) dump_elf_thread(dest, regs);
89
90/* This yields a mask that user programs can use to figure out what
91 instruction set this cpu supports. This could be done in userspace,
92 but it's not easy, and we've already done it here. */
93
94#define ELF_HWCAP (0)
95
96/* This yields a string that ld.so will use to load implementation
97 specific libraries for optimization. This is more specific in
98 intent than poking at uname or /proc/cpuinfo.
99
100 For the moment, we have only optimizations for the Intel generations,
101 but that could change... */
102
103#define ELF_PLATFORM (NULL)
104
105#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
106
107#endif /* __KERNEL__ */
108#endif
diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h
new file mode 100644
index 00000000000..52733416c1f
--- /dev/null
+++ b/arch/openrisc/include/asm/fixmap.h
@@ -0,0 +1,87 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_FIXMAP_H
20#define __ASM_OPENRISC_FIXMAP_H
21
22/* Why exactly do we need 2 empty pages between the top of the fixed
23 * addresses and the top of virtual memory? Something is using that
24 * memory space but not sure what right now... If you find it, leave
25 * a comment here.
26 */
27#define FIXADDR_TOP ((unsigned long) (-2*PAGE_SIZE))
28
29#include <linux/kernel.h>
30#include <asm/page.h>
31
32/*
33 * On OpenRISC we use these special fixed_addresses for doing ioremap
34 * early in the boot process before memory initialization is complete.
35 * This is used, in particular, by the early serial console code.
36 *
37 * It's not really 'fixmap', per se, but fits loosely into the same
38 * paradigm.
39 */
40enum fixed_addresses {
41 /*
42 * FIX_IOREMAP entries are useful for mapping physical address
43 * space before ioremap() is useable, e.g. really early in boot
44 * before kmalloc() is working.
45 */
46#define FIX_N_IOREMAPS 32
47 FIX_IOREMAP_BEGIN,
48 FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
49 __end_of_fixed_addresses
50};
51
52#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
53/* FIXADDR_BOTTOM might be a better name here... */
54#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
55
56#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
57#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
58
59/*
60 * 'index to address' translation. If anyone tries to use the idx
61 * directly without tranlation, we catch the bug with a NULL-deference
62 * kernel oops. Illegal ranges of incoming indices are caught too.
63 */
64static __always_inline unsigned long fix_to_virt(const unsigned int idx)
65{
66 /*
67 * this branch gets completely eliminated after inlining,
68 * except when someone tries to use fixaddr indices in an
69 * illegal way. (such as mixing up address types or using
70 * out-of-range indices).
71 *
72 * If it doesn't get removed, the linker will complain
73 * loudly with a reasonably clear error message..
74 */
75 if (idx >= __end_of_fixed_addresses)
76 BUG();
77
78 return __fix_to_virt(idx);
79}
80
81static inline unsigned long virt_to_fix(const unsigned long vaddr)
82{
83 BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
84 return __virt_to_fix(vaddr);
85}
86
87#endif
diff --git a/arch/openrisc/include/asm/gpio.h b/arch/openrisc/include/asm/gpio.h
new file mode 100644
index 00000000000..0b0d174f47c
--- /dev/null
+++ b/arch/openrisc/include/asm/gpio.h
@@ -0,0 +1,65 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_GPIO_H
20#define __ASM_OPENRISC_GPIO_H
21
22#include <linux/errno.h>
23#include <asm-generic/gpio.h>
24
25#ifdef CONFIG_GPIOLIB
26
27/*
28 * OpenRISC (or1k) does not have on-chip GPIO's so there is not really
29 * any standardized implementation that makes sense here. If passing
30 * through gpiolib becomes a bottleneck then it may make sense, on a
31 * case-by-case basis, to implement these inlined/rapid versions.
32 *
33 * Just call gpiolib.
34 */
35static inline int gpio_get_value(unsigned int gpio)
36{
37 return __gpio_get_value(gpio);
38}
39
40static inline void gpio_set_value(unsigned int gpio, int value)
41{
42 __gpio_set_value(gpio, value);
43}
44
45static inline int gpio_cansleep(unsigned int gpio)
46{
47 return __gpio_cansleep(gpio);
48}
49
50/*
51 * Not implemented, yet.
52 */
53static inline int gpio_to_irq(unsigned int gpio)
54{
55 return -ENOSYS;
56}
57
58static inline int irq_to_gpio(unsigned int irq)
59{
60 return -EINVAL;
61}
62
63#endif /* CONFIG_GPIOLIB */
64
65#endif /* __ASM_OPENRISC_GPIO_H */
diff --git a/arch/openrisc/include/asm/io.h b/arch/openrisc/include/asm/io.h
new file mode 100644
index 00000000000..07f5299d6c2
--- /dev/null
+++ b/arch/openrisc/include/asm/io.h
@@ -0,0 +1,51 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 * et al.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18#ifndef __ASM_OPENRISC_IO_H
19#define __ASM_OPENRISC_IO_H
20
21/*
22 * PCI: can we really do 0 here if we have no port IO?
23 */
24#define IO_SPACE_LIMIT 0
25
26/* OpenRISC has no port IO */
27#define HAVE_ARCH_PIO_SIZE 1
28#define PIO_RESERVED 0X0UL
29#define PIO_OFFSET 0
30#define PIO_MASK 0
31
32#include <asm-generic/io.h>
33
34extern void __iomem *__ioremap(phys_addr_t offset, unsigned long size,
35 pgprot_t prot);
36
37static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
38{
39 return __ioremap(offset, size, PAGE_KERNEL);
40}
41
42/* #define _PAGE_CI 0x002 */
43static inline void __iomem *ioremap_nocache(phys_addr_t offset,
44 unsigned long size)
45{
46 return __ioremap(offset, size,
47 __pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_CI));
48}
49
50extern void iounmap(void *addr);
51#endif
diff --git a/arch/openrisc/include/asm/irq.h b/arch/openrisc/include/asm/irq.h
new file mode 100644
index 00000000000..eb612b1865d
--- /dev/null
+++ b/arch/openrisc/include/asm/irq.h
@@ -0,0 +1,27 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_IRQ_H__
20#define __ASM_OPENRISC_IRQ_H__
21
22#define NR_IRQS 32
23#include <asm-generic/irq.h>
24
25#define NO_IRQ (-1)
26
27#endif /* __ASM_OPENRISC_IRQ_H__ */
diff --git a/arch/openrisc/include/asm/irqflags.h b/arch/openrisc/include/asm/irqflags.h
new file mode 100644
index 00000000000..dc86c653d70
--- /dev/null
+++ b/arch/openrisc/include/asm/irqflags.h
@@ -0,0 +1,29 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef ___ASM_OPENRISC_IRQFLAGS_H
20#define ___ASM_OPENRISC_IRQFLAGS_H
21
22#include <asm/spr_defs.h>
23
24#define ARCH_IRQ_DISABLED 0x00
25#define ARCH_IRQ_ENABLED (SPR_SR_IEE|SPR_SR_TEE)
26
27#include <asm-generic/irqflags.h>
28
29#endif /* ___ASM_OPENRISC_IRQFLAGS_H */
diff --git a/arch/openrisc/include/asm/linkage.h b/arch/openrisc/include/asm/linkage.h
new file mode 100644
index 00000000000..e2638752091
--- /dev/null
+++ b/arch/openrisc/include/asm/linkage.h
@@ -0,0 +1,25 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_LINKAGE_H
20#define __ASM_OPENRISC_LINKAGE_H
21
22#define __ALIGN .align 0
23#define __ALIGN_STR ".align 0"
24
25#endif /* __ASM_OPENRISC_LINKAGE_H */
diff --git a/arch/openrisc/include/asm/memblock.h b/arch/openrisc/include/asm/memblock.h
new file mode 100644
index 00000000000..bbe5a1c788c
--- /dev/null
+++ b/arch/openrisc/include/asm/memblock.h
@@ -0,0 +1,24 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_MEMBLOCK_H
20#define __ASM_OPENRISC_MEMBLOCK_H
21
22/* empty */
23
24#endif /* __ASM_OPENRISC_MEMBLOCK_H */
diff --git a/arch/openrisc/include/asm/mmu.h b/arch/openrisc/include/asm/mmu.h
new file mode 100644
index 00000000000..d069bc2ddfa
--- /dev/null
+++ b/arch/openrisc/include/asm/mmu.h
@@ -0,0 +1,26 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_MMU_H
20#define __ASM_OPENRISC_MMU_H
21
22#ifndef __ASSEMBLY__
23typedef unsigned long mm_context_t;
24#endif
25
26#endif
diff --git a/arch/openrisc/include/asm/mmu_context.h b/arch/openrisc/include/asm/mmu_context.h
new file mode 100644
index 00000000000..e94b814d2e3
--- /dev/null
+++ b/arch/openrisc/include/asm/mmu_context.h
@@ -0,0 +1,43 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_MMU_CONTEXT_H
20#define __ASM_OPENRISC_MMU_CONTEXT_H
21
22#include <asm-generic/mm_hooks.h>
23
24extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
25extern void destroy_context(struct mm_struct *mm);
26extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
27 struct task_struct *tsk);
28
29#define deactivate_mm(tsk, mm) do { } while (0)
30
31#define activate_mm(prev, next) switch_mm((prev), (next), NULL)
32
33/* current active pgd - this is similar to other processors pgd
34 * registers like cr3 on the i386
35 */
36
37extern volatile pgd_t *current_pgd; /* defined in arch/openrisc/mm/fault.c */
38
39static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
40{
41}
42
43#endif
diff --git a/arch/openrisc/include/asm/mutex.h b/arch/openrisc/include/asm/mutex.h
new file mode 100644
index 00000000000..b85a0cfa9fc
--- /dev/null
+++ b/arch/openrisc/include/asm/mutex.h
@@ -0,0 +1,27 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19/*
20 * Pull in the generic implementation for the mutex fastpath.
21 *
22 * TODO: implement optimized primitives instead, or leave the generic
23 * implementation in place, or pick the atomic_xchg() based generic
24 * implementation. (see asm-generic/mutex-xchg.h for details)
25 */
26
27#include <asm-generic/mutex-dec.h>
diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h
new file mode 100644
index 00000000000..b041b344b22
--- /dev/null
+++ b/arch/openrisc/include/asm/page.h
@@ -0,0 +1,110 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_PAGE_H
20#define __ASM_OPENRISC_PAGE_H
21
22
23/* PAGE_SHIFT determines the page size */
24
25#define PAGE_SHIFT 13
26#ifdef __ASSEMBLY__
27#define PAGE_SIZE (1 << PAGE_SHIFT)
28#else
29#define PAGE_SIZE (1UL << PAGE_SHIFT)
30#endif
31#define PAGE_MASK (~(PAGE_SIZE-1))
32
33#define PAGE_OFFSET 0xc0000000
34#define KERNELBASE PAGE_OFFSET
35
36/* This is not necessarily the right place for this, but it's needed by
37 * drivers/of/fdt.c
38 */
39#include <asm/setup.h>
40
41#ifndef __ASSEMBLY__
42
43#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
44#define free_user_page(page, addr) free_page(addr)
45
46#define clear_page(page) memset((page), 0, PAGE_SIZE)
47#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
48
49#define clear_user_page(page, vaddr, pg) clear_page(page)
50#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
51
52/*
53 * These are used to make use of C type-checking..
54 */
55typedef struct {
56 unsigned long pte;
57} pte_t;
58typedef struct {
59 unsigned long pgd;
60} pgd_t;
61typedef struct {
62 unsigned long pgprot;
63} pgprot_t;
64typedef struct page *pgtable_t;
65
66#define pte_val(x) ((x).pte)
67#define pgd_val(x) ((x).pgd)
68#define pgprot_val(x) ((x).pgprot)
69
70#define __pte(x) ((pte_t) { (x) })
71#define __pgd(x) ((pgd_t) { (x) })
72#define __pgprot(x) ((pgprot_t) { (x) })
73
74extern unsigned long memory_start;
75extern unsigned long memory_end;
76
77#endif /* !__ASSEMBLY__ */
78
79
80#ifndef __ASSEMBLY__
81
82#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
83#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
84
85#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
86#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
87
88#define virt_to_page(addr) \
89 (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
90#define page_to_virt(page) \
91 ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
92
93#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
94
95#define pfn_valid(pfn) ((pfn) < max_mapnr)
96
97#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
98 ((void *)(kaddr) < (void *)memory_end))
99
100#endif /* __ASSEMBLY__ */
101
102
103#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
104 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
105
106
107#include <asm-generic/memory_model.h>
108#include <asm-generic/getorder.h>
109
110#endif /* __ASM_OPENRISC_PAGE_H */
diff --git a/arch/openrisc/include/asm/param.h b/arch/openrisc/include/asm/param.h
new file mode 100644
index 00000000000..c39a336610e
--- /dev/null
+++ b/arch/openrisc/include/asm/param.h
@@ -0,0 +1,26 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_PARAM_H
20#define __ASM_OPENRISC_PARAM_H
21
22#define EXEC_PAGESIZE 8192
23
24#include <asm-generic/param.h>
25
26#endif /* __ASM_OPENRISC_PARAM_H */
diff --git a/arch/openrisc/include/asm/pgalloc.h b/arch/openrisc/include/asm/pgalloc.h
new file mode 100644
index 00000000000..05c39ecd2ef
--- /dev/null
+++ b/arch/openrisc/include/asm/pgalloc.h
@@ -0,0 +1,102 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_PGALLOC_H
20#define __ASM_OPENRISC_PGALLOC_H
21
22#include <asm/page.h>
23#include <linux/threads.h>
24#include <linux/mm.h>
25#include <linux/memblock.h>
26#include <linux/bootmem.h>
27
28extern int mem_init_done;
29
30#define pmd_populate_kernel(mm, pmd, pte) \
31 set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
32
33static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
34 struct page *pte)
35{
36 set_pmd(pmd, __pmd(_KERNPG_TABLE +
37 ((unsigned long)page_to_pfn(pte) <<
38 (unsigned long) PAGE_SHIFT)));
39}
40
41/*
42 * Allocate and free page tables.
43 */
44static inline pgd_t *pgd_alloc(struct mm_struct *mm)
45{
46 pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
47
48 if (ret) {
49 memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
50 memcpy(ret + USER_PTRS_PER_PGD,
51 swapper_pg_dir + USER_PTRS_PER_PGD,
52 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
53
54 }
55 return ret;
56}
57
58#if 0
59/* FIXME: This seems to be the preferred style, but we are using
60 * current_pgd (from mm->pgd) to load kernel pages so we need it
61 * initialized. This needs to be looked into.
62 */
63extern inline pgd_t *pgd_alloc(struct mm_struct *mm)
64{
65 return (pgd_t *)get_zeroed_page(GFP_KERNEL);
66}
67#endif
68
69static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
70{
71 free_page((unsigned long)pgd);
72}
73
74extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address);
75
76static inline struct page *pte_alloc_one(struct mm_struct *mm,
77 unsigned long address)
78{
79 struct page *pte;
80 pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
81 if (pte)
82 clear_page(page_address(pte));
83 return pte;
84}
85
86static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
87{
88 free_page((unsigned long)pte);
89}
90
91static inline void pte_free(struct mm_struct *mm, struct page *pte)
92{
93 __free_page(pte);
94}
95
96
97#define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte))
98#define pmd_pgtable(pmd) pmd_page(pmd)
99
100#define check_pgt_cache() do { } while (0)
101
102#endif
diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h
new file mode 100644
index 00000000000..043505d7f68
--- /dev/null
+++ b/arch/openrisc/include/asm/pgtable.h
@@ -0,0 +1,463 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19/* or32 pgtable.h - macros and functions to manipulate page tables
20 *
21 * Based on:
22 * include/asm-cris/pgtable.h
23 */
24
25#ifndef __ASM_OPENRISC_PGTABLE_H
26#define __ASM_OPENRISC_PGTABLE_H
27
28#include <asm-generic/pgtable-nopmd.h>
29
30#ifndef __ASSEMBLY__
31#include <asm/mmu.h>
32#include <asm/fixmap.h>
33
34/*
35 * The Linux memory management assumes a three-level page table setup. On
36 * or32, we use that, but "fold" the mid level into the top-level page
37 * table. Since the MMU TLB is software loaded through an interrupt, it
38 * supports any page table structure, so we could have used a three-level
39 * setup, but for the amounts of memory we normally use, a two-level is
40 * probably more efficient.
41 *
42 * This file contains the functions and defines necessary to modify and use
43 * the or32 page table tree.
44 */
45
46extern void paging_init(void);
47
48/* Certain architectures need to do special things when pte's
49 * within a page table are directly modified. Thus, the following
50 * hook is made available.
51 */
52#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
53#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
54/*
55 * (pmds are folded into pgds so this doesn't get actually called,
56 * but the define is needed for a generic inline function.)
57 */
58#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
59
60#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-2))
61#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
62#define PGDIR_MASK (~(PGDIR_SIZE-1))
63
64/*
65 * entries per page directory level: we use a two-level, so
66 * we don't really have any PMD directory physically.
67 * pointers are 4 bytes so we can use the page size and
68 * divide it by 4 (shift by 2).
69 */
70#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-2))
71
72#define PTRS_PER_PGD (1UL << (PAGE_SHIFT-2))
73
74/* calculate how many PGD entries a user-level program can use
75 * the first mappable virtual address is 0
76 * (TASK_SIZE is the maximum virtual address space)
77 */
78
79#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
80#define FIRST_USER_ADDRESS 0
81
82/*
83 * Kernels own virtual memory area.
84 */
85
86/*
87 * The size and location of the vmalloc area are chosen so that modules
88 * placed in this area aren't more than a 28-bit signed offset from any
89 * kernel functions that they may need. This greatly simplifies handling
90 * of the relocations for l.j and l.jal instructions as we don't need to
91 * introduce any trampolines for reaching "distant" code.
92 *
93 * 64 MB of vmalloc area is comparable to what's available on other arches.
94 */
95
96#define VMALLOC_START (PAGE_OFFSET-0x04000000)
97#define VMALLOC_END (PAGE_OFFSET)
98#define VMALLOC_VMADDR(x) ((unsigned long)(x))
99
100/* Define some higher level generic page attributes.
101 *
102 * If you change _PAGE_CI definition be sure to change it in
103 * io.h for ioremap_nocache() too.
104 */
105
106/*
107 * An OR32 PTE looks like this:
108 *
109 * | 31 ... 10 | 9 | 8 ... 6 | 5 | 4 | 3 | 2 | 1 | 0 |
110 * Phys pg.num L PP Index D A WOM WBC CI CC
111 *
112 * L : link
113 * PPI: Page protection index
114 * D : Dirty
115 * A : Accessed
116 * WOM: Weakly ordered memory
117 * WBC: Write-back cache
118 * CI : Cache inhibit
119 * CC : Cache coherent
120 *
121 * The protection bits below should correspond to the layout of the actual
122 * PTE as per above
123 */
124
125#define _PAGE_CC 0x001 /* software: pte contains a translation */
126#define _PAGE_CI 0x002 /* cache inhibit */
127#define _PAGE_WBC 0x004 /* write back cache */
128#define _PAGE_FILE 0x004 /* set: pagecache, unset: swap (when !PRESENT) */
129#define _PAGE_WOM 0x008 /* weakly ordered memory */
130
131#define _PAGE_A 0x010 /* accessed */
132#define _PAGE_D 0x020 /* dirty */
133#define _PAGE_URE 0x040 /* user read enable */
134#define _PAGE_UWE 0x080 /* user write enable */
135
136#define _PAGE_SRE 0x100 /* superuser read enable */
137#define _PAGE_SWE 0x200 /* superuser write enable */
138#define _PAGE_EXEC 0x400 /* software: page is executable */
139#define _PAGE_U_SHARED 0x800 /* software: page is shared in user space */
140
141/* 0x001 is cache coherency bit, which should always be set to
142 * 1 - for SMP (when we support it)
143 * 0 - otherwise
144 *
145 * we just reuse this bit in software for _PAGE_PRESENT and
146 * force it to 0 when loading it into TLB.
147 */
148#define _PAGE_PRESENT _PAGE_CC
149#define _PAGE_USER _PAGE_URE
150#define _PAGE_WRITE (_PAGE_UWE | _PAGE_SWE)
151#define _PAGE_DIRTY _PAGE_D
152#define _PAGE_ACCESSED _PAGE_A
153#define _PAGE_NO_CACHE _PAGE_CI
154#define _PAGE_SHARED _PAGE_U_SHARED
155#define _PAGE_READ (_PAGE_URE | _PAGE_SRE)
156
157#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
158#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
159#define _PAGE_ALL (_PAGE_PRESENT | _PAGE_ACCESSED)
160#define _KERNPG_TABLE \
161 (_PAGE_BASE | _PAGE_SRE | _PAGE_SWE | _PAGE_ACCESSED | _PAGE_DIRTY)
162
163#define PAGE_NONE __pgprot(_PAGE_ALL)
164#define PAGE_READONLY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
165#define PAGE_READONLY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
166#define PAGE_SHARED \
167 __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
168 | _PAGE_SHARED)
169#define PAGE_SHARED_X \
170 __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
171 | _PAGE_SHARED | _PAGE_EXEC)
172#define PAGE_COPY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
173#define PAGE_COPY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
174
175#define PAGE_KERNEL \
176 __pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
177 | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
178#define PAGE_KERNEL_RO \
179 __pgprot(_PAGE_ALL | _PAGE_SRE \
180 | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
181#define PAGE_KERNEL_NOCACHE \
182 __pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
183 | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC | _PAGE_CI)
184
185#define __P000 PAGE_NONE
186#define __P001 PAGE_READONLY_X
187#define __P010 PAGE_COPY
188#define __P011 PAGE_COPY_X
189#define __P100 PAGE_READONLY
190#define __P101 PAGE_READONLY_X
191#define __P110 PAGE_COPY
192#define __P111 PAGE_COPY_X
193
194#define __S000 PAGE_NONE
195#define __S001 PAGE_READONLY_X
196#define __S010 PAGE_SHARED
197#define __S011 PAGE_SHARED_X
198#define __S100 PAGE_READONLY
199#define __S101 PAGE_READONLY_X
200#define __S110 PAGE_SHARED
201#define __S111 PAGE_SHARED_X
202
203/* zero page used for uninitialized stuff */
204extern unsigned long empty_zero_page[2048];
205#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
206
207/* number of bits that fit into a memory pointer */
208#define BITS_PER_PTR (8*sizeof(unsigned long))
209
210/* to align the pointer to a pointer address */
211#define PTR_MASK (~(sizeof(void *)-1))
212
213/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
214/* 64-bit machines, beware! SRB. */
215#define SIZEOF_PTR_LOG2 2
216
217/* to find an entry in a page-table */
218#define PAGE_PTR(address) \
219((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
220
221/* to set the page-dir */
222#define SET_PAGE_DIR(tsk, pgdir)
223
224#define pte_none(x) (!pte_val(x))
225#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
226#define pte_clear(mm, addr, xp) do { pte_val(*(xp)) = 0; } while (0)
227
228#define pmd_none(x) (!pmd_val(x))
229#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK)) != _KERNPG_TABLE)
230#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
231#define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0)
232
233/*
234 * The following only work if pte_present() is true.
235 * Undefined behaviour if not..
236 */
237
238static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
239static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
240static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
241static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
242static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
243static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
244static inline int pte_special(pte_t pte) { return 0; }
245static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
246
247static inline pte_t pte_wrprotect(pte_t pte)
248{
249 pte_val(pte) &= ~(_PAGE_WRITE);
250 return pte;
251}
252
253static inline pte_t pte_rdprotect(pte_t pte)
254{
255 pte_val(pte) &= ~(_PAGE_READ);
256 return pte;
257}
258
259static inline pte_t pte_exprotect(pte_t pte)
260{
261 pte_val(pte) &= ~(_PAGE_EXEC);
262 return pte;
263}
264
265static inline pte_t pte_mkclean(pte_t pte)
266{
267 pte_val(pte) &= ~(_PAGE_DIRTY);
268 return pte;
269}
270
271static inline pte_t pte_mkold(pte_t pte)
272{
273 pte_val(pte) &= ~(_PAGE_ACCESSED);
274 return pte;
275}
276
277static inline pte_t pte_mkwrite(pte_t pte)
278{
279 pte_val(pte) |= _PAGE_WRITE;
280 return pte;
281}
282
283static inline pte_t pte_mkread(pte_t pte)
284{
285 pte_val(pte) |= _PAGE_READ;
286 return pte;
287}
288
289static inline pte_t pte_mkexec(pte_t pte)
290{
291 pte_val(pte) |= _PAGE_EXEC;
292 return pte;
293}
294
295static inline pte_t pte_mkdirty(pte_t pte)
296{
297 pte_val(pte) |= _PAGE_DIRTY;
298 return pte;
299}
300
301static inline pte_t pte_mkyoung(pte_t pte)
302{
303 pte_val(pte) |= _PAGE_ACCESSED;
304 return pte;
305}
306
307/*
308 * Conversion functions: convert a page and protection to a page entry,
309 * and a page entry and page directory to the page they refer to.
310 */
311
312/* What actually goes as arguments to the various functions is less than
313 * obvious, but a rule of thumb is that struct page's goes as struct page *,
314 * really physical DRAM addresses are unsigned long's, and DRAM "virtual"
315 * addresses (the 0xc0xxxxxx's) goes as void *'s.
316 */
317
318static inline pte_t __mk_pte(void *page, pgprot_t pgprot)
319{
320 pte_t pte;
321 /* the PTE needs a physical address */
322 pte_val(pte) = __pa(page) | pgprot_val(pgprot);
323 return pte;
324}
325
326#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
327
328#define mk_pte_phys(physpage, pgprot) \
329({ \
330 pte_t __pte; \
331 \
332 pte_val(__pte) = (physpage) + pgprot_val(pgprot); \
333 __pte; \
334})
335
336static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
337{
338 pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
339 return pte;
340}
341
342
343/*
344 * pte_val refers to a page in the 0x0xxxxxxx physical DRAM interval
345 * __pte_page(pte_val) refers to the "virtual" DRAM interval
346 * pte_pagenr refers to the page-number counted starting from the virtual
347 * DRAM start
348 */
349
350static inline unsigned long __pte_page(pte_t pte)
351{
352 /* the PTE contains a physical address */
353 return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
354}
355
356#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
357
358/* permanent address of a page */
359
360#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
361#define pte_page(pte) (mem_map+pte_pagenr(pte))
362
363/*
364 * only the pte's themselves need to point to physical DRAM (see above)
365 * the pagetable links are purely handled within the kernel SW and thus
366 * don't need the __pa and __va transformations.
367 */
368static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
369{
370 pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep;
371}
372
373#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
374#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
375
376/* to find an entry in a page-table-directory. */
377#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
378
379#define __pgd_offset(address) pgd_index(address)
380
381#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
382
383/* to find an entry in a kernel page-table-directory */
384#define pgd_offset_k(address) pgd_offset(&init_mm, address)
385
386#define __pmd_offset(address) \
387 (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
388
389/*
390 * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
391 *
392 * this macro returns the index of the entry in the pte page which would
393 * control the given virtual address
394 */
395#define __pte_offset(address) \
396 (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
397#define pte_offset_kernel(dir, address) \
398 ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address))
399#define pte_offset_map(dir, address) \
400 ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
401#define pte_offset_map_nested(dir, address) \
402 pte_offset_map(dir, address)
403
404#define pte_unmap(pte) do { } while (0)
405#define pte_unmap_nested(pte) do { } while (0)
406#define pte_pfn(x) ((unsigned long)(((x).pte)) >> PAGE_SHIFT)
407#define pfn_pte(pfn, prot) __pte((((pfn) << PAGE_SHIFT)) | pgprot_val(prot))
408
409#define pte_ERROR(e) \
410 printk(KERN_ERR "%s:%d: bad pte %p(%08lx).\n", \
411 __FILE__, __LINE__, &(e), pte_val(e))
412#define pgd_ERROR(e) \
413 printk(KERN_ERR "%s:%d: bad pgd %p(%08lx).\n", \
414 __FILE__, __LINE__, &(e), pgd_val(e))
415
416extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
417
418/*
419 * or32 doesn't have any external MMU info: the kernel page
420 * tables contain all the necessary information.
421 *
422 * Actually I am not sure on what this could be used for.
423 */
424static inline void update_mmu_cache(struct vm_area_struct *vma,
425 unsigned long address, pte_t *pte)
426{
427}
428
429/* __PHX__ FIXME, SWAP, this probably doesn't work */
430
431/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
432/* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */
433
434#define __swp_type(x) (((x).val >> 5) & 0x7f)
435#define __swp_offset(x) ((x).val >> 12)
436#define __swp_entry(type, offset) \
437 ((swp_entry_t) { ((type) << 5) | ((offset) << 12) })
438#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
439#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
440
441/* Encode and decode a nonlinear file mapping entry */
442
443#define PTE_FILE_MAX_BITS 26
444#define pte_to_pgoff(x) (pte_val(x) >> 6)
445#define pgoff_to_pte(x) __pte(((x) << 6) | _PAGE_FILE)
446
447#define kern_addr_valid(addr) (1)
448
449#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
450 remap_pfn_range(vma, vaddr, pfn, size, prot)
451
452#include <asm-generic/pgtable.h>
453
454/*
455 * No page table caches to initialise
456 */
457#define pgtable_cache_init() do { } while (0)
458#define io_remap_page_range remap_page_range
459
460typedef pte_t *pte_addr_t;
461
462#endif /* __ASSEMBLY__ */
463#endif /* __ASM_OPENRISC_PGTABLE_H */
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
new file mode 100644
index 00000000000..bb54c97b978
--- /dev/null
+++ b/arch/openrisc/include/asm/processor.h
@@ -0,0 +1,113 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_PROCESSOR_H
20#define __ASM_OPENRISC_PROCESSOR_H
21
22#include <asm/spr_defs.h>
23#include <asm/page.h>
24#include <asm/ptrace.h>
25
26#define STACK_TOP TASK_SIZE
27#define STACK_TOP_MAX STACK_TOP
28/* Kernel and user SR register setting */
29#define KERNEL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
30 | SPR_SR_DCE | SPR_SR_SM)
31#define USER_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
32 | SPR_SR_DCE | SPR_SR_IEE | SPR_SR_TEE)
33/*
34 * Default implementation of macro that returns current
35 * instruction pointer ("program counter").
36 */
37#define current_text_addr() ({ __label__ _l; _l: &&_l; })
38
39/*
40 * User space process size. This is hardcoded into a few places,
41 * so don't change it unless you know what you are doing.
42 */
43
44#define TASK_SIZE (0x80000000UL)
45
46/* This decides where the kernel will search for a free chunk of vm
47 * space during mmap's.
48 */
49#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
50
51#ifndef __ASSEMBLY__
52
53struct task_struct;
54
55struct thread_struct {
56};
57
58/*
59 * At user->kernel entry, the pt_regs struct is stacked on the top of the
60 * kernel-stack. This macro allows us to find those regs for a task.
61 * Notice that subsequent pt_regs stackings, like recursive interrupts
62 * occurring while we're in the kernel, won't affect this - only the first
63 * user->kernel transition registers are reached by this (i.e. not regs
64 * for running signal handler)
65 */
66#define user_regs(thread_info) (((struct pt_regs *)((unsigned long)(thread_info) + THREAD_SIZE - STACK_FRAME_OVERHEAD)) - 1)
67
68/*
69 * Dito but for the currently running task
70 */
71
72#define task_pt_regs(task) user_regs(task_thread_info(task))
73#define current_regs() user_regs(current_thread_info())
74
75extern inline void prepare_to_copy(struct task_struct *tsk)
76{
77}
78
79#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
80
81#define INIT_THREAD { }
82
83
84#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc);
85#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp);
86
87
88extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
89
90void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
91void release_thread(struct task_struct *);
92unsigned long get_wchan(struct task_struct *p);
93
94/*
95 * Free current thread data structures etc..
96 */
97
98extern inline void exit_thread(void)
99{
100 /* Nothing needs to be done. */
101}
102
103/*
104 * Return saved PC of a blocked thread. For now, this is the "user" PC
105 */
106extern unsigned long thread_saved_pc(struct task_struct *t);
107
108#define init_stack (init_thread_union.stack)
109
110#define cpu_relax() do { } while (0)
111
112#endif /* __ASSEMBLY__ */
113#endif /* __ASM_OPENRISC_PROCESSOR_H */
diff --git a/arch/openrisc/include/asm/prom.h b/arch/openrisc/include/asm/prom.h
new file mode 100644
index 00000000000..e1f3fe26606
--- /dev/null
+++ b/arch/openrisc/include/asm/prom.h
@@ -0,0 +1,77 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 * et al.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 */
17
18#include <linux/of.h> /* linux/of.h gets to determine #include ordering */
19
20#ifndef _ASM_OPENRISC_PROM_H
21#define _ASM_OPENRISC_PROM_H
22#ifdef __KERNEL__
23#ifndef __ASSEMBLY__
24
25#include <linux/types.h>
26#include <asm/irq.h>
27#include <linux/atomic.h>
28#include <linux/of_irq.h>
29#include <linux/of_fdt.h>
30#include <linux/of_address.h>
31#include <linux/proc_fs.h>
32#include <linux/platform_device.h>
33#define HAVE_ARCH_DEVTREE_FIXUPS
34
35/* Other Prototypes */
36extern int early_uartlite_console(void);
37
38/* Parse the ibm,dma-window property of an OF node into the busno, phys and
39 * size parameters.
40 */
41void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
42 unsigned long *busno, unsigned long *phys, unsigned long *size);
43
44extern void kdump_move_device_tree(void);
45
46/* CPU OF node matching */
47struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
48
49/* Get the MAC address */
50extern const void *of_get_mac_address(struct device_node *np);
51
52/**
53 * of_irq_map_pci - Resolve the interrupt for a PCI device
54 * @pdev: the device whose interrupt is to be resolved
55 * @out_irq: structure of_irq filled by this function
56 *
57 * This function resolves the PCI interrupt for a given PCI device. If a
58 * device-node exists for a given pci_dev, it will use normal OF tree
59 * walking. If not, it will implement standard swizzling and walk up the
60 * PCI tree until an device-node is found, at which point it will finish
61 * resolving using the OF tree walking.
62 */
63struct pci_dev;
64extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
65
66/* This routine is here to provide compatibility with how powerpc
67 * handles IRQ mapping for OF device nodes. We precompute and permanently
68 * register them in the platform_device objects, whereas powerpc computes them
69 * on request.
70 */
71static inline void irq_dispose_mapping(unsigned int virq)
72{
73}
74
75#endif /* __ASSEMBLY__ */
76#endif /* __KERNEL__ */
77#endif /* _ASM_OPENRISC_PROM_H */
diff --git a/arch/openrisc/include/asm/ptrace.h b/arch/openrisc/include/asm/ptrace.h
new file mode 100644
index 00000000000..054537c5f9c
--- /dev/null
+++ b/arch/openrisc/include/asm/ptrace.h
@@ -0,0 +1,131 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_PTRACE_H
20#define __ASM_OPENRISC_PTRACE_H
21
22#include <asm/spr_defs.h>
23
24#ifndef __ASSEMBLY__
25/*
26 * This is the layout of the regset returned by the GETREGSET ptrace call
27 */
28struct user_regs_struct {
29 /* GPR R0-R31... */
30 unsigned long gpr[32];
31 unsigned long pc;
32 unsigned long sr;
33 unsigned long pad1;
34 unsigned long pad2;
35};
36#endif
37
38#ifdef __KERNEL__
39
40/*
41 * Make kernel PTrace/register structures opaque to userspace... userspace can
42 * access thread state via the regset mechanism. This allows us a bit of
43 * flexibility in how we order the registers on the stack, permitting some
44 * optimizations like packing call-clobbered registers together so that
45 * they share a cacheline (not done yet, though... future optimization).
46 */
47
48#ifndef __ASSEMBLY__
49/*
50 * This struct describes how the registers are laid out on the kernel stack
51 * during a syscall or other kernel entry.
52 *
53 * This structure should always be cacheline aligned on the stack.
54 * FIXME: I don't think that's the case right now. The alignment is
55 * taken care of elsewhere... head.S, process.c, etc.
56 */
57
58struct pt_regs {
59 union {
60 struct {
61 /* Named registers */
62 long sr; /* Stored in place of r0 */
63 long sp; /* r1 */
64 };
65 struct {
66 /* Old style */
67 long offset[2];
68 long gprs[30];
69 };
70 struct {
71 /* New style */
72 long gpr[32];
73 };
74 };
75 long pc;
76 long orig_gpr11; /* For restarting system calls */
77 long syscallno; /* Syscall number (used by strace) */
78 long dummy; /* Cheap alignment fix */
79};
80#endif /* __ASSEMBLY__ */
81
82/* TODO: Rename this to REDZONE because that's what it is */
83#define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */
84
85#define instruction_pointer(regs) ((regs)->pc)
86#define user_mode(regs) (((regs)->sr & SPR_SR_SM) == 0)
87#define user_stack_pointer(regs) ((unsigned long)(regs)->sp)
88#define profile_pc(regs) instruction_pointer(regs)
89
90/*
91 * Offsets used by 'ptrace' system call interface.
92 */
93#define PT_SR 0
94#define PT_SP 4
95#define PT_GPR2 8
96#define PT_GPR3 12
97#define PT_GPR4 16
98#define PT_GPR5 20
99#define PT_GPR6 24
100#define PT_GPR7 28
101#define PT_GPR8 32
102#define PT_GPR9 36
103#define PT_GPR10 40
104#define PT_GPR11 44
105#define PT_GPR12 48
106#define PT_GPR13 52
107#define PT_GPR14 56
108#define PT_GPR15 60
109#define PT_GPR16 64
110#define PT_GPR17 68
111#define PT_GPR18 72
112#define PT_GPR19 76
113#define PT_GPR20 80
114#define PT_GPR21 84
115#define PT_GPR22 88
116#define PT_GPR23 92
117#define PT_GPR24 96
118#define PT_GPR25 100
119#define PT_GPR26 104
120#define PT_GPR27 108
121#define PT_GPR28 112
122#define PT_GPR29 116
123#define PT_GPR30 120
124#define PT_GPR31 124
125#define PT_PC 128
126#define PT_ORIG_GPR11 132
127#define PT_SYSCALLNO 136
128
129#endif /* __KERNEL__ */
130
131#endif /* __ASM_OPENRISC_PTRACE_H */
diff --git a/arch/openrisc/include/asm/serial.h b/arch/openrisc/include/asm/serial.h
new file mode 100644
index 00000000000..270a4524163
--- /dev/null
+++ b/arch/openrisc/include/asm/serial.h
@@ -0,0 +1,36 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_SERIAL_H
20#define __ASM_OPENRISC_SERIAL_H
21
22#ifdef __KERNEL__
23
24#include <asm/cpuinfo.h>
25
26/* There's a generic version of this file, but it assumes a 1.8MHz UART clk...
27 * this, on the other hand, assumes the UART clock is tied to the system
28 * clock... 8250_early.c (early 8250 serial console) actually uses this, so
29 * it needs to be correct to get the early console working.
30 */
31
32#define BASE_BAUD (cpuinfo.clock_frequency/16)
33
34#endif /* __KERNEL__ */
35
36#endif /* __ASM_OPENRISC_SERIAL_H */
diff --git a/arch/openrisc/include/asm/sigcontext.h b/arch/openrisc/include/asm/sigcontext.h
new file mode 100644
index 00000000000..b79c2b19afb
--- /dev/null
+++ b/arch/openrisc/include/asm/sigcontext.h
@@ -0,0 +1,33 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_SIGCONTEXT_H
20#define __ASM_OPENRISC_SIGCONTEXT_H
21
22#include <asm/ptrace.h>
23
24/* This struct is saved by setup_frame in signal.c, to keep the current
25 context while a signal handler is executed. It's restored by sys_sigreturn.
26*/
27
28struct sigcontext {
29 struct user_regs_struct regs; /* needs to be first */
30 unsigned long oldmask;
31};
32
33#endif /* __ASM_OPENRISC_SIGCONTEXT_H */
diff --git a/arch/openrisc/include/asm/spinlock.h b/arch/openrisc/include/asm/spinlock.h
new file mode 100644
index 00000000000..fd00a3a2412
--- /dev/null
+++ b/arch/openrisc/include/asm/spinlock.h
@@ -0,0 +1,24 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_SPINLOCK_H
20#define __ASM_OPENRISC_SPINLOCK_H
21
22#error "or32 doesn't do SMP yet"
23
24#endif
diff --git a/arch/openrisc/include/asm/spr.h b/arch/openrisc/include/asm/spr.h
new file mode 100644
index 00000000000..1cccb42dd47
--- /dev/null
+++ b/arch/openrisc/include/asm/spr.h
@@ -0,0 +1,42 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#ifndef __ASM_OPENRISC_SPR_H
18#define __ASM_OPENRISC_SPR_H
19
20#define mtspr(_spr, _val) __asm__ __volatile__ ( \
21 "l.mtspr r0,%1,%0" \
22 : : "K" (_spr), "r" (_val))
23#define mtspr_off(_spr, _off, _val) __asm__ __volatile__ ( \
24 "l.mtspr %0,%1,%2" \
25 : : "r" (_off), "r" (_val), "K" (_spr))
26
27static inline unsigned long mfspr(unsigned long add)
28{
29 unsigned long ret;
30 __asm__ __volatile__ ("l.mfspr %0,r0,%1" : "=r" (ret) : "K" (add));
31 return ret;
32}
33
34static inline unsigned long mfspr_off(unsigned long add, unsigned long offset)
35{
36 unsigned long ret;
37 __asm__ __volatile__ ("l.mfspr %0,%1,%2" : "=r" (ret)
38 : "r" (offset), "K" (add));
39 return ret;
40}
41
42#endif
diff --git a/arch/openrisc/include/asm/spr_defs.h b/arch/openrisc/include/asm/spr_defs.h
new file mode 100644
index 00000000000..5dbc668865c
--- /dev/null
+++ b/arch/openrisc/include/asm/spr_defs.h
@@ -0,0 +1,604 @@
1/*
2 * OpenRISC Linux
3 *
4 * SPR Definitions
5 *
6 * Copyright (C) 2000 Damjan Lampret
7 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
8 * Copyright (C) 2008, 2010 Embecosm Limited
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 * et al.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This file is part of OpenRISC 1000 Architectural Simulator.
18 */
19
20#ifndef SPR_DEFS__H
21#define SPR_DEFS__H
22
23/* Definition of special-purpose registers (SPRs). */
24
25#define MAX_GRPS (32)
26#define MAX_SPRS_PER_GRP_BITS (11)
27#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS)
28#define MAX_SPRS (0x10000)
29
30/* Base addresses for the groups */
31#define SPRGROUP_SYS (0 << MAX_SPRS_PER_GRP_BITS)
32#define SPRGROUP_DMMU (1 << MAX_SPRS_PER_GRP_BITS)
33#define SPRGROUP_IMMU (2 << MAX_SPRS_PER_GRP_BITS)
34#define SPRGROUP_DC (3 << MAX_SPRS_PER_GRP_BITS)
35#define SPRGROUP_IC (4 << MAX_SPRS_PER_GRP_BITS)
36#define SPRGROUP_MAC (5 << MAX_SPRS_PER_GRP_BITS)
37#define SPRGROUP_D (6 << MAX_SPRS_PER_GRP_BITS)
38#define SPRGROUP_PC (7 << MAX_SPRS_PER_GRP_BITS)
39#define SPRGROUP_PM (8 << MAX_SPRS_PER_GRP_BITS)
40#define SPRGROUP_PIC (9 << MAX_SPRS_PER_GRP_BITS)
41#define SPRGROUP_TT (10 << MAX_SPRS_PER_GRP_BITS)
42#define SPRGROUP_FP (11 << MAX_SPRS_PER_GRP_BITS)
43
44/* System control and status group */
45#define SPR_VR (SPRGROUP_SYS + 0)
46#define SPR_UPR (SPRGROUP_SYS + 1)
47#define SPR_CPUCFGR (SPRGROUP_SYS + 2)
48#define SPR_DMMUCFGR (SPRGROUP_SYS + 3)
49#define SPR_IMMUCFGR (SPRGROUP_SYS + 4)
50#define SPR_DCCFGR (SPRGROUP_SYS + 5)
51#define SPR_ICCFGR (SPRGROUP_SYS + 6)
52#define SPR_DCFGR (SPRGROUP_SYS + 7)
53#define SPR_PCCFGR (SPRGROUP_SYS + 8)
54#define SPR_NPC (SPRGROUP_SYS + 16) /* CZ 21/06/01 */
55#define SPR_SR (SPRGROUP_SYS + 17) /* CZ 21/06/01 */
56#define SPR_PPC (SPRGROUP_SYS + 18) /* CZ 21/06/01 */
57#define SPR_FPCSR (SPRGROUP_SYS + 20) /* CZ 21/06/01 */
58#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) /* CZ 21/06/01 */
59#define SPR_EPCR_LAST (SPRGROUP_SYS + 47) /* CZ 21/06/01 */
60#define SPR_EEAR_BASE (SPRGROUP_SYS + 48)
61#define SPR_EEAR_LAST (SPRGROUP_SYS + 63)
62#define SPR_ESR_BASE (SPRGROUP_SYS + 64)
63#define SPR_ESR_LAST (SPRGROUP_SYS + 79)
64#define SPR_GPR_BASE (SPRGROUP_SYS + 1024)
65
66/* Data MMU group */
67#define SPR_DMMUCR (SPRGROUP_DMMU + 0)
68#define SPR_DTLBEIR (SPRGROUP_DMMU + 2)
69#define SPR_DTLBMR_BASE(WAY) (SPRGROUP_DMMU + 0x200 + (WAY) * 0x100)
70#define SPR_DTLBMR_LAST(WAY) (SPRGROUP_DMMU + 0x27f + (WAY) * 0x100)
71#define SPR_DTLBTR_BASE(WAY) (SPRGROUP_DMMU + 0x280 + (WAY) * 0x100)
72#define SPR_DTLBTR_LAST(WAY) (SPRGROUP_DMMU + 0x2ff + (WAY) * 0x100)
73
74/* Instruction MMU group */
75#define SPR_IMMUCR (SPRGROUP_IMMU + 0)
76#define SPR_ITLBEIR (SPRGROUP_IMMU + 2)
77#define SPR_ITLBMR_BASE(WAY) (SPRGROUP_IMMU + 0x200 + (WAY) * 0x100)
78#define SPR_ITLBMR_LAST(WAY) (SPRGROUP_IMMU + 0x27f + (WAY) * 0x100)
79#define SPR_ITLBTR_BASE(WAY) (SPRGROUP_IMMU + 0x280 + (WAY) * 0x100)
80#define SPR_ITLBTR_LAST(WAY) (SPRGROUP_IMMU + 0x2ff + (WAY) * 0x100)
81
82/* Data cache group */
83#define SPR_DCCR (SPRGROUP_DC + 0)
84#define SPR_DCBPR (SPRGROUP_DC + 1)
85#define SPR_DCBFR (SPRGROUP_DC + 2)
86#define SPR_DCBIR (SPRGROUP_DC + 3)
87#define SPR_DCBWR (SPRGROUP_DC + 4)
88#define SPR_DCBLR (SPRGROUP_DC + 5)
89#define SPR_DCR_BASE(WAY) (SPRGROUP_DC + 0x200 + (WAY) * 0x200)
90#define SPR_DCR_LAST(WAY) (SPRGROUP_DC + 0x3ff + (WAY) * 0x200)
91
92/* Instruction cache group */
93#define SPR_ICCR (SPRGROUP_IC + 0)
94#define SPR_ICBPR (SPRGROUP_IC + 1)
95#define SPR_ICBIR (SPRGROUP_IC + 2)
96#define SPR_ICBLR (SPRGROUP_IC + 3)
97#define SPR_ICR_BASE(WAY) (SPRGROUP_IC + 0x200 + (WAY) * 0x200)
98#define SPR_ICR_LAST(WAY) (SPRGROUP_IC + 0x3ff + (WAY) * 0x200)
99
100/* MAC group */
101#define SPR_MACLO (SPRGROUP_MAC + 1)
102#define SPR_MACHI (SPRGROUP_MAC + 2)
103
104/* Debug group */
105#define SPR_DVR(N) (SPRGROUP_D + (N))
106#define SPR_DCR(N) (SPRGROUP_D + 8 + (N))
107#define SPR_DMR1 (SPRGROUP_D + 16)
108#define SPR_DMR2 (SPRGROUP_D + 17)
109#define SPR_DWCR0 (SPRGROUP_D + 18)
110#define SPR_DWCR1 (SPRGROUP_D + 19)
111#define SPR_DSR (SPRGROUP_D + 20)
112#define SPR_DRR (SPRGROUP_D + 21)
113
114/* Performance counters group */
115#define SPR_PCCR(N) (SPRGROUP_PC + (N))
116#define SPR_PCMR(N) (SPRGROUP_PC + 8 + (N))
117
118/* Power management group */
119#define SPR_PMR (SPRGROUP_PM + 0)
120
121/* PIC group */
122#define SPR_PICMR (SPRGROUP_PIC + 0)
123#define SPR_PICPR (SPRGROUP_PIC + 1)
124#define SPR_PICSR (SPRGROUP_PIC + 2)
125
126/* Tick Timer group */
127#define SPR_TTMR (SPRGROUP_TT + 0)
128#define SPR_TTCR (SPRGROUP_TT + 1)
129
130/*
131 * Bit definitions for the Version Register
132 *
133 */
134#define SPR_VR_VER 0xff000000 /* Processor version */
135#define SPR_VR_CFG 0x00ff0000 /* Processor configuration */
136#define SPR_VR_RES 0x0000ffc0 /* Reserved */
137#define SPR_VR_REV 0x0000003f /* Processor revision */
138
139#define SPR_VR_VER_OFF 24
140#define SPR_VR_CFG_OFF 16
141#define SPR_VR_REV_OFF 0
142
143/*
144 * Bit definitions for the Unit Present Register
145 *
146 */
147#define SPR_UPR_UP 0x00000001 /* UPR present */
148#define SPR_UPR_DCP 0x00000002 /* Data cache present */
149#define SPR_UPR_ICP 0x00000004 /* Instruction cache present */
150#define SPR_UPR_DMP 0x00000008 /* Data MMU present */
151#define SPR_UPR_IMP 0x00000010 /* Instruction MMU present */
152#define SPR_UPR_MP 0x00000020 /* MAC present */
153#define SPR_UPR_DUP 0x00000040 /* Debug unit present */
154#define SPR_UPR_PCUP 0x00000080 /* Performance counters unit present */
155#define SPR_UPR_PMP 0x00000100 /* Power management present */
156#define SPR_UPR_PICP 0x00000200 /* PIC present */
157#define SPR_UPR_TTP 0x00000400 /* Tick timer present */
158#define SPR_UPR_RES 0x00fe0000 /* Reserved */
159#define SPR_UPR_CUP 0xff000000 /* Context units present */
160
161/*
162 * JPB: Bit definitions for the CPU configuration register
163 *
164 */
165#define SPR_CPUCFGR_NSGF 0x0000000f /* Number of shadow GPR files */
166#define SPR_CPUCFGR_CGF 0x00000010 /* Custom GPR file */
167#define SPR_CPUCFGR_OB32S 0x00000020 /* ORBIS32 supported */
168#define SPR_CPUCFGR_OB64S 0x00000040 /* ORBIS64 supported */
169#define SPR_CPUCFGR_OF32S 0x00000080 /* ORFPX32 supported */
170#define SPR_CPUCFGR_OF64S 0x00000100 /* ORFPX64 supported */
171#define SPR_CPUCFGR_OV64S 0x00000200 /* ORVDX64 supported */
172#define SPR_CPUCFGR_RES 0xfffffc00 /* Reserved */
173
174/*
175 * JPB: Bit definitions for the Debug configuration register and other
176 * constants.
177 *
178 */
179
180#define SPR_DCFGR_NDP 0x00000007 /* Number of matchpoints mask */
181#define SPR_DCFGR_NDP1 0x00000000 /* One matchpoint supported */
182#define SPR_DCFGR_NDP2 0x00000001 /* Two matchpoints supported */
183#define SPR_DCFGR_NDP3 0x00000002 /* Three matchpoints supported */
184#define SPR_DCFGR_NDP4 0x00000003 /* Four matchpoints supported */
185#define SPR_DCFGR_NDP5 0x00000004 /* Five matchpoints supported */
186#define SPR_DCFGR_NDP6 0x00000005 /* Six matchpoints supported */
187#define SPR_DCFGR_NDP7 0x00000006 /* Seven matchpoints supported */
188#define SPR_DCFGR_NDP8 0x00000007 /* Eight matchpoints supported */
189#define SPR_DCFGR_WPCI 0x00000008 /* Watchpoint counters implemented */
190
191#define MATCHPOINTS_TO_NDP(n) (1 == n ? SPR_DCFGR_NDP1 : \
192 2 == n ? SPR_DCFGR_NDP2 : \
193 3 == n ? SPR_DCFGR_NDP3 : \
194 4 == n ? SPR_DCFGR_NDP4 : \
195 5 == n ? SPR_DCFGR_NDP5 : \
196 6 == n ? SPR_DCFGR_NDP6 : \
197 7 == n ? SPR_DCFGR_NDP7 : SPR_DCFGR_NDP8)
198#define MAX_MATCHPOINTS 8
199#define MAX_WATCHPOINTS (MAX_MATCHPOINTS + 2)
200
201/*
202 * Bit definitions for the Supervision Register
203 *
204 */
205#define SPR_SR_SM 0x00000001 /* Supervisor Mode */
206#define SPR_SR_TEE 0x00000002 /* Tick timer Exception Enable */
207#define SPR_SR_IEE 0x00000004 /* Interrupt Exception Enable */
208#define SPR_SR_DCE 0x00000008 /* Data Cache Enable */
209#define SPR_SR_ICE 0x00000010 /* Instruction Cache Enable */
210#define SPR_SR_DME 0x00000020 /* Data MMU Enable */
211#define SPR_SR_IME 0x00000040 /* Instruction MMU Enable */
212#define SPR_SR_LEE 0x00000080 /* Little Endian Enable */
213#define SPR_SR_CE 0x00000100 /* CID Enable */
214#define SPR_SR_F 0x00000200 /* Condition Flag */
215#define SPR_SR_CY 0x00000400 /* Carry flag */
216#define SPR_SR_OV 0x00000800 /* Overflow flag */
217#define SPR_SR_OVE 0x00001000 /* Overflow flag Exception */
218#define SPR_SR_DSX 0x00002000 /* Delay Slot Exception */
219#define SPR_SR_EPH 0x00004000 /* Exception Prefix High */
220#define SPR_SR_FO 0x00008000 /* Fixed one */
221#define SPR_SR_SUMRA 0x00010000 /* Supervisor SPR read access */
222#define SPR_SR_RES 0x0ffe0000 /* Reserved */
223#define SPR_SR_CID 0xf0000000 /* Context ID */
224
225/*
226 * Bit definitions for the Data MMU Control Register
227 *
228 */
229#define SPR_DMMUCR_P2S 0x0000003e /* Level 2 Page Size */
230#define SPR_DMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
231#define SPR_DMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
232#define SPR_DMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
233
234/*
235 * Bit definitions for the Instruction MMU Control Register
236 *
237 */
238#define SPR_IMMUCR_P2S 0x0000003e /* Level 2 Page Size */
239#define SPR_IMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
240#define SPR_IMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
241#define SPR_IMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
242
243/*
244 * Bit definitions for the Data TLB Match Register
245 *
246 */
247#define SPR_DTLBMR_V 0x00000001 /* Valid */
248#define SPR_DTLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
249#define SPR_DTLBMR_CID 0x0000003c /* Context ID */
250#define SPR_DTLBMR_LRU 0x000000c0 /* Least Recently Used */
251#define SPR_DTLBMR_VPN 0xfffff000 /* Virtual Page Number */
252
253/*
254 * Bit definitions for the Data TLB Translate Register
255 *
256 */
257#define SPR_DTLBTR_CC 0x00000001 /* Cache Coherency */
258#define SPR_DTLBTR_CI 0x00000002 /* Cache Inhibit */
259#define SPR_DTLBTR_WBC 0x00000004 /* Write-Back Cache */
260#define SPR_DTLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
261#define SPR_DTLBTR_A 0x00000010 /* Accessed */
262#define SPR_DTLBTR_D 0x00000020 /* Dirty */
263#define SPR_DTLBTR_URE 0x00000040 /* User Read Enable */
264#define SPR_DTLBTR_UWE 0x00000080 /* User Write Enable */
265#define SPR_DTLBTR_SRE 0x00000100 /* Supervisor Read Enable */
266#define SPR_DTLBTR_SWE 0x00000200 /* Supervisor Write Enable */
267#define SPR_DTLBTR_PPN 0xfffff000 /* Physical Page Number */
268
269/*
270 * Bit definitions for the Instruction TLB Match Register
271 *
272 */
273#define SPR_ITLBMR_V 0x00000001 /* Valid */
274#define SPR_ITLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
275#define SPR_ITLBMR_CID 0x0000003c /* Context ID */
276#define SPR_ITLBMR_LRU 0x000000c0 /* Least Recently Used */
277#define SPR_ITLBMR_VPN 0xfffff000 /* Virtual Page Number */
278
279/*
280 * Bit definitions for the Instruction TLB Translate Register
281 *
282 */
283#define SPR_ITLBTR_CC 0x00000001 /* Cache Coherency */
284#define SPR_ITLBTR_CI 0x00000002 /* Cache Inhibit */
285#define SPR_ITLBTR_WBC 0x00000004 /* Write-Back Cache */
286#define SPR_ITLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
287#define SPR_ITLBTR_A 0x00000010 /* Accessed */
288#define SPR_ITLBTR_D 0x00000020 /* Dirty */
289#define SPR_ITLBTR_SXE 0x00000040 /* User Read Enable */
290#define SPR_ITLBTR_UXE 0x00000080 /* User Write Enable */
291#define SPR_ITLBTR_PPN 0xfffff000 /* Physical Page Number */
292
293/*
294 * Bit definitions for Data Cache Control register
295 *
296 */
297#define SPR_DCCR_EW 0x000000ff /* Enable ways */
298
299/*
300 * Bit definitions for Insn Cache Control register
301 *
302 */
303#define SPR_ICCR_EW 0x000000ff /* Enable ways */
304
305/*
306 * Bit definitions for Data Cache Configuration Register
307 *
308 */
309
310#define SPR_DCCFGR_NCW 0x00000007
311#define SPR_DCCFGR_NCS 0x00000078
312#define SPR_DCCFGR_CBS 0x00000080
313#define SPR_DCCFGR_CWS 0x00000100
314#define SPR_DCCFGR_CCRI 0x00000200
315#define SPR_DCCFGR_CBIRI 0x00000400
316#define SPR_DCCFGR_CBPRI 0x00000800
317#define SPR_DCCFGR_CBLRI 0x00001000
318#define SPR_DCCFGR_CBFRI 0x00002000
319#define SPR_DCCFGR_CBWBRI 0x00004000
320
321#define SPR_DCCFGR_NCW_OFF 0
322#define SPR_DCCFGR_NCS_OFF 3
323#define SPR_DCCFGR_CBS_OFF 7
324
325/*
326 * Bit definitions for Instruction Cache Configuration Register
327 *
328 */
329#define SPR_ICCFGR_NCW 0x00000007
330#define SPR_ICCFGR_NCS 0x00000078
331#define SPR_ICCFGR_CBS 0x00000080
332#define SPR_ICCFGR_CCRI 0x00000200
333#define SPR_ICCFGR_CBIRI 0x00000400
334#define SPR_ICCFGR_CBPRI 0x00000800
335#define SPR_ICCFGR_CBLRI 0x00001000
336
337#define SPR_ICCFGR_NCW_OFF 0
338#define SPR_ICCFGR_NCS_OFF 3
339#define SPR_ICCFGR_CBS_OFF 7
340
341/*
342 * Bit definitions for Data MMU Configuration Register
343 *
344 */
345
346#define SPR_DMMUCFGR_NTW 0x00000003
347#define SPR_DMMUCFGR_NTS 0x0000001C
348#define SPR_DMMUCFGR_NAE 0x000000E0
349#define SPR_DMMUCFGR_CRI 0x00000100
350#define SPR_DMMUCFGR_PRI 0x00000200
351#define SPR_DMMUCFGR_TEIRI 0x00000400
352#define SPR_DMMUCFGR_HTR 0x00000800
353
354#define SPR_DMMUCFGR_NTW_OFF 0
355#define SPR_DMMUCFGR_NTS_OFF 2
356
357/*
358 * Bit definitions for Instruction MMU Configuration Register
359 *
360 */
361
362#define SPR_IMMUCFGR_NTW 0x00000003
363#define SPR_IMMUCFGR_NTS 0x0000001C
364#define SPR_IMMUCFGR_NAE 0x000000E0
365#define SPR_IMMUCFGR_CRI 0x00000100
366#define SPR_IMMUCFGR_PRI 0x00000200
367#define SPR_IMMUCFGR_TEIRI 0x00000400
368#define SPR_IMMUCFGR_HTR 0x00000800
369
370#define SPR_IMMUCFGR_NTW_OFF 0
371#define SPR_IMMUCFGR_NTS_OFF 2
372
373/*
374 * Bit definitions for Debug Control registers
375 *
376 */
377#define SPR_DCR_DP 0x00000001 /* DVR/DCR present */
378#define SPR_DCR_CC 0x0000000e /* Compare condition */
379#define SPR_DCR_SC 0x00000010 /* Signed compare */
380#define SPR_DCR_CT 0x000000e0 /* Compare to */
381
382/* Bit results with SPR_DCR_CC mask */
383#define SPR_DCR_CC_MASKED 0x00000000
384#define SPR_DCR_CC_EQUAL 0x00000002
385#define SPR_DCR_CC_LESS 0x00000004
386#define SPR_DCR_CC_LESSE 0x00000006
387#define SPR_DCR_CC_GREAT 0x00000008
388#define SPR_DCR_CC_GREATE 0x0000000a
389#define SPR_DCR_CC_NEQUAL 0x0000000c
390
391/* Bit results with SPR_DCR_CT mask */
392#define SPR_DCR_CT_DISABLED 0x00000000
393#define SPR_DCR_CT_IFEA 0x00000020
394#define SPR_DCR_CT_LEA 0x00000040
395#define SPR_DCR_CT_SEA 0x00000060
396#define SPR_DCR_CT_LD 0x00000080
397#define SPR_DCR_CT_SD 0x000000a0
398#define SPR_DCR_CT_LSEA 0x000000c0
399#define SPR_DCR_CT_LSD 0x000000e0
400/* SPR_DCR_CT_LSD doesn't seem to be implemented anywhere in or1ksim. 2004-1-30 HP */
401
402/*
403 * Bit definitions for Debug Mode 1 register
404 *
405 */
406#define SPR_DMR1_CW 0x000fffff /* Chain register pair data */
407#define SPR_DMR1_CW0_AND 0x00000001
408#define SPR_DMR1_CW0_OR 0x00000002
409#define SPR_DMR1_CW0 (SPR_DMR1_CW0_AND | SPR_DMR1_CW0_OR)
410#define SPR_DMR1_CW1_AND 0x00000004
411#define SPR_DMR1_CW1_OR 0x00000008
412#define SPR_DMR1_CW1 (SPR_DMR1_CW1_AND | SPR_DMR1_CW1_OR)
413#define SPR_DMR1_CW2_AND 0x00000010
414#define SPR_DMR1_CW2_OR 0x00000020
415#define SPR_DMR1_CW2 (SPR_DMR1_CW2_AND | SPR_DMR1_CW2_OR)
416#define SPR_DMR1_CW3_AND 0x00000040
417#define SPR_DMR1_CW3_OR 0x00000080
418#define SPR_DMR1_CW3 (SPR_DMR1_CW3_AND | SPR_DMR1_CW3_OR)
419#define SPR_DMR1_CW4_AND 0x00000100
420#define SPR_DMR1_CW4_OR 0x00000200
421#define SPR_DMR1_CW4 (SPR_DMR1_CW4_AND | SPR_DMR1_CW4_OR)
422#define SPR_DMR1_CW5_AND 0x00000400
423#define SPR_DMR1_CW5_OR 0x00000800
424#define SPR_DMR1_CW5 (SPR_DMR1_CW5_AND | SPR_DMR1_CW5_OR)
425#define SPR_DMR1_CW6_AND 0x00001000
426#define SPR_DMR1_CW6_OR 0x00002000
427#define SPR_DMR1_CW6 (SPR_DMR1_CW6_AND | SPR_DMR1_CW6_OR)
428#define SPR_DMR1_CW7_AND 0x00004000
429#define SPR_DMR1_CW7_OR 0x00008000
430#define SPR_DMR1_CW7 (SPR_DMR1_CW7_AND | SPR_DMR1_CW7_OR)
431#define SPR_DMR1_CW8_AND 0x00010000
432#define SPR_DMR1_CW8_OR 0x00020000
433#define SPR_DMR1_CW8 (SPR_DMR1_CW8_AND | SPR_DMR1_CW8_OR)
434#define SPR_DMR1_CW9_AND 0x00040000
435#define SPR_DMR1_CW9_OR 0x00080000
436#define SPR_DMR1_CW9 (SPR_DMR1_CW9_AND | SPR_DMR1_CW9_OR)
437#define SPR_DMR1_RES1 0x00300000 /* Reserved */
438#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/
439#define SPR_DMR1_BT 0x00800000 /* Branch trace */
440#define SPR_DMR1_RES2 0xff000000 /* Reserved */
441
442/*
443 * Bit definitions for Debug Mode 2 register. AWTC and WGB corrected by JPB
444 *
445 */
446#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter 0 enable */
447#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter 0 enable */
448#define SPR_DMR2_AWTC 0x00000ffc /* Assign watchpoints to counters */
449#define SPR_DMR2_AWTC_OFF 2 /* Bit offset to AWTC field */
450#define SPR_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */
451#define SPR_DMR2_WGB_OFF 12 /* Bit offset to WGB field */
452#define SPR_DMR2_WBS 0xffc00000 /* JPB: Watchpoint status */
453#define SPR_DMR2_WBS_OFF 22 /* Bit offset to WBS field */
454
455/*
456 * Bit definitions for Debug watchpoint counter registers
457 *
458 */
459#define SPR_DWCR_COUNT 0x0000ffff /* Count */
460#define SPR_DWCR_MATCH 0xffff0000 /* Match */
461#define SPR_DWCR_MATCH_OFF 16 /* Match bit offset */
462
463/*
464 * Bit definitions for Debug stop register
465 *
466 */
467#define SPR_DSR_RSTE 0x00000001 /* Reset exception */
468#define SPR_DSR_BUSEE 0x00000002 /* Bus error exception */
469#define SPR_DSR_DPFE 0x00000004 /* Data Page Fault exception */
470#define SPR_DSR_IPFE 0x00000008 /* Insn Page Fault exception */
471#define SPR_DSR_TTE 0x00000010 /* Tick Timer exception */
472#define SPR_DSR_AE 0x00000020 /* Alignment exception */
473#define SPR_DSR_IIE 0x00000040 /* Illegal Instruction exception */
474#define SPR_DSR_IE 0x00000080 /* Interrupt exception */
475#define SPR_DSR_DME 0x00000100 /* DTLB miss exception */
476#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */
477#define SPR_DSR_RE 0x00000400 /* Range exception */
478#define SPR_DSR_SCE 0x00000800 /* System call exception */
479#define SPR_DSR_FPE 0x00001000 /* Floating Point Exception */
480#define SPR_DSR_TE 0x00002000 /* Trap exception */
481
482/*
483 * Bit definitions for Debug reason register
484 *
485 */
486#define SPR_DRR_RSTE 0x00000001 /* Reset exception */
487#define SPR_DRR_BUSEE 0x00000002 /* Bus error exception */
488#define SPR_DRR_DPFE 0x00000004 /* Data Page Fault exception */
489#define SPR_DRR_IPFE 0x00000008 /* Insn Page Fault exception */
490#define SPR_DRR_TTE 0x00000010 /* Tick Timer exception */
491#define SPR_DRR_AE 0x00000020 /* Alignment exception */
492#define SPR_DRR_IIE 0x00000040 /* Illegal Instruction exception */
493#define SPR_DRR_IE 0x00000080 /* Interrupt exception */
494#define SPR_DRR_DME 0x00000100 /* DTLB miss exception */
495#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */
496#define SPR_DRR_RE 0x00000400 /* Range exception */
497#define SPR_DRR_SCE 0x00000800 /* System call exception */
498#define SPR_DRR_FPE 0x00001000 /* Floating Point Exception */
499#define SPR_DRR_TE 0x00002000 /* Trap exception */
500
501/*
502 * Bit definitions for Performance counters mode registers
503 *
504 */
505#define SPR_PCMR_CP 0x00000001 /* Counter present */
506#define SPR_PCMR_UMRA 0x00000002 /* User mode read access */
507#define SPR_PCMR_CISM 0x00000004 /* Count in supervisor mode */
508#define SPR_PCMR_CIUM 0x00000008 /* Count in user mode */
509#define SPR_PCMR_LA 0x00000010 /* Load access event */
510#define SPR_PCMR_SA 0x00000020 /* Store access event */
511#define SPR_PCMR_IF 0x00000040 /* Instruction fetch event*/
512#define SPR_PCMR_DCM 0x00000080 /* Data cache miss event */
513#define SPR_PCMR_ICM 0x00000100 /* Insn cache miss event */
514#define SPR_PCMR_IFS 0x00000200 /* Insn fetch stall event */
515#define SPR_PCMR_LSUS 0x00000400 /* LSU stall event */
516#define SPR_PCMR_BS 0x00000800 /* Branch stall event */
517#define SPR_PCMR_DTLBM 0x00001000 /* DTLB miss event */
518#define SPR_PCMR_ITLBM 0x00002000 /* ITLB miss event */
519#define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */
520#define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */
521
522/*
523 * Bit definitions for the Power management register
524 *
525 */
526#define SPR_PMR_SDF 0x0000000f /* Slow down factor */
527#define SPR_PMR_DME 0x00000010 /* Doze mode enable */
528#define SPR_PMR_SME 0x00000020 /* Sleep mode enable */
529#define SPR_PMR_DCGE 0x00000040 /* Dynamic clock gating enable */
530#define SPR_PMR_SUME 0x00000080 /* Suspend mode enable */
531
532/*
533 * Bit definitions for PICMR
534 *
535 */
536#define SPR_PICMR_IUM 0xfffffffc /* Interrupt unmask */
537
538/*
539 * Bit definitions for PICPR
540 *
541 */
542#define SPR_PICPR_IPRIO 0xfffffffc /* Interrupt priority */
543
544/*
545 * Bit definitions for PICSR
546 *
547 */
548#define SPR_PICSR_IS 0xffffffff /* Interrupt status */
549
550/*
551 * Bit definitions for Tick Timer Control Register
552 *
553 */
554
555#define SPR_TTCR_CNT 0xffffffff /* Count, time period */
556#define SPR_TTMR_TP 0x0fffffff /* Time period */
557#define SPR_TTMR_IP 0x10000000 /* Interrupt Pending */
558#define SPR_TTMR_IE 0x20000000 /* Interrupt Enable */
559#define SPR_TTMR_DI 0x00000000 /* Disabled */
560#define SPR_TTMR_RT 0x40000000 /* Restart tick */
561#define SPR_TTMR_SR 0x80000000 /* Single run */
562#define SPR_TTMR_CR 0xc0000000 /* Continuous run */
563#define SPR_TTMR_M 0xc0000000 /* Tick mode */
564
565/*
566 * Bit definitions for the FP Control Status Register
567 *
568 */
569#define SPR_FPCSR_FPEE 0x00000001 /* Floating Point Exception Enable */
570#define SPR_FPCSR_RM 0x00000006 /* Rounding Mode */
571#define SPR_FPCSR_OVF 0x00000008 /* Overflow Flag */
572#define SPR_FPCSR_UNF 0x00000010 /* Underflow Flag */
573#define SPR_FPCSR_SNF 0x00000020 /* SNAN Flag */
574#define SPR_FPCSR_QNF 0x00000040 /* QNAN Flag */
575#define SPR_FPCSR_ZF 0x00000080 /* Zero Flag */
576#define SPR_FPCSR_IXF 0x00000100 /* Inexact Flag */
577#define SPR_FPCSR_IVF 0x00000200 /* Invalid Flag */
578#define SPR_FPCSR_INF 0x00000400 /* Infinity Flag */
579#define SPR_FPCSR_DZF 0x00000800 /* Divide By Zero Flag */
580#define SPR_FPCSR_ALLF (SPR_FPCSR_OVF | SPR_FPCSR_UNF | SPR_FPCSR_SNF | \
581 SPR_FPCSR_QNF | SPR_FPCSR_ZF | SPR_FPCSR_IXF | \
582 SPR_FPCSR_IVF | SPR_FPCSR_INF | SPR_FPCSR_DZF)
583
584#define FPCSR_RM_RN (0<<1)
585#define FPCSR_RM_RZ (1<<1)
586#define FPCSR_RM_RIP (2<<1)
587#define FPCSR_RM_RIN (3<<1)
588
589/*
590 * l.nop constants
591 *
592 */
593#define NOP_NOP 0x0000 /* Normal nop instruction */
594#define NOP_EXIT 0x0001 /* End of simulation */
595#define NOP_REPORT 0x0002 /* Simple report */
596/*#define NOP_PRINTF 0x0003 Simprintf instruction (obsolete)*/
597#define NOP_PUTC 0x0004 /* JPB: Simputc instruction */
598#define NOP_CNT_RESET 0x0005 /* Reset statistics counters */
599#define NOP_GET_TICKS 0x0006 /* JPB: Get # ticks running */
600#define NOP_GET_PS 0x0007 /* JPB: Get picosecs/cycle */
601#define NOP_REPORT_FIRST 0x0400 /* Report with number */
602#define NOP_REPORT_LAST 0x03ff /* Report with number */
603
604#endif /* SPR_DEFS__H */
diff --git a/arch/openrisc/include/asm/syscall.h b/arch/openrisc/include/asm/syscall.h
new file mode 100644
index 00000000000..9f0337055d2
--- /dev/null
+++ b/arch/openrisc/include/asm/syscall.h
@@ -0,0 +1,77 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_SYSCALL_H__
20#define __ASM_OPENRISC_SYSCALL_H__
21
22#include <linux/err.h>
23#include <linux/sched.h>
24
25static inline int
26syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
27{
28 return regs->syscallno ? regs->syscallno : -1;
29}
30
31static inline void
32syscall_rollback(struct task_struct *task, struct pt_regs *regs)
33{
34 regs->gpr[11] = regs->orig_gpr11;
35}
36
37static inline long
38syscall_get_error(struct task_struct *task, struct pt_regs *regs)
39{
40 return IS_ERR_VALUE(regs->gpr[11]) ? regs->gpr[11] : 0;
41}
42
43static inline long
44syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
45{
46 return regs->gpr[11];
47}
48
49static inline void
50syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
51 int error, long val)
52{
53 if (error)
54 regs->gpr[11] = -error;
55 else
56 regs->gpr[11] = val;
57}
58
59static inline void
60syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
61 unsigned int i, unsigned int n, unsigned long *args)
62{
63 BUG_ON(i + n > 6);
64
65 memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
66}
67
68static inline void
69syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
70 unsigned int i, unsigned int n, const unsigned long *args)
71{
72 BUG_ON(i + n > 6);
73
74 memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
75}
76
77#endif
diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h
new file mode 100644
index 00000000000..84a978af44d
--- /dev/null
+++ b/arch/openrisc/include/asm/syscalls.h
@@ -0,0 +1,27 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_SYSCALLS_H
20#define __ASM_OPENRISC_SYSCALLS_H
21
22asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1,
23 unsigned long *v2);
24
25#include <asm-generic/syscalls.h>
26
27#endif /* __ASM_OPENRISC_SYSCALLS_H */
diff --git a/arch/openrisc/include/asm/system.h b/arch/openrisc/include/asm/system.h
new file mode 100644
index 00000000000..cf658882186
--- /dev/null
+++ b/arch/openrisc/include/asm/system.h
@@ -0,0 +1,35 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_SYSTEM_H
20#define __ASM_OPENRISC_SYSTEM_H
21
22#ifdef __KERNEL__
23#ifndef __ASSEMBLY__
24
25#include <asm/spr.h>
26#include <asm-generic/system.h>
27
28/* We probably need this definition, but the generic system.h provides it
29 * and it's not used on our arch anyway...
30 */
31/*#define nop() __asm__ __volatile__ ("l.nop"::)*/
32
33#endif /* __ASSEMBLY__ */
34#endif /* __KERNEL__ */
35#endif /* __ASM_OPENRISC_SYSTEM_H */
diff --git a/arch/openrisc/include/asm/thread_info.h b/arch/openrisc/include/asm/thread_info.h
new file mode 100644
index 00000000000..07a8bc080ef
--- /dev/null
+++ b/arch/openrisc/include/asm/thread_info.h
@@ -0,0 +1,134 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef _ASM_THREAD_INFO_H
20#define _ASM_THREAD_INFO_H
21
22#ifdef __KERNEL__
23
24#ifndef __ASSEMBLY__
25#include <asm/types.h>
26#include <asm/processor.h>
27#endif
28
29
30/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
31 * normally, the stack is found by doing something like p + THREAD_SIZE
32 * in or32, a page is 8192 bytes, which seems like a sane size
33 */
34
35#define THREAD_SIZE_ORDER 0
36#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
37
38/*
39 * low level task data that entry.S needs immediate access to
40 * - this struct should fit entirely inside of one cache line
41 * - this struct shares the supervisor stack pages
42 * - if the contents of this structure are changed, the assembly constants
43 * must also be changed
44 */
45#ifndef __ASSEMBLY__
46
47typedef unsigned long mm_segment_t;
48
49struct thread_info {
50 struct task_struct *task; /* main task structure */
51 struct exec_domain *exec_domain; /* execution domain */
52 unsigned long flags; /* low level flags */
53 __u32 cpu; /* current CPU */
54 __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
55
56 mm_segment_t addr_limit; /* thread address space:
57 0-0x7FFFFFFF for user-thead
58 0-0xFFFFFFFF for kernel-thread
59 */
60 struct restart_block restart_block;
61 __u8 supervisor_stack[0];
62
63 /* saved context data */
64 unsigned long ksp;
65};
66#endif
67
68/*
69 * macros/functions for gaining access to the thread information structure
70 *
71 * preempt_count needs to be 1 initially, until the scheduler is functional.
72 */
73#ifndef __ASSEMBLY__
74#define INIT_THREAD_INFO(tsk) \
75{ \
76 .task = &tsk, \
77 .exec_domain = &default_exec_domain, \
78 .flags = 0, \
79 .cpu = 0, \
80 .preempt_count = 1, \
81 .addr_limit = KERNEL_DS, \
82 .restart_block = { \
83 .fn = do_no_restart_syscall, \
84 }, \
85 .ksp = 0, \
86}
87
88#define init_thread_info (init_thread_union.thread_info)
89
90/* how to get the thread information struct from C */
91register struct thread_info *current_thread_info_reg asm("r10");
92#define current_thread_info() (current_thread_info_reg)
93
94#define get_thread_info(ti) get_task_struct((ti)->task)
95#define put_thread_info(ti) put_task_struct((ti)->task)
96
97#endif /* !__ASSEMBLY__ */
98
99/*
100 * thread information flags
101 * these are process state flags that various assembly files may need to
102 * access
103 * - pending work-to-be-done flags are in LSW
104 * - other flags in MSW
105 */
106#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
107#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
108#define TIF_SIGPENDING 2 /* signal pending */
109#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
110#define TIF_SINGLESTEP 4 /* restore singlestep on return to user
111 * mode
112 */
113#define TIF_SYSCALL_TRACEPOINT 8 /* for ftrace syscall instrumentation */
114#define TIF_RESTORE_SIGMASK 9
115#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling * TIF_NEED_RESCHED
116 */
117#define TIF_MEMDIE 17
118
119#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
120#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
121#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
122#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
123#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
124#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
125#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
126
127
128/* Work to do when returning from interrupt/exception */
129/* For OpenRISC, this is anything in the LSW other than syscall trace */
130#define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP))
131
132#endif /* __KERNEL__ */
133
134#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/openrisc/include/asm/timex.h b/arch/openrisc/include/asm/timex.h
new file mode 100644
index 00000000000..9935cad1b9b
--- /dev/null
+++ b/arch/openrisc/include/asm/timex.h
@@ -0,0 +1,36 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#ifndef __ASM_OPENRISC_TIMEX_H
18#define __ASM_OPENRISC_TIMEX_H
19
20#define get_cycles get_cycles
21
22#include <asm-generic/timex.h>
23#include <asm/spr.h>
24#include <asm/spr_defs.h>
25
26static inline cycles_t get_cycles(void)
27{
28 return mfspr(SPR_TTCR);
29}
30
31/* This isn't really used any more */
32#define CLOCK_TICK_RATE 1000
33
34#define ARCH_HAS_READ_CURRENT_TIMER
35
36#endif
diff --git a/arch/openrisc/include/asm/tlb.h b/arch/openrisc/include/asm/tlb.h
new file mode 100644
index 00000000000..fa4376a4515
--- /dev/null
+++ b/arch/openrisc/include/asm/tlb.h
@@ -0,0 +1,34 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_TLB_H__
20#define __ASM_OPENRISC_TLB_H__
21
22/*
23 * or32 doesn't need any special per-pte or
24 * per-vma handling..
25 */
26#define tlb_start_vma(tlb, vma) do { } while (0)
27#define tlb_end_vma(tlb, vma) do { } while (0)
28#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
29
30#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
31#include <linux/pagemap.h>
32#include <asm-generic/tlb.h>
33
34#endif /* __ASM_OPENRISC_TLB_H__ */
diff --git a/arch/openrisc/include/asm/tlbflush.h b/arch/openrisc/include/asm/tlbflush.h
new file mode 100644
index 00000000000..6a2accd6cb6
--- /dev/null
+++ b/arch/openrisc/include/asm/tlbflush.h
@@ -0,0 +1,55 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_TLBFLUSH_H
20#define __ASM_OPENRISC_TLBFLUSH_H
21
22#include <linux/mm.h>
23#include <asm/processor.h>
24#include <asm/pgtable.h>
25#include <asm/pgalloc.h>
26#include <asm/current.h>
27#include <linux/sched.h>
28
29/*
30 * - flush_tlb() flushes the current mm struct TLBs
31 * - flush_tlb_all() flushes all processes TLBs
32 * - flush_tlb_mm(mm) flushes the specified mm context TLB's
33 * - flush_tlb_page(vma, vmaddr) flushes one page
34 * - flush_tlb_range(mm, start, end) flushes a range of pages
35 */
36
37void flush_tlb_all(void);
38void flush_tlb_mm(struct mm_struct *mm);
39void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
40void flush_tlb_range(struct vm_area_struct *vma,
41 unsigned long start,
42 unsigned long end);
43
44static inline void flush_tlb(void)
45{
46 flush_tlb_mm(current->mm);
47}
48
49static inline void flush_tlb_kernel_range(unsigned long start,
50 unsigned long end)
51{
52 flush_tlb_range(NULL, start, end);
53}
54
55#endif /* __ASM_OPENRISC_TLBFLUSH_H */
diff --git a/arch/openrisc/include/asm/uaccess.h b/arch/openrisc/include/asm/uaccess.h
new file mode 100644
index 00000000000..c310e45b538
--- /dev/null
+++ b/arch/openrisc/include/asm/uaccess.h
@@ -0,0 +1,355 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_UACCESS_H
20#define __ASM_OPENRISC_UACCESS_H
21
22/*
23 * User space memory access functions
24 */
25#include <linux/errno.h>
26#include <linux/thread_info.h>
27#include <linux/prefetch.h>
28#include <linux/string.h>
29#include <linux/thread_info.h>
30#include <asm/page.h>
31
32#define VERIFY_READ 0
33#define VERIFY_WRITE 1
34
35/*
36 * The fs value determines whether argument validity checking should be
37 * performed or not. If get_fs() == USER_DS, checking is performed, with
38 * get_fs() == KERNEL_DS, checking is bypassed.
39 *
40 * For historical reasons, these macros are grossly misnamed.
41 */
42
43/* addr_limit is the maximum accessible address for the task. we misuse
44 * the KERNEL_DS and USER_DS values to both assign and compare the
45 * addr_limit values through the equally misnamed get/set_fs macros.
46 * (see above)
47 */
48
49#define KERNEL_DS (~0UL)
50#define get_ds() (KERNEL_DS)
51
52#define USER_DS (TASK_SIZE)
53#define get_fs() (current_thread_info()->addr_limit)
54#define set_fs(x) (current_thread_info()->addr_limit = (x))
55
56#define segment_eq(a, b) ((a) == (b))
57
58/* Ensure that the range from addr to addr+size is all within the process'
59 * address space
60 */
61#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size))
62
63/* Ensure that addr is below task's addr_limit */
64#define __addr_ok(addr) ((unsigned long) addr < get_fs())
65
66#define access_ok(type, addr, size) \
67 __range_ok((unsigned long)addr, (unsigned long)size)
68
69/*
70 * The exception table consists of pairs of addresses: the first is the
71 * address of an instruction that is allowed to fault, and the second is
72 * the address at which the program should continue. No registers are
73 * modified, so it is entirely up to the continuation code to figure out
74 * what to do.
75 *
76 * All the routines below use bits of fixup code that are out of line
77 * with the main instruction path. This means when everything is well,
78 * we don't even have to jump over them. Further, they do not intrude
79 * on our cache or tlb entries.
80 */
81
82struct exception_table_entry {
83 unsigned long insn, fixup;
84};
85
86/* Returns 0 if exception not found and fixup otherwise. */
87extern unsigned long search_exception_table(unsigned long);
88extern void sort_exception_table(void);
89
90/*
91 * These are the main single-value transfer routines. They automatically
92 * use the right size if we just have the right pointer type.
93 *
94 * This gets kind of ugly. We want to return _two_ values in "get_user()"
95 * and yet we don't want to do any pointers, because that is too much
96 * of a performance impact. Thus we have a few rather ugly macros here,
97 * and hide all the uglyness from the user.
98 *
99 * The "__xxx" versions of the user access functions are versions that
100 * do not verify the address space, that must have been done previously
101 * with a separate "access_ok()" call (this is used when we do multiple
102 * accesses to the same area of user memory).
103 *
104 * As we use the same address space for kernel and user data on the
105 * PowerPC, we can just do these as direct assignments. (Of course, the
106 * exception handling means that it's no longer "just"...)
107 */
108#define get_user(x, ptr) \
109 __get_user_check((x), (ptr), sizeof(*(ptr)))
110#define put_user(x, ptr) \
111 __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
112
113#define __get_user(x, ptr) \
114 __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
115#define __put_user(x, ptr) \
116 __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
117
118extern long __put_user_bad(void);
119
120#define __put_user_nocheck(x, ptr, size) \
121({ \
122 long __pu_err; \
123 __put_user_size((x), (ptr), (size), __pu_err); \
124 __pu_err; \
125})
126
127#define __put_user_check(x, ptr, size) \
128({ \
129 long __pu_err = -EFAULT; \
130 __typeof__(*(ptr)) *__pu_addr = (ptr); \
131 if (access_ok(VERIFY_WRITE, __pu_addr, size)) \
132 __put_user_size((x), __pu_addr, (size), __pu_err); \
133 __pu_err; \
134})
135
136#define __put_user_size(x, ptr, size, retval) \
137do { \
138 retval = 0; \
139 switch (size) { \
140 case 1: __put_user_asm(x, ptr, retval, "l.sb"); break; \
141 case 2: __put_user_asm(x, ptr, retval, "l.sh"); break; \
142 case 4: __put_user_asm(x, ptr, retval, "l.sw"); break; \
143 case 8: __put_user_asm2(x, ptr, retval); break; \
144 default: __put_user_bad(); \
145 } \
146} while (0)
147
148struct __large_struct {
149 unsigned long buf[100];
150};
151#define __m(x) (*(struct __large_struct *)(x))
152
153/*
154 * We don't tell gcc that we are accessing memory, but this is OK
155 * because we do not write to any memory gcc knows about, so there
156 * are no aliasing issues.
157 */
158#define __put_user_asm(x, addr, err, op) \
159 __asm__ __volatile__( \
160 "1: "op" 0(%2),%1\n" \
161 "2:\n" \
162 ".section .fixup,\"ax\"\n" \
163 "3: l.addi %0,r0,%3\n" \
164 " l.j 2b\n" \
165 " l.nop\n" \
166 ".previous\n" \
167 ".section __ex_table,\"a\"\n" \
168 " .align 2\n" \
169 " .long 1b,3b\n" \
170 ".previous" \
171 : "=r"(err) \
172 : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
173
174#define __put_user_asm2(x, addr, err) \
175 __asm__ __volatile__( \
176 "1: l.sw 0(%2),%1\n" \
177 "2: l.sw 4(%2),%H1\n" \
178 "3:\n" \
179 ".section .fixup,\"ax\"\n" \
180 "4: l.addi %0,r0,%3\n" \
181 " l.j 3b\n" \
182 " l.nop\n" \
183 ".previous\n" \
184 ".section __ex_table,\"a\"\n" \
185 " .align 2\n" \
186 " .long 1b,4b\n" \
187 " .long 2b,4b\n" \
188 ".previous" \
189 : "=r"(err) \
190 : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
191
192#define __get_user_nocheck(x, ptr, size) \
193({ \
194 long __gu_err, __gu_val; \
195 __get_user_size(__gu_val, (ptr), (size), __gu_err); \
196 (x) = (__typeof__(*(ptr)))__gu_val; \
197 __gu_err; \
198})
199
200#define __get_user_check(x, ptr, size) \
201({ \
202 long __gu_err = -EFAULT, __gu_val = 0; \
203 const __typeof__(*(ptr)) * __gu_addr = (ptr); \
204 if (access_ok(VERIFY_READ, __gu_addr, size)) \
205 __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
206 (x) = (__typeof__(*(ptr)))__gu_val; \
207 __gu_err; \
208})
209
210extern long __get_user_bad(void);
211
212#define __get_user_size(x, ptr, size, retval) \
213do { \
214 retval = 0; \
215 switch (size) { \
216 case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break; \
217 case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \
218 case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \
219 case 8: __get_user_asm2(x, ptr, retval); \
220 default: (x) = __get_user_bad(); \
221 } \
222} while (0)
223
224#define __get_user_asm(x, addr, err, op) \
225 __asm__ __volatile__( \
226 "1: "op" %1,0(%2)\n" \
227 "2:\n" \
228 ".section .fixup,\"ax\"\n" \
229 "3: l.addi %0,r0,%3\n" \
230 " l.addi %1,r0,0\n" \
231 " l.j 2b\n" \
232 " l.nop\n" \
233 ".previous\n" \
234 ".section __ex_table,\"a\"\n" \
235 " .align 2\n" \
236 " .long 1b,3b\n" \
237 ".previous" \
238 : "=r"(err), "=r"(x) \
239 : "r"(addr), "i"(-EFAULT), "0"(err))
240
241#define __get_user_asm2(x, addr, err) \
242 __asm__ __volatile__( \
243 "1: l.lwz %1,0(%2)\n" \
244 "2: l.lwz %H1,4(%2)\n" \
245 "3:\n" \
246 ".section .fixup,\"ax\"\n" \
247 "4: l.addi %0,r0,%3\n" \
248 " l.addi %1,r0,0\n" \
249 " l.addi %H1,r0,0\n" \
250 " l.j 3b\n" \
251 " l.nop\n" \
252 ".previous\n" \
253 ".section __ex_table,\"a\"\n" \
254 " .align 2\n" \
255 " .long 1b,4b\n" \
256 " .long 2b,4b\n" \
257 ".previous" \
258 : "=r"(err), "=&r"(x) \
259 : "r"(addr), "i"(-EFAULT), "0"(err))
260
261/* more complex routines */
262
263extern unsigned long __must_check
264__copy_tofrom_user(void *to, const void *from, unsigned long size);
265
266#define __copy_from_user(to, from, size) \
267 __copy_tofrom_user(to, from, size)
268#define __copy_to_user(to, from, size) \
269 __copy_tofrom_user(to, from, size)
270
271#define __copy_to_user_inatomic __copy_to_user
272#define __copy_from_user_inatomic __copy_from_user
273
274static inline unsigned long
275copy_from_user(void *to, const void *from, unsigned long n)
276{
277 unsigned long over;
278
279 if (access_ok(VERIFY_READ, from, n))
280 return __copy_tofrom_user(to, from, n);
281 if ((unsigned long)from < TASK_SIZE) {
282 over = (unsigned long)from + n - TASK_SIZE;
283 return __copy_tofrom_user(to, from, n - over) + over;
284 }
285 return n;
286}
287
288static inline unsigned long
289copy_to_user(void *to, const void *from, unsigned long n)
290{
291 unsigned long over;
292
293 if (access_ok(VERIFY_WRITE, to, n))
294 return __copy_tofrom_user(to, from, n);
295 if ((unsigned long)to < TASK_SIZE) {
296 over = (unsigned long)to + n - TASK_SIZE;
297 return __copy_tofrom_user(to, from, n - over) + over;
298 }
299 return n;
300}
301
302extern unsigned long __clear_user(void *addr, unsigned long size);
303
304static inline __must_check unsigned long
305clear_user(void *addr, unsigned long size)
306{
307
308 if (access_ok(VERIFY_WRITE, addr, size))
309 return __clear_user(addr, size);
310 if ((unsigned long)addr < TASK_SIZE) {
311 unsigned long over = (unsigned long)addr + size - TASK_SIZE;
312 return __clear_user(addr, size - over) + over;
313 }
314 return size;
315}
316
317extern int __strncpy_from_user(char *dst, const char *src, long count);
318
319static inline long strncpy_from_user(char *dst, const char *src, long count)
320{
321 if (access_ok(VERIFY_READ, src, 1))
322 return __strncpy_from_user(dst, src, count);
323 return -EFAULT;
324}
325
326/*
327 * Return the size of a string (including the ending 0)
328 *
329 * Return 0 for error
330 */
331
332extern int __strnlen_user(const char *str, long len, unsigned long top);
333
334/*
335 * Returns the length of the string at str (including the null byte),
336 * or 0 if we hit a page we can't access,
337 * or something > len if we didn't find a null byte.
338 *
339 * The `top' parameter to __strnlen_user is to make sure that
340 * we can never overflow from the user area into kernel space.
341 */
342static inline long strnlen_user(const char __user *str, long len)
343{
344 unsigned long top = (unsigned long)get_fs();
345 unsigned long res = 0;
346
347 if (__addr_ok(str))
348 res = __strnlen_user(str, len, top);
349
350 return res;
351}
352
353#define strlen_user(str) strnlen_user(str, TASK_SIZE-1)
354
355#endif /* __ASM_OPENRISC_UACCESS_H */
diff --git a/arch/openrisc/include/asm/unaligned.h b/arch/openrisc/include/asm/unaligned.h
new file mode 100644
index 00000000000..1141cbd6fd7
--- /dev/null
+++ b/arch/openrisc/include/asm/unaligned.h
@@ -0,0 +1,51 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#ifndef __ASM_OPENRISC_UNALIGNED_H
20#define __ASM_OPENRISC_UNALIGNED_H
21
22/*
23 * This is copied from the generic implementation and the C-struct
24 * variant replaced with the memmove variant. The GCC compiler
25 * for the OR32 arch optimizes too aggressively for the C-struct
26 * variant to work, so use the memmove variant instead.
27 *
28 * It may be worth considering implementing the unaligned access
29 * exception handler and allowing unaligned accesses (access_ok.h)...
30 * not sure if it would be much of a performance win without further
31 * investigation.
32 */
33#include <asm/byteorder.h>
34
35#if defined(__LITTLE_ENDIAN)
36# include <linux/unaligned/le_memmove.h>
37# include <linux/unaligned/be_byteshift.h>
38# include <linux/unaligned/generic.h>
39# define get_unaligned __get_unaligned_le
40# define put_unaligned __put_unaligned_le
41#elif defined(__BIG_ENDIAN)
42# include <linux/unaligned/be_memmove.h>
43# include <linux/unaligned/le_byteshift.h>
44# include <linux/unaligned/generic.h>
45# define get_unaligned __get_unaligned_be
46# define put_unaligned __put_unaligned_be
47#else
48# error need to define endianess
49#endif
50
51#endif /* __ASM_OPENRISC_UNALIGNED_H */
diff --git a/arch/openrisc/include/asm/unistd.h b/arch/openrisc/include/asm/unistd.h
new file mode 100644
index 00000000000..89af3ab5c2e
--- /dev/null
+++ b/arch/openrisc/include/asm/unistd.h
@@ -0,0 +1,31 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * OpenRISC implementation:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 * et al.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 */
18
19#if !defined(__ASM_OPENRISC_UNISTD_H) || defined(__SYSCALL)
20#define __ASM_OPENRISC_UNISTD_H
21
22#define __ARCH_HAVE_MMU
23
24#define sys_mmap2 sys_mmap_pgoff
25
26#include <asm-generic/unistd.h>
27
28#define __NR_or1k_atomic __NR_arch_specific_syscall
29__SYSCALL(__NR_or1k_atomic, sys_or1k_atomic)
30
31#endif /* __ASM_OPENRISC_UNISTD_H */
diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile
new file mode 100644
index 00000000000..9a4c2706d79
--- /dev/null
+++ b/arch/openrisc/kernel/Makefile
@@ -0,0 +1,14 @@
1#
2# Makefile for the linux kernel.
3#
4
5extra-y := head.o vmlinux.lds init_task.o
6
7obj-y := setup.o idle.o or32_ksyms.o process.o dma.o \
8 traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \
9 sys_call_table.o
10
11obj-$(CONFIG_MODULES) += module.o
12obj-$(CONFIG_OF) += prom.o
13
14clean:
diff --git a/arch/openrisc/kernel/asm-offsets.c b/arch/openrisc/kernel/asm-offsets.c
new file mode 100644
index 00000000000..1a242a0d758
--- /dev/null
+++ b/arch/openrisc/kernel/asm-offsets.c
@@ -0,0 +1,70 @@
1/*
2 * OpenRISC asm-offsets.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * This program is used to generate definitions needed by
18 * assembly language modules.
19 *
20 * We use the technique used in the OSF Mach kernel code:
21 * generate asm statements containing #defines,
22 * compile this file to assembler, and then extract the
23 * #defines from the assembly-language output.
24 */
25
26#include <linux/signal.h>
27#include <linux/sched.h>
28#include <linux/kernel.h>
29#include <linux/errno.h>
30#include <linux/string.h>
31#include <linux/types.h>
32#include <linux/ptrace.h>
33#include <linux/mman.h>
34#include <linux/mm.h>
35#include <linux/io.h>
36#include <linux/thread_info.h>
37#include <asm/page.h>
38#include <asm/pgtable.h>
39#include <asm/processor.h>
40
41#define DEFINE(sym, val) \
42 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
43
44#define BLANK() asm volatile("\n->" : : )
45
46int main(void)
47{
48 /* offsets into the task_struct */
49 DEFINE(TASK_STATE, offsetof(struct task_struct, state));
50 DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
51 DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
52 DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
53 DEFINE(TASK_MM, offsetof(struct task_struct, mm));
54 DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
55
56 /* offsets into thread_info */
57 DEFINE(TI_TASK, offsetof(struct thread_info, task));
58 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
59 DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
60 DEFINE(TI_KSP, offsetof(struct thread_info, ksp));
61
62 DEFINE(PT_SIZE, sizeof(struct pt_regs));
63
64 /* Interrupt register frame */
65 DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
66 DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
67
68 DEFINE(NUM_USER_SEGMENTS, TASK_SIZE >> 28);
69 return 0;
70}
diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c
new file mode 100644
index 00000000000..f1c8ee2895d
--- /dev/null
+++ b/arch/openrisc/kernel/dma.c
@@ -0,0 +1,217 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * DMA mapping callbacks...
18 * As alloc_coherent is the only DMA callback being used currently, that's
19 * the only thing implemented properly. The rest need looking into...
20 */
21
22#include <linux/dma-mapping.h>
23#include <linux/dma-debug.h>
24
25#include <asm/cpuinfo.h>
26#include <asm/spr_defs.h>
27#include <asm/tlbflush.h>
28
29static int page_set_nocache(pte_t *pte, unsigned long addr,
30 unsigned long next, struct mm_walk *walk)
31{
32 unsigned long cl;
33
34 pte_val(*pte) |= _PAGE_CI;
35
36 /*
37 * Flush the page out of the TLB so that the new page flags get
38 * picked up next time there's an access
39 */
40 flush_tlb_page(NULL, addr);
41
42 /* Flush page out of dcache */
43 for (cl = __pa(addr); cl < __pa(next); cl += cpuinfo.dcache_block_size)
44 mtspr(SPR_DCBFR, cl);
45
46 return 0;
47}
48
49static int page_clear_nocache(pte_t *pte, unsigned long addr,
50 unsigned long next, struct mm_walk *walk)
51{
52 pte_val(*pte) &= ~_PAGE_CI;
53
54 /*
55 * Flush the page out of the TLB so that the new page flags get
56 * picked up next time there's an access
57 */
58 flush_tlb_page(NULL, addr);
59
60 return 0;
61}
62
63/*
64 * Alloc "coherent" memory, which for OpenRISC means simply uncached.
65 *
66 * This function effectively just calls __get_free_pages, sets the
67 * cache-inhibit bit on those pages, and makes sure that the pages are
68 * flushed out of the cache before they are used.
69 *
70 */
71void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
72 dma_addr_t *dma_handle, gfp_t gfp)
73{
74 unsigned long va;
75 void *page;
76 struct mm_walk walk = {
77 .pte_entry = page_set_nocache,
78 .mm = &init_mm
79 };
80
81 page = alloc_pages_exact(size, gfp);
82 if (!page)
83 return NULL;
84
85 /* This gives us the real physical address of the first page. */
86 *dma_handle = __pa(page);
87
88 va = (unsigned long)page;
89
90 /*
91 * We need to iterate through the pages, clearing the dcache for
92 * them and setting the cache-inhibit bit.
93 */
94 if (walk_page_range(va, va + size, &walk)) {
95 free_pages_exact(page, size);
96 return NULL;
97 }
98
99 return (void *)va;
100}
101
102void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
103 dma_addr_t dma_handle)
104{
105 unsigned long va = (unsigned long)vaddr;
106 struct mm_walk walk = {
107 .pte_entry = page_clear_nocache,
108 .mm = &init_mm
109 };
110
111 /* walk_page_range shouldn't be able to fail here */
112 WARN_ON(walk_page_range(va, va + size, &walk));
113
114 free_pages_exact(vaddr, size);
115}
116
117dma_addr_t or1k_map_page(struct device *dev, struct page *page,
118 unsigned long offset, size_t size,
119 enum dma_data_direction dir,
120 struct dma_attrs *attrs)
121{
122 unsigned long cl;
123 dma_addr_t addr = page_to_phys(page) + offset;
124
125 switch (dir) {
126 case DMA_TO_DEVICE:
127 /* Flush the dcache for the requested range */
128 for (cl = addr; cl < addr + size;
129 cl += cpuinfo.dcache_block_size)
130 mtspr(SPR_DCBFR, cl);
131 break;
132 case DMA_FROM_DEVICE:
133 /* Invalidate the dcache for the requested range */
134 for (cl = addr; cl < addr + size;
135 cl += cpuinfo.dcache_block_size)
136 mtspr(SPR_DCBIR, cl);
137 break;
138 default:
139 /*
140 * NOTE: If dir == DMA_BIDIRECTIONAL then there's no need to
141 * flush nor invalidate the cache here as the area will need
142 * to be manually synced anyway.
143 */
144 break;
145 }
146
147 return addr;
148}
149
150void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
151 size_t size, enum dma_data_direction dir,
152 struct dma_attrs *attrs)
153{
154 /* Nothing special to do here... */
155}
156
157int or1k_map_sg(struct device *dev, struct scatterlist *sg,
158 int nents, enum dma_data_direction dir,
159 struct dma_attrs *attrs)
160{
161 struct scatterlist *s;
162 int i;
163
164 for_each_sg(sg, s, nents, i) {
165 s->dma_address = or1k_map_page(dev, sg_page(s), s->offset,
166 s->length, dir, NULL);
167 }
168
169 return nents;
170}
171
172void or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
173 int nents, enum dma_data_direction dir,
174 struct dma_attrs *attrs)
175{
176 struct scatterlist *s;
177 int i;
178
179 for_each_sg(sg, s, nents, i) {
180 or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, NULL);
181 }
182}
183
184void or1k_sync_single_for_cpu(struct device *dev,
185 dma_addr_t dma_handle, size_t size,
186 enum dma_data_direction dir)
187{
188 unsigned long cl;
189 dma_addr_t addr = dma_handle;
190
191 /* Invalidate the dcache for the requested range */
192 for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
193 mtspr(SPR_DCBIR, cl);
194}
195
196void or1k_sync_single_for_device(struct device *dev,
197 dma_addr_t dma_handle, size_t size,
198 enum dma_data_direction dir)
199{
200 unsigned long cl;
201 dma_addr_t addr = dma_handle;
202
203 /* Flush the dcache for the requested range */
204 for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
205 mtspr(SPR_DCBFR, cl);
206}
207
208/* Number of entries preallocated for DMA-API debugging */
209#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
210
211static int __init dma_init(void)
212{
213 dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
214
215 return 0;
216}
217fs_initcall(dma_init);
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
new file mode 100644
index 00000000000..d5f9c35a583
--- /dev/null
+++ b/arch/openrisc/kernel/entry.S
@@ -0,0 +1,1128 @@
1/*
2 * OpenRISC entry.S
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com>
11 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 */
18
19#include <linux/linkage.h>
20
21#include <asm/processor.h>
22#include <asm/unistd.h>
23#include <asm/thread_info.h>
24#include <asm/errno.h>
25#include <asm/spr_defs.h>
26#include <asm/page.h>
27#include <asm/mmu.h>
28#include <asm/pgtable.h>
29#include <asm/asm-offsets.h>
30
31#define DISABLE_INTERRUPTS(t1,t2) \
32 l.mfspr t2,r0,SPR_SR ;\
33 l.movhi t1,hi(~(SPR_SR_IEE|SPR_SR_TEE)) ;\
34 l.ori t1,t1,lo(~(SPR_SR_IEE|SPR_SR_TEE)) ;\
35 l.and t2,t2,t1 ;\
36 l.mtspr r0,t2,SPR_SR
37
38#define ENABLE_INTERRUPTS(t1) \
39 l.mfspr t1,r0,SPR_SR ;\
40 l.ori t1,t1,lo(SPR_SR_IEE|SPR_SR_TEE) ;\
41 l.mtspr r0,t1,SPR_SR
42
43/* =========================================================[ macros ]=== */
44
45/*
46 * We need to disable interrupts at beginning of RESTORE_ALL
47 * since interrupt might come in after we've loaded EPC return address
48 * and overwrite EPC with address somewhere in RESTORE_ALL
49 * which is of course wrong!
50 */
51
52#define RESTORE_ALL \
53 DISABLE_INTERRUPTS(r3,r4) ;\
54 l.lwz r3,PT_PC(r1) ;\
55 l.mtspr r0,r3,SPR_EPCR_BASE ;\
56 l.lwz r3,PT_SR(r1) ;\
57 l.mtspr r0,r3,SPR_ESR_BASE ;\
58 l.lwz r2,PT_GPR2(r1) ;\
59 l.lwz r3,PT_GPR3(r1) ;\
60 l.lwz r4,PT_GPR4(r1) ;\
61 l.lwz r5,PT_GPR5(r1) ;\
62 l.lwz r6,PT_GPR6(r1) ;\
63 l.lwz r7,PT_GPR7(r1) ;\
64 l.lwz r8,PT_GPR8(r1) ;\
65 l.lwz r9,PT_GPR9(r1) ;\
66 l.lwz r10,PT_GPR10(r1) ;\
67 l.lwz r11,PT_GPR11(r1) ;\
68 l.lwz r12,PT_GPR12(r1) ;\
69 l.lwz r13,PT_GPR13(r1) ;\
70 l.lwz r14,PT_GPR14(r1) ;\
71 l.lwz r15,PT_GPR15(r1) ;\
72 l.lwz r16,PT_GPR16(r1) ;\
73 l.lwz r17,PT_GPR17(r1) ;\
74 l.lwz r18,PT_GPR18(r1) ;\
75 l.lwz r19,PT_GPR19(r1) ;\
76 l.lwz r20,PT_GPR20(r1) ;\
77 l.lwz r21,PT_GPR21(r1) ;\
78 l.lwz r22,PT_GPR22(r1) ;\
79 l.lwz r23,PT_GPR23(r1) ;\
80 l.lwz r24,PT_GPR24(r1) ;\
81 l.lwz r25,PT_GPR25(r1) ;\
82 l.lwz r26,PT_GPR26(r1) ;\
83 l.lwz r27,PT_GPR27(r1) ;\
84 l.lwz r28,PT_GPR28(r1) ;\
85 l.lwz r29,PT_GPR29(r1) ;\
86 l.lwz r30,PT_GPR30(r1) ;\
87 l.lwz r31,PT_GPR31(r1) ;\
88 l.lwz r1,PT_SP(r1) ;\
89 l.rfe
90
91
92#define EXCEPTION_ENTRY(handler) \
93 .global handler ;\
94handler: ;\
95 /* r1, EPCR, ESR a already saved */ ;\
96 l.sw PT_GPR2(r1),r2 ;\
97 l.sw PT_GPR3(r1),r3 ;\
98 l.sw PT_ORIG_GPR11(r1),r11 ;\
99 /* r4 already save */ ;\
100 l.sw PT_GPR5(r1),r5 ;\
101 l.sw PT_GPR6(r1),r6 ;\
102 l.sw PT_GPR7(r1),r7 ;\
103 l.sw PT_GPR8(r1),r8 ;\
104 l.sw PT_GPR9(r1),r9 ;\
105 /* r10 already saved */ ;\
106 l.sw PT_GPR11(r1),r11 ;\
107 /* r12 already saved */ ;\
108 l.sw PT_GPR13(r1),r13 ;\
109 l.sw PT_GPR14(r1),r14 ;\
110 l.sw PT_GPR15(r1),r15 ;\
111 l.sw PT_GPR16(r1),r16 ;\
112 l.sw PT_GPR17(r1),r17 ;\
113 l.sw PT_GPR18(r1),r18 ;\
114 l.sw PT_GPR19(r1),r19 ;\
115 l.sw PT_GPR20(r1),r20 ;\
116 l.sw PT_GPR21(r1),r21 ;\
117 l.sw PT_GPR22(r1),r22 ;\
118 l.sw PT_GPR23(r1),r23 ;\
119 l.sw PT_GPR24(r1),r24 ;\
120 l.sw PT_GPR25(r1),r25 ;\
121 l.sw PT_GPR26(r1),r26 ;\
122 l.sw PT_GPR27(r1),r27 ;\
123 l.sw PT_GPR28(r1),r28 ;\
124 l.sw PT_GPR29(r1),r29 ;\
125 /* r30 already save */ ;\
126/* l.sw PT_GPR30(r1),r30*/ ;\
127 l.sw PT_GPR31(r1),r31 ;\
128 l.sw PT_SYSCALLNO(r1),r0
129
130#define UNHANDLED_EXCEPTION(handler,vector) \
131 .global handler ;\
132handler: ;\
133 /* r1, EPCR, ESR already saved */ ;\
134 l.sw PT_GPR2(r1),r2 ;\
135 l.sw PT_GPR3(r1),r3 ;\
136 l.sw PT_ORIG_GPR11(r1),r11 ;\
137 l.sw PT_GPR5(r1),r5 ;\
138 l.sw PT_GPR6(r1),r6 ;\
139 l.sw PT_GPR7(r1),r7 ;\
140 l.sw PT_GPR8(r1),r8 ;\
141 l.sw PT_GPR9(r1),r9 ;\
142 /* r10 already saved */ ;\
143 l.sw PT_GPR11(r1),r11 ;\
144 /* r12 already saved */ ;\
145 l.sw PT_GPR13(r1),r13 ;\
146 l.sw PT_GPR14(r1),r14 ;\
147 l.sw PT_GPR15(r1),r15 ;\
148 l.sw PT_GPR16(r1),r16 ;\
149 l.sw PT_GPR17(r1),r17 ;\
150 l.sw PT_GPR18(r1),r18 ;\
151 l.sw PT_GPR19(r1),r19 ;\
152 l.sw PT_GPR20(r1),r20 ;\
153 l.sw PT_GPR21(r1),r21 ;\
154 l.sw PT_GPR22(r1),r22 ;\
155 l.sw PT_GPR23(r1),r23 ;\
156 l.sw PT_GPR24(r1),r24 ;\
157 l.sw PT_GPR25(r1),r25 ;\
158 l.sw PT_GPR26(r1),r26 ;\
159 l.sw PT_GPR27(r1),r27 ;\
160 l.sw PT_GPR28(r1),r28 ;\
161 l.sw PT_GPR29(r1),r29 ;\
162 /* r31 already saved */ ;\
163 l.sw PT_GPR30(r1),r30 ;\
164/* l.sw PT_GPR31(r1),r31 */ ;\
165 l.sw PT_SYSCALLNO(r1),r0 ;\
166 l.addi r3,r1,0 ;\
167 /* r4 is exception EA */ ;\
168 l.addi r5,r0,vector ;\
169 l.jal unhandled_exception ;\
170 l.nop ;\
171 l.j _ret_from_exception ;\
172 l.nop
173
174/*
175 * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR
176 * contain the same values as when exception we're handling
177 * occured. in fact they never do. if you need them use
178 * values saved on stack (for SPR_EPC, SPR_ESR) or content
179 * of r4 (for SPR_EEAR). for details look at EXCEPTION_HANDLE()
180 * in 'arch/or32/kernel/head.S'
181 */
182
183/* =====================================================[ exceptions] === */
184
185/* ---[ 0x100: RESET exception ]----------------------------------------- */
186
187EXCEPTION_ENTRY(_tng_kernel_start)
188 l.jal _start
189 l.andi r0,r0,0
190
191/* ---[ 0x200: BUS exception ]------------------------------------------- */
192
193EXCEPTION_ENTRY(_bus_fault_handler)
194 /* r4: EA of fault (set by EXCEPTION_HANDLE) */
195 l.jal do_bus_fault
196 l.addi r3,r1,0 /* pt_regs */
197
198 l.j _ret_from_exception
199 l.nop
200
201/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
202
203EXCEPTION_ENTRY(_data_page_fault_handler)
204 /* set up parameters for do_page_fault */
205 l.addi r3,r1,0 // pt_regs
206 /* r4 set be EXCEPTION_HANDLE */ // effective address of fault
207 l.ori r5,r0,0x300 // exception vector
208
209 /*
210 * __PHX__: TODO
211 *
212 * all this can be written much simpler. look at
213 * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part
214 */
215#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
216 l.lwz r6,PT_PC(r3) // address of an offending insn
217 l.lwz r6,0(r6) // instruction that caused pf
218
219 l.srli r6,r6,26 // check opcode for jump insn
220 l.sfeqi r6,0 // l.j
221 l.bf 8f
222 l.sfeqi r6,1 // l.jal
223 l.bf 8f
224 l.sfeqi r6,3 // l.bnf
225 l.bf 8f
226 l.sfeqi r6,4 // l.bf
227 l.bf 8f
228 l.sfeqi r6,0x11 // l.jr
229 l.bf 8f
230 l.sfeqi r6,0x12 // l.jalr
231 l.bf 8f
232
233 l.nop
234
235 l.j 9f
236 l.nop
2378:
238
239 l.lwz r6,PT_PC(r3) // address of an offending insn
240 l.addi r6,r6,4
241 l.lwz r6,0(r6) // instruction that caused pf
242 l.srli r6,r6,26 // get opcode
2439:
244
245#else
246
247 l.mfspr r6,r0,SPR_SR // SR
248// l.lwz r6,PT_SR(r3) // ESR
249 l.andi r6,r6,SPR_SR_DSX // check for delay slot exception
250 l.sfeqi r6,0x1 // exception happened in delay slot
251 l.bnf 7f
252 l.lwz r6,PT_PC(r3) // address of an offending insn
253
254 l.addi r6,r6,4 // offending insn is in delay slot
2557:
256 l.lwz r6,0(r6) // instruction that caused pf
257 l.srli r6,r6,26 // check opcode for write access
258#endif
259
260 l.sfgeui r6,0x34 // check opcode for write access
261 l.bnf 1f
262 l.sfleui r6,0x37
263 l.bnf 1f
264 l.ori r6,r0,0x1 // write access
265 l.j 2f
266 l.nop
2671: l.ori r6,r0,0x0 // !write access
2682:
269
270 /* call fault.c handler in or32/mm/fault.c */
271 l.jal do_page_fault
272 l.nop
273 l.j _ret_from_exception
274 l.nop
275
276/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
277
278EXCEPTION_ENTRY(_insn_page_fault_handler)
279 /* set up parameters for do_page_fault */
280 l.addi r3,r1,0 // pt_regs
281 /* r4 set be EXCEPTION_HANDLE */ // effective address of fault
282 l.ori r5,r0,0x400 // exception vector
283 l.ori r6,r0,0x0 // !write access
284
285 /* call fault.c handler in or32/mm/fault.c */
286 l.jal do_page_fault
287 l.nop
288 l.j _ret_from_exception
289 l.nop
290
291
292/* ---[ 0x500: Timer exception ]----------------------------------------- */
293
294EXCEPTION_ENTRY(_timer_handler)
295 l.jal timer_interrupt
296 l.addi r3,r1,0 /* pt_regs */
297
298 l.j _ret_from_intr
299 l.nop
300
301/* ---[ 0x600: Aligment exception ]-------------------------------------- */
302
303EXCEPTION_ENTRY(_alignment_handler)
304 /* r4: EA of fault (set by EXCEPTION_HANDLE) */
305 l.jal do_unaligned_access
306 l.addi r3,r1,0 /* pt_regs */
307
308 l.j _ret_from_exception
309 l.nop
310
311#if 0
312EXCEPTION_ENTRY(_aligment_handler)
313// l.mfspr r2,r0,SPR_EEAR_BASE /* Load the efective addres */
314 l.addi r2,r4,0
315// l.mfspr r5,r0,SPR_EPCR_BASE /* Load the insn address */
316 l.lwz r5,PT_PC(r1)
317
318 l.lwz r3,0(r5) /* Load insn */
319 l.srli r4,r3,26 /* Shift left to get the insn opcode */
320
321 l.sfeqi r4,0x00 /* Check if the load/store insn is in delay slot */
322 l.bf jmp
323 l.sfeqi r4,0x01
324 l.bf jmp
325 l.sfeqi r4,0x03
326 l.bf jmp
327 l.sfeqi r4,0x04
328 l.bf jmp
329 l.sfeqi r4,0x11
330 l.bf jr
331 l.sfeqi r4,0x12
332 l.bf jr
333 l.nop
334 l.j 1f
335 l.addi r5,r5,4 /* Increment PC to get return insn address */
336
337jmp:
338 l.slli r4,r3,6 /* Get the signed extended jump length */
339 l.srai r4,r4,4
340
341 l.lwz r3,4(r5) /* Load the real load/store insn */
342
343 l.add r5,r5,r4 /* Calculate jump target address */
344
345 l.j 1f
346 l.srli r4,r3,26 /* Shift left to get the insn opcode */
347
348jr:
349 l.slli r4,r3,9 /* Shift to get the reg nb */
350 l.andi r4,r4,0x7c
351
352 l.lwz r3,4(r5) /* Load the real load/store insn */
353
354 l.add r4,r4,r1 /* Load the jump register value from the stack */
355 l.lwz r5,0(r4)
356
357 l.srli r4,r3,26 /* Shift left to get the insn opcode */
358
359
3601:
361// l.mtspr r0,r5,SPR_EPCR_BASE
362 l.sw PT_PC(r1),r5
363
364 l.sfeqi r4,0x26
365 l.bf lhs
366 l.sfeqi r4,0x25
367 l.bf lhz
368 l.sfeqi r4,0x22
369 l.bf lws
370 l.sfeqi r4,0x21
371 l.bf lwz
372 l.sfeqi r4,0x37
373 l.bf sh
374 l.sfeqi r4,0x35
375 l.bf sw
376 l.nop
377
3781: l.j 1b /* I don't know what to do */
379 l.nop
380
381lhs: l.lbs r5,0(r2)
382 l.slli r5,r5,8
383 l.lbz r6,1(r2)
384 l.or r5,r5,r6
385 l.srli r4,r3,19
386 l.andi r4,r4,0x7c
387 l.add r4,r4,r1
388 l.j align_end
389 l.sw 0(r4),r5
390
391lhz: l.lbz r5,0(r2)
392 l.slli r5,r5,8
393 l.lbz r6,1(r2)
394 l.or r5,r5,r6
395 l.srli r4,r3,19
396 l.andi r4,r4,0x7c
397 l.add r4,r4,r1
398 l.j align_end
399 l.sw 0(r4),r5
400
401lws: l.lbs r5,0(r2)
402 l.slli r5,r5,24
403 l.lbz r6,1(r2)
404 l.slli r6,r6,16
405 l.or r5,r5,r6
406 l.lbz r6,2(r2)
407 l.slli r6,r6,8
408 l.or r5,r5,r6
409 l.lbz r6,3(r2)
410 l.or r5,r5,r6
411 l.srli r4,r3,19
412 l.andi r4,r4,0x7c
413 l.add r4,r4,r1
414 l.j align_end
415 l.sw 0(r4),r5
416
417lwz: l.lbz r5,0(r2)
418 l.slli r5,r5,24
419 l.lbz r6,1(r2)
420 l.slli r6,r6,16
421 l.or r5,r5,r6
422 l.lbz r6,2(r2)
423 l.slli r6,r6,8
424 l.or r5,r5,r6
425 l.lbz r6,3(r2)
426 l.or r5,r5,r6
427 l.srli r4,r3,19
428 l.andi r4,r4,0x7c
429 l.add r4,r4,r1
430 l.j align_end
431 l.sw 0(r4),r5
432
433sh:
434 l.srli r4,r3,9
435 l.andi r4,r4,0x7c
436 l.add r4,r4,r1
437 l.lwz r5,0(r4)
438 l.sb 1(r2),r5
439 l.srli r5,r5,8
440 l.j align_end
441 l.sb 0(r2),r5
442
443sw:
444 l.srli r4,r3,9
445 l.andi r4,r4,0x7c
446 l.add r4,r4,r1
447 l.lwz r5,0(r4)
448 l.sb 3(r2),r5
449 l.srli r5,r5,8
450 l.sb 2(r2),r5
451 l.srli r5,r5,8
452 l.sb 1(r2),r5
453 l.srli r5,r5,8
454 l.j align_end
455 l.sb 0(r2),r5
456
457align_end:
458 l.j _ret_from_intr
459 l.nop
460#endif
461
462/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
463
464EXCEPTION_ENTRY(_illegal_instruction_handler)
465 /* r4: EA of fault (set by EXCEPTION_HANDLE) */
466 l.jal do_illegal_instruction
467 l.addi r3,r1,0 /* pt_regs */
468
469 l.j _ret_from_exception
470 l.nop
471
472/* ---[ 0x800: External interrupt exception ]---------------------------- */
473
474EXCEPTION_ENTRY(_external_irq_handler)
475#ifdef CONFIG_OPENRISC_ESR_EXCEPTION_BUG_CHECK
476 l.lwz r4,PT_SR(r1) // were interrupts enabled ?
477 l.andi r4,r4,SPR_SR_IEE
478 l.sfeqi r4,0
479 l.bnf 1f // ext irq enabled, all ok.
480 l.nop
481
482 l.addi r1,r1,-0x8
483 l.movhi r3,hi(42f)
484 l.ori r3,r3,lo(42f)
485 l.sw 0x0(r1),r3
486 l.jal printk
487 l.sw 0x4(r1),r4
488 l.addi r1,r1,0x8
489
490 .section .rodata, "a"
49142:
492 .string "\n\rESR interrupt bug: in _external_irq_handler (ESR %x)\n\r"
493 .align 4
494 .previous
495
496 l.ori r4,r4,SPR_SR_IEE // fix the bug
497// l.sw PT_SR(r1),r4
4981:
499#endif
500 l.addi r3,r1,0
501 l.movhi r8,hi(do_IRQ)
502 l.ori r8,r8,lo(do_IRQ)
503 l.jalr r8
504 l.nop
505 l.j _ret_from_intr
506 l.nop
507
508/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
509
510
511/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
512
513
514/* ---[ 0xb00: Range exception ]----------------------------------------- */
515
516UNHANDLED_EXCEPTION(_vector_0xb00,0xb00)
517
518/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
519
520/*
521 * Syscalls are a special type of exception in that they are
522 * _explicitly_ invoked by userspace and can therefore be
523 * held to conform to the same ABI as normal functions with
524 * respect to whether registers are preserved across the call
525 * or not.
526 */
527
528/* Upon syscall entry we just save the callee-saved registers
529 * and not the call-clobbered ones.
530 */
531
532_string_syscall_return:
533 .string "syscall return %ld \n\r\0"
534 .align 4
535
536ENTRY(_sys_call_handler)
537 /* syscalls run with interrupts enabled */
538 ENABLE_INTERRUPTS(r29) // enable interrupts, r29 is temp
539
540 /* r1, EPCR, ESR a already saved */
541 l.sw PT_GPR2(r1),r2
542 /* r3-r8 must be saved because syscall restart relies
543 * on us being able to restart the syscall args... technically
544 * they should be clobbered, otherwise
545 */
546 l.sw PT_GPR3(r1),r3
547 /* r4 already saved */
548 /* r4 holds the EEAR address of the fault, load the original r4 */
549 l.lwz r4,PT_GPR4(r1)
550 l.sw PT_GPR5(r1),r5
551 l.sw PT_GPR6(r1),r6
552 l.sw PT_GPR7(r1),r7
553 l.sw PT_GPR8(r1),r8
554 l.sw PT_GPR9(r1),r9
555 /* r10 already saved */
556 l.sw PT_GPR11(r1),r11
557 l.sw PT_ORIG_GPR11(r1),r11
558 /* r12,r13 already saved */
559
560 /* r14-r28 (even) aren't touched by the syscall fast path below
561 * so we don't need to save them. However, the functions that return
562 * to userspace via a call to switch() DO need to save these because
563 * switch() effectively clobbers them... saving these registers for
564 * such functions is handled in their syscall wrappers (see fork, vfork,
565 * and clone, below).
566
567 /* r30 is the only register we clobber in the fast path */
568 /* r30 already saved */
569/* l.sw PT_GPR30(r1),r30 */
570 /* This is used by do_signal to determine whether to check for
571 * syscall restart or not */
572 l.sw PT_SYSCALLNO(r1),r11
573
574_syscall_check_trace_enter:
575 /* If TIF_SYSCALL_TRACE is set, then we want to do syscall tracing */
576 l.lwz r30,TI_FLAGS(r10)
577 l.andi r30,r30,_TIF_SYSCALL_TRACE
578 l.sfne r30,r0
579 l.bf _syscall_trace_enter
580 l.nop
581
582_syscall_check:
583 /* Ensure that the syscall number is reasonable */
584 l.sfgeui r11,__NR_syscalls
585 l.bf _syscall_badsys
586 l.nop
587
588_syscall_call:
589 l.movhi r29,hi(sys_call_table)
590 l.ori r29,r29,lo(sys_call_table)
591 l.slli r11,r11,2
592 l.add r29,r29,r11
593 l.lwz r29,0(r29)
594
595 l.jalr r29
596 l.nop
597
598_syscall_return:
599 /* All syscalls return here... just pay attention to ret_from_fork
600 * which does it in a round-about way.
601 */
602 l.sw PT_GPR11(r1),r11 // save return value
603
604#if 0
605_syscall_debug:
606 l.movhi r3,hi(_string_syscall_return)
607 l.ori r3,r3,lo(_string_syscall_return)
608 l.ori r27,r0,1
609 l.sw -4(r1),r27
610 l.sw -8(r1),r11
611 l.addi r1,r1,-8
612 l.movhi r27,hi(printk)
613 l.ori r27,r27,lo(printk)
614 l.jalr r27
615 l.nop
616 l.addi r1,r1,8
617#endif
618
619_syscall_check_trace_leave:
620 /* r30 is a callee-saved register so this should still hold the
621 * _TIF_SYSCALL_TRACE flag from _syscall_check_trace_enter above...
622 * _syscall_trace_leave expects syscall result to be in pt_regs->r11.
623 */
624 l.sfne r30,r0
625 l.bf _syscall_trace_leave
626 l.nop
627
628/* This is where the exception-return code begins... interrupts need to be
629 * disabled the rest of the way here because we can't afford to miss any
630 * interrupts that set NEED_RESCHED or SIGNALPENDING... really true? */
631
632_syscall_check_work:
633 /* Here we need to disable interrupts */
634 DISABLE_INTERRUPTS(r27,r29)
635 l.lwz r30,TI_FLAGS(r10)
636 l.andi r30,r30,_TIF_WORK_MASK
637 l.sfne r30,r0
638
639 l.bnf _syscall_resume_userspace
640 l.nop
641
642 /* Work pending follows a different return path, so we need to
643 * make sure that all the call-saved registers get into pt_regs
644 * before branching...
645 */
646 l.sw PT_GPR14(r1),r14
647 l.sw PT_GPR16(r1),r16
648 l.sw PT_GPR18(r1),r18
649 l.sw PT_GPR20(r1),r20
650 l.sw PT_GPR22(r1),r22
651 l.sw PT_GPR24(r1),r24
652 l.sw PT_GPR26(r1),r26
653 l.sw PT_GPR28(r1),r28
654
655 /* _work_pending needs to be called with interrupts disabled */
656 l.j _work_pending
657 l.nop
658
659_syscall_resume_userspace:
660// ENABLE_INTERRUPTS(r29)
661
662
663/* This is the hot path for returning to userspace from a syscall. If there's
664 * work to be done and the branch to _work_pending was taken above, then the
665 * return to userspace will be done via the normal exception return path...
666 * that path restores _all_ registers and will overwrite the "clobbered"
667 * registers with whatever garbage is in pt_regs -- that's OK because those
668 * registers are clobbered anyway and because the extra work is insignificant
669 * in the context of the extra work that _work_pending is doing.
670
671/* Once again, syscalls are special and only guarantee to preserve the
672 * same registers as a normal function call */
673
674/* The assumption here is that the registers r14-r28 (even) are untouched and
675 * don't need to be restored... be sure that that's really the case!
676 */
677
678/* This is still too much... we should only be restoring what we actually
679 * clobbered... we should even be using 'scratch' (odd) regs above so that
680 * we don't need to restore anything, hardly...
681 */
682
683 l.lwz r2,PT_GPR2(r1)
684
685 /* Restore args */
686 /* r3-r8 are technically clobbered, but syscall restart needs these
687 * to be restored...
688 */
689 l.lwz r3,PT_GPR3(r1)
690 l.lwz r4,PT_GPR4(r1)
691 l.lwz r5,PT_GPR5(r1)
692 l.lwz r6,PT_GPR6(r1)
693 l.lwz r7,PT_GPR7(r1)
694 l.lwz r8,PT_GPR8(r1)
695
696 l.lwz r9,PT_GPR9(r1)
697 l.lwz r10,PT_GPR10(r1)
698 l.lwz r11,PT_GPR11(r1)
699
700 /* r30 is the only register we clobber in the fast path */
701 l.lwz r30,PT_GPR30(r1)
702
703 /* Here we use r13-r19 (odd) as scratch regs */
704 l.lwz r13,PT_PC(r1)
705 l.lwz r15,PT_SR(r1)
706 l.lwz r1,PT_SP(r1)
707 /* Interrupts need to be disabled for setting EPCR and ESR
708 * so that another interrupt doesn't come in here and clobber
709 * them before we can use them for our l.rfe */
710 DISABLE_INTERRUPTS(r17,r19)
711 l.mtspr r0,r13,SPR_EPCR_BASE
712 l.mtspr r0,r15,SPR_ESR_BASE
713 l.rfe
714
715/* End of hot path!
716 * Keep the below tracing and error handling out of the hot path...
717*/
718
719_syscall_trace_enter:
720 /* Here we pass pt_regs to do_syscall_trace_enter. Make sure
721 * that function is really getting all the info it needs as
722 * pt_regs isn't a complete set of userspace regs, just the
723 * ones relevant to the syscall...
724 *
725 * Note use of delay slot for setting argument.
726 */
727 l.jal do_syscall_trace_enter
728 l.addi r3,r1,0
729
730 /* Restore arguments (not preserved across do_syscall_trace_enter)
731 * so that we can do the syscall for real and return to the syscall
732 * hot path.
733 */
734 l.lwz r11,PT_SYSCALLNO(r1)
735 l.lwz r3,PT_GPR3(r1)
736 l.lwz r4,PT_GPR4(r1)
737 l.lwz r5,PT_GPR5(r1)
738 l.lwz r6,PT_GPR6(r1)
739 l.lwz r7,PT_GPR7(r1)
740
741 l.j _syscall_check
742 l.lwz r8,PT_GPR8(r1)
743
744_syscall_trace_leave:
745 l.jal do_syscall_trace_leave
746 l.addi r3,r1,0
747
748 l.j _syscall_check_work
749 l.nop
750
751_syscall_badsys:
752 /* Here we effectively pretend to have executed an imaginary
753 * syscall that returns -ENOSYS and then return to the regular
754 * syscall hot path.
755 * Note that "return value" is set in the delay slot...
756 */
757 l.j _syscall_return
758 l.addi r11,r0,-ENOSYS
759
760/******* END SYSCALL HANDLING *******/
761
762/* ---[ 0xd00: Trap exception ]------------------------------------------ */
763
764UNHANDLED_EXCEPTION(_vector_0xd00,0xd00)
765
766/* ---[ 0xe00: Trap exception ]------------------------------------------ */
767
768EXCEPTION_ENTRY(_trap_handler)
769 /* r4: EA of fault (set by EXCEPTION_HANDLE) */
770 l.jal do_trap
771 l.addi r3,r1,0 /* pt_regs */
772
773 l.j _ret_from_exception
774 l.nop
775
776/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
777
778UNHANDLED_EXCEPTION(_vector_0xf00,0xf00)
779
780/* ---[ 0x1000: Reserved exception ]------------------------------------- */
781
782UNHANDLED_EXCEPTION(_vector_0x1000,0x1000)
783
784/* ---[ 0x1100: Reserved exception ]------------------------------------- */
785
786UNHANDLED_EXCEPTION(_vector_0x1100,0x1100)
787
788/* ---[ 0x1200: Reserved exception ]------------------------------------- */
789
790UNHANDLED_EXCEPTION(_vector_0x1200,0x1200)
791
792/* ---[ 0x1300: Reserved exception ]------------------------------------- */
793
794UNHANDLED_EXCEPTION(_vector_0x1300,0x1300)
795
796/* ---[ 0x1400: Reserved exception ]------------------------------------- */
797
798UNHANDLED_EXCEPTION(_vector_0x1400,0x1400)
799
800/* ---[ 0x1500: Reserved exception ]------------------------------------- */
801
802UNHANDLED_EXCEPTION(_vector_0x1500,0x1500)
803
804/* ---[ 0x1600: Reserved exception ]------------------------------------- */
805
806UNHANDLED_EXCEPTION(_vector_0x1600,0x1600)
807
808/* ---[ 0x1700: Reserved exception ]------------------------------------- */
809
810UNHANDLED_EXCEPTION(_vector_0x1700,0x1700)
811
812/* ---[ 0x1800: Reserved exception ]------------------------------------- */
813
814UNHANDLED_EXCEPTION(_vector_0x1800,0x1800)
815
816/* ---[ 0x1900: Reserved exception ]------------------------------------- */
817
818UNHANDLED_EXCEPTION(_vector_0x1900,0x1900)
819
820/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
821
822UNHANDLED_EXCEPTION(_vector_0x1a00,0x1a00)
823
824/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
825
826UNHANDLED_EXCEPTION(_vector_0x1b00,0x1b00)
827
828/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
829
830UNHANDLED_EXCEPTION(_vector_0x1c00,0x1c00)
831
832/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
833
834UNHANDLED_EXCEPTION(_vector_0x1d00,0x1d00)
835
836/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
837
838UNHANDLED_EXCEPTION(_vector_0x1e00,0x1e00)
839
840/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
841
842UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00)
843
844/* ========================================================[ return ] === */
845
846_work_pending:
847 /*
848 * if (current_thread_info->flags & _TIF_NEED_RESCHED)
849 * schedule();
850 */
851 l.lwz r5,TI_FLAGS(r10)
852 l.andi r3,r5,_TIF_NEED_RESCHED
853 l.sfnei r3,0
854 l.bnf _work_notifysig
855 l.nop
856 l.jal schedule
857 l.nop
858 l.j _resume_userspace
859 l.nop
860
861/* Handle pending signals and notify-resume requests.
862 * do_notify_resume must be passed the latest pushed pt_regs, not
863 * necessarily the "userspace" ones. Also, pt_regs->syscallno
864 * must be set so that the syscall restart functionality works.
865 */
866_work_notifysig:
867 l.jal do_notify_resume
868 l.ori r3,r1,0 /* pt_regs */
869
870_resume_userspace:
871 DISABLE_INTERRUPTS(r3,r4)
872 l.lwz r3,TI_FLAGS(r10)
873 l.andi r3,r3,_TIF_WORK_MASK
874 l.sfnei r3,0
875 l.bf _work_pending
876 l.nop
877
878_restore_all:
879 RESTORE_ALL
880 /* This returns to userspace code */
881
882
883ENTRY(_ret_from_intr)
884ENTRY(_ret_from_exception)
885 l.lwz r4,PT_SR(r1)
886 l.andi r3,r4,SPR_SR_SM
887 l.sfeqi r3,0
888 l.bnf _restore_all
889 l.nop
890 l.j _resume_userspace
891 l.nop
892
893ENTRY(ret_from_fork)
894 l.jal schedule_tail
895 l.nop
896
897 /* _syscall_returns expect r11 to contain return value */
898 l.lwz r11,PT_GPR11(r1)
899
900 /* The syscall fast path return expects call-saved registers
901 * r12-r28 to be untouched, so we restore them here as they
902 * will have been effectively clobbered when arriving here
903 * via the call to switch()
904 */
905 l.lwz r12,PT_GPR12(r1)
906 l.lwz r14,PT_GPR14(r1)
907 l.lwz r16,PT_GPR16(r1)
908 l.lwz r18,PT_GPR18(r1)
909 l.lwz r20,PT_GPR20(r1)
910 l.lwz r22,PT_GPR22(r1)
911 l.lwz r24,PT_GPR24(r1)
912 l.lwz r26,PT_GPR26(r1)
913 l.lwz r28,PT_GPR28(r1)
914
915 l.j _syscall_return
916 l.nop
917
918/* Since syscalls don't save call-clobbered registers, the args to
919 * kernel_thread_helper will need to be passed through callee-saved
920 * registers and copied to the parameter registers when the thread
921 * begins running.
922 *
923 * See arch/openrisc/kernel/process.c:
924 * The args are passed as follows:
925 * arg1 (r3) : passed in r20
926 * arg2 (r4) : passed in r22
927 */
928
929ENTRY(_kernel_thread_helper)
930 l.or r3,r20,r0
931 l.or r4,r22,r0
932 l.movhi r31,hi(kernel_thread_helper)
933 l.ori r31,r31,lo(kernel_thread_helper)
934 l.jr r31
935 l.nop
936
937
938/* ========================================================[ switch ] === */
939
940/*
941 * This routine switches between two different tasks. The process
942 * state of one is saved on its kernel stack. Then the state
943 * of the other is restored from its kernel stack. The memory
944 * management hardware is updated to the second process's state.
945 * Finally, we can return to the second process, via the 'return'.
946 *
947 * Note: there are two ways to get to the "going out" portion
948 * of this code; either by coming in via the entry (_switch)
949 * or via "fork" which must set up an environment equivalent
950 * to the "_switch" path. If you change this (or in particular, the
951 * SAVE_REGS macro), you'll have to change the fork code also.
952 */
953
954
955/* _switch MUST never lay on page boundry, cause it runs from
956 * effective addresses and beeing interrupted by iTLB miss would kill it.
957 * dTLB miss seams to never accour in the bad place since data accesses
958 * are from task structures which are always page aligned.
959 *
960 * The problem happens in RESTORE_ALL_NO_R11 where we first set the EPCR
961 * register, then load the previous register values and only at the end call
962 * the l.rfe instruction. If get TLB miss in beetwen the EPCR register gets
963 * garbled and we end up calling l.rfe with the wrong EPCR. (same probably
964 * holds for ESR)
965 *
966 * To avoid this problems it is sufficient to align _switch to
967 * some nice round number smaller than it's size...
968 */
969
970/* ABI rules apply here... we either enter _switch via schedule() or via
971 * an imaginary call to which we shall return at return_from_fork. Either
972 * way, we are a function call and only need to preserve the callee-saved
973 * registers when we return. As such, we don't need to save the registers
974 * on the stack that we won't be returning as they were...
975 */
976
977 .align 0x400
978ENTRY(_switch)
979 /* We don't store SR as _switch only gets called in a context where
980 * the SR will be the same going in and coming out... */
981
982 /* Set up new pt_regs struct for saving task state */
983 l.addi r1,r1,-(INT_FRAME_SIZE)
984
985 /* No need to store r1/PT_SP as it goes into KSP below */
986 l.sw PT_GPR2(r1),r2
987 l.sw PT_GPR9(r1),r9
988 /* This is wrong, r12 shouldn't be here... but GCC is broken for the time being
989 * and expects r12 to be callee-saved... */
990 l.sw PT_GPR12(r1),r12
991 l.sw PT_GPR14(r1),r14
992 l.sw PT_GPR16(r1),r16
993 l.sw PT_GPR18(r1),r18
994 l.sw PT_GPR20(r1),r20
995 l.sw PT_GPR22(r1),r22
996 l.sw PT_GPR24(r1),r24
997 l.sw PT_GPR26(r1),r26
998 l.sw PT_GPR28(r1),r28
999 l.sw PT_GPR30(r1),r30
1000
1001 l.addi r11,r10,0 /* Save old 'current' to 'last' return value*/
1002
1003 /* We use thread_info->ksp for storing the address of the above
1004 * structure so that we can get back to it later... we don't want
1005 * to lose the value of thread_info->ksp, though, so store it as
1006 * pt_regs->sp so that we can easily restore it when we are made
1007 * live again...
1008 */
1009
1010 /* Save the old value of thread_info->ksp as pt_regs->sp */
1011 l.lwz r29,TI_KSP(r10)
1012 l.sw PT_SP(r1),r29
1013
1014 /* Swap kernel stack pointers */
1015 l.sw TI_KSP(r10),r1 /* Save old stack pointer */
1016 l.or r10,r4,r0 /* Set up new current_thread_info */
1017 l.lwz r1,TI_KSP(r10) /* Load new stack pointer */
1018
1019 /* Restore the old value of thread_info->ksp */
1020 l.lwz r29,PT_SP(r1)
1021 l.sw TI_KSP(r10),r29
1022
1023 /* ...and restore the registers, except r11 because the return value
1024 * has already been set above.
1025 */
1026 l.lwz r2,PT_GPR2(r1)
1027 l.lwz r9,PT_GPR9(r1)
1028 /* No need to restore r10 */
1029 /* ...and do not restore r11 */
1030
1031 /* This is wrong, r12 shouldn't be here... but GCC is broken for the time being
1032 * and expects r12 to be callee-saved... */
1033 l.lwz r12,PT_GPR12(r1)
1034 l.lwz r14,PT_GPR14(r1)
1035 l.lwz r16,PT_GPR16(r1)
1036 l.lwz r18,PT_GPR18(r1)
1037 l.lwz r20,PT_GPR20(r1)
1038 l.lwz r22,PT_GPR22(r1)
1039 l.lwz r24,PT_GPR24(r1)
1040 l.lwz r26,PT_GPR26(r1)
1041 l.lwz r28,PT_GPR28(r1)
1042 l.lwz r30,PT_GPR30(r1)
1043
1044 /* Unwind stack to pre-switch state */
1045 l.addi r1,r1,(INT_FRAME_SIZE)
1046
1047 /* Return via the link-register back to where we 'came from', where that can be
1048 * either schedule() or return_from_fork()... */
1049 l.jr r9
1050 l.nop
1051
1052/* ==================================================================== */
1053
1054/* These all use the delay slot for setting the argument register, so the
1055 * jump is always happening after the l.addi instruction.
1056 *
1057 * These are all just wrappers that don't touch the link-register r9, so the
1058 * return from the "real" syscall function will return back to the syscall
1059 * code that did the l.jal that brought us here.
1060 */
1061
1062/* fork requires that we save all the callee-saved registers because they
1063 * are all effectively clobbered by the call to _switch. Here we store
1064 * all the registers that aren't touched by the syscall fast path and thus
1065 * weren't saved there.
1066 */
1067
1068_fork_save_extra_regs_and_call:
1069 l.sw PT_GPR14(r1),r14
1070 l.sw PT_GPR16(r1),r16
1071 l.sw PT_GPR18(r1),r18
1072 l.sw PT_GPR20(r1),r20
1073 l.sw PT_GPR22(r1),r22
1074 l.sw PT_GPR24(r1),r24
1075 l.sw PT_GPR26(r1),r26
1076 l.jr r29
1077 l.sw PT_GPR28(r1),r28
1078
1079ENTRY(sys_clone)
1080 l.movhi r29,hi(_sys_clone)
1081 l.ori r29,r29,lo(_sys_clone)
1082 l.j _fork_save_extra_regs_and_call
1083 l.addi r7,r1,0
1084
1085ENTRY(sys_fork)
1086 l.movhi r29,hi(_sys_fork)
1087 l.ori r29,r29,lo(_sys_fork)
1088 l.j _fork_save_extra_regs_and_call
1089 l.addi r3,r1,0
1090
1091ENTRY(sys_execve)
1092 l.j _sys_execve
1093 l.addi r6,r1,0
1094
1095ENTRY(sys_sigaltstack)
1096 l.j _sys_sigaltstack
1097 l.addi r5,r1,0
1098
1099ENTRY(sys_rt_sigreturn)
1100 l.j _sys_rt_sigreturn
1101 l.addi r3,r1,0
1102
1103/* This is a catch-all syscall for atomic instructions for the OpenRISC 1000.
1104 * The functions takes a variable number of parameters depending on which
1105 * particular flavour of atomic you want... parameter 1 is a flag identifying
1106 * the atomic in question. Currently, this function implements the
1107 * following variants:
1108 *
1109 * XCHG:
1110 * @flag: 1
1111 * @ptr1:
1112 * @ptr2:
1113 * Atomically exchange the values in pointers 1 and 2.
1114 *
1115 */
1116
1117ENTRY(sys_or1k_atomic)
1118 /* FIXME: This ignores r3 and always does an XCHG */
1119 DISABLE_INTERRUPTS(r17,r19)
1120 l.lwz r30,0(r4)
1121 l.lwz r28,0(r5)
1122 l.sw 0(r4),r28
1123 l.sw 0(r5),r30
1124 ENABLE_INTERRUPTS(r17)
1125 l.jr r9
1126 l.or r11,r0,r0
1127
1128/* ============================================================[ EOF ]=== */
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S
new file mode 100644
index 00000000000..c75018d2264
--- /dev/null
+++ b/arch/openrisc/kernel/head.S
@@ -0,0 +1,1607 @@
1/*
2 * OpenRISC head.S
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/linkage.h>
19#include <linux/threads.h>
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <asm/processor.h>
23#include <asm/page.h>
24#include <asm/mmu.h>
25#include <asm/pgtable.h>
26#include <asm/cache.h>
27#include <asm/spr_defs.h>
28#include <asm/asm-offsets.h>
29
30#define tophys(rd,rs) \
31 l.movhi rd,hi(-KERNELBASE) ;\
32 l.add rd,rd,rs
33
34#define CLEAR_GPR(gpr) \
35 l.or gpr,r0,r0
36
37#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
38 l.movhi gpr,hi(symbol) ;\
39 l.ori gpr,gpr,lo(symbol)
40
41
42#define UART_BASE_ADD 0x90000000
43
44#define EXCEPTION_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
45#define SYSCALL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
46
47/* ============================================[ tmp store locations ]=== */
48
49/*
50 * emergency_print temporary stores
51 */
52#define EMERGENCY_PRINT_STORE_GPR4 l.sw 0x20(r0),r4
53#define EMERGENCY_PRINT_LOAD_GPR4 l.lwz r4,0x20(r0)
54
55#define EMERGENCY_PRINT_STORE_GPR5 l.sw 0x24(r0),r5
56#define EMERGENCY_PRINT_LOAD_GPR5 l.lwz r5,0x24(r0)
57
58#define EMERGENCY_PRINT_STORE_GPR6 l.sw 0x28(r0),r6
59#define EMERGENCY_PRINT_LOAD_GPR6 l.lwz r6,0x28(r0)
60
61#define EMERGENCY_PRINT_STORE_GPR7 l.sw 0x2c(r0),r7
62#define EMERGENCY_PRINT_LOAD_GPR7 l.lwz r7,0x2c(r0)
63
64#define EMERGENCY_PRINT_STORE_GPR8 l.sw 0x30(r0),r8
65#define EMERGENCY_PRINT_LOAD_GPR8 l.lwz r8,0x30(r0)
66
67#define EMERGENCY_PRINT_STORE_GPR9 l.sw 0x34(r0),r9
68#define EMERGENCY_PRINT_LOAD_GPR9 l.lwz r9,0x34(r0)
69
70
71/*
72 * TLB miss handlers temorary stores
73 */
74#define EXCEPTION_STORE_GPR9 l.sw 0x10(r0),r9
75#define EXCEPTION_LOAD_GPR9 l.lwz r9,0x10(r0)
76
77#define EXCEPTION_STORE_GPR2 l.sw 0x64(r0),r2
78#define EXCEPTION_LOAD_GPR2 l.lwz r2,0x64(r0)
79
80#define EXCEPTION_STORE_GPR3 l.sw 0x68(r0),r3
81#define EXCEPTION_LOAD_GPR3 l.lwz r3,0x68(r0)
82
83#define EXCEPTION_STORE_GPR4 l.sw 0x6c(r0),r4
84#define EXCEPTION_LOAD_GPR4 l.lwz r4,0x6c(r0)
85
86#define EXCEPTION_STORE_GPR5 l.sw 0x70(r0),r5
87#define EXCEPTION_LOAD_GPR5 l.lwz r5,0x70(r0)
88
89#define EXCEPTION_STORE_GPR6 l.sw 0x74(r0),r6
90#define EXCEPTION_LOAD_GPR6 l.lwz r6,0x74(r0)
91
92
93/*
94 * EXCEPTION_HANDLE temporary stores
95 */
96
97#define EXCEPTION_T_STORE_GPR30 l.sw 0x78(r0),r30
98#define EXCEPTION_T_LOAD_GPR30(reg) l.lwz reg,0x78(r0)
99
100#define EXCEPTION_T_STORE_GPR10 l.sw 0x7c(r0),r10
101#define EXCEPTION_T_LOAD_GPR10(reg) l.lwz reg,0x7c(r0)
102
103#define EXCEPTION_T_STORE_SP l.sw 0x80(r0),r1
104#define EXCEPTION_T_LOAD_SP(reg) l.lwz reg,0x80(r0)
105
106/*
107 * For UNHANLDED_EXCEPTION
108 */
109
110#define EXCEPTION_T_STORE_GPR31 l.sw 0x84(r0),r31
111#define EXCEPTION_T_LOAD_GPR31(reg) l.lwz reg,0x84(r0)
112
113/* =========================================================[ macros ]=== */
114
115
116#define GET_CURRENT_PGD(reg,t1) \
117 LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
118 tophys (t1,reg) ;\
119 l.lwz reg,0(t1)
120
121
122/*
123 * DSCR: this is a common hook for handling exceptions. it will save
124 * the needed registers, set up stack and pointer to current
125 * then jump to the handler while enabling MMU
126 *
127 * PRMS: handler - a function to jump to. it has to save the
128 * remaining registers to kernel stack, call
129 * appropriate arch-independant exception handler
130 * and finaly jump to ret_from_except
131 *
132 * PREQ: unchanged state from the time exception happened
133 *
134 * POST: SAVED the following registers original value
135 * to the new created exception frame pointed to by r1
136 *
137 * r1 - ksp pointing to the new (exception) frame
138 * r4 - EEAR exception EA
139 * r10 - current pointing to current_thread_info struct
140 * r12 - syscall 0, since we didn't come from syscall
141 * r13 - temp it actually contains new SR, not needed anymore
142 * r31 - handler address of the handler we'll jump to
143 *
144 * handler has to save remaining registers to the exception
145 * ksp frame *before* tainting them!
146 *
147 * NOTE: this function is not reentrant per se. reentrancy is guaranteed
148 * by processor disabling all exceptions/interrupts when exception
149 * accours.
150 *
151 * OPTM: no need to make it so wasteful to extract ksp when in user mode
152 */
153
154#define EXCEPTION_HANDLE(handler) \
155 EXCEPTION_T_STORE_GPR30 ;\
156 l.mfspr r30,r0,SPR_ESR_BASE ;\
157 l.andi r30,r30,SPR_SR_SM ;\
158 l.sfeqi r30,0 ;\
159 EXCEPTION_T_STORE_GPR10 ;\
160 l.bnf 2f /* kernel_mode */ ;\
161 EXCEPTION_T_STORE_SP /* delay slot */ ;\
1621: /* user_mode: */ ;\
163 LOAD_SYMBOL_2_GPR(r1,current_thread_info_set) ;\
164 tophys (r30,r1) ;\
165 /* r10: current_thread_info */ ;\
166 l.lwz r10,0(r30) ;\
167 tophys (r30,r10) ;\
168 l.lwz r1,(TI_KSP)(r30) ;\
169 /* fall through */ ;\
1702: /* kernel_mode: */ ;\
171 /* create new stack frame, save only needed gprs */ ;\
172 /* r1: KSP, r10: current, r4: EEAR, r31: __pa(KSP) */ ;\
173 /* r12: temp, syscall indicator */ ;\
174 l.addi r1,r1,-(INT_FRAME_SIZE) ;\
175 /* r1 is KSP, r30 is __pa(KSP) */ ;\
176 tophys (r30,r1) ;\
177 l.sw PT_GPR12(r30),r12 ;\
178 l.mfspr r12,r0,SPR_EPCR_BASE ;\
179 l.sw PT_PC(r30),r12 ;\
180 l.mfspr r12,r0,SPR_ESR_BASE ;\
181 l.sw PT_SR(r30),r12 ;\
182 /* save r30 */ ;\
183 EXCEPTION_T_LOAD_GPR30(r12) ;\
184 l.sw PT_GPR30(r30),r12 ;\
185 /* save r10 as was prior to exception */ ;\
186 EXCEPTION_T_LOAD_GPR10(r12) ;\
187 l.sw PT_GPR10(r30),r12 ;\
188 /* save PT_SP as was prior to exception */ ;\
189 EXCEPTION_T_LOAD_SP(r12) ;\
190 l.sw PT_SP(r30),r12 ;\
191 /* save exception r4, set r4 = EA */ ;\
192 l.sw PT_GPR4(r30),r4 ;\
193 l.mfspr r4,r0,SPR_EEAR_BASE ;\
194 /* r12 == 1 if we come from syscall */ ;\
195 CLEAR_GPR(r12) ;\
196 /* ----- turn on MMU ----- */ ;\
197 l.ori r30,r0,(EXCEPTION_SR) ;\
198 l.mtspr r0,r30,SPR_ESR_BASE ;\
199 /* r30: EA address of handler */ ;\
200 LOAD_SYMBOL_2_GPR(r30,handler) ;\
201 l.mtspr r0,r30,SPR_EPCR_BASE ;\
202 l.rfe
203
204/*
205 * this doesn't work
206 *
207 *
208 * #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
209 * #define UNHANDLED_EXCEPTION(handler) \
210 * l.ori r3,r0,0x1 ;\
211 * l.mtspr r0,r3,SPR_SR ;\
212 * l.movhi r3,hi(0xf0000100) ;\
213 * l.ori r3,r3,lo(0xf0000100) ;\
214 * l.jr r3 ;\
215 * l.nop 1
216 *
217 * #endif
218 */
219
220/* DSCR: this is the same as EXCEPTION_HANDLE(), we are just
221 * a bit more carefull (if we have a PT_SP or current pointer
222 * corruption) and set them up from 'current_set'
223 *
224 */
225#define UNHANDLED_EXCEPTION(handler) \
226 EXCEPTION_T_STORE_GPR31 ;\
227 EXCEPTION_T_STORE_GPR10 ;\
228 EXCEPTION_T_STORE_SP ;\
229 /* temporary store r3, r9 into r1, r10 */ ;\
230 l.addi r1,r3,0x0 ;\
231 l.addi r10,r9,0x0 ;\
232 /* the string referenced by r3 must be low enough */ ;\
233 l.jal _emergency_print ;\
234 l.ori r3,r0,lo(_string_unhandled_exception) ;\
235 l.mfspr r3,r0,SPR_NPC ;\
236 l.jal _emergency_print_nr ;\
237 l.andi r3,r3,0x1f00 ;\
238 /* the string referenced by r3 must be low enough */ ;\
239 l.jal _emergency_print ;\
240 l.ori r3,r0,lo(_string_epc_prefix) ;\
241 l.jal _emergency_print_nr ;\
242 l.mfspr r3,r0,SPR_EPCR_BASE ;\
243 l.jal _emergency_print ;\
244 l.ori r3,r0,lo(_string_nl) ;\
245 /* end of printing */ ;\
246 l.addi r3,r1,0x0 ;\
247 l.addi r9,r10,0x0 ;\
248 /* extract current, ksp from current_set */ ;\
249 LOAD_SYMBOL_2_GPR(r1,_unhandled_stack_top) ;\
250 LOAD_SYMBOL_2_GPR(r10,init_thread_union) ;\
251 /* create new stack frame, save only needed gprs */ ;\
252 /* r1: KSP, r10: current, r31: __pa(KSP) */ ;\
253 /* r12: temp, syscall indicator, r13 temp */ ;\
254 l.addi r1,r1,-(INT_FRAME_SIZE) ;\
255 /* r1 is KSP, r31 is __pa(KSP) */ ;\
256 tophys (r31,r1) ;\
257 l.sw PT_GPR12(r31),r12 ;\
258 l.mfspr r12,r0,SPR_EPCR_BASE ;\
259 l.sw PT_PC(r31),r12 ;\
260 l.mfspr r12,r0,SPR_ESR_BASE ;\
261 l.sw PT_SR(r31),r12 ;\
262 /* save r31 */ ;\
263 EXCEPTION_T_LOAD_GPR31(r12) ;\
264 l.sw PT_GPR31(r31),r12 ;\
265 /* save r10 as was prior to exception */ ;\
266 EXCEPTION_T_LOAD_GPR10(r12) ;\
267 l.sw PT_GPR10(r31),r12 ;\
268 /* save PT_SP as was prior to exception */ ;\
269 EXCEPTION_T_LOAD_SP(r12) ;\
270 l.sw PT_SP(r31),r12 ;\
271 l.sw PT_GPR13(r31),r13 ;\
272 /* --> */ ;\
273 /* save exception r4, set r4 = EA */ ;\
274 l.sw PT_GPR4(r31),r4 ;\
275 l.mfspr r4,r0,SPR_EEAR_BASE ;\
276 /* r12 == 1 if we come from syscall */ ;\
277 CLEAR_GPR(r12) ;\
278 /* ----- play a MMU trick ----- */ ;\
279 l.ori r31,r0,(EXCEPTION_SR) ;\
280 l.mtspr r0,r31,SPR_ESR_BASE ;\
281 /* r31: EA address of handler */ ;\
282 LOAD_SYMBOL_2_GPR(r31,handler) ;\
283 l.mtspr r0,r31,SPR_EPCR_BASE ;\
284 l.rfe
285
286/* =====================================================[ exceptions] === */
287
288/* ---[ 0x100: RESET exception ]----------------------------------------- */
289 .org 0x100
290 /* Jump to .init code at _start which lives in the .head section
291 * and will be discarded after boot.
292 */
293 LOAD_SYMBOL_2_GPR(r4, _start)
294 tophys (r3,r4) /* MMU disabled */
295 l.jr r3
296 l.nop
297
298/* ---[ 0x200: BUS exception ]------------------------------------------- */
299 .org 0x200
300_dispatch_bus_fault:
301 EXCEPTION_HANDLE(_bus_fault_handler)
302
303/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
304 .org 0x300
305_dispatch_do_dpage_fault:
306// totaly disable timer interrupt
307// l.mtspr r0,r0,SPR_TTMR
308// DEBUG_TLB_PROBE(0x300)
309// EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x300)
310 EXCEPTION_HANDLE(_data_page_fault_handler)
311
312/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
313 .org 0x400
314_dispatch_do_ipage_fault:
315// totaly disable timer interrupt
316// l.mtspr r0,r0,SPR_TTMR
317// DEBUG_TLB_PROBE(0x400)
318// EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x400)
319 EXCEPTION_HANDLE(_insn_page_fault_handler)
320
321/* ---[ 0x500: Timer exception ]----------------------------------------- */
322 .org 0x500
323 EXCEPTION_HANDLE(_timer_handler)
324
325/* ---[ 0x600: Aligment exception ]-------------------------------------- */
326 .org 0x600
327 EXCEPTION_HANDLE(_alignment_handler)
328
329/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
330 .org 0x700
331 EXCEPTION_HANDLE(_illegal_instruction_handler)
332
333/* ---[ 0x800: External interrupt exception ]---------------------------- */
334 .org 0x800
335 EXCEPTION_HANDLE(_external_irq_handler)
336
337/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
338 .org 0x900
339 l.j boot_dtlb_miss_handler
340 l.nop
341
342/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
343 .org 0xa00
344 l.j boot_itlb_miss_handler
345 l.nop
346
347/* ---[ 0xb00: Range exception ]----------------------------------------- */
348 .org 0xb00
349 UNHANDLED_EXCEPTION(_vector_0xb00)
350
351/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
352 .org 0xc00
353 EXCEPTION_HANDLE(_sys_call_handler)
354
355/* ---[ 0xd00: Trap exception ]------------------------------------------ */
356 .org 0xd00
357 UNHANDLED_EXCEPTION(_vector_0xd00)
358
359/* ---[ 0xe00: Trap exception ]------------------------------------------ */
360 .org 0xe00
361// UNHANDLED_EXCEPTION(_vector_0xe00)
362 EXCEPTION_HANDLE(_trap_handler)
363
364/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
365 .org 0xf00
366 UNHANDLED_EXCEPTION(_vector_0xf00)
367
368/* ---[ 0x1000: Reserved exception ]------------------------------------- */
369 .org 0x1000
370 UNHANDLED_EXCEPTION(_vector_0x1000)
371
372/* ---[ 0x1100: Reserved exception ]------------------------------------- */
373 .org 0x1100
374 UNHANDLED_EXCEPTION(_vector_0x1100)
375
376/* ---[ 0x1200: Reserved exception ]------------------------------------- */
377 .org 0x1200
378 UNHANDLED_EXCEPTION(_vector_0x1200)
379
380/* ---[ 0x1300: Reserved exception ]------------------------------------- */
381 .org 0x1300
382 UNHANDLED_EXCEPTION(_vector_0x1300)
383
384/* ---[ 0x1400: Reserved exception ]------------------------------------- */
385 .org 0x1400
386 UNHANDLED_EXCEPTION(_vector_0x1400)
387
388/* ---[ 0x1500: Reserved exception ]------------------------------------- */
389 .org 0x1500
390 UNHANDLED_EXCEPTION(_vector_0x1500)
391
392/* ---[ 0x1600: Reserved exception ]------------------------------------- */
393 .org 0x1600
394 UNHANDLED_EXCEPTION(_vector_0x1600)
395
396/* ---[ 0x1700: Reserved exception ]------------------------------------- */
397 .org 0x1700
398 UNHANDLED_EXCEPTION(_vector_0x1700)
399
400/* ---[ 0x1800: Reserved exception ]------------------------------------- */
401 .org 0x1800
402 UNHANDLED_EXCEPTION(_vector_0x1800)
403
404/* ---[ 0x1900: Reserved exception ]------------------------------------- */
405 .org 0x1900
406 UNHANDLED_EXCEPTION(_vector_0x1900)
407
408/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
409 .org 0x1a00
410 UNHANDLED_EXCEPTION(_vector_0x1a00)
411
412/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
413 .org 0x1b00
414 UNHANDLED_EXCEPTION(_vector_0x1b00)
415
416/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
417 .org 0x1c00
418 UNHANDLED_EXCEPTION(_vector_0x1c00)
419
420/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
421 .org 0x1d00
422 UNHANDLED_EXCEPTION(_vector_0x1d00)
423
424/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
425 .org 0x1e00
426 UNHANDLED_EXCEPTION(_vector_0x1e00)
427
428/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
429 .org 0x1f00
430 UNHANDLED_EXCEPTION(_vector_0x1f00)
431
432 .org 0x2000
433/* ===================================================[ kernel start ]=== */
434
435/* .text*/
436
437/* This early stuff belongs in HEAD, but some of the functions below definitely
438 * don't... */
439
440 __HEAD
441 .global _start
442_start:
443 /*
444 * ensure a deterministic start
445 */
446
447 l.ori r3,r0,0x1
448 l.mtspr r0,r3,SPR_SR
449
450 CLEAR_GPR(r1)
451 CLEAR_GPR(r2)
452 CLEAR_GPR(r3)
453 CLEAR_GPR(r4)
454 CLEAR_GPR(r5)
455 CLEAR_GPR(r6)
456 CLEAR_GPR(r7)
457 CLEAR_GPR(r8)
458 CLEAR_GPR(r9)
459 CLEAR_GPR(r10)
460 CLEAR_GPR(r11)
461 CLEAR_GPR(r12)
462 CLEAR_GPR(r13)
463 CLEAR_GPR(r14)
464 CLEAR_GPR(r15)
465 CLEAR_GPR(r16)
466 CLEAR_GPR(r17)
467 CLEAR_GPR(r18)
468 CLEAR_GPR(r19)
469 CLEAR_GPR(r20)
470 CLEAR_GPR(r21)
471 CLEAR_GPR(r22)
472 CLEAR_GPR(r23)
473 CLEAR_GPR(r24)
474 CLEAR_GPR(r25)
475 CLEAR_GPR(r26)
476 CLEAR_GPR(r27)
477 CLEAR_GPR(r28)
478 CLEAR_GPR(r29)
479 CLEAR_GPR(r30)
480 CLEAR_GPR(r31)
481
482 /*
483 * set up initial ksp and current
484 */
485 LOAD_SYMBOL_2_GPR(r1,init_thread_union+0x2000) // setup kernel stack
486 LOAD_SYMBOL_2_GPR(r10,init_thread_union) // setup current
487 tophys (r31,r10)
488 l.sw TI_KSP(r31), r1
489
490 l.ori r4,r0,0x0
491
492
493 /*
494 * .data contains initialized data,
495 * .bss contains uninitialized data - clear it up
496 */
497clear_bss:
498 LOAD_SYMBOL_2_GPR(r24, __bss_start)
499 LOAD_SYMBOL_2_GPR(r26, _end)
500 tophys(r28,r24)
501 tophys(r30,r26)
502 CLEAR_GPR(r24)
503 CLEAR_GPR(r26)
5041:
505 l.sw (0)(r28),r0
506 l.sfltu r28,r30
507 l.bf 1b
508 l.addi r28,r28,4
509
510enable_ic:
511 l.jal _ic_enable
512 l.nop
513
514enable_dc:
515 l.jal _dc_enable
516 l.nop
517
518flush_tlb:
519 /*
520 * I N V A L I D A T E T L B e n t r i e s
521 */
522 LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
523 LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
524 l.addi r7,r0,128 /* Maximum number of sets */
5251:
526 l.mtspr r5,r0,0x0
527 l.mtspr r6,r0,0x0
528
529 l.addi r5,r5,1
530 l.addi r6,r6,1
531 l.sfeq r7,r0
532 l.bnf 1b
533 l.addi r7,r7,-1
534
535
536/* The MMU needs to be enabled before or32_early_setup is called */
537
538enable_mmu:
539 /*
540 * enable dmmu & immu
541 * SR[5] = 0, SR[6] = 0, 6th and 7th bit of SR set to 0
542 */
543 l.mfspr r30,r0,SPR_SR
544 l.movhi r28,hi(SPR_SR_DME | SPR_SR_IME)
545 l.ori r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
546 l.or r30,r30,r28
547 l.mtspr r0,r30,SPR_SR
548 l.nop
549 l.nop
550 l.nop
551 l.nop
552 l.nop
553 l.nop
554 l.nop
555 l.nop
556 l.nop
557 l.nop
558 l.nop
559 l.nop
560 l.nop
561 l.nop
562 l.nop
563 l.nop
564
565 // reset the simulation counters
566 l.nop 5
567
568 LOAD_SYMBOL_2_GPR(r24, or32_early_setup)
569 l.jalr r24
570 l.nop
571
572clear_regs:
573 /*
574 * clear all GPRS to increase determinism
575 */
576 CLEAR_GPR(r2)
577 CLEAR_GPR(r3)
578 CLEAR_GPR(r4)
579 CLEAR_GPR(r5)
580 CLEAR_GPR(r6)
581 CLEAR_GPR(r7)
582 CLEAR_GPR(r8)
583 CLEAR_GPR(r9)
584 CLEAR_GPR(r11)
585 CLEAR_GPR(r12)
586 CLEAR_GPR(r13)
587 CLEAR_GPR(r14)
588 CLEAR_GPR(r15)
589 CLEAR_GPR(r16)
590 CLEAR_GPR(r17)
591 CLEAR_GPR(r18)
592 CLEAR_GPR(r19)
593 CLEAR_GPR(r20)
594 CLEAR_GPR(r21)
595 CLEAR_GPR(r22)
596 CLEAR_GPR(r23)
597 CLEAR_GPR(r24)
598 CLEAR_GPR(r25)
599 CLEAR_GPR(r26)
600 CLEAR_GPR(r27)
601 CLEAR_GPR(r28)
602 CLEAR_GPR(r29)
603 CLEAR_GPR(r30)
604 CLEAR_GPR(r31)
605
606jump_start_kernel:
607 /*
608 * jump to kernel entry (start_kernel)
609 */
610 LOAD_SYMBOL_2_GPR(r30, start_kernel)
611 l.jr r30
612 l.nop
613
614/* ========================================[ cache ]=== */
615
616 /* aligment here so we don't change memory offsets with
617 * memory controler defined
618 */
619 .align 0x2000
620
621_ic_enable:
622 /* Check if IC present and skip enabling otherwise */
623 l.mfspr r24,r0,SPR_UPR
624 l.andi r26,r24,SPR_UPR_ICP
625 l.sfeq r26,r0
626 l.bf 9f
627 l.nop
628
629 /* Disable IC */
630 l.mfspr r6,r0,SPR_SR
631 l.addi r5,r0,-1
632 l.xori r5,r5,SPR_SR_ICE
633 l.and r5,r6,r5
634 l.mtspr r0,r5,SPR_SR
635
636 /* Establish cache block size
637 If BS=0, 16;
638 If BS=1, 32;
639 r14 contain block size
640 */
641 l.mfspr r24,r0,SPR_ICCFGR
642 l.andi r26,r24,SPR_ICCFGR_CBS
643 l.srli r28,r26,7
644 l.ori r30,r0,16
645 l.sll r14,r30,r28
646
647 /* Establish number of cache sets
648 r16 contains number of cache sets
649 r28 contains log(# of cache sets)
650 */
651 l.andi r26,r24,SPR_ICCFGR_NCS
652 l.srli r28,r26,3
653 l.ori r30,r0,1
654 l.sll r16,r30,r28
655
656 /* Invalidate IC */
657 l.addi r6,r0,0
658 l.sll r5,r14,r28
659// l.mul r5,r14,r16
660// l.trap 1
661// l.addi r5,r0,IC_SIZE
6621:
663 l.mtspr r0,r6,SPR_ICBIR
664 l.sfne r6,r5
665 l.bf 1b
666 l.add r6,r6,r14
667 // l.addi r6,r6,IC_LINE
668
669 /* Enable IC */
670 l.mfspr r6,r0,SPR_SR
671 l.ori r6,r6,SPR_SR_ICE
672 l.mtspr r0,r6,SPR_SR
673 l.nop
674 l.nop
675 l.nop
676 l.nop
677 l.nop
678 l.nop
679 l.nop
680 l.nop
681 l.nop
682 l.nop
6839:
684 l.jr r9
685 l.nop
686
687_dc_enable:
688 /* Check if DC present and skip enabling otherwise */
689 l.mfspr r24,r0,SPR_UPR
690 l.andi r26,r24,SPR_UPR_DCP
691 l.sfeq r26,r0
692 l.bf 9f
693 l.nop
694
695 /* Disable DC */
696 l.mfspr r6,r0,SPR_SR
697 l.addi r5,r0,-1
698 l.xori r5,r5,SPR_SR_DCE
699 l.and r5,r6,r5
700 l.mtspr r0,r5,SPR_SR
701
702 /* Establish cache block size
703 If BS=0, 16;
704 If BS=1, 32;
705 r14 contain block size
706 */
707 l.mfspr r24,r0,SPR_DCCFGR
708 l.andi r26,r24,SPR_DCCFGR_CBS
709 l.srli r28,r26,7
710 l.ori r30,r0,16
711 l.sll r14,r30,r28
712
713 /* Establish number of cache sets
714 r16 contains number of cache sets
715 r28 contains log(# of cache sets)
716 */
717 l.andi r26,r24,SPR_DCCFGR_NCS
718 l.srli r28,r26,3
719 l.ori r30,r0,1
720 l.sll r16,r30,r28
721
722 /* Invalidate DC */
723 l.addi r6,r0,0
724 l.sll r5,r14,r28
7251:
726 l.mtspr r0,r6,SPR_DCBIR
727 l.sfne r6,r5
728 l.bf 1b
729 l.add r6,r6,r14
730
731 /* Enable DC */
732 l.mfspr r6,r0,SPR_SR
733 l.ori r6,r6,SPR_SR_DCE
734 l.mtspr r0,r6,SPR_SR
7359:
736 l.jr r9
737 l.nop
738
739/* ===============================================[ page table masks ]=== */
740
741/* bit 4 is used in hardware as write back cache bit. we never use this bit
742 * explicitly, so we can reuse it as _PAGE_FILE bit and mask it out when
743 * writing into hardware pte's
744 */
745
746#define DTLB_UP_CONVERT_MASK 0x3fa
747#define ITLB_UP_CONVERT_MASK 0x3a
748
749/* for SMP we'd have (this is a bit subtle, CC must be always set
750 * for SMP, but since we have _PAGE_PRESENT bit always defined
751 * we can just modify the mask)
752 */
753#define DTLB_SMP_CONVERT_MASK 0x3fb
754#define ITLB_SMP_CONVERT_MASK 0x3b
755
756/* ---[ boot dtlb miss handler ]----------------------------------------- */
757
758boot_dtlb_miss_handler:
759
760/* mask for DTLB_MR register: - (0) sets V (valid) bit,
761 * - (31-12) sets bits belonging to VPN (31-12)
762 */
763#define DTLB_MR_MASK 0xfffff001
764
765/* mask for DTLB_TR register: - (2) sets CI (cache inhibit) bit,
766 * - (4) sets A (access) bit,
767 * - (5) sets D (dirty) bit,
768 * - (8) sets SRE (superuser read) bit
769 * - (9) sets SWE (superuser write) bit
770 * - (31-12) sets bits belonging to VPN (31-12)
771 */
772#define DTLB_TR_MASK 0xfffff332
773
774/* These are for masking out the VPN/PPN value from the MR/TR registers...
775 * it's not the same as the PFN */
776#define VPN_MASK 0xfffff000
777#define PPN_MASK 0xfffff000
778
779
780 EXCEPTION_STORE_GPR6
781
782#if 0
783 l.mfspr r6,r0,SPR_ESR_BASE //
784 l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
785 l.sfeqi r6,0 // r6 == 0x1 --> SM
786 l.bf exit_with_no_dtranslation //
787 l.nop
788#endif
789
790 /* this could be optimized by moving storing of
791 * non r6 registers here, and jumping r6 restore
792 * if not in supervisor mode
793 */
794
795 EXCEPTION_STORE_GPR2
796 EXCEPTION_STORE_GPR3
797 EXCEPTION_STORE_GPR4
798 EXCEPTION_STORE_GPR5
799
800 l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
801
802immediate_translation:
803 CLEAR_GPR(r6)
804
805 l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
806
807 l.mfspr r6, r0, SPR_DMMUCFGR
808 l.andi r6, r6, SPR_DMMUCFGR_NTS
809 l.srli r6, r6, SPR_DMMUCFGR_NTS_OFF
810 l.ori r5, r0, 0x1
811 l.sll r5, r5, r6 // r5 = number DMMU sets
812 l.addi r6, r5, -1 // r6 = nsets mask
813 l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
814
815 l.or r6,r6,r4 // r6 <- r4
816 l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
817 l.movhi r5,hi(DTLB_MR_MASK) // r5 <- ffff:0000.x000
818 l.ori r5,r5,lo(DTLB_MR_MASK) // r5 <- ffff:1111.x001 - apply DTLB_MR_MASK
819 l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have DTLBMR entry
820 l.mtspr r2,r5,SPR_DTLBMR_BASE(0) // set DTLBMR
821
822 /* set up DTLB with no translation for EA <= 0xbfffffff */
823 LOAD_SYMBOL_2_GPR(r6,0xbfffffff)
824 l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xbfffffff >= EA)
825 l.bf 1f // goto out
826 l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
827
828 tophys(r3,r4) // r3 <- PA
8291:
830 l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
831 l.movhi r5,hi(DTLB_TR_MASK) // r5 <- ffff:0000.x000
832 l.ori r5,r5,lo(DTLB_TR_MASK) // r5 <- ffff:1111.x330 - apply DTLB_MR_MASK
833 l.and r5,r5,r3 // r5 <- PPN :PPN .x330 - we have DTLBTR entry
834 l.mtspr r2,r5,SPR_DTLBTR_BASE(0) // set DTLBTR
835
836 EXCEPTION_LOAD_GPR6
837 EXCEPTION_LOAD_GPR5
838 EXCEPTION_LOAD_GPR4
839 EXCEPTION_LOAD_GPR3
840 EXCEPTION_LOAD_GPR2
841
842 l.rfe // SR <- ESR, PC <- EPC
843
844exit_with_no_dtranslation:
845 /* EA out of memory or not in supervisor mode */
846 EXCEPTION_LOAD_GPR6
847 EXCEPTION_LOAD_GPR4
848 l.j _dispatch_bus_fault
849
850/* ---[ boot itlb miss handler ]----------------------------------------- */
851
852boot_itlb_miss_handler:
853
854/* mask for ITLB_MR register: - sets V (valid) bit,
855 * - sets bits belonging to VPN (15-12)
856 */
857#define ITLB_MR_MASK 0xfffff001
858
859/* mask for ITLB_TR register: - sets A (access) bit,
860 * - sets SXE (superuser execute) bit
861 * - sets bits belonging to VPN (15-12)
862 */
863#define ITLB_TR_MASK 0xfffff050
864
865/*
866#define VPN_MASK 0xffffe000
867#define PPN_MASK 0xffffe000
868*/
869
870
871
872 EXCEPTION_STORE_GPR2
873 EXCEPTION_STORE_GPR3
874 EXCEPTION_STORE_GPR4
875 EXCEPTION_STORE_GPR5
876 EXCEPTION_STORE_GPR6
877
878#if 0
879 l.mfspr r6,r0,SPR_ESR_BASE //
880 l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
881 l.sfeqi r6,0 // r6 == 0x1 --> SM
882 l.bf exit_with_no_itranslation
883 l.nop
884#endif
885
886
887 l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
888
889earlyearly:
890 CLEAR_GPR(r6)
891
892 l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
893
894 l.mfspr r6, r0, SPR_IMMUCFGR
895 l.andi r6, r6, SPR_IMMUCFGR_NTS
896 l.srli r6, r6, SPR_IMMUCFGR_NTS_OFF
897 l.ori r5, r0, 0x1
898 l.sll r5, r5, r6 // r5 = number IMMU sets from IMMUCFGR
899 l.addi r6, r5, -1 // r6 = nsets mask
900 l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
901
902 l.or r6,r6,r4 // r6 <- r4
903 l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
904 l.movhi r5,hi(ITLB_MR_MASK) // r5 <- ffff:0000.x000
905 l.ori r5,r5,lo(ITLB_MR_MASK) // r5 <- ffff:1111.x001 - apply ITLB_MR_MASK
906 l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have ITLBMR entry
907 l.mtspr r2,r5,SPR_ITLBMR_BASE(0) // set ITLBMR
908
909 /*
910 * set up ITLB with no translation for EA <= 0x0fffffff
911 *
912 * we need this for head.S mapping (EA = PA). if we move all functions
913 * which run with mmu enabled into entry.S, we might be able to eliminate this.
914 *
915 */
916 LOAD_SYMBOL_2_GPR(r6,0x0fffffff)
917 l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xb0ffffff >= EA)
918 l.bf 1f // goto out
919 l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
920
921 tophys(r3,r4) // r3 <- PA
9221:
923 l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
924 l.movhi r5,hi(ITLB_TR_MASK) // r5 <- ffff:0000.x000
925 l.ori r5,r5,lo(ITLB_TR_MASK) // r5 <- ffff:1111.x050 - apply ITLB_MR_MASK
926 l.and r5,r5,r3 // r5 <- PPN :PPN .x050 - we have ITLBTR entry
927 l.mtspr r2,r5,SPR_ITLBTR_BASE(0) // set ITLBTR
928
929 EXCEPTION_LOAD_GPR6
930 EXCEPTION_LOAD_GPR5
931 EXCEPTION_LOAD_GPR4
932 EXCEPTION_LOAD_GPR3
933 EXCEPTION_LOAD_GPR2
934
935 l.rfe // SR <- ESR, PC <- EPC
936
937exit_with_no_itranslation:
938 EXCEPTION_LOAD_GPR4
939 EXCEPTION_LOAD_GPR6
940 l.j _dispatch_bus_fault
941 l.nop
942
943/* ====================================================================== */
944/*
945 * Stuff below here shouldn't go into .head section... maybe this stuff
946 * can be moved to entry.S ???
947 */
948
949/* ==============================================[ DTLB miss handler ]=== */
950
951/*
952 * Comments:
953 * Exception handlers are entered with MMU off so the following handler
954 * needs to use physical addressing
955 *
956 */
957
958 .text
959ENTRY(dtlb_miss_handler)
960 EXCEPTION_STORE_GPR2
961 EXCEPTION_STORE_GPR3
962 EXCEPTION_STORE_GPR4
963 EXCEPTION_STORE_GPR5
964 EXCEPTION_STORE_GPR6
965 /*
966 * get EA of the miss
967 */
968 l.mfspr r2,r0,SPR_EEAR_BASE
969 /*
970 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
971 */
972 GET_CURRENT_PGD(r3,r5) // r3 is current_pgd, r5 is temp
973 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
974 l.slli r4,r4,0x2 // to get address << 2
975 l.add r5,r4,r3 // r4 is pgd_index(daddr)
976 /*
977 * if (pmd_none(*pmd))
978 * goto pmd_none:
979 */
980 tophys (r4,r5)
981 l.lwz r3,0x0(r4) // get *pmd value
982 l.sfne r3,r0
983 l.bnf d_pmd_none
984 l.andi r3,r3,~PAGE_MASK //0x1fff // ~PAGE_MASK
985 /*
986 * if (pmd_bad(*pmd))
987 * pmd_clear(pmd)
988 * goto pmd_bad:
989 */
990// l.sfeq r3,r0 // check *pmd value
991// l.bf d_pmd_good
992 l.addi r3,r0,0xffffe000 // PAGE_MASK
993// l.j d_pmd_bad
994// l.sw 0x0(r4),r0 // clear pmd
995d_pmd_good:
996 /*
997 * pte = *pte_offset(pmd, daddr);
998 */
999 l.lwz r4,0x0(r4) // get **pmd value
1000 l.and r4,r4,r3 // & PAGE_MASK
1001 l.srli r5,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
1002 l.andi r3,r5,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
1003 l.slli r3,r3,0x2 // to get address << 2
1004 l.add r3,r3,r4
1005 l.lwz r2,0x0(r3) // this is pte at last
1006 /*
1007 * if (!pte_present(pte))
1008 */
1009 l.andi r4,r2,0x1
1010 l.sfne r4,r0 // is pte present
1011 l.bnf d_pte_not_present
1012 l.addi r3,r0,0xffffe3fa // PAGE_MASK | DTLB_UP_CONVERT_MASK
1013 /*
1014 * fill DTLB TR register
1015 */
1016 l.and r4,r2,r3 // apply the mask
1017 // Determine number of DMMU sets
1018 l.mfspr r6, r0, SPR_DMMUCFGR
1019 l.andi r6, r6, SPR_DMMUCFGR_NTS
1020 l.srli r6, r6, SPR_DMMUCFGR_NTS_OFF
1021 l.ori r3, r0, 0x1
1022 l.sll r3, r3, r6 // r3 = number DMMU sets DMMUCFGR
1023 l.addi r6, r3, -1 // r6 = nsets mask
1024 l.and r5, r5, r6 // calc offset: & (NUM_TLB_ENTRIES-1)
1025 //NUM_TLB_ENTRIES
1026 l.mtspr r5,r4,SPR_DTLBTR_BASE(0)
1027 /*
1028 * fill DTLB MR register
1029 */
1030 l.mfspr r2,r0,SPR_EEAR_BASE
1031 l.addi r3,r0,0xffffe000 // PAGE_MASK
1032 l.and r4,r2,r3 // apply PAGE_MASK to EA (__PHX__ do we really need this?)
1033 l.ori r4,r4,0x1 // set hardware valid bit: DTBL_MR entry
1034 l.mtspr r5,r4,SPR_DTLBMR_BASE(0)
1035
1036 EXCEPTION_LOAD_GPR2
1037 EXCEPTION_LOAD_GPR3
1038 EXCEPTION_LOAD_GPR4
1039 EXCEPTION_LOAD_GPR5
1040 EXCEPTION_LOAD_GPR6
1041 l.rfe
1042d_pmd_bad:
1043 l.nop 1
1044 EXCEPTION_LOAD_GPR2
1045 EXCEPTION_LOAD_GPR3
1046 EXCEPTION_LOAD_GPR4
1047 EXCEPTION_LOAD_GPR5
1048 EXCEPTION_LOAD_GPR6
1049 l.rfe
1050d_pmd_none:
1051d_pte_not_present:
1052 EXCEPTION_LOAD_GPR2
1053 EXCEPTION_LOAD_GPR3
1054 EXCEPTION_LOAD_GPR4
1055 EXCEPTION_LOAD_GPR5
1056 EXCEPTION_LOAD_GPR6
1057 l.j _dispatch_do_dpage_fault
1058 l.nop
1059
1060/* ==============================================[ ITLB miss handler ]=== */
1061ENTRY(itlb_miss_handler)
1062 EXCEPTION_STORE_GPR2
1063 EXCEPTION_STORE_GPR3
1064 EXCEPTION_STORE_GPR4
1065 EXCEPTION_STORE_GPR5
1066 EXCEPTION_STORE_GPR6
1067 /*
1068 * get EA of the miss
1069 */
1070 l.mfspr r2,r0,SPR_EEAR_BASE
1071
1072 /*
1073 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
1074 *
1075 */
1076 GET_CURRENT_PGD(r3,r5) // r3 is current_pgd, r5 is temp
1077 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
1078 l.slli r4,r4,0x2 // to get address << 2
1079 l.add r5,r4,r3 // r4 is pgd_index(daddr)
1080 /*
1081 * if (pmd_none(*pmd))
1082 * goto pmd_none:
1083 */
1084 tophys (r4,r5)
1085 l.lwz r3,0x0(r4) // get *pmd value
1086 l.sfne r3,r0
1087 l.bnf i_pmd_none
1088 l.andi r3,r3,0x1fff // ~PAGE_MASK
1089 /*
1090 * if (pmd_bad(*pmd))
1091 * pmd_clear(pmd)
1092 * goto pmd_bad:
1093 */
1094
1095// l.sfeq r3,r0 // check *pmd value
1096// l.bf i_pmd_good
1097 l.addi r3,r0,0xffffe000 // PAGE_MASK
1098// l.j i_pmd_bad
1099// l.sw 0x0(r4),r0 // clear pmd
1100
1101i_pmd_good:
1102 /*
1103 * pte = *pte_offset(pmd, iaddr);
1104 *
1105 */
1106 l.lwz r4,0x0(r4) // get **pmd value
1107 l.and r4,r4,r3 // & PAGE_MASK
1108 l.srli r5,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
1109 l.andi r3,r5,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
1110 l.slli r3,r3,0x2 // to get address << 2
1111 l.add r3,r3,r4
1112 l.lwz r2,0x0(r3) // this is pte at last
1113 /*
1114 * if (!pte_present(pte))
1115 *
1116 */
1117 l.andi r4,r2,0x1
1118 l.sfne r4,r0 // is pte present
1119 l.bnf i_pte_not_present
1120 l.addi r3,r0,0xffffe03a // PAGE_MASK | ITLB_UP_CONVERT_MASK
1121 /*
1122 * fill ITLB TR register
1123 */
1124 l.and r4,r2,r3 // apply the mask
1125 l.andi r3,r2,0x7c0 // _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE | _PAGE_URE | _PAGE_UWE
1126// l.andi r3,r2,0x400 // _PAGE_EXEC
1127 l.sfeq r3,r0
1128 l.bf itlb_tr_fill //_workaround
1129 // Determine number of IMMU sets
1130 l.mfspr r6, r0, SPR_IMMUCFGR
1131 l.andi r6, r6, SPR_IMMUCFGR_NTS
1132 l.srli r6, r6, SPR_IMMUCFGR_NTS_OFF
1133 l.ori r3, r0, 0x1
1134 l.sll r3, r3, r6 // r3 = number IMMU sets IMMUCFGR
1135 l.addi r6, r3, -1 // r6 = nsets mask
1136 l.and r5, r5, r6 // calc offset: & (NUM_TLB_ENTRIES-1)
1137
1138/*
1139 * __PHX__ :: fixme
1140 * we should not just blindly set executable flags,
1141 * but it does help with ping. the clean way would be to find out
1142 * (and fix it) why stack doesn't have execution permissions
1143 */
1144
1145itlb_tr_fill_workaround:
1146 l.ori r4,r4,0xc0 // | (SPR_ITLBTR_UXE | ITLBTR_SXE)
1147itlb_tr_fill:
1148 l.mtspr r5,r4,SPR_ITLBTR_BASE(0)
1149 /*
1150 * fill DTLB MR register
1151 */
1152 l.mfspr r2,r0,SPR_EEAR_BASE
1153 l.addi r3,r0,0xffffe000 // PAGE_MASK
1154 l.and r4,r2,r3 // apply PAGE_MASK to EA (__PHX__ do we really need this?)
1155 l.ori r4,r4,0x1 // set hardware valid bit: DTBL_MR entry
1156 l.mtspr r5,r4,SPR_ITLBMR_BASE(0)
1157
1158 EXCEPTION_LOAD_GPR2
1159 EXCEPTION_LOAD_GPR3
1160 EXCEPTION_LOAD_GPR4
1161 EXCEPTION_LOAD_GPR5
1162 EXCEPTION_LOAD_GPR6
1163 l.rfe
1164
1165i_pmd_bad:
1166 l.nop 1
1167 EXCEPTION_LOAD_GPR2
1168 EXCEPTION_LOAD_GPR3
1169 EXCEPTION_LOAD_GPR4
1170 EXCEPTION_LOAD_GPR5
1171 EXCEPTION_LOAD_GPR6
1172 l.rfe
1173i_pmd_none:
1174i_pte_not_present:
1175 EXCEPTION_LOAD_GPR2
1176 EXCEPTION_LOAD_GPR3
1177 EXCEPTION_LOAD_GPR4
1178 EXCEPTION_LOAD_GPR5
1179 EXCEPTION_LOAD_GPR6
1180 l.j _dispatch_do_ipage_fault
1181 l.nop
1182
1183/* ==============================================[ boot tlb handlers ]=== */
1184
1185
1186/* =================================================[ debugging aids ]=== */
1187
1188 .align 64
1189_immu_trampoline:
1190 .space 64
1191_immu_trampoline_top:
1192
1193#define TRAMP_SLOT_0 (0x0)
1194#define TRAMP_SLOT_1 (0x4)
1195#define TRAMP_SLOT_2 (0x8)
1196#define TRAMP_SLOT_3 (0xc)
1197#define TRAMP_SLOT_4 (0x10)
1198#define TRAMP_SLOT_5 (0x14)
1199#define TRAMP_FRAME_SIZE (0x18)
1200
1201ENTRY(_immu_trampoline_workaround)
1202 // r2 EEA
1203 // r6 is physical EEA
1204 tophys(r6,r2)
1205
1206 LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
1207 tophys (r3,r5) // r3 is trampoline (physical)
1208
1209 LOAD_SYMBOL_2_GPR(r4,0x15000000)
1210 l.sw TRAMP_SLOT_0(r3),r4
1211 l.sw TRAMP_SLOT_1(r3),r4
1212 l.sw TRAMP_SLOT_4(r3),r4
1213 l.sw TRAMP_SLOT_5(r3),r4
1214
1215 // EPC = EEA - 0x4
1216 l.lwz r4,0x0(r6) // load op @ EEA + 0x0 (fc address)
1217 l.sw TRAMP_SLOT_3(r3),r4 // store it to _immu_trampoline_data
1218 l.lwz r4,-0x4(r6) // load op @ EEA - 0x4 (f8 address)
1219 l.sw TRAMP_SLOT_2(r3),r4 // store it to _immu_trampoline_data
1220
1221 l.srli r5,r4,26 // check opcode for write access
1222 l.sfeqi r5,0 // l.j
1223 l.bf 0f
1224 l.sfeqi r5,0x11 // l.jr
1225 l.bf 1f
1226 l.sfeqi r5,1 // l.jal
1227 l.bf 2f
1228 l.sfeqi r5,0x12 // l.jalr
1229 l.bf 3f
1230 l.sfeqi r5,3 // l.bnf
1231 l.bf 4f
1232 l.sfeqi r5,4 // l.bf
1233 l.bf 5f
123499:
1235 l.nop
1236 l.j 99b // should never happen
1237 l.nop 1
1238
1239 // r2 is EEA
1240 // r3 is trampoline address (physical)
1241 // r4 is instruction
1242 // r6 is physical(EEA)
1243 //
1244 // r5
1245
12462: // l.jal
1247
1248 /* 19 20 aa aa l.movhi r9,0xaaaa
1249 * a9 29 bb bb l.ori r9,0xbbbb
1250 *
1251 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
1252 */
1253
1254 l.addi r6,r2,0x4 // this is 0xaaaabbbb
1255
1256 // l.movhi r9,0xaaaa
1257 l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
1258 l.sh (TRAMP_SLOT_0+0x0)(r3),r5
1259 l.srli r5,r6,16
1260 l.sh (TRAMP_SLOT_0+0x2)(r3),r5
1261
1262 // l.ori r9,0xbbbb
1263 l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
1264 l.sh (TRAMP_SLOT_1+0x0)(r3),r5
1265 l.andi r5,r6,0xffff
1266 l.sh (TRAMP_SLOT_1+0x2)(r3),r5
1267
1268 /* falthrough, need to set up new jump offset */
1269
1270
12710: // l.j
1272 l.slli r6,r4,6 // original offset shifted left 6 - 2
1273// l.srli r6,r6,6 // original offset shifted right 2
1274
1275 l.slli r4,r2,4 // old jump position: EEA shifted left 4
1276// l.srli r4,r4,6 // old jump position: shifted right 2
1277
1278 l.addi r5,r3,0xc // new jump position (physical)
1279 l.slli r5,r5,4 // new jump position: shifted left 4
1280
1281 // calculate new jump offset
1282 // new_off = old_off + (old_jump - new_jump)
1283
1284 l.sub r5,r4,r5 // old_jump - new_jump
1285 l.add r5,r6,r5 // orig_off + (old_jump - new_jump)
1286 l.srli r5,r5,6 // new offset shifted right 2
1287
1288 // r5 is new jump offset
1289 // l.j has opcode 0x0...
1290 l.sw TRAMP_SLOT_2(r3),r5 // write it back
1291
1292 l.j trampoline_out
1293 l.nop
1294
1295/* ----------------------------- */
1296
12973: // l.jalr
1298
1299 /* 19 20 aa aa l.movhi r9,0xaaaa
1300 * a9 29 bb bb l.ori r9,0xbbbb
1301 *
1302 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
1303 */
1304
1305 l.addi r6,r2,0x4 // this is 0xaaaabbbb
1306
1307 // l.movhi r9,0xaaaa
1308 l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
1309 l.sh (TRAMP_SLOT_0+0x0)(r3),r5
1310 l.srli r5,r6,16
1311 l.sh (TRAMP_SLOT_0+0x2)(r3),r5
1312
1313 // l.ori r9,0xbbbb
1314 l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
1315 l.sh (TRAMP_SLOT_1+0x0)(r3),r5
1316 l.andi r5,r6,0xffff
1317 l.sh (TRAMP_SLOT_1+0x2)(r3),r5
1318
1319 l.lhz r5,(TRAMP_SLOT_2+0x0)(r3) // load hi part of jump instruction
1320 l.andi r5,r5,0x3ff // clear out opcode part
1321 l.ori r5,r5,0x4400 // opcode changed from l.jalr -> l.jr
1322 l.sh (TRAMP_SLOT_2+0x0)(r3),r5 // write it back
1323
1324 /* falthrough */
1325
13261: // l.jr
1327 l.j trampoline_out
1328 l.nop
1329
1330/* ----------------------------- */
1331
13324: // l.bnf
13335: // l.bf
1334 l.slli r6,r4,6 // original offset shifted left 6 - 2
1335// l.srli r6,r6,6 // original offset shifted right 2
1336
1337 l.slli r4,r2,4 // old jump position: EEA shifted left 4
1338// l.srli r4,r4,6 // old jump position: shifted right 2
1339
1340 l.addi r5,r3,0xc // new jump position (physical)
1341 l.slli r5,r5,4 // new jump position: shifted left 4
1342
1343 // calculate new jump offset
1344 // new_off = old_off + (old_jump - new_jump)
1345
1346 l.add r6,r6,r4 // (orig_off + old_jump)
1347 l.sub r6,r6,r5 // (orig_off + old_jump) - new_jump
1348 l.srli r6,r6,6 // new offset shifted right 2
1349
1350 // r6 is new jump offset
1351 l.lwz r4,(TRAMP_SLOT_2+0x0)(r3) // load jump instruction
1352 l.srli r4,r4,16
1353 l.andi r4,r4,0xfc00 // get opcode part
1354 l.slli r4,r4,16
1355 l.or r6,r4,r6 // l.b(n)f new offset
1356 l.sw TRAMP_SLOT_2(r3),r6 // write it back
1357
1358 /* we need to add l.j to EEA + 0x8 */
1359 tophys (r4,r2) // may not be needed (due to shifts down_
1360 l.addi r4,r4,(0x8 - 0x8) // jump target = r2 + 0x8 (compensate for 0x8)
1361 // jump position = r5 + 0x8 (0x8 compensated)
1362 l.sub r4,r4,r5 // jump offset = target - new_position + 0x8
1363
1364 l.slli r4,r4,4 // the amount of info in imediate of jump
1365 l.srli r4,r4,6 // jump instruction with offset
1366 l.sw TRAMP_SLOT_4(r3),r4 // write it to 4th slot
1367
1368 /* fallthrough */
1369
1370trampoline_out:
1371 // set up new EPC to point to our trampoline code
1372 LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
1373 l.mtspr r0,r5,SPR_EPCR_BASE
1374
1375 // immu_trampoline is (4x) CACHE_LINE aligned
1376 // and only 6 instructions long,
1377 // so we need to invalidate only 2 lines
1378
1379 /* Establish cache block size
1380 If BS=0, 16;
1381 If BS=1, 32;
1382 r14 contain block size
1383 */
1384 l.mfspr r21,r0,SPR_ICCFGR
1385 l.andi r21,r21,SPR_ICCFGR_CBS
1386 l.srli r21,r21,7
1387 l.ori r23,r0,16
1388 l.sll r14,r23,r21
1389
1390 l.mtspr r0,r5,SPR_ICBIR
1391 l.add r5,r5,r14
1392 l.mtspr r0,r5,SPR_ICBIR
1393
1394 l.jr r9
1395 l.nop
1396
1397
1398/*
1399 * DSCR: prints a string referenced by r3.
1400 *
1401 * PRMS: r3 - address of the first character of null
1402 * terminated string to be printed
1403 *
1404 * PREQ: UART at UART_BASE_ADD has to be initialized
1405 *
1406 * POST: caller should be aware that r3, r9 are changed
1407 */
1408ENTRY(_emergency_print)
1409 EMERGENCY_PRINT_STORE_GPR4
1410 EMERGENCY_PRINT_STORE_GPR5
1411 EMERGENCY_PRINT_STORE_GPR6
1412 EMERGENCY_PRINT_STORE_GPR7
14132:
1414 l.lbz r7,0(r3)
1415 l.sfeq r7,r0
1416 l.bf 9f
1417 l.nop
1418
1419// putc:
1420 l.movhi r4,hi(UART_BASE_ADD)
1421
1422 l.addi r6,r0,0x20
14231: l.lbz r5,5(r4)
1424 l.andi r5,r5,0x20
1425 l.sfeq r5,r6
1426 l.bnf 1b
1427 l.nop
1428
1429 l.sb 0(r4),r7
1430
1431 l.addi r6,r0,0x60
14321: l.lbz r5,5(r4)
1433 l.andi r5,r5,0x60
1434 l.sfeq r5,r6
1435 l.bnf 1b
1436 l.nop
1437
1438 /* next character */
1439 l.j 2b
1440 l.addi r3,r3,0x1
1441
14429:
1443 EMERGENCY_PRINT_LOAD_GPR7
1444 EMERGENCY_PRINT_LOAD_GPR6
1445 EMERGENCY_PRINT_LOAD_GPR5
1446 EMERGENCY_PRINT_LOAD_GPR4
1447 l.jr r9
1448 l.nop
1449
1450ENTRY(_emergency_print_nr)
1451 EMERGENCY_PRINT_STORE_GPR4
1452 EMERGENCY_PRINT_STORE_GPR5
1453 EMERGENCY_PRINT_STORE_GPR6
1454 EMERGENCY_PRINT_STORE_GPR7
1455 EMERGENCY_PRINT_STORE_GPR8
1456
1457 l.addi r8,r0,32 // shift register
1458
14591: /* remove leading zeros */
1460 l.addi r8,r8,-0x4
1461 l.srl r7,r3,r8
1462 l.andi r7,r7,0xf
1463
1464 /* don't skip the last zero if number == 0x0 */
1465 l.sfeqi r8,0x4
1466 l.bf 2f
1467 l.nop
1468
1469 l.sfeq r7,r0
1470 l.bf 1b
1471 l.nop
1472
14732:
1474 l.srl r7,r3,r8
1475
1476 l.andi r7,r7,0xf
1477 l.sflts r8,r0
1478 l.bf 9f
1479
1480 l.sfgtui r7,0x9
1481 l.bnf 8f
1482 l.nop
1483 l.addi r7,r7,0x27
1484
14858:
1486 l.addi r7,r7,0x30
1487// putc:
1488 l.movhi r4,hi(UART_BASE_ADD)
1489
1490 l.addi r6,r0,0x20
14911: l.lbz r5,5(r4)
1492 l.andi r5,r5,0x20
1493 l.sfeq r5,r6
1494 l.bnf 1b
1495 l.nop
1496
1497 l.sb 0(r4),r7
1498
1499 l.addi r6,r0,0x60
15001: l.lbz r5,5(r4)
1501 l.andi r5,r5,0x60
1502 l.sfeq r5,r6
1503 l.bnf 1b
1504 l.nop
1505
1506 /* next character */
1507 l.j 2b
1508 l.addi r8,r8,-0x4
1509
15109:
1511 EMERGENCY_PRINT_LOAD_GPR8
1512 EMERGENCY_PRINT_LOAD_GPR7
1513 EMERGENCY_PRINT_LOAD_GPR6
1514 EMERGENCY_PRINT_LOAD_GPR5
1515 EMERGENCY_PRINT_LOAD_GPR4
1516 l.jr r9
1517 l.nop
1518
1519
1520/*
1521 * This should be used for debugging only.
1522 * It messes up the Linux early serial output
1523 * somehow, so use it sparingly and essentially
1524 * only if you need to debug something that goes wrong
1525 * before Linux gets the early serial going.
1526 *
1527 * Furthermore, you'll have to make sure you set the
1528 * UART_DEVISOR correctly according to the system
1529 * clock rate.
1530 *
1531 *
1532 */
1533
1534
1535
1536#define SYS_CLK 20000000
1537//#define SYS_CLK 1843200
1538#define OR32_CONSOLE_BAUD 115200
1539#define UART_DIVISOR SYS_CLK/(16*OR32_CONSOLE_BAUD)
1540
1541ENTRY(_early_uart_init)
1542 l.movhi r3,hi(UART_BASE_ADD)
1543
1544 l.addi r4,r0,0x7
1545 l.sb 0x2(r3),r4
1546
1547 l.addi r4,r0,0x0
1548 l.sb 0x1(r3),r4
1549
1550 l.addi r4,r0,0x3
1551 l.sb 0x3(r3),r4
1552
1553 l.lbz r5,3(r3)
1554 l.ori r4,r5,0x80
1555 l.sb 0x3(r3),r4
1556 l.addi r4,r0,((UART_DIVISOR>>8) & 0x000000ff)
1557 l.sb UART_DLM(r3),r4
1558 l.addi r4,r0,((UART_DIVISOR) & 0x000000ff)
1559 l.sb UART_DLL(r3),r4
1560 l.sb 0x3(r3),r5
1561
1562 l.jr r9
1563 l.nop
1564
1565_string_copying_linux:
1566 .string "\n\n\n\n\n\rCopying Linux... \0"
1567
1568_string_ok_booting:
1569 .string "Ok, booting the kernel.\n\r\0"
1570
1571_string_unhandled_exception:
1572 .string "\n\rRunarunaround: Unhandled exception 0x\0"
1573
1574_string_epc_prefix:
1575 .string ": EPC=0x\0"
1576
1577_string_nl:
1578 .string "\n\r\0"
1579
1580 .global _string_esr_irq_bug
1581_string_esr_irq_bug:
1582 .string "\n\rESR external interrupt bug, for details look into entry.S\n\r\0"
1583
1584
1585
1586/* ========================================[ page aligned structures ]=== */
1587
1588/*
1589 * .data section should be page aligned
1590 * (look into arch/or32/kernel/vmlinux.lds)
1591 */
1592 .section .data,"aw"
1593 .align 8192
1594 .global empty_zero_page
1595empty_zero_page:
1596 .space 8192
1597
1598 .global swapper_pg_dir
1599swapper_pg_dir:
1600 .space 8192
1601
1602 .global _unhandled_stack
1603_unhandled_stack:
1604 .space 8192
1605_unhandled_stack_top:
1606
1607/* ============================================================[ EOF ]=== */
diff --git a/arch/openrisc/kernel/idle.c b/arch/openrisc/kernel/idle.c
new file mode 100644
index 00000000000..d5bc5f813e8
--- /dev/null
+++ b/arch/openrisc/kernel/idle.c
@@ -0,0 +1,77 @@
1/*
2 * OpenRISC idle.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * Idle daemon for or32. Idle daemon will handle any action
18 * that needs to be taken when the system becomes idle.
19 */
20
21#include <linux/errno.h>
22#include <linux/sched.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/smp.h>
26#include <linux/stddef.h>
27#include <linux/unistd.h>
28#include <linux/ptrace.h>
29#include <linux/slab.h>
30#include <linux/tick.h>
31
32#include <asm/pgtable.h>
33#include <asm/uaccess.h>
34#include <asm/system.h>
35#include <asm/io.h>
36#include <asm/processor.h>
37#include <asm/mmu.h>
38#include <asm/cache.h>
39#include <asm/pgalloc.h>
40
41void (*powersave) (void) = NULL;
42
43static inline void pm_idle(void)
44{
45 barrier();
46}
47
48void cpu_idle(void)
49{
50 set_thread_flag(TIF_POLLING_NRFLAG);
51
52 /* endless idle loop with no priority at all */
53 while (1) {
54 tick_nohz_stop_sched_tick(1);
55
56 while (!need_resched()) {
57 check_pgt_cache();
58 rmb();
59
60 clear_thread_flag(TIF_POLLING_NRFLAG);
61
62 local_irq_disable();
63 /* Don't trace irqs off for idle */
64 stop_critical_timings();
65 if (!need_resched() && powersave != NULL)
66 powersave();
67 start_critical_timings();
68 local_irq_enable();
69 set_thread_flag(TIF_POLLING_NRFLAG);
70 }
71
72 tick_nohz_restart_sched_tick();
73 preempt_enable_no_resched();
74 schedule();
75 preempt_disable();
76 }
77}
diff --git a/arch/openrisc/kernel/init_task.c b/arch/openrisc/kernel/init_task.c
new file mode 100644
index 00000000000..45744a38492
--- /dev/null
+++ b/arch/openrisc/kernel/init_task.c
@@ -0,0 +1,41 @@
1/*
2 * OpenRISC init_task.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/init_task.h>
19#include <linux/mqueue.h>
20
21static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
22static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
23
24/*
25 * Initial thread structure.
26 *
27 * We need to make sure that this is THREAD_SIZE aligned due to the
28 * way process stacks are handled. This is done by having a special
29 * "init_task" linker map entry..
30 */
31union thread_union init_thread_union __init_task_data = {
32 INIT_THREAD_INFO(init_task)
33};
34
35/*
36 * Initial task structure.
37 *
38 * All other task structs will be allocated on slabs in fork.c
39 */
40struct task_struct init_task = INIT_TASK(init_task);
41EXPORT_SYMBOL(init_task);
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
new file mode 100644
index 00000000000..59b30233833
--- /dev/null
+++ b/arch/openrisc/kernel/irq.c
@@ -0,0 +1,172 @@
1/*
2 * OpenRISC irq.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#include <linux/ptrace.h>
18#include <linux/errno.h>
19#include <linux/interrupt.h>
20#include <linux/init.h>
21#include <linux/of.h>
22#include <linux/ftrace.h>
23#include <linux/irq.h>
24#include <linux/seq_file.h>
25#include <linux/kernel_stat.h>
26
27#include <linux/irqflags.h>
28
29/* read interrupt enabled status */
30unsigned long arch_local_save_flags(void)
31{
32 return mfspr(SPR_SR) & (SPR_SR_IEE|SPR_SR_TEE);
33}
34EXPORT_SYMBOL(arch_local_save_flags);
35
36/* set interrupt enabled status */
37void arch_local_irq_restore(unsigned long flags)
38{
39 mtspr(SPR_SR, ((mfspr(SPR_SR) & ~(SPR_SR_IEE|SPR_SR_TEE)) | flags));
40}
41EXPORT_SYMBOL(arch_local_irq_restore);
42
43
44/* OR1K PIC implementation */
45
46/* We're a couple of cycles faster than the generic implementations with
47 * these 'fast' versions.
48 */
49
50static void or1k_pic_mask(struct irq_data *data)
51{
52 mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->irq));
53}
54
55static void or1k_pic_unmask(struct irq_data *data)
56{
57 mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->irq));
58}
59
60static void or1k_pic_ack(struct irq_data *data)
61{
62 /* EDGE-triggered interrupts need to be ack'ed in order to clear
63 * the latch.
64 * LEVER-triggered interrupts do not need to be ack'ed; however,
65 * ack'ing the interrupt has no ill-effect and is quicker than
66 * trying to figure out what type it is...
67 */
68
69 /* The OpenRISC 1000 spec says to write a 1 to the bit to ack the
70 * interrupt, but the OR1200 does this backwards and requires a 0
71 * to be written...
72 */
73
74#ifdef CONFIG_OR1K_1200
75 /* There are two oddities with the OR1200 PIC implementation:
76 * i) LEVEL-triggered interrupts are latched and need to be cleared
77 * ii) the interrupt latch is cleared by writing a 0 to the bit,
78 * as opposed to a 1 as mandated by the spec
79 */
80
81 mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
82#else
83 WARN(1, "Interrupt handling possibily broken\n");
84 mtspr(SPR_PICSR, (1UL << irq));
85#endif
86}
87
88static void or1k_pic_mask_ack(struct irq_data *data)
89{
90 /* Comments for pic_ack apply here, too */
91
92#ifdef CONFIG_OR1K_1200
93 mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
94#else
95 WARN(1, "Interrupt handling possibily broken\n");
96 mtspr(SPR_PICSR, (1UL << irq));
97#endif
98}
99
100static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
101{
102 /* There's nothing to do in the PIC configuration when changing
103 * flow type. Level and edge-triggered interrupts are both
104 * supported, but it's PIC-implementation specific which type
105 * is handled. */
106
107 return irq_setup_alt_chip(data, flow_type);
108}
109
110static inline int pic_get_irq(int first)
111{
112 int irq;
113
114 irq = ffs(mfspr(SPR_PICSR) >> first);
115
116 return irq ? irq + first - 1 : NO_IRQ;
117}
118
119static void __init or1k_irq_init(void)
120{
121 struct irq_chip_generic *gc;
122 struct irq_chip_type *ct;
123
124 /* Disable all interrupts until explicitly requested */
125 mtspr(SPR_PICMR, (0UL));
126
127 gc = irq_alloc_generic_chip("or1k-PIC", 1, 0, 0, handle_level_irq);
128 ct = gc->chip_types;
129
130 ct->chip.irq_unmask = or1k_pic_unmask;
131 ct->chip.irq_mask = or1k_pic_mask;
132 ct->chip.irq_ack = or1k_pic_ack;
133 ct->chip.irq_mask_ack = or1k_pic_mask_ack;
134 ct->chip.irq_set_type = or1k_pic_set_type;
135
136 /* The OR1K PIC can handle both level and edge trigged
137 * interrupts in roughly the same manner
138 */
139#if 0
140 /* FIXME: chip.type??? */
141 ct->chip.type = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_MASK;
142#endif
143
144 irq_setup_generic_chip(gc, IRQ_MSK(NR_IRQS), 0,
145 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
146}
147
148void __init init_IRQ(void)
149{
150 or1k_irq_init();
151}
152
153void __irq_entry do_IRQ(struct pt_regs *regs)
154{
155 int irq = -1;
156 struct pt_regs *old_regs = set_irq_regs(regs);
157
158 irq_enter();
159
160 while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
161 generic_handle_irq(irq);
162
163 irq_exit();
164 set_irq_regs(old_regs);
165}
166
167unsigned int irq_create_of_mapping(struct device_node *controller,
168 const u32 *intspec, unsigned int intsize)
169{
170 return intspec[0];
171}
172EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/openrisc/kernel/module.c b/arch/openrisc/kernel/module.c
new file mode 100644
index 00000000000..10ff50f0202
--- /dev/null
+++ b/arch/openrisc/kernel/module.c
@@ -0,0 +1,72 @@
1/*
2 * OpenRISC module.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#include <linux/moduleloader.h>
18#include <linux/elf.h>
19
20int apply_relocate_add(Elf32_Shdr *sechdrs,
21 const char *strtab,
22 unsigned int symindex,
23 unsigned int relsec,
24 struct module *me)
25{
26 unsigned int i;
27 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
28 Elf32_Sym *sym;
29 uint32_t *location;
30 uint32_t value;
31
32 pr_debug("Applying relocate section %u to %u\n", relsec,
33 sechdrs[relsec].sh_info);
34 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
35 /* This is where to make the change */
36 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
37 + rel[i].r_offset;
38
39 /* This is the symbol it is referring to. Note that all
40 undefined symbols have been resolved. */
41 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
42 + ELF32_R_SYM(rel[i].r_info);
43 value = sym->st_value + rel[i].r_addend;
44
45 switch (ELF32_R_TYPE(rel[i].r_info)) {
46 case R_OR32_32:
47 *location = value;
48 break;
49 case R_OR32_CONST:
50 location = (uint16_t *)location + 1;
51 *((uint16_t *)location) = (uint16_t) (value);
52 break;
53 case R_OR32_CONSTH:
54 location = (uint16_t *)location + 1;
55 *((uint16_t *)location) = (uint16_t) (value >> 16);
56 break;
57 case R_OR32_JUMPTARG:
58 value -= (uint32_t)location;
59 value >>= 2;
60 value &= 0x03ffffff;
61 value |= *location & 0xfc000000;
62 *location = value;
63 break;
64 default:
65 pr_err("module %s: Unknown relocation: %u\n",
66 me->name, ELF32_R_TYPE(rel[i].r_info));
67 break;
68 }
69 }
70
71 return 0;
72}
diff --git a/arch/openrisc/kernel/or32_ksyms.c b/arch/openrisc/kernel/or32_ksyms.c
new file mode 100644
index 00000000000..83ccf7c0c58
--- /dev/null
+++ b/arch/openrisc/kernel/or32_ksyms.c
@@ -0,0 +1,46 @@
1/*
2 * OpenRISC or32_ksyms.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/module.h>
19#include <linux/elfcore.h>
20#include <linux/sched.h>
21#include <linux/in6.h>
22#include <linux/interrupt.h>
23#include <linux/vmalloc.h>
24#include <linux/semaphore.h>
25
26#include <asm/processor.h>
27#include <asm/uaccess.h>
28#include <asm/checksum.h>
29#include <asm/io.h>
30#include <asm/hardirq.h>
31#include <asm/delay.h>
32#include <asm/pgalloc.h>
33
34#define DECLARE_EXPORT(name) extern void name(void); EXPORT_SYMBOL(name)
35
36/* compiler generated symbols */
37DECLARE_EXPORT(__udivsi3);
38DECLARE_EXPORT(__divsi3);
39DECLARE_EXPORT(__umodsi3);
40DECLARE_EXPORT(__modsi3);
41DECLARE_EXPORT(__muldi3);
42DECLARE_EXPORT(__ashrdi3);
43DECLARE_EXPORT(__ashldi3);
44DECLARE_EXPORT(__lshrdi3);
45
46EXPORT_SYMBOL(__copy_tofrom_user);
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
new file mode 100644
index 00000000000..e4209af879e
--- /dev/null
+++ b/arch/openrisc/kernel/process.c
@@ -0,0 +1,311 @@
1/*
2 * OpenRISC process.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * This file handles the architecture-dependent parts of process handling...
18 */
19
20#define __KERNEL_SYSCALLS__
21#include <stdarg.h>
22
23#include <linux/errno.h>
24#include <linux/sched.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/mm.h>
28#include <linux/stddef.h>
29#include <linux/unistd.h>
30#include <linux/ptrace.h>
31#include <linux/slab.h>
32#include <linux/elfcore.h>
33#include <linux/interrupt.h>
34#include <linux/delay.h>
35#include <linux/init_task.h>
36#include <linux/mqueue.h>
37#include <linux/fs.h>
38
39#include <asm/uaccess.h>
40#include <asm/pgtable.h>
41#include <asm/system.h>
42#include <asm/io.h>
43#include <asm/processor.h>
44#include <asm/spr_defs.h>
45
46#include <linux/smp.h>
47
48/*
49 * Pointer to Current thread info structure.
50 *
51 * Used at user space -> kernel transitions.
52 */
53struct thread_info *current_thread_info_set[NR_CPUS] = { &init_thread_info, };
54
55void machine_restart(void)
56{
57 printk(KERN_INFO "*** MACHINE RESTART ***\n");
58 __asm__("l.nop 1");
59}
60
61/*
62 * Similar to machine_power_off, but don't shut off power. Add code
63 * here to freeze the system for e.g. post-mortem debug purpose when
64 * possible. This halt has nothing to do with the idle halt.
65 */
66void machine_halt(void)
67{
68 printk(KERN_INFO "*** MACHINE HALT ***\n");
69 __asm__("l.nop 1");
70}
71
72/* If or when software power-off is implemented, add code here. */
73void machine_power_off(void)
74{
75 printk(KERN_INFO "*** MACHINE POWER OFF ***\n");
76 __asm__("l.nop 1");
77}
78
79void (*pm_power_off) (void) = machine_power_off;
80
81/*
82 * When a process does an "exec", machine state like FPU and debug
83 * registers need to be reset. This is a hook function for that.
84 * Currently we don't have any such state to reset, so this is empty.
85 */
86void flush_thread(void)
87{
88}
89
90void show_regs(struct pt_regs *regs)
91{
92 extern void show_registers(struct pt_regs *regs);
93
94 /* __PHX__ cleanup this mess */
95 show_registers(regs);
96}
97
98unsigned long thread_saved_pc(struct task_struct *t)
99{
100 return (unsigned long)user_regs(t->stack)->pc;
101}
102
103void release_thread(struct task_struct *dead_task)
104{
105}
106
107/*
108 * Copy the thread-specific (arch specific) info from the current
109 * process to the new one p
110 */
111extern asmlinkage void ret_from_fork(void);
112
113int
114copy_thread(unsigned long clone_flags, unsigned long usp,
115 unsigned long unused, struct task_struct *p, struct pt_regs *regs)
116{
117 struct pt_regs *childregs;
118 struct pt_regs *kregs;
119 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
120 struct thread_info *ti;
121 unsigned long top_of_kernel_stack;
122
123 top_of_kernel_stack = sp;
124
125 p->set_child_tid = p->clear_child_tid = NULL;
126
127 /* Copy registers */
128 /* redzone */
129 sp -= STACK_FRAME_OVERHEAD;
130 sp -= sizeof(struct pt_regs);
131 childregs = (struct pt_regs *)sp;
132
133 /* Copy parent registers */
134 *childregs = *regs;
135
136 if ((childregs->sr & SPR_SR_SM) == 1) {
137 /* for kernel thread, set `current_thread_info'
138 * and stackptr in new task
139 */
140 childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
141 childregs->gpr[10] = (unsigned long)task_thread_info(p);
142 } else {
143 childregs->sp = usp;
144 }
145
146 childregs->gpr[11] = 0; /* Result from fork() */
147
148 /*
149 * The way this works is that at some point in the future
150 * some task will call _switch to switch to the new task.
151 * That will pop off the stack frame created below and start
152 * the new task running at ret_from_fork. The new task will
153 * do some house keeping and then return from the fork or clone
154 * system call, using the stack frame created above.
155 */
156 /* redzone */
157 sp -= STACK_FRAME_OVERHEAD;
158 sp -= sizeof(struct pt_regs);
159 kregs = (struct pt_regs *)sp;
160
161 ti = task_thread_info(p);
162 ti->ksp = sp;
163
164 /* kregs->sp must store the location of the 'pre-switch' kernel stack
165 * pointer... for a newly forked process, this is simply the top of
166 * the kernel stack.
167 */
168 kregs->sp = top_of_kernel_stack;
169 kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */
170 kregs->gpr[10] = (unsigned long)task_thread_info(p);
171 kregs->gpr[9] = (unsigned long)ret_from_fork;
172
173 return 0;
174}
175
176/*
177 * Set up a thread for executing a new program
178 */
179void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
180{
181 unsigned long sr = regs->sr & ~SPR_SR_SM;
182
183 set_fs(USER_DS);
184 memset(regs->gpr, 0, sizeof(regs->gpr));
185
186 regs->pc = pc;
187 regs->sr = sr;
188 regs->sp = sp;
189
190/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/
191}
192
193/* Fill in the fpu structure for a core dump. */
194int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
195{
196 /* TODO */
197 return 0;
198}
199
200extern struct thread_info *_switch(struct thread_info *old_ti,
201 struct thread_info *new_ti);
202
203struct task_struct *__switch_to(struct task_struct *old,
204 struct task_struct *new)
205{
206 struct task_struct *last;
207 struct thread_info *new_ti, *old_ti;
208 unsigned long flags;
209
210 local_irq_save(flags);
211
212 /* current_set is an array of saved current pointers
213 * (one for each cpu). we need them at user->kernel transition,
214 * while we save them at kernel->user transition
215 */
216 new_ti = new->stack;
217 old_ti = old->stack;
218
219 current_thread_info_set[smp_processor_id()] = new_ti;
220 last = (_switch(old_ti, new_ti))->task;
221
222 local_irq_restore(flags);
223
224 return last;
225}
226
227/*
228 * Write out registers in core dump format, as defined by the
229 * struct user_regs_struct
230 */
231void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs)
232{
233 dest[0] = 0; /* r0 */
234 memcpy(dest+1, regs->gpr+1, 31*sizeof(unsigned long));
235 dest[32] = regs->pc;
236 dest[33] = regs->sr;
237 dest[34] = 0;
238 dest[35] = 0;
239}
240
241extern void _kernel_thread_helper(void);
242
243void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg)
244{
245 do_exit(fn(arg));
246}
247
248/*
249 * Create a kernel thread.
250 */
251int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
252{
253 struct pt_regs regs;
254
255 memset(&regs, 0, sizeof(regs));
256
257 regs.gpr[20] = (unsigned long)fn;
258 regs.gpr[22] = (unsigned long)arg;
259 regs.sr = mfspr(SPR_SR);
260 regs.pc = (unsigned long)_kernel_thread_helper;
261
262 return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
263 0, &regs, 0, NULL, NULL);
264}
265
266/*
267 * sys_execve() executes a new program.
268 */
269asmlinkage long _sys_execve(const char __user *name,
270 const char __user * const __user *argv,
271 const char __user * const __user *envp,
272 struct pt_regs *regs)
273{
274 int error;
275 char *filename;
276
277 filename = getname(name);
278 error = PTR_ERR(filename);
279
280 if (IS_ERR(filename))
281 goto out;
282
283 error = do_execve(filename, argv, envp, regs);
284 putname(filename);
285
286out:
287 return error;
288}
289
290unsigned long get_wchan(struct task_struct *p)
291{
292 /* TODO */
293
294 return 0;
295}
296
297int kernel_execve(const char *filename, char *const argv[], char *const envp[])
298{
299 register long __res asm("r11") = __NR_execve;
300 register long __a asm("r3") = (long)(filename);
301 register long __b asm("r4") = (long)(argv);
302 register long __c asm("r5") = (long)(envp);
303 __asm__ volatile ("l.sys 1"
304 : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c)
305 : "0"(__res), "1"(__a), "2"(__b), "3"(__c)
306 : "r6", "r7", "r8", "r12", "r13", "r15",
307 "r17", "r19", "r21", "r23", "r25", "r27",
308 "r29", "r31");
309 __asm__ volatile ("l.nop");
310 return __res;
311}
diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c
new file mode 100644
index 00000000000..1bb58ba89af
--- /dev/null
+++ b/arch/openrisc/kernel/prom.c
@@ -0,0 +1,108 @@
1/*
2 * OpenRISC prom.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 *
16 * Architecture specific procedures for creating, accessing and
17 * interpreting the device tree.
18 *
19 */
20
21#include <stdarg.h>
22#include <linux/kernel.h>
23#include <linux/string.h>
24#include <linux/init.h>
25#include <linux/threads.h>
26#include <linux/spinlock.h>
27#include <linux/types.h>
28#include <linux/pci.h>
29#include <linux/stringify.h>
30#include <linux/delay.h>
31#include <linux/initrd.h>
32#include <linux/bitops.h>
33#include <linux/module.h>
34#include <linux/kexec.h>
35#include <linux/debugfs.h>
36#include <linux/irq.h>
37#include <linux/memblock.h>
38#include <linux/of_fdt.h>
39
40#include <asm/prom.h>
41#include <asm/page.h>
42#include <asm/processor.h>
43#include <asm/irq.h>
44#include <linux/io.h>
45#include <asm/system.h>
46#include <asm/mmu.h>
47#include <asm/pgtable.h>
48#include <asm/sections.h>
49#include <asm/setup.h>
50
51extern char cmd_line[COMMAND_LINE_SIZE];
52
53void __init early_init_dt_add_memory_arch(u64 base, u64 size)
54{
55 size &= PAGE_MASK;
56 memblock_add(base, size);
57}
58
59void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
60{
61 return __va(memblock_alloc(size, align));
62}
63
64void __init early_init_devtree(void *params)
65{
66 void *alloc;
67
68 /* Setup flat device-tree pointer */
69 initial_boot_params = params;
70
71
72 /* Retrieve various informations from the /chosen node of the
73 * device-tree, including the platform type, initrd location and
74 * size, TCE reserve, and more ...
75 */
76 of_scan_flat_dt(early_init_dt_scan_chosen, cmd_line);
77
78 /* Scan memory nodes and rebuild MEMBLOCKs */
79 memblock_init();
80 of_scan_flat_dt(early_init_dt_scan_root, NULL);
81 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
82
83 /* Save command line for /proc/cmdline and then parse parameters */
84 strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
85
86 memblock_analyze();
87
88 /* We must copy the flattend device tree from init memory to regular
89 * memory because the device tree references the strings in it
90 * directly.
91 */
92
93 alloc = __va(memblock_alloc(initial_boot_params->totalsize, PAGE_SIZE));
94
95 memcpy(alloc, initial_boot_params, initial_boot_params->totalsize);
96
97 initial_boot_params = alloc;
98}
99
100#ifdef CONFIG_BLK_DEV_INITRD
101void __init early_init_dt_setup_initrd_arch(unsigned long start,
102 unsigned long end)
103{
104 initrd_start = (unsigned long)__va(start);
105 initrd_end = (unsigned long)__va(end);
106 initrd_below_start_ok = 1;
107}
108#endif
diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c
new file mode 100644
index 00000000000..656b94beab8
--- /dev/null
+++ b/arch/openrisc/kernel/ptrace.c
@@ -0,0 +1,211 @@
1/*
2 * OpenRISC ptrace.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com>
11 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 */
18
19#include <stddef.h>
20#include <linux/kernel.h>
21#include <linux/sched.h>
22#include <linux/string.h>
23
24#include <linux/mm.h>
25#include <linux/errno.h>
26#include <linux/ptrace.h>
27#include <linux/audit.h>
28#include <linux/regset.h>
29#include <linux/tracehook.h>
30#include <linux/elf.h>
31
32#include <asm/thread_info.h>
33#include <asm/segment.h>
34#include <asm/page.h>
35#include <asm/pgtable.h>
36#include <asm/system.h>
37
38/*
39 * Copy the thread state to a regset that can be interpreted by userspace.
40 *
41 * It doesn't matter what our internal pt_regs structure looks like. The
42 * important thing is that we export a consistent view of the thread state
43 * to userspace. As such, we need to make sure that the regset remains
44 * ABI compatible as defined by the struct user_regs_struct:
45 *
46 * (Each item is a 32-bit word)
47 * r0 = 0 (exported for clarity)
48 * 31 GPRS r1-r31
49 * PC (Program counter)
50 * SR (Supervision register)
51 */
52static int genregs_get(struct task_struct *target,
53 const struct user_regset *regset,
54 unsigned int pos, unsigned int count,
55 void *kbuf, void __user * ubuf)
56{
57 const struct pt_regs *regs = task_pt_regs(target);
58 int ret;
59
60 /* r0 */
61 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 0, 4);
62
63 if (!ret)
64 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
65 regs->gpr+1, 4, 4*32);
66 if (!ret)
67 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
68 &regs->pc, 4*32, 4*33);
69 if (!ret)
70 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
71 &regs->sr, 4*33, 4*34);
72 if (!ret)
73 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
74 4*34, -1);
75
76 return ret;
77}
78
79/*
80 * Set the thread state from a regset passed in via ptrace
81 */
82static int genregs_set(struct task_struct *target,
83 const struct user_regset *regset,
84 unsigned int pos, unsigned int count,
85 const void *kbuf, const void __user * ubuf)
86{
87 struct pt_regs *regs = task_pt_regs(target);
88 int ret;
89
90 /* ignore r0 */
91 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
92 /* r1 - r31 */
93 if (!ret)
94 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
95 regs->gpr+1, 4, 4*32);
96 /* PC */
97 if (!ret)
98 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
99 &regs->pc, 4*32, 4*33);
100 /*
101 * Skip SR and padding... userspace isn't allowed to changes bits in
102 * the Supervision register
103 */
104 if (!ret)
105 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
106 4*33, -1);
107
108 return ret;
109}
110
111/*
112 * Define the register sets available on OpenRISC under Linux
113 */
114enum or1k_regset {
115 REGSET_GENERAL,
116};
117
118static const struct user_regset or1k_regsets[] = {
119 [REGSET_GENERAL] = {
120 .core_note_type = NT_PRSTATUS,
121 .n = ELF_NGREG,
122 .size = sizeof(long),
123 .align = sizeof(long),
124 .get = genregs_get,
125 .set = genregs_set,
126 },
127};
128
129static const struct user_regset_view user_or1k_native_view = {
130 .name = "or1k",
131 .e_machine = EM_OPENRISC,
132 .regsets = or1k_regsets,
133 .n = ARRAY_SIZE(or1k_regsets),
134};
135
136const struct user_regset_view *task_user_regset_view(struct task_struct *task)
137{
138 return &user_or1k_native_view;
139}
140
141/*
142 * does not yet catch signals sent when the child dies.
143 * in exit.c or in signal.c.
144 */
145
146
147/*
148 * Called by kernel/ptrace.c when detaching..
149 *
150 * Make sure the single step bit is not set.
151 */
152void ptrace_disable(struct task_struct *child)
153{
154 pr_debug("ptrace_disable(): TODO\n");
155
156 user_disable_single_step(child);
157 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
158}
159
160long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
161 unsigned long data)
162{
163 int ret;
164
165 switch (request) {
166 default:
167 ret = ptrace_request(child, request, addr, data);
168 break;
169 }
170
171 return ret;
172}
173
174/*
175 * Notification of system call entry/exit
176 * - triggered by current->work.syscall_trace
177 */
178asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
179{
180 long ret = 0;
181
182 if (test_thread_flag(TIF_SYSCALL_TRACE) &&
183 tracehook_report_syscall_entry(regs))
184 /*
185 * Tracing decided this syscall should not happen.
186 * We'll return a bogus call number to get an ENOSYS
187 * error, but leave the original number in <something>.
188 */
189 ret = -1L;
190
191 /* Are these regs right??? */
192 if (unlikely(current->audit_context))
193 audit_syscall_entry(audit_arch(), regs->syscallno,
194 regs->gpr[3], regs->gpr[4],
195 regs->gpr[5], regs->gpr[6]);
196
197 return ret ? : regs->syscallno;
198}
199
200asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
201{
202 int step;
203
204 if (unlikely(current->audit_context))
205 audit_syscall_exit(AUDITSC_RESULT(regs->gpr[11]),
206 regs->gpr[11]);
207
208 step = test_thread_flag(TIF_SINGLESTEP);
209 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
210 tracehook_report_syscall_exit(regs, step);
211}
diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
new file mode 100644
index 00000000000..1422f747f52
--- /dev/null
+++ b/arch/openrisc/kernel/setup.c
@@ -0,0 +1,381 @@
1/*
2 * OpenRISC setup.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * This file handles the architecture-dependent parts of initialization
18 */
19
20#include <linux/errno.h>
21#include <linux/sched.h>
22#include <linux/kernel.h>
23#include <linux/mm.h>
24#include <linux/stddef.h>
25#include <linux/unistd.h>
26#include <linux/ptrace.h>
27#include <linux/slab.h>
28#include <linux/tty.h>
29#include <linux/ioport.h>
30#include <linux/delay.h>
31#include <linux/console.h>
32#include <linux/init.h>
33#include <linux/bootmem.h>
34#include <linux/seq_file.h>
35#include <linux/serial.h>
36#include <linux/initrd.h>
37#include <linux/of_fdt.h>
38#include <linux/of.h>
39#include <linux/memblock.h>
40#include <linux/device.h>
41#include <linux/of_platform.h>
42
43#include <asm/segment.h>
44#include <asm/system.h>
45#include <asm/pgtable.h>
46#include <asm/types.h>
47#include <asm/setup.h>
48#include <asm/io.h>
49#include <asm/cpuinfo.h>
50#include <asm/delay.h>
51
52#include "vmlinux.h"
53
54char __initdata cmd_line[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
55
56static unsigned long __init setup_memory(void)
57{
58 unsigned long bootmap_size;
59 unsigned long ram_start_pfn;
60 unsigned long free_ram_start_pfn;
61 unsigned long ram_end_pfn;
62 phys_addr_t memory_start, memory_end;
63 struct memblock_region *region;
64
65 memory_end = memory_start = 0;
66
67 /* Find main memory where is the kernel */
68 for_each_memblock(memory, region) {
69 memory_start = region->base;
70 memory_end = region->base + region->size;
71 printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
72 memory_start, memory_end);
73 }
74
75 if (!memory_end) {
76 panic("No memory!");
77 }
78
79 ram_start_pfn = PFN_UP(memory_start);
80 /* free_ram_start_pfn is first page after kernel */
81 free_ram_start_pfn = PFN_UP(__pa(&_end));
82 ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
83
84 max_pfn = ram_end_pfn;
85
86 /*
87 * initialize the boot-time allocator (with low memory only).
88 *
89 * This makes the memory from the end of the kernel to the end of
90 * RAM usable.
91 * init_bootmem sets the global values min_low_pfn, max_low_pfn.
92 */
93 bootmap_size = init_bootmem(free_ram_start_pfn,
94 ram_end_pfn - ram_start_pfn);
95 free_bootmem(PFN_PHYS(free_ram_start_pfn),
96 (ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
97 reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
98 BOOTMEM_DEFAULT);
99
100 for_each_memblock(reserved, region) {
101 printk(KERN_INFO "Reserved - 0x%08x-0x%08x\n",
102 (u32) region->base, (u32) region->size);
103 reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
104 }
105
106 return ram_end_pfn;
107}
108
109struct cpuinfo cpuinfo;
110
111static void print_cpuinfo(void)
112{
113 unsigned long upr = mfspr(SPR_UPR);
114 unsigned long vr = mfspr(SPR_VR);
115 unsigned int version;
116 unsigned int revision;
117
118 version = (vr & SPR_VR_VER) >> 24;
119 revision = (vr & SPR_VR_REV);
120
121 printk(KERN_INFO "CPU: OpenRISC-%x (revision %d) @%d MHz\n",
122 version, revision, cpuinfo.clock_frequency / 1000000);
123
124 if (!(upr & SPR_UPR_UP)) {
125 printk(KERN_INFO
126 "-- no UPR register... unable to detect configuration\n");
127 return;
128 }
129
130 if (upr & SPR_UPR_DCP)
131 printk(KERN_INFO
132 "-- dcache: %4d bytes total, %2d bytes/line, %d way(s)\n",
133 cpuinfo.dcache_size, cpuinfo.dcache_block_size, 1);
134 else
135 printk(KERN_INFO "-- dcache disabled\n");
136 if (upr & SPR_UPR_ICP)
137 printk(KERN_INFO
138 "-- icache: %4d bytes total, %2d bytes/line, %d way(s)\n",
139 cpuinfo.icache_size, cpuinfo.icache_block_size, 1);
140 else
141 printk(KERN_INFO "-- icache disabled\n");
142
143 if (upr & SPR_UPR_DMP)
144 printk(KERN_INFO "-- dmmu: %4d entries, %lu way(s)\n",
145 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2),
146 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW));
147 if (upr & SPR_UPR_IMP)
148 printk(KERN_INFO "-- immu: %4d entries, %lu way(s)\n",
149 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2),
150 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW));
151
152 printk(KERN_INFO "-- additional features:\n");
153 if (upr & SPR_UPR_DUP)
154 printk(KERN_INFO "-- debug unit\n");
155 if (upr & SPR_UPR_PCUP)
156 printk(KERN_INFO "-- performance counters\n");
157 if (upr & SPR_UPR_PMP)
158 printk(KERN_INFO "-- power management\n");
159 if (upr & SPR_UPR_PICP)
160 printk(KERN_INFO "-- PIC\n");
161 if (upr & SPR_UPR_TTP)
162 printk(KERN_INFO "-- timer\n");
163 if (upr & SPR_UPR_CUP)
164 printk(KERN_INFO "-- custom unit(s)\n");
165}
166
167void __init setup_cpuinfo(void)
168{
169 struct device_node *cpu;
170 unsigned long iccfgr, dccfgr;
171 unsigned long cache_set_size, cache_ways;
172
173 cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481");
174 if (!cpu)
175 panic("No compatible CPU found in device tree...\n");
176
177 iccfgr = mfspr(SPR_ICCFGR);
178 cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
179 cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
180 cpuinfo.icache_block_size = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> 7);
181 cpuinfo.icache_size =
182 cache_set_size * cache_ways * cpuinfo.icache_block_size;
183
184 dccfgr = mfspr(SPR_DCCFGR);
185 cache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
186 cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
187 cpuinfo.dcache_block_size = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> 7);
188 cpuinfo.dcache_size =
189 cache_set_size * cache_ways * cpuinfo.dcache_block_size;
190
191 if (of_property_read_u32(cpu, "clock-frequency",
192 &cpuinfo.clock_frequency)) {
193 printk(KERN_WARNING
194 "Device tree missing CPU 'clock-frequency' parameter."
195 "Assuming frequency 25MHZ"
196 "This is probably not what you want.");
197 }
198
199 of_node_put(cpu);
200
201 print_cpuinfo();
202}
203
204/**
205 * or32_early_setup
206 *
207 * Handles the pointer to the device tree that this kernel is to use
208 * for establishing the available platform devices.
209 *
210 * For now, this is limited to using the built-in device tree. In the future,
211 * it is intended that this function will take a pointer to the device tree
212 * that is potentially built-in, but potentially also passed in by the
213 * bootloader, or discovered by some equally clever means...
214 */
215
216void __init or32_early_setup(void)
217{
218
219 early_init_devtree(__dtb_start);
220
221 printk(KERN_INFO "Compiled-in FDT at 0x%p\n", __dtb_start);
222}
223
224static int __init openrisc_device_probe(void)
225{
226 of_platform_populate(NULL, NULL, NULL, NULL);
227
228 return 0;
229}
230
231device_initcall(openrisc_device_probe);
232
233static inline unsigned long extract_value_bits(unsigned long reg,
234 short bit_nr, short width)
235{
236 return (reg >> bit_nr) & (0 << width);
237}
238
239static inline unsigned long extract_value(unsigned long reg, unsigned long mask)
240{
241 while (!(mask & 0x1)) {
242 reg = reg >> 1;
243 mask = mask >> 1;
244 }
245 return mask & reg;
246}
247
248void __init detect_unit_config(unsigned long upr, unsigned long mask,
249 char *text, void (*func) (void))
250{
251 if (text != NULL)
252 printk("%s", text);
253
254 if (upr & mask) {
255 if (func != NULL)
256 func();
257 else
258 printk("present\n");
259 } else
260 printk("not present\n");
261}
262
263/*
264 * calibrate_delay
265 *
266 * Lightweight calibrate_delay implementation that calculates loops_per_jiffy
267 * from the clock frequency passed in via the device tree
268 *
269 */
270
271void __cpuinit calibrate_delay(void)
272{
273 const int *val;
274 struct device_node *cpu = NULL;
275 cpu = of_find_compatible_node(NULL, NULL, "opencores,or1200-rtlsvn481");
276 val = of_get_property(cpu, "clock-frequency", NULL);
277 if (!val)
278 panic("no cpu 'clock-frequency' parameter in device tree");
279 loops_per_jiffy = *val / HZ;
280 pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
281 loops_per_jiffy / (500000 / HZ),
282 (loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
283}
284
285void __init setup_arch(char **cmdline_p)
286{
287 unsigned long max_low_pfn;
288
289 unflatten_device_tree();
290
291 setup_cpuinfo();
292
293 /* process 1's initial memory region is the kernel code/data */
294 init_mm.start_code = (unsigned long)&_stext;
295 init_mm.end_code = (unsigned long)&_etext;
296 init_mm.end_data = (unsigned long)&_edata;
297 init_mm.brk = (unsigned long)&_end;
298
299#ifdef CONFIG_BLK_DEV_INITRD
300 initrd_start = (unsigned long)&__initrd_start;
301 initrd_end = (unsigned long)&__initrd_end;
302 if (initrd_start == initrd_end) {
303 initrd_start = 0;
304 initrd_end = 0;
305 }
306 initrd_below_start_ok = 1;
307#endif
308
309 /* setup bootmem allocator */
310 max_low_pfn = setup_memory();
311
312 /* paging_init() sets up the MMU and marks all pages as reserved */
313 paging_init();
314
315#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
316 if (!conswitchp)
317 conswitchp = &dummy_con;
318#endif
319
320 *cmdline_p = cmd_line;
321
322 printk(KERN_INFO "OpenRISC Linux -- http://openrisc.net\n");
323}
324
325static int show_cpuinfo(struct seq_file *m, void *v)
326{
327 unsigned long vr;
328 int version, revision;
329
330 vr = mfspr(SPR_VR);
331 version = (vr & SPR_VR_VER) >> 24;
332 revision = vr & SPR_VR_REV;
333
334 return seq_printf(m,
335 "cpu\t\t: OpenRISC-%x\n"
336 "revision\t: %d\n"
337 "frequency\t: %ld\n"
338 "dcache size\t: %d bytes\n"
339 "dcache block size\t: %d bytes\n"
340 "icache size\t: %d bytes\n"
341 "icache block size\t: %d bytes\n"
342 "immu\t\t: %d entries, %lu ways\n"
343 "dmmu\t\t: %d entries, %lu ways\n"
344 "bogomips\t: %lu.%02lu\n",
345 version,
346 revision,
347 loops_per_jiffy * HZ,
348 cpuinfo.dcache_size,
349 cpuinfo.dcache_block_size,
350 cpuinfo.icache_size,
351 cpuinfo.icache_block_size,
352 1 << ((mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTS) >> 2),
353 1 + (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_NTW),
354 1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> 2),
355 1 + (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTW),
356 (loops_per_jiffy * HZ) / 500000,
357 ((loops_per_jiffy * HZ) / 5000) % 100);
358}
359
360static void *c_start(struct seq_file *m, loff_t * pos)
361{
362 /* We only have one CPU... */
363 return *pos < 1 ? (void *)1 : NULL;
364}
365
366static void *c_next(struct seq_file *m, void *v, loff_t * pos)
367{
368 ++*pos;
369 return NULL;
370}
371
372static void c_stop(struct seq_file *m, void *v)
373{
374}
375
376const struct seq_operations cpuinfo_op = {
377 .start = c_start,
378 .next = c_next,
379 .stop = c_stop,
380 .show = show_cpuinfo,
381};
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
new file mode 100644
index 00000000000..95207ab0c99
--- /dev/null
+++ b/arch/openrisc/kernel/signal.c
@@ -0,0 +1,389 @@
1/*
2 * OpenRISC signal.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/sched.h>
19#include <linux/mm.h>
20#include <linux/smp.h>
21#include <linux/kernel.h>
22#include <linux/signal.h>
23#include <linux/errno.h>
24#include <linux/wait.h>
25#include <linux/ptrace.h>
26#include <linux/unistd.h>
27#include <linux/stddef.h>
28#include <linux/tracehook.h>
29
30#include <asm/processor.h>
31#include <asm/ucontext.h>
32#include <asm/uaccess.h>
33
34#define DEBUG_SIG 0
35
36#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
37
38asmlinkage long
39_sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
40{
41 return do_sigaltstack(uss, uoss, regs->sp);
42}
43
44struct rt_sigframe {
45 struct siginfo *pinfo;
46 void *puc;
47 struct siginfo info;
48 struct ucontext uc;
49 unsigned char retcode[16]; /* trampoline code */
50};
51
52static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
53{
54 unsigned int err = 0;
55
56 /* Alwys make any pending restarted system call return -EINTR */
57 current_thread_info()->restart_block.fn = do_no_restart_syscall;
58
59 /*
60 * Restore the regs from &sc->regs.
61 * (sc is already checked for VERIFY_READ since the sigframe was
62 * checked in sys_sigreturn previously)
63 */
64 if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)))
65 goto badframe;
66 if (__copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long)))
67 goto badframe;
68 if (__copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)))
69 goto badframe;
70
71 /* make sure the SM-bit is cleared so user-mode cannot fool us */
72 regs->sr &= ~SPR_SR_SM;
73
74 /* TODO: the other ports use regs->orig_XX to disable syscall checks
75 * after this completes, but we don't use that mechanism. maybe we can
76 * use it now ?
77 */
78
79 return err;
80
81badframe:
82 return 1;
83}
84
85asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
86{
87 struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp;
88 sigset_t set;
89 stack_t st;
90
91 /*
92 * Since we stacked the signal on a dword boundary,
93 * then frame should be dword aligned here. If it's
94 * not, then the user is trying to mess with us.
95 */
96 if (((long)frame) & 3)
97 goto badframe;
98
99 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
100 goto badframe;
101 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
102 goto badframe;
103
104 sigdelsetmask(&set, ~_BLOCKABLE);
105 spin_lock_irq(&current->sighand->siglock);
106 current->blocked = set;
107 recalc_sigpending();
108 spin_unlock_irq(&current->sighand->siglock);
109
110 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
111 goto badframe;
112
113 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
114 goto badframe;
115 /* It is more difficult to avoid calling this function than to
116 call it and ignore errors. */
117 do_sigaltstack(&st, NULL, regs->sp);
118
119 return regs->gpr[11];
120
121badframe:
122 force_sig(SIGSEGV, current);
123 return 0;
124}
125
126/*
127 * Set up a signal frame.
128 */
129
130static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
131 unsigned long mask)
132{
133 int err = 0;
134
135 /* copy the regs */
136
137 err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
138 err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
139 err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
140
141 /* then some other stuff */
142
143 err |= __put_user(mask, &sc->oldmask);
144
145 return err;
146}
147
148static inline unsigned long align_sigframe(unsigned long sp)
149{
150 return sp & ~3UL;
151}
152
153/*
154 * Work out where the signal frame should go. It's either on the user stack
155 * or the alternate stack.
156 */
157
158static inline void __user *get_sigframe(struct k_sigaction *ka,
159 struct pt_regs *regs, size_t frame_size)
160{
161 unsigned long sp = regs->sp;
162 int onsigstack = on_sig_stack(sp);
163
164 /* redzone */
165 sp -= STACK_FRAME_OVERHEAD;
166
167 /* This is the X/Open sanctioned signal stack switching. */
168 if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
169 if (current->sas_ss_size)
170 sp = current->sas_ss_sp + current->sas_ss_size;
171 }
172
173 sp = align_sigframe(sp - frame_size);
174
175 /*
176 * If we are on the alternate signal stack and would overflow it, don't.
177 * Return an always-bogus address instead so we will die with SIGSEGV.
178 */
179 if (onsigstack && !likely(on_sig_stack(sp)))
180 return (void __user *)-1L;
181
182 return (void __user *)sp;
183}
184
185/* grab and setup a signal frame.
186 *
187 * basically we stack a lot of state info, and arrange for the
188 * user-mode program to return to the kernel using either a
189 * trampoline which performs the syscall sigreturn, or a provided
190 * user-mode trampoline.
191 */
192static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
193 sigset_t *set, struct pt_regs *regs)
194{
195 struct rt_sigframe *frame;
196 unsigned long return_ip;
197 int err = 0;
198
199 frame = get_sigframe(ka, regs, sizeof(*frame));
200
201 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
202 goto give_sigsegv;
203
204 err |= __put_user(&frame->info, &frame->pinfo);
205 err |= __put_user(&frame->uc, &frame->puc);
206
207 if (ka->sa.sa_flags & SA_SIGINFO)
208 err |= copy_siginfo_to_user(&frame->info, info);
209 if (err)
210 goto give_sigsegv;
211
212 /* Clear all the bits of the ucontext we don't use. */
213 err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
214 err |= __put_user(0, &frame->uc.uc_flags);
215 err |= __put_user(NULL, &frame->uc.uc_link);
216 err |= __put_user((void *)current->sas_ss_sp,
217 &frame->uc.uc_stack.ss_sp);
218 err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags);
219 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
220 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
221
222 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
223
224 if (err)
225 goto give_sigsegv;
226
227 /* trampoline - the desired return ip is the retcode itself */
228 return_ip = (unsigned long)&frame->retcode;
229 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
230 err |= __put_user(0xa960, (short *)(frame->retcode + 0));
231 err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
232 err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
233 err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
234
235 if (err)
236 goto give_sigsegv;
237
238 /* TODO what is the current->exec_domain stuff and invmap ? */
239
240 /* Set up registers for signal handler */
241 regs->pc = (unsigned long)ka->sa.sa_handler; /* what we enter NOW */
242 regs->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
243 regs->gpr[3] = (unsigned long)sig; /* arg 1: signo */
244 regs->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
245 regs->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
246
247 /* actually move the usp to reflect the stacked frame */
248 regs->sp = (unsigned long)frame;
249
250 return;
251
252give_sigsegv:
253 if (sig == SIGSEGV)
254 ka->sa.sa_handler = SIG_DFL;
255 force_sig(SIGSEGV, current);
256}
257
258static inline void
259handle_signal(unsigned long sig,
260 siginfo_t *info, struct k_sigaction *ka,
261 sigset_t *oldset, struct pt_regs *regs)
262{
263 setup_rt_frame(sig, ka, info, oldset, regs);
264
265 if (ka->sa.sa_flags & SA_ONESHOT)
266 ka->sa.sa_handler = SIG_DFL;
267
268 spin_lock_irq(&current->sighand->siglock);
269 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
270 if (!(ka->sa.sa_flags & SA_NODEFER))
271 sigaddset(&current->blocked, sig);
272 recalc_sigpending();
273
274 spin_unlock_irq(&current->sighand->siglock);
275}
276
277/*
278 * Note that 'init' is a special process: it doesn't get signals it doesn't
279 * want to handle. Thus you cannot kill init even with a SIGKILL even by
280 * mistake.
281 *
282 * Also note that the regs structure given here as an argument, is the latest
283 * pushed pt_regs. It may or may not be the same as the first pushed registers
284 * when the initial usermode->kernelmode transition took place. Therefore
285 * we can use user_mode(regs) to see if we came directly from kernel or user
286 * mode below.
287 */
288
289void do_signal(struct pt_regs *regs)
290{
291 siginfo_t info;
292 int signr;
293 struct k_sigaction ka;
294
295 /*
296 * We want the common case to go fast, which
297 * is why we may in certain cases get here from
298 * kernel mode. Just return without doing anything
299 * if so.
300 */
301 if (!user_mode(regs))
302 return;
303
304 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
305
306 /* If we are coming out of a syscall then we need
307 * to check if the syscall was interrupted and wants to be
308 * restarted after handling the signal. If so, the original
309 * syscall number is put back into r11 and the PC rewound to
310 * point at the l.sys instruction that resulted in the
311 * original syscall. Syscall results other than the four
312 * below mean that the syscall executed to completion and no
313 * restart is necessary.
314 */
315 if (regs->syscallno) {
316 int restart = 0;
317
318 switch (regs->gpr[11]) {
319 case -ERESTART_RESTARTBLOCK:
320 case -ERESTARTNOHAND:
321 /* Restart if there is no signal handler */
322 restart = (signr <= 0);
323 break;
324 case -ERESTARTSYS:
325 /* Restart if there no signal handler or
326 * SA_RESTART flag is set */
327 restart = (signr <= 0 || (ka.sa.sa_flags & SA_RESTART));
328 break;
329 case -ERESTARTNOINTR:
330 /* Always restart */
331 restart = 1;
332 break;
333 }
334
335 if (restart) {
336 if (regs->gpr[11] == -ERESTART_RESTARTBLOCK)
337 regs->gpr[11] = __NR_restart_syscall;
338 else
339 regs->gpr[11] = regs->orig_gpr11;
340 regs->pc -= 4;
341 } else {
342 regs->gpr[11] = -EINTR;
343 }
344 }
345
346 if (signr <= 0) {
347 /* no signal to deliver so we just put the saved sigmask
348 * back */
349 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
350 clear_thread_flag(TIF_RESTORE_SIGMASK);
351 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
352 }
353
354 } else { /* signr > 0 */
355 sigset_t *oldset;
356
357 if (current_thread_info()->flags & _TIF_RESTORE_SIGMASK)
358 oldset = &current->saved_sigmask;
359 else
360 oldset = &current->blocked;
361
362 /* Whee! Actually deliver the signal. */
363 handle_signal(signr, &info, &ka, oldset, regs);
364 /* a signal was successfully delivered; the saved
365 * sigmask will have been stored in the signal frame,
366 * and will be restored by sigreturn, so we can simply
367 * clear the TIF_RESTORE_SIGMASK flag */
368 if (test_thread_flag(TIF_RESTORE_SIGMASK))
369 clear_thread_flag(TIF_RESTORE_SIGMASK);
370
371 tracehook_signal_handler(signr, &info, &ka, regs,
372 test_thread_flag(TIF_SINGLESTEP));
373 }
374
375 return;
376}
377
378asmlinkage void do_notify_resume(struct pt_regs *regs)
379{
380 if (current_thread_info()->flags & _TIF_SIGPENDING)
381 do_signal(regs);
382
383 if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) {
384 clear_thread_flag(TIF_NOTIFY_RESUME);
385 tracehook_notify_resume(regs);
386 if (current->replacement_session_keyring)
387 key_replace_session_keyring();
388 }
389}
diff --git a/arch/openrisc/kernel/sys_call_table.c b/arch/openrisc/kernel/sys_call_table.c
new file mode 100644
index 00000000000..e1f8ce8c72a
--- /dev/null
+++ b/arch/openrisc/kernel/sys_call_table.c
@@ -0,0 +1,28 @@
1/*
2 * OpenRISC sys_call_table.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#include <linux/syscalls.h>
18#include <linux/signal.h>
19#include <linux/unistd.h>
20
21#include <asm/syscalls.h>
22
23#undef __SYSCALL
24#define __SYSCALL(nr, call) [nr] = (call),
25
26void *sys_call_table[__NR_syscalls] = {
27#include <asm/unistd.h>
28};
diff --git a/arch/openrisc/kernel/sys_or32.c b/arch/openrisc/kernel/sys_or32.c
new file mode 100644
index 00000000000..57060084c0c
--- /dev/null
+++ b/arch/openrisc/kernel/sys_or32.c
@@ -0,0 +1,57 @@
1/*
2 * OpenRISC sys_or32.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * This file contains various random system calls that
18 * have a non-standard calling sequence on some platforms.
19 * Since we don't have to do any backwards compatibility, our
20 * versions are done in the most "normal" way possible.
21 */
22
23#include <linux/errno.h>
24#include <linux/syscalls.h>
25#include <linux/mm.h>
26
27#include <asm/syscalls.h>
28
29/* These are secondary entry points as the primary entry points are defined in
30 * entry.S where we add the 'regs' parameter value
31 */
32
33asmlinkage long _sys_clone(unsigned long clone_flags, unsigned long newsp,
34 int __user *parent_tid, int __user *child_tid,
35 struct pt_regs *regs)
36{
37 long ret;
38
39 /* FIXME: Is alignment necessary? */
40 /* newsp = ALIGN(newsp, 4); */
41
42 if (!newsp)
43 newsp = regs->sp;
44
45 ret = do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
46
47 return ret;
48}
49
50asmlinkage int _sys_fork(struct pt_regs *regs)
51{
52#ifdef CONFIG_MMU
53 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
54#else
55 return -EINVAL;
56#endif
57}
diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c
new file mode 100644
index 00000000000..bd946ef1623
--- /dev/null
+++ b/arch/openrisc/kernel/time.c
@@ -0,0 +1,181 @@
1/*
2 * OpenRISC time.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#include <linux/kernel.h>
18#include <linux/time.h>
19#include <linux/timex.h>
20#include <linux/interrupt.h>
21#include <linux/ftrace.h>
22
23#include <linux/clocksource.h>
24#include <linux/clockchips.h>
25#include <linux/irq.h>
26#include <linux/io.h>
27
28#include <asm/cpuinfo.h>
29
30static int openrisc_timer_set_next_event(unsigned long delta,
31 struct clock_event_device *dev)
32{
33 u32 c;
34
35 /* Read 32-bit counter value, add delta, mask off the low 28 bits.
36 * We're guaranteed delta won't be bigger than 28 bits because the
37 * generic timekeeping code ensures that for us.
38 */
39 c = mfspr(SPR_TTCR);
40 c += delta;
41 c &= SPR_TTMR_TP;
42
43 /* Set counter and enable interrupt.
44 * Keep timer in continuous mode always.
45 */
46 mtspr(SPR_TTMR, SPR_TTMR_CR | SPR_TTMR_IE | c);
47
48 return 0;
49}
50
51static void openrisc_timer_set_mode(enum clock_event_mode mode,
52 struct clock_event_device *evt)
53{
54 switch (mode) {
55 case CLOCK_EVT_MODE_PERIODIC:
56 pr_debug(KERN_INFO "%s: periodic\n", __func__);
57 BUG();
58 break;
59 case CLOCK_EVT_MODE_ONESHOT:
60 pr_debug(KERN_INFO "%s: oneshot\n", __func__);
61 break;
62 case CLOCK_EVT_MODE_UNUSED:
63 pr_debug(KERN_INFO "%s: unused\n", __func__);
64 break;
65 case CLOCK_EVT_MODE_SHUTDOWN:
66 pr_debug(KERN_INFO "%s: shutdown\n", __func__);
67 break;
68 case CLOCK_EVT_MODE_RESUME:
69 pr_debug(KERN_INFO "%s: resume\n", __func__);
70 break;
71 }
72}
73
74/* This is the clock event device based on the OR1K tick timer.
75 * As the timer is being used as a continuous clock-source (required for HR
76 * timers) we cannot enable the PERIODIC feature. The tick timer can run using
77 * one-shot events, so no problem.
78 */
79
80static struct clock_event_device clockevent_openrisc_timer = {
81 .name = "openrisc_timer_clockevent",
82 .features = CLOCK_EVT_FEAT_ONESHOT,
83 .rating = 300,
84 .set_next_event = openrisc_timer_set_next_event,
85 .set_mode = openrisc_timer_set_mode,
86};
87
88static inline void timer_ack(void)
89{
90 /* Clear the IP bit and disable further interrupts */
91 /* This can be done very simply... we just need to keep the timer
92 running, so just maintain the CR bits while clearing the rest
93 of the register
94 */
95 mtspr(SPR_TTMR, SPR_TTMR_CR);
96}
97
98/*
99 * The timer interrupt is mostly handled in generic code nowadays... this
100 * function just acknowledges the interrupt and fires the event handler that
101 * has been set on the clockevent device by the generic time management code.
102 *
103 * This function needs to be called by the timer exception handler and that's
104 * all the exception handler needs to do.
105 */
106
107irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs)
108{
109 struct pt_regs *old_regs = set_irq_regs(regs);
110 struct clock_event_device *evt = &clockevent_openrisc_timer;
111
112 timer_ack();
113
114 /*
115 * update_process_times() expects us to have called irq_enter().
116 */
117 irq_enter();
118 evt->event_handler(evt);
119 irq_exit();
120
121 set_irq_regs(old_regs);
122
123 return IRQ_HANDLED;
124}
125
126static __init void openrisc_clockevent_init(void)
127{
128 clockevents_calc_mult_shift(&clockevent_openrisc_timer,
129 cpuinfo.clock_frequency, 4);
130
131 /* We only have 28 bits */
132 clockevent_openrisc_timer.max_delta_ns =
133 clockevent_delta2ns((u32) 0x0fffffff, &clockevent_openrisc_timer);
134 clockevent_openrisc_timer.min_delta_ns =
135 clockevent_delta2ns(1, &clockevent_openrisc_timer);
136 clockevent_openrisc_timer.cpumask = cpumask_of(0);
137 clockevents_register_device(&clockevent_openrisc_timer);
138}
139
140/**
141 * Clocksource: Based on OpenRISC timer/counter
142 *
143 * This sets up the OpenRISC Tick Timer as a clock source. The tick timer
144 * is 32 bits wide and runs at the CPU clock frequency.
145 */
146
147static cycle_t openrisc_timer_read(struct clocksource *cs)
148{
149 return (cycle_t) mfspr(SPR_TTCR);
150}
151
152static struct clocksource openrisc_timer = {
153 .name = "openrisc_timer",
154 .rating = 200,
155 .read = openrisc_timer_read,
156 .mask = CLOCKSOURCE_MASK(32),
157 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
158};
159
160static int __init openrisc_timer_init(void)
161{
162 if (clocksource_register_hz(&openrisc_timer, cpuinfo.clock_frequency))
163 panic("failed to register clocksource");
164
165 /* Enable the incrementer: 'continuous' mode with interrupt disabled */
166 mtspr(SPR_TTMR, SPR_TTMR_CR);
167
168 return 0;
169}
170
171void __init time_init(void)
172{
173 u32 upr;
174
175 upr = mfspr(SPR_UPR);
176 if (!(upr & SPR_UPR_TTP))
177 panic("Linux not supported on devices without tick timer");
178
179 openrisc_timer_init();
180 openrisc_clockevent_init();
181}
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
new file mode 100644
index 00000000000..a4ec44a052b
--- /dev/null
+++ b/arch/openrisc/kernel/traps.c
@@ -0,0 +1,366 @@
1/*
2 * OpenRISC traps.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * Here we handle the break vectors not used by the system call
18 * mechanism, as well as some general stack/register dumping
19 * things.
20 *
21 */
22
23#include <linux/init.h>
24#include <linux/sched.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/kmod.h>
28#include <linux/string.h>
29#include <linux/errno.h>
30#include <linux/ptrace.h>
31#include <linux/timer.h>
32#include <linux/mm.h>
33#include <linux/kallsyms.h>
34#include <asm/uaccess.h>
35
36#include <asm/system.h>
37#include <asm/segment.h>
38#include <asm/io.h>
39#include <asm/pgtable.h>
40
41extern char _etext, _stext;
42
43int kstack_depth_to_print = 0x180;
44
45static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
46{
47 return p > (void *)tinfo && p < (void *)tinfo + THREAD_SIZE - 3;
48}
49
50void show_trace(struct task_struct *task, unsigned long *stack)
51{
52 struct thread_info *context;
53 unsigned long addr;
54
55 context = (struct thread_info *)
56 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
57
58 while (valid_stack_ptr(context, stack)) {
59 addr = *stack++;
60 if (__kernel_text_address(addr)) {
61 printk(" [<%08lx>]", addr);
62 print_symbol(" %s", addr);
63 printk("\n");
64 }
65 }
66 printk(" =======================\n");
67}
68
69/* displays a short stack trace */
70void show_stack(struct task_struct *task, unsigned long *esp)
71{
72 unsigned long addr, *stack;
73 int i;
74
75 if (esp == NULL)
76 esp = (unsigned long *)&esp;
77
78 stack = esp;
79
80 printk("Stack dump [0x%08lx]:\n", (unsigned long)esp);
81 for (i = 0; i < kstack_depth_to_print; i++) {
82 if (kstack_end(stack))
83 break;
84 if (__get_user(addr, stack)) {
85 /* This message matches "failing address" marked
86 s390 in ksymoops, so lines containing it will
87 not be filtered out by ksymoops. */
88 printk("Failing address 0x%lx\n", (unsigned long)stack);
89 break;
90 }
91 stack++;
92
93 printk("sp + %02d: 0x%08lx\n", i * 4, addr);
94 }
95 printk("\n");
96
97 show_trace(task, esp);
98
99 return;
100}
101
102void show_trace_task(struct task_struct *tsk)
103{
104 /*
105 * TODO: SysRq-T trace dump...
106 */
107}
108
109/*
110 * The architecture-independent backtrace generator
111 */
112void dump_stack(void)
113{
114 unsigned long stack;
115
116 show_stack(current, &stack);
117}
118
119void show_registers(struct pt_regs *regs)
120{
121 int i;
122 int in_kernel = 1;
123 unsigned long esp;
124
125 esp = (unsigned long)(&regs->sp);
126 if (user_mode(regs))
127 in_kernel = 0;
128
129 printk("CPU #: %d\n"
130 " PC: %08lx SR: %08lx SP: %08lx\n",
131 smp_processor_id(), regs->pc, regs->sr, regs->sp);
132 printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
133 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
134 printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
135 regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
136 printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
137 regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
138 printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
139 regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
140 printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
141 regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
142 printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
143 regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
144 printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
145 regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
146 printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
147 regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
148 printk(" RES: %08lx oGPR11: %08lx syscallno: %08lx\n",
149 regs->gpr[11], regs->orig_gpr11, regs->syscallno);
150
151 printk("Process %s (pid: %d, stackpage=%08lx)\n",
152 current->comm, current->pid, (unsigned long)current);
153 /*
154 * When in-kernel, we also print out the stack and code at the
155 * time of the fault..
156 */
157 if (in_kernel) {
158
159 printk("\nStack: ");
160 show_stack(NULL, (unsigned long *)esp);
161
162 printk("\nCode: ");
163 if (regs->pc < PAGE_OFFSET)
164 goto bad;
165
166 for (i = -24; i < 24; i++) {
167 unsigned char c;
168 if (__get_user(c, &((unsigned char *)regs->pc)[i])) {
169bad:
170 printk(" Bad PC value.");
171 break;
172 }
173
174 if (i == 0)
175 printk("(%02x) ", c);
176 else
177 printk("%02x ", c);
178 }
179 }
180 printk("\n");
181}
182
183void nommu_dump_state(struct pt_regs *regs,
184 unsigned long ea, unsigned long vector)
185{
186 int i;
187 unsigned long addr, stack = regs->sp;
188
189 printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector);
190
191 printk("CPU #: %d\n"
192 " PC: %08lx SR: %08lx SP: %08lx\n",
193 0, regs->pc, regs->sr, regs->sp);
194 printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
195 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
196 printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
197 regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
198 printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
199 regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
200 printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
201 regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
202 printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
203 regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
204 printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
205 regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
206 printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
207 regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
208 printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
209 regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
210 printk(" RES: %08lx oGPR11: %08lx syscallno: %08lx\n",
211 regs->gpr[11], regs->orig_gpr11, regs->syscallno);
212
213 printk("Process %s (pid: %d, stackpage=%08lx)\n",
214 ((struct task_struct *)(__pa(current)))->comm,
215 ((struct task_struct *)(__pa(current)))->pid,
216 (unsigned long)current);
217
218 printk("\nStack: ");
219 printk("Stack dump [0x%08lx]:\n", (unsigned long)stack);
220 for (i = 0; i < kstack_depth_to_print; i++) {
221 if (((long)stack & (THREAD_SIZE - 1)) == 0)
222 break;
223 stack++;
224
225 printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4,
226 *((unsigned long *)(__pa(stack))));
227 }
228 printk("\n");
229
230 printk("Call Trace: ");
231 i = 1;
232 while (((long)stack & (THREAD_SIZE - 1)) != 0) {
233 addr = *((unsigned long *)__pa(stack));
234 stack++;
235
236 if (kernel_text_address(addr)) {
237 if (i && ((i % 6) == 0))
238 printk("\n ");
239 printk(" [<%08lx>]", addr);
240 i++;
241 }
242 }
243 printk("\n");
244
245 printk("\nCode: ");
246
247 for (i = -24; i < 24; i++) {
248 unsigned char c;
249 c = ((unsigned char *)(__pa(regs->pc)))[i];
250
251 if (i == 0)
252 printk("(%02x) ", c);
253 else
254 printk("%02x ", c);
255 }
256 printk("\n");
257}
258
259/* This is normally the 'Oops' routine */
260void die(const char *str, struct pt_regs *regs, long err)
261{
262
263 console_verbose();
264 printk("\n%s#: %04lx\n", str, err & 0xffff);
265 show_registers(regs);
266#ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
267 printk("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n");
268
269 /* shut down interrupts */
270 local_irq_disable();
271
272 __asm__ __volatile__("l.nop 1");
273 do {} while (1);
274#endif
275 do_exit(SIGSEGV);
276}
277
278/* This is normally the 'Oops' routine */
279void die_if_kernel(const char *str, struct pt_regs *regs, long err)
280{
281 if (user_mode(regs))
282 return;
283
284 die(str, regs, err);
285}
286
287void unhandled_exception(struct pt_regs *regs, int ea, int vector)
288{
289 printk("Unable to handle exception at EA =0x%x, vector 0x%x",
290 ea, vector);
291 die("Oops", regs, 9);
292}
293
294void __init trap_init(void)
295{
296 /* Nothing needs to be done */
297}
298
299asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
300{
301 siginfo_t info;
302 memset(&info, 0, sizeof(info));
303 info.si_signo = SIGTRAP;
304 info.si_code = TRAP_TRACE;
305 info.si_addr = (void *)address;
306 force_sig_info(SIGTRAP, &info, current);
307
308 regs->pc += 4;
309}
310
311asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
312{
313 siginfo_t info;
314
315 if (user_mode(regs)) {
316 /* Send a SIGSEGV */
317 info.si_signo = SIGSEGV;
318 info.si_errno = 0;
319 /* info.si_code has been set above */
320 info.si_addr = (void *)address;
321 force_sig_info(SIGSEGV, &info, current);
322 } else {
323 printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
324 show_registers(regs);
325 die("Die:", regs, address);
326 }
327
328}
329
330asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
331{
332 siginfo_t info;
333
334 if (user_mode(regs)) {
335 /* Send a SIGBUS */
336 info.si_signo = SIGBUS;
337 info.si_errno = 0;
338 info.si_code = BUS_ADRERR;
339 info.si_addr = (void *)address;
340 force_sig_info(SIGBUS, &info, current);
341 } else { /* Kernel mode */
342 printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address);
343 show_registers(regs);
344 die("Die:", regs, address);
345 }
346}
347
348asmlinkage void do_illegal_instruction(struct pt_regs *regs,
349 unsigned long address)
350{
351 siginfo_t info;
352
353 if (user_mode(regs)) {
354 /* Send a SIGILL */
355 info.si_signo = SIGILL;
356 info.si_errno = 0;
357 info.si_code = ILL_ILLOPC;
358 info.si_addr = (void *)address;
359 force_sig_info(SIGBUS, &info, current);
360 } else { /* Kernel mode */
361 printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n",
362 address);
363 show_registers(regs);
364 die("Die:", regs, address);
365 }
366}
diff --git a/arch/openrisc/kernel/vmlinux.h b/arch/openrisc/kernel/vmlinux.h
new file mode 100644
index 00000000000..ee842a2d3f3
--- /dev/null
+++ b/arch/openrisc/kernel/vmlinux.h
@@ -0,0 +1,12 @@
1#ifndef __OPENRISC_VMLINUX_H_
2#define __OPENRISC_VMLINUX_H_
3
4extern char _stext, _etext, _edata, _end;
5#ifdef CONFIG_BLK_DEV_INITRD
6extern char __initrd_start, __initrd_end;
7extern char __initramfs_start;
8#endif
9
10extern u32 __dtb_start[];
11
12#endif
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
new file mode 100644
index 00000000000..2d69a853b74
--- /dev/null
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -0,0 +1,115 @@
1/*
2 * OpenRISC vmlinux.lds.S
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * ld script for OpenRISC architecture
18 */
19
20/* TODO
21 * - clean up __offset & stuff
22 * - change all 8192 aligment to PAGE !!!
23 * - recheck if all aligments are really needed
24 */
25
26# define LOAD_OFFSET PAGE_OFFSET
27# define LOAD_BASE PAGE_OFFSET
28
29#include <asm/page.h>
30#include <asm/cache.h>
31#include <asm-generic/vmlinux.lds.h>
32
33OUTPUT_FORMAT("elf32-or32", "elf32-or32", "elf32-or32")
34jiffies = jiffies_64 + 4;
35
36SECTIONS
37{
38 /* Read-only sections, merged into text segment: */
39 . = LOAD_BASE ;
40
41 /* _s_kernel_ro must be page aligned */
42 . = ALIGN(PAGE_SIZE);
43 _s_kernel_ro = .;
44
45 .text : AT(ADDR(.text) - LOAD_OFFSET)
46 {
47 _stext = .;
48 TEXT_TEXT
49 SCHED_TEXT
50 LOCK_TEXT
51 KPROBES_TEXT
52 IRQENTRY_TEXT
53 *(.fixup)
54 *(.text.__*)
55 _etext = .;
56 }
57 /* TODO: Check if fixup and text.__* are really necessary
58 * fixup is definitely necessary
59 */
60
61 _sdata = .;
62
63 /* Page alignment required for RO_DATA_SECTION */
64 RO_DATA_SECTION(PAGE_SIZE)
65 _e_kernel_ro = .;
66
67 /* Whatever comes after _e_kernel_ro had better be page-aligend, too */
68
69 /* 32 here is cacheline size... recheck this */
70 RW_DATA_SECTION(32, PAGE_SIZE, PAGE_SIZE)
71
72 _edata = .;
73
74 EXCEPTION_TABLE(4)
75 NOTES
76
77 /* Init code and data */
78 . = ALIGN(PAGE_SIZE);
79 __init_begin = .;
80
81 HEAD_TEXT_SECTION
82
83 /* Page aligned */
84 INIT_TEXT_SECTION(PAGE_SIZE)
85
86 /* Align __setup_start on 16 byte boundary */
87 INIT_DATA_SECTION(16)
88
89 PERCPU_SECTION(L1_CACHE_BYTES)
90
91 __init_end = .;
92
93 . = ALIGN(PAGE_SIZE);
94 .initrd : AT(ADDR(.initrd) - LOAD_OFFSET)
95 {
96 __initrd_start = .;
97 *(.initrd)
98 __initrd_end = .;
99 FILL (0);
100 . = ALIGN (PAGE_SIZE);
101 }
102
103 __vmlinux_end = .; /* last address of the physical file */
104
105 BSS_SECTION(0, 0, 0x20)
106
107 _end = .;
108
109 /* Throw in the debugging sections */
110 STABS_DEBUG
111 DWARF_DEBUG
112
113 /* Sections to be discarded -- must be last */
114 DISCARDS
115}
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
new file mode 100644
index 00000000000..966f65dbc6f
--- /dev/null
+++ b/arch/openrisc/lib/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for or32 specific library files..
3#
4
5obj-y = string.o delay.o
diff --git a/arch/openrisc/lib/delay.c b/arch/openrisc/lib/delay.c
new file mode 100644
index 00000000000..01d9740ae6f
--- /dev/null
+++ b/arch/openrisc/lib/delay.c
@@ -0,0 +1,60 @@
1/*
2 * OpenRISC Linux
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation
14 *
15 * Precise Delay Loops
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <asm/delay.h>
22#include <asm/timex.h>
23#include <asm/processor.h>
24
25int __devinit read_current_timer(unsigned long *timer_value)
26{
27 *timer_value = mfspr(SPR_TTCR);
28 return 0;
29}
30
31void __delay(unsigned long cycles)
32{
33 cycles_t target = get_cycles() + cycles;
34
35 while (get_cycles() < target)
36 cpu_relax();
37}
38EXPORT_SYMBOL(__delay);
39
40inline void __const_udelay(unsigned long xloops)
41{
42 unsigned long long loops;
43
44 loops = xloops * loops_per_jiffy * HZ;
45
46 __delay(loops >> 32);
47}
48EXPORT_SYMBOL(__const_udelay);
49
50void __udelay(unsigned long usecs)
51{
52 __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
53}
54EXPORT_SYMBOL(__udelay);
55
56void __ndelay(unsigned long nsecs)
57{
58 __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
59}
60EXPORT_SYMBOL(__ndelay);
diff --git a/arch/openrisc/lib/string.S b/arch/openrisc/lib/string.S
new file mode 100644
index 00000000000..465f04bc7de
--- /dev/null
+++ b/arch/openrisc/lib/string.S
@@ -0,0 +1,204 @@
1/*
2 * OpenRISC string.S
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/linkage.h>
19#include <asm/errno.h>
20
21 /*
22 * this can be optimized by doing gcc inline assemlby with
23 * proper constraints (no need to save args registers...)
24 *
25 */
26
27
28/*
29 *
30 * int __copy_tofrom_user(void *to, const void *from, unsigned long size);
31 *
32 * NOTE: it returns number of bytes NOT copied !!!
33 *
34 */
35 .global __copy_tofrom_user
36__copy_tofrom_user:
37 l.addi r1,r1,-12
38 l.sw 0(r1),r6
39 l.sw 4(r1),r4
40 l.sw 8(r1),r3
41
42 l.addi r11,r5,0
432: l.sfeq r11,r0
44 l.bf 1f
45 l.addi r11,r11,-1
468: l.lbz r6,0(r4)
479: l.sb 0(r3),r6
48 l.addi r3,r3,1
49 l.j 2b
50 l.addi r4,r4,1
511:
52 l.addi r11,r11,1 // r11 holds the return value
53
54 l.lwz r6,0(r1)
55 l.lwz r4,4(r1)
56 l.lwz r3,8(r1)
57 l.jr r9
58 l.addi r1,r1,12
59
60 .section .fixup, "ax"
6199:
62 l.j 1b
63 l.nop
64 .previous
65
66 .section __ex_table, "a"
67 .long 8b, 99b // read fault
68 .long 9b, 99b // write fault
69 .previous
70
71/*
72 * unsigned long clear_user(void *addr, unsigned long size) ;
73 *
74 * NOTE: it returns number of bytes NOT cleared !!!
75 */
76 .global __clear_user
77__clear_user:
78 l.addi r1,r1,-8
79 l.sw 0(r1),r4
80 l.sw 4(r1),r3
81
822: l.sfeq r4,r0
83 l.bf 1f
84 l.addi r4,r4,-1
859: l.sb 0(r3),r0
86 l.j 2b
87 l.addi r3,r3,1
88
891:
90 l.addi r11,r4,1
91
92 l.lwz r4,0(r1)
93 l.lwz r3,4(r1)
94 l.jr r9
95 l.addi r1,r1,8
96
97 .section .fixup, "ax"
9899:
99 l.j 1b
100 l.nop
101 .previous
102
103 .section __ex_table, "a"
104 .long 9b, 99b // write fault
105 .previous
106
107/*
108 * long strncpy_from_user(char *dst, const char *src, long count)
109 *
110 *
111 */
112 .global __strncpy_from_user
113__strncpy_from_user:
114 l.addi r1,r1,-16
115 l.sw 0(r1),r6
116 l.sw 4(r1),r5
117 l.sw 8(r1),r4
118 l.sw 12(r1),r3
119
120 l.addi r11,r5,0
1212: l.sfeq r5,r0
122 l.bf 1f
123 l.addi r5,r5,-1
1248: l.lbz r6,0(r4)
125 l.sfeq r6,r0
126 l.bf 1f
1279: l.sb 0(r3),r6
128 l.addi r3,r3,1
129 l.j 2b
130 l.addi r4,r4,1
1311:
132 l.lwz r6,0(r1)
133 l.addi r5,r5,1
134 l.sub r11,r11,r5 // r11 holds the return value
135
136 l.lwz r6,0(r1)
137 l.lwz r5,4(r1)
138 l.lwz r4,8(r1)
139 l.lwz r3,12(r1)
140 l.jr r9
141 l.addi r1,r1,16
142
143 .section .fixup, "ax"
14499:
145 l.movhi r11,hi(-EFAULT)
146 l.ori r11,r11,lo(-EFAULT)
147
148 l.lwz r6,0(r1)
149 l.lwz r5,4(r1)
150 l.lwz r4,8(r1)
151 l.lwz r3,12(r1)
152 l.jr r9
153 l.addi r1,r1,16
154 .previous
155
156 .section __ex_table, "a"
157 .long 8b, 99b // read fault
158 .previous
159
160/*
161 * extern int __strnlen_user(const char *str, long len, unsigned long top);
162 *
163 *
164 * RTRN: - length of a string including NUL termination character
165 * - on page fault 0
166 */
167
168 .global __strnlen_user
169__strnlen_user:
170 l.addi r1,r1,-8
171 l.sw 0(r1),r6
172 l.sw 4(r1),r3
173
174 l.addi r11,r0,0
1752: l.sfeq r11,r4
176 l.bf 1f
177 l.addi r11,r11,1
1788: l.lbz r6,0(r3)
179 l.sfeq r6,r0
180 l.bf 1f
181 l.sfgeu r3,r5 // are we over the top ?
182 l.bf 99f
183 l.j 2b
184 l.addi r3,r3,1
185
1861:
187 l.lwz r6,0(r1)
188 l.lwz r3,4(r1)
189 l.jr r9
190 l.addi r1,r1,8
191
192 .section .fixup, "ax"
19399:
194 l.addi r11,r0,0
195
196 l.lwz r6,0(r1)
197 l.lwz r3,4(r1)
198 l.jr r9
199 l.addi r1,r1,8
200 .previous
201
202 .section __ex_table, "a"
203 .long 8b, 99b // read fault
204 .previous
diff --git a/arch/openrisc/mm/Makefile b/arch/openrisc/mm/Makefile
new file mode 100644
index 00000000000..324ba263452
--- /dev/null
+++ b/arch/openrisc/mm/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the linux openrisc-specific parts of the memory manager.
3#
4
5obj-y := fault.o tlb.o init.o ioremap.o
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
new file mode 100644
index 00000000000..a5dce82f864
--- /dev/null
+++ b/arch/openrisc/mm/fault.c
@@ -0,0 +1,338 @@
1/*
2 * OpenRISC fault.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/mm.h>
19#include <linux/interrupt.h>
20#include <linux/module.h>
21#include <linux/sched.h>
22
23#include <asm/uaccess.h>
24#include <asm/siginfo.h>
25#include <asm/signal.h>
26
27#define NUM_TLB_ENTRIES 64
28#define TLB_OFFSET(add) (((add) >> PAGE_SHIFT) & (NUM_TLB_ENTRIES-1))
29
30unsigned long pte_misses; /* updated by do_page_fault() */
31unsigned long pte_errors; /* updated by do_page_fault() */
32
33/* __PHX__ :: - check the vmalloc_fault in do_page_fault()
34 * - also look into include/asm-or32/mmu_context.h
35 */
36volatile pgd_t *current_pgd;
37
38extern void die(char *, struct pt_regs *, long);
39
40/*
41 * This routine handles page faults. It determines the address,
42 * and the problem, and then passes it off to one of the appropriate
43 * routines.
44 *
45 * If this routine detects a bad access, it returns 1, otherwise it
46 * returns 0.
47 */
48
49asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
50 unsigned long vector, int write_acc)
51{
52 struct task_struct *tsk;
53 struct mm_struct *mm;
54 struct vm_area_struct *vma;
55 siginfo_t info;
56 int fault;
57
58 tsk = current;
59
60 /*
61 * We fault-in kernel-space virtual memory on-demand. The
62 * 'reference' page table is init_mm.pgd.
63 *
64 * NOTE! We MUST NOT take any locks for this case. We may
65 * be in an interrupt or a critical region, and should
66 * only copy the information from the master page table,
67 * nothing more.
68 *
69 * NOTE2: This is done so that, when updating the vmalloc
70 * mappings we don't have to walk all processes pgdirs and
71 * add the high mappings all at once. Instead we do it as they
72 * are used. However vmalloc'ed page entries have the PAGE_GLOBAL
73 * bit set so sometimes the TLB can use a lingering entry.
74 *
75 * This verifies that the fault happens in kernel space
76 * and that the fault was not a protection error.
77 */
78
79 if (address >= VMALLOC_START &&
80 (vector != 0x300 && vector != 0x400) &&
81 !user_mode(regs))
82 goto vmalloc_fault;
83
84 /* If exceptions were enabled, we can reenable them here */
85 if (user_mode(regs)) {
86 /* Exception was in userspace: reenable interrupts */
87 local_irq_enable();
88 } else {
89 /* If exception was in a syscall, then IRQ's may have
90 * been enabled or disabled. If they were enabled,
91 * reenable them.
92 */
93 if (regs->sr && (SPR_SR_IEE | SPR_SR_TEE))
94 local_irq_enable();
95 }
96
97 mm = tsk->mm;
98 info.si_code = SEGV_MAPERR;
99
100 /*
101 * If we're in an interrupt or have no user
102 * context, we must not take the fault..
103 */
104
105 if (in_interrupt() || !mm)
106 goto no_context;
107
108 down_read(&mm->mmap_sem);
109 vma = find_vma(mm, address);
110
111 if (!vma)
112 goto bad_area;
113
114 if (vma->vm_start <= address)
115 goto good_area;
116
117 if (!(vma->vm_flags & VM_GROWSDOWN))
118 goto bad_area;
119
120 if (user_mode(regs)) {
121 /*
122 * accessing the stack below usp is always a bug.
123 * we get page-aligned addresses so we can only check
124 * if we're within a page from usp, but that might be
125 * enough to catch brutal errors at least.
126 */
127 if (address + PAGE_SIZE < regs->sp)
128 goto bad_area;
129 }
130 if (expand_stack(vma, address))
131 goto bad_area;
132
133 /*
134 * Ok, we have a good vm_area for this memory access, so
135 * we can handle it..
136 */
137
138good_area:
139 info.si_code = SEGV_ACCERR;
140
141 /* first do some preliminary protection checks */
142
143 if (write_acc) {
144 if (!(vma->vm_flags & VM_WRITE))
145 goto bad_area;
146 } else {
147 /* not present */
148 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
149 goto bad_area;
150 }
151
152 /* are we trying to execute nonexecutable area */
153 if ((vector == 0x400) && !(vma->vm_page_prot.pgprot & _PAGE_EXEC))
154 goto bad_area;
155
156 /*
157 * If for any reason at all we couldn't handle the fault,
158 * make sure we exit gracefully rather than endlessly redo
159 * the fault.
160 */
161
162 fault = handle_mm_fault(mm, vma, address, write_acc);
163 if (unlikely(fault & VM_FAULT_ERROR)) {
164 if (fault & VM_FAULT_OOM)
165 goto out_of_memory;
166 else if (fault & VM_FAULT_SIGBUS)
167 goto do_sigbus;
168 BUG();
169 }
170 /*RGD modeled on Cris */
171 if (fault & VM_FAULT_MAJOR)
172 tsk->maj_flt++;
173 else
174 tsk->min_flt++;
175
176 up_read(&mm->mmap_sem);
177 return;
178
179 /*
180 * Something tried to access memory that isn't in our memory map..
181 * Fix it, but check if it's kernel or user first..
182 */
183
184bad_area:
185 up_read(&mm->mmap_sem);
186
187bad_area_nosemaphore:
188
189 /* User mode accesses just cause a SIGSEGV */
190
191 if (user_mode(regs)) {
192 info.si_signo = SIGSEGV;
193 info.si_errno = 0;
194 /* info.si_code has been set above */
195 info.si_addr = (void *)address;
196 force_sig_info(SIGSEGV, &info, tsk);
197 return;
198 }
199
200no_context:
201
202 /* Are we prepared to handle this kernel fault?
203 *
204 * (The kernel has valid exception-points in the source
205 * when it acesses user-memory. When it fails in one
206 * of those points, we find it in a table and do a jump
207 * to some fixup code that loads an appropriate error
208 * code)
209 */
210
211 {
212 const struct exception_table_entry *entry;
213
214 __asm__ __volatile__("l.nop 42");
215
216 if ((entry = search_exception_tables(regs->pc)) != NULL) {
217 /* Adjust the instruction pointer in the stackframe */
218 regs->pc = entry->fixup;
219 return;
220 }
221 }
222
223 /*
224 * Oops. The kernel tried to access some bad page. We'll have to
225 * terminate things with extreme prejudice.
226 */
227
228 if ((unsigned long)(address) < PAGE_SIZE)
229 printk(KERN_ALERT
230 "Unable to handle kernel NULL pointer dereference");
231 else
232 printk(KERN_ALERT "Unable to handle kernel access");
233 printk(" at virtual address 0x%08lx\n", address);
234
235 die("Oops", regs, write_acc);
236
237 do_exit(SIGKILL);
238
239 /*
240 * We ran out of memory, or some other thing happened to us that made
241 * us unable to handle the page fault gracefully.
242 */
243
244out_of_memory:
245 __asm__ __volatile__("l.nop 42");
246 __asm__ __volatile__("l.nop 1");
247
248 up_read(&mm->mmap_sem);
249 printk("VM: killing process %s\n", tsk->comm);
250 if (user_mode(regs))
251 do_exit(SIGKILL);
252 goto no_context;
253
254do_sigbus:
255 up_read(&mm->mmap_sem);
256
257 /*
258 * Send a sigbus, regardless of whether we were in kernel
259 * or user mode.
260 */
261 info.si_signo = SIGBUS;
262 info.si_errno = 0;
263 info.si_code = BUS_ADRERR;
264 info.si_addr = (void *)address;
265 force_sig_info(SIGBUS, &info, tsk);
266
267 /* Kernel mode? Handle exceptions or die */
268 if (!user_mode(regs))
269 goto no_context;
270 return;
271
272vmalloc_fault:
273 {
274 /*
275 * Synchronize this task's top level page-table
276 * with the 'reference' page table.
277 *
278 * Use current_pgd instead of tsk->active_mm->pgd
279 * since the latter might be unavailable if this
280 * code is executed in a misfortunately run irq
281 * (like inside schedule() between switch_mm and
282 * switch_to...).
283 */
284
285 int offset = pgd_index(address);
286 pgd_t *pgd, *pgd_k;
287 pud_t *pud, *pud_k;
288 pmd_t *pmd, *pmd_k;
289 pte_t *pte_k;
290
291/*
292 phx_warn("do_page_fault(): vmalloc_fault will not work, "
293 "since current_pgd assign a proper value somewhere\n"
294 "anyhow we don't need this at the moment\n");
295
296 phx_mmu("vmalloc_fault");
297*/
298 pgd = (pgd_t *)current_pgd + offset;
299 pgd_k = init_mm.pgd + offset;
300
301 /* Since we're two-level, we don't need to do both
302 * set_pgd and set_pmd (they do the same thing). If
303 * we go three-level at some point, do the right thing
304 * with pgd_present and set_pgd here.
305 *
306 * Also, since the vmalloc area is global, we don't
307 * need to copy individual PTE's, it is enough to
308 * copy the pgd pointer into the pte page of the
309 * root task. If that is there, we'll find our pte if
310 * it exists.
311 */
312
313 pud = pud_offset(pgd, address);
314 pud_k = pud_offset(pgd_k, address);
315 if (!pud_present(*pud_k))
316 goto no_context;
317
318 pmd = pmd_offset(pud, address);
319 pmd_k = pmd_offset(pud_k, address);
320
321 if (!pmd_present(*pmd_k))
322 goto bad_area_nosemaphore;
323
324 set_pmd(pmd, *pmd_k);
325
326 /* Make sure the actual PTE exists as well to
327 * catch kernel vmalloc-area accesses to non-mapped
328 * addresses. If we don't do this, this will just
329 * silently loop forever.
330 */
331
332 pte_k = pte_offset_kernel(pmd_k, address);
333 if (!pte_present(*pte_k))
334 goto no_context;
335
336 return;
337 }
338}
diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c
new file mode 100644
index 00000000000..359dcb20fe8
--- /dev/null
+++ b/arch/openrisc/mm/init.c
@@ -0,0 +1,283 @@
1/*
2 * OpenRISC idle.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/signal.h>
19#include <linux/sched.h>
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/string.h>
23#include <linux/types.h>
24#include <linux/ptrace.h>
25#include <linux/mman.h>
26#include <linux/mm.h>
27#include <linux/swap.h>
28#include <linux/smp.h>
29#include <linux/bootmem.h>
30#include <linux/init.h>
31#include <linux/delay.h>
32#include <linux/blkdev.h> /* for initrd_* */
33#include <linux/pagemap.h>
34#include <linux/memblock.h>
35
36#include <asm/system.h>
37#include <asm/segment.h>
38#include <asm/pgalloc.h>
39#include <asm/pgtable.h>
40#include <asm/dma.h>
41#include <asm/io.h>
42#include <asm/tlb.h>
43#include <asm/mmu_context.h>
44#include <asm/kmap_types.h>
45#include <asm/fixmap.h>
46#include <asm/tlbflush.h>
47
48int mem_init_done;
49
50DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
51
52static void __init zone_sizes_init(void)
53{
54 unsigned long zones_size[MAX_NR_ZONES];
55
56 /* Clear the zone sizes */
57 memset(zones_size, 0, sizeof(zones_size));
58
59 /*
60 * We use only ZONE_NORMAL
61 */
62 zones_size[ZONE_NORMAL] = max_low_pfn;
63
64 free_area_init(zones_size);
65}
66
67extern const char _s_kernel_ro[], _e_kernel_ro[];
68
69/*
70 * Map all physical memory into kernel's address space.
71 *
72 * This is explicitly coded for two-level page tables, so if you need
73 * something else then this needs to change.
74 */
75static void __init map_ram(void)
76{
77 unsigned long v, p, e;
78 pgprot_t prot;
79 pgd_t *pge;
80 pud_t *pue;
81 pmd_t *pme;
82 pte_t *pte;
83 /* These mark extents of read-only kernel pages...
84 * ...from vmlinux.lds.S
85 */
86 struct memblock_region *region;
87
88 v = PAGE_OFFSET;
89
90 for_each_memblock(memory, region) {
91 p = (u32) region->base & PAGE_MASK;
92 e = p + (u32) region->size;
93
94 v = (u32) __va(p);
95 pge = pgd_offset_k(v);
96
97 while (p < e) {
98 int j;
99 pue = pud_offset(pge, v);
100 pme = pmd_offset(pue, v);
101
102 if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) {
103 panic("%s: OR1K kernel hardcoded for "
104 "two-level page tables",
105 __func__);
106 }
107
108 /* Alloc one page for holding PTE's... */
109 pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
110 set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte)));
111
112 /* Fill the newly allocated page with PTE'S */
113 for (j = 0; p < e && j < PTRS_PER_PGD;
114 v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
115 if (v >= (u32) _e_kernel_ro ||
116 v < (u32) _s_kernel_ro)
117 prot = PAGE_KERNEL;
118 else
119 prot = PAGE_KERNEL_RO;
120
121 set_pte(pte, mk_pte_phys(p, prot));
122 }
123
124 pge++;
125 }
126
127 printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
128 region->base, region->base + region->size);
129 }
130}
131
132void __init paging_init(void)
133{
134 extern void tlb_init(void);
135
136 unsigned long end;
137 int i;
138
139 printk(KERN_INFO "Setting up paging and PTEs.\n");
140
141 /* clear out the init_mm.pgd that will contain the kernel's mappings */
142
143 for (i = 0; i < PTRS_PER_PGD; i++)
144 swapper_pg_dir[i] = __pgd(0);
145
146 /* make sure the current pgd table points to something sane
147 * (even if it is most probably not used until the next
148 * switch_mm)
149 */
150 current_pgd = init_mm.pgd;
151
152 end = (unsigned long)__va(max_low_pfn * PAGE_SIZE);
153
154 map_ram();
155
156 zone_sizes_init();
157
158 /* self modifying code ;) */
159 /* Since the old TLB miss handler has been running up until now,
160 * the kernel pages are still all RW, so we can still modify the
161 * text directly... after this change and a TLB flush, the kernel
162 * pages will become RO.
163 */
164 {
165 extern unsigned long dtlb_miss_handler;
166 extern unsigned long itlb_miss_handler;
167
168 unsigned long *dtlb_vector = __va(0x900);
169 unsigned long *itlb_vector = __va(0xa00);
170
171 printk(KERN_INFO "dtlb_miss_handler %p\n", &dtlb_miss_handler);
172 *dtlb_vector = ((unsigned long)&dtlb_miss_handler -
173 (unsigned long)dtlb_vector) >> 2;
174
175 printk(KERN_INFO "itlb_miss_handler %p\n", &itlb_miss_handler);
176 *itlb_vector = ((unsigned long)&itlb_miss_handler -
177 (unsigned long)itlb_vector) >> 2;
178 }
179
180 /* Invalidate instruction caches after code modification */
181 mtspr(SPR_ICBIR, 0x900);
182 mtspr(SPR_ICBIR, 0xa00);
183
184 /* New TLB miss handlers and kernel page tables are in now place.
185 * Make sure that page flags get updated for all pages in TLB by
186 * flushing the TLB and forcing all TLB entries to be recreated
187 * from their page table flags.
188 */
189 flush_tlb_all();
190}
191
192/* References to section boundaries */
193
194extern char _stext, _etext, _edata, __bss_start, _end;
195extern char __init_begin, __init_end;
196
197static int __init free_pages_init(void)
198{
199 int reservedpages, pfn;
200
201 /* this will put all low memory onto the freelists */
202 totalram_pages = free_all_bootmem();
203
204 reservedpages = 0;
205 for (pfn = 0; pfn < max_low_pfn; pfn++) {
206 /*
207 * Only count reserved RAM pages
208 */
209 if (PageReserved(mem_map + pfn))
210 reservedpages++;
211 }
212
213 return reservedpages;
214}
215
216static void __init set_max_mapnr_init(void)
217{
218 max_mapnr = num_physpages = max_low_pfn;
219}
220
221void __init mem_init(void)
222{
223 int codesize, reservedpages, datasize, initsize;
224
225 if (!mem_map)
226 BUG();
227
228 set_max_mapnr_init();
229
230 high_memory = (void *)__va(max_low_pfn * PAGE_SIZE);
231
232 /* clear the zero-page */
233 memset((void *)empty_zero_page, 0, PAGE_SIZE);
234
235 reservedpages = free_pages_init();
236
237 codesize = (unsigned long)&_etext - (unsigned long)&_stext;
238 datasize = (unsigned long)&_edata - (unsigned long)&_etext;
239 initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
240
241 printk(KERN_INFO
242 "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
243 (unsigned long)nr_free_pages() << (PAGE_SHIFT - 10),
244 max_mapnr << (PAGE_SHIFT - 10), codesize >> 10,
245 reservedpages << (PAGE_SHIFT - 10), datasize >> 10,
246 initsize >> 10, (unsigned long)(0 << (PAGE_SHIFT - 10))
247 );
248
249 printk("mem_init_done ...........................................\n");
250 mem_init_done = 1;
251 return;
252}
253
254#ifdef CONFIG_BLK_DEV_INITRD
255void free_initrd_mem(unsigned long start, unsigned long end)
256{
257 printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
258 (end - start) >> 10);
259
260 for (; start < end; start += PAGE_SIZE) {
261 ClearPageReserved(virt_to_page(start));
262 init_page_count(virt_to_page(start));
263 free_page(start);
264 totalram_pages++;
265 }
266}
267#endif
268
269void free_initmem(void)
270{
271 unsigned long addr;
272
273 addr = (unsigned long)(&__init_begin);
274 for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
275 ClearPageReserved(virt_to_page(addr));
276 init_page_count(virt_to_page(addr));
277 free_page(addr);
278 totalram_pages++;
279 }
280 printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n",
281 ((unsigned long)&__init_end -
282 (unsigned long)&__init_begin) >> 10);
283}
diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c
new file mode 100644
index 00000000000..62b08ef392b
--- /dev/null
+++ b/arch/openrisc/mm/ioremap.c
@@ -0,0 +1,137 @@
1/*
2 * OpenRISC ioremap.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/vmalloc.h>
19#include <linux/io.h>
20#include <asm/pgalloc.h>
21#include <asm/kmap_types.h>
22#include <asm/fixmap.h>
23#include <asm/bug.h>
24#include <asm/pgtable.h>
25#include <linux/sched.h>
26#include <asm/tlbflush.h>
27
28extern int mem_init_done;
29
30static unsigned int fixmaps_used __initdata;
31
32/*
33 * Remap an arbitrary physical address space into the kernel virtual
34 * address space. Needed when the kernel wants to access high addresses
35 * directly.
36 *
37 * NOTE! We need to allow non-page-aligned mappings too: we will obviously
38 * have to convert them into an offset in a page-aligned mapping, but the
39 * caller shouldn't need to know that small detail.
40 */
41void __iomem *__init_refok
42__ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot)
43{
44 phys_addr_t p;
45 unsigned long v;
46 unsigned long offset, last_addr;
47 struct vm_struct *area = NULL;
48
49 /* Don't allow wraparound or zero size */
50 last_addr = addr + size - 1;
51 if (!size || last_addr < addr)
52 return NULL;
53
54 /*
55 * Mappings have to be page-aligned
56 */
57 offset = addr & ~PAGE_MASK;
58 p = addr & PAGE_MASK;
59 size = PAGE_ALIGN(last_addr + 1) - p;
60
61 if (likely(mem_init_done)) {
62 area = get_vm_area(size, VM_IOREMAP);
63 if (!area)
64 return NULL;
65 v = (unsigned long)area->addr;
66 } else {
67 if ((fixmaps_used + (size >> PAGE_SHIFT)) > FIX_N_IOREMAPS)
68 return NULL;
69 v = fix_to_virt(FIX_IOREMAP_BEGIN + fixmaps_used);
70 fixmaps_used += (size >> PAGE_SHIFT);
71 }
72
73 if (ioremap_page_range(v, v + size, p, prot)) {
74 if (likely(mem_init_done))
75 vfree(area->addr);
76 else
77 fixmaps_used -= (size >> PAGE_SHIFT);
78 return NULL;
79 }
80
81 return (void __iomem *)(offset + (char *)v);
82}
83
84void iounmap(void *addr)
85{
86 /* If the page is from the fixmap pool then we just clear out
87 * the fixmap mapping.
88 */
89 if (unlikely((unsigned long)addr > FIXADDR_START)) {
90 /* This is a bit broken... we don't really know
91 * how big the area is so it's difficult to know
92 * how many fixed pages to invalidate...
93 * just flush tlb and hope for the best...
94 * consider this a FIXME
95 *
96 * Really we should be clearing out one or more page
97 * table entries for these virtual addresses so that
98 * future references cause a page fault... for now, we
99 * rely on two things:
100 * i) this code never gets called on known boards
101 * ii) invalid accesses to the freed areas aren't made
102 */
103 flush_tlb_all();
104 return;
105 }
106
107 return vfree((void *)(PAGE_MASK & (unsigned long)addr));
108}
109
110/**
111 * OK, this one's a bit tricky... ioremap can get called before memory is
112 * initialized (early serial console does this) and will want to alloc a page
113 * for its mapping. No userspace pages will ever get allocated before memory
114 * is initialized so this applies only to kernel pages. In the event that
115 * this is called before memory is initialized we allocate the page using
116 * the memblock infrastructure.
117 */
118
119pte_t __init_refok *pte_alloc_one_kernel(struct mm_struct *mm,
120 unsigned long address)
121{
122 pte_t *pte;
123
124 if (likely(mem_init_done)) {
125 pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT);
126 } else {
127 pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
128#if 0
129 /* FIXME: use memblock... */
130 pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
131#endif
132 }
133
134 if (pte)
135 clear_page(pte);
136 return pte;
137}
diff --git a/arch/openrisc/mm/tlb.c b/arch/openrisc/mm/tlb.c
new file mode 100644
index 00000000000..56b0b89624a
--- /dev/null
+++ b/arch/openrisc/mm/tlb.c
@@ -0,0 +1,193 @@
1/*
2 * OpenRISC tlb.c
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Julius Baxter <julius.baxter@orsoc.se>
11 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 */
18
19#include <linux/sched.h>
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/string.h>
23#include <linux/types.h>
24#include <linux/ptrace.h>
25#include <linux/mman.h>
26#include <linux/mm.h>
27#include <linux/init.h>
28
29#include <asm/system.h>
30#include <asm/segment.h>
31#include <asm/tlbflush.h>
32#include <asm/pgtable.h>
33#include <asm/mmu_context.h>
34#include <asm/spr_defs.h>
35
36#define NO_CONTEXT -1
37
38#define NUM_DTLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \
39 SPR_DMMUCFGR_NTS_OFF))
40#define NUM_ITLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \
41 SPR_IMMUCFGR_NTS_OFF))
42#define DTLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_DTLB_SETS-1))
43#define ITLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_ITLB_SETS-1))
44/*
45 * Invalidate all TLB entries.
46 *
47 * This comes down to setting the 'valid' bit for all xTLBMR registers to 0.
48 * Easiest way to accomplish this is to just zero out the xTLBMR register
49 * completely.
50 *
51 */
52
53void flush_tlb_all(void)
54{
55 int i;
56 unsigned long num_tlb_sets;
57
58 /* Determine number of sets for IMMU. */
59 /* FIXME: Assumption is I & D nsets equal. */
60 num_tlb_sets = NUM_ITLB_SETS;
61
62 for (i = 0; i < num_tlb_sets; i++) {
63 mtspr_off(SPR_DTLBMR_BASE(0), i, 0);
64 mtspr_off(SPR_ITLBMR_BASE(0), i, 0);
65 }
66}
67
68#define have_dtlbeir (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_TEIRI)
69#define have_itlbeir (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_TEIRI)
70
71/*
72 * Invalidate a single page. This is what the xTLBEIR register is for.
73 *
74 * There's no point in checking the vma for PAGE_EXEC to determine whether it's
75 * the data or instruction TLB that should be flushed... that would take more
76 * than the few instructions that the following compiles down to!
77 *
78 * The case where we don't have the xTLBEIR register really only works for
79 * MMU's with a single way and is hard-coded that way.
80 */
81
82#define flush_dtlb_page_eir(addr) mtspr(SPR_DTLBEIR, addr)
83#define flush_dtlb_page_no_eir(addr) \
84 mtspr_off(SPR_DTLBMR_BASE(0), DTLB_OFFSET(addr), 0);
85
86#define flush_itlb_page_eir(addr) mtspr(SPR_ITLBEIR, addr)
87#define flush_itlb_page_no_eir(addr) \
88 mtspr_off(SPR_ITLBMR_BASE(0), ITLB_OFFSET(addr), 0);
89
90void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
91{
92 if (have_dtlbeir)
93 flush_dtlb_page_eir(addr);
94 else
95 flush_dtlb_page_no_eir(addr);
96
97 if (have_itlbeir)
98 flush_itlb_page_eir(addr);
99 else
100 flush_itlb_page_no_eir(addr);
101}
102
103void flush_tlb_range(struct vm_area_struct *vma,
104 unsigned long start, unsigned long end)
105{
106 int addr;
107 bool dtlbeir;
108 bool itlbeir;
109
110 dtlbeir = have_dtlbeir;
111 itlbeir = have_itlbeir;
112
113 for (addr = start; addr < end; addr += PAGE_SIZE) {
114 if (dtlbeir)
115 flush_dtlb_page_eir(addr);
116 else
117 flush_dtlb_page_no_eir(addr);
118
119 if (itlbeir)
120 flush_itlb_page_eir(addr);
121 else
122 flush_itlb_page_no_eir(addr);
123 }
124}
125
126/*
127 * Invalidate the selected mm context only.
128 *
129 * FIXME: Due to some bug here, we're flushing everything for now.
130 * This should be changed to loop over over mm and call flush_tlb_range.
131 */
132
133void flush_tlb_mm(struct mm_struct *mm)
134{
135
136 /* Was seeing bugs with the mm struct passed to us. Scrapped most of
137 this function. */
138 /* Several architctures do this */
139 flush_tlb_all();
140}
141
142/* called in schedule() just before actually doing the switch_to */
143
144void switch_mm(struct mm_struct *prev, struct mm_struct *next,
145 struct task_struct *next_tsk)
146{
147 /* remember the pgd for the fault handlers
148 * this is similar to the pgd register in some other CPU's.
149 * we need our own copy of it because current and active_mm
150 * might be invalid at points where we still need to derefer
151 * the pgd.
152 */
153 current_pgd = next->pgd;
154
155 /* We don't have context support implemented, so flush all
156 * entries belonging to previous map
157 */
158
159 if (prev != next)
160 flush_tlb_mm(prev);
161
162}
163
164/*
165 * Initialize the context related info for a new mm_struct
166 * instance.
167 */
168
169int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
170{
171 mm->context = NO_CONTEXT;
172 return 0;
173}
174
175/* called by __exit_mm to destroy the used MMU context if any before
176 * destroying the mm itself. this is only called when the last user of the mm
177 * drops it.
178 */
179
180void destroy_context(struct mm_struct *mm)
181{
182 flush_tlb_mm(mm);
183
184}
185
186/* called once during VM initialization, from init.c */
187
188void __init tlb_init(void)
189{
190 /* Do nothing... */
191 /* invalidate the entire TLB */
192 /* flush_tlb_all(); */
193}