diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-18 12:45:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-18 12:45:08 -0400 |
commit | 81ce31b773226332475f89501b1072bec0c0e241 (patch) | |
tree | cd66f3c1caf731cc552ae90af2068aecabaed334 /arch | |
parent | 515b696b282f856c3ad1679ccd658120faa387d0 (diff) | |
parent | 9973affe9bbcde64041890d8793eb2e74143c298 (diff) |
Merge branch 'for-linus' of git://gitserver.sunplusct.com/linux-2.6-score
* 'for-linus' of git://gitserver.sunplusct.com/linux-2.6-score: (22 commits)
score: add TIF_NOTIFY_RESUME define in asm/thread_info.h
score: make init_thread_union align to THREAD_SIZE
score: update files according to review comments.
score: add old syscall support
score: add MEMORY_START and MEMORY_SIZE define, to make the code clear
score: update inconsistent declare after .c was changed
score: remove unused code, add include files in .c
score: clean up mm/init.c
score: make irq.h definitions local
score: cleanups: dead code, 0 as pointer, shadowed variables
score: fix function prototypes
score: add address space annotations
score: add missing #includes
score: move save arg5 and arg6 instruction in front of enable_irq
score: add prototypes for wrapped syscalls
score: remove init_mm
score: add generic sys_call_table
score: remove __{put,get}_user_unknown
score: unset __ARCH_WANT_IPC_PARSE_VERSION
score: update files according to review comments
...
Diffstat (limited to 'arch')
128 files changed, 8873 insertions, 0 deletions
diff --git a/arch/score/Kconfig b/arch/score/Kconfig new file mode 100644 index 000000000000..55d413e6dcf2 --- /dev/null +++ b/arch/score/Kconfig | |||
@@ -0,0 +1,141 @@ | |||
1 | # For a description of the syntax of this configuration file, | ||
2 | # see Documentation/kbuild/kconfig-language.txt. | ||
3 | |||
4 | mainmenu "Linux/SCORE Kernel Configuration" | ||
5 | |||
6 | menu "Machine selection" | ||
7 | |||
8 | choice | ||
9 | prompt "System type" | ||
10 | default MACH_SPCT6600 | ||
11 | |||
12 | config ARCH_SCORE7 | ||
13 | bool "SCORE7 processor" | ||
14 | select SYS_SUPPORTS_32BIT_KERNEL | ||
15 | select CPU_SCORE7 | ||
16 | select GENERIC_HAS_IOMAP | ||
17 | |||
18 | config MACH_SPCT6600 | ||
19 | bool "SPCT6600 series based machines" | ||
20 | select SYS_SUPPORTS_32BIT_KERNEL | ||
21 | select CPU_SCORE7 | ||
22 | select GENERIC_HAS_IOMAP | ||
23 | |||
24 | config SCORE_SIM | ||
25 | bool "Score simulator" | ||
26 | select SYS_SUPPORTS_32BIT_KERNEL | ||
27 | select CPU_SCORE7 | ||
28 | select GENERIC_HAS_IOMAP | ||
29 | endchoice | ||
30 | |||
31 | endmenu | ||
32 | |||
33 | config CPU_SCORE7 | ||
34 | bool | ||
35 | |||
36 | config GENERIC_IOMAP | ||
37 | def_bool y | ||
38 | |||
39 | config NO_DMA | ||
40 | bool | ||
41 | default y | ||
42 | |||
43 | config RWSEM_GENERIC_SPINLOCK | ||
44 | def_bool y | ||
45 | |||
46 | config GENERIC_FIND_NEXT_BIT | ||
47 | def_bool y | ||
48 | |||
49 | config GENERIC_HWEIGHT | ||
50 | def_bool y | ||
51 | |||
52 | config GENERIC_CALIBRATE_DELAY | ||
53 | def_bool y | ||
54 | |||
55 | config GENERIC_CLOCKEVENTS | ||
56 | def_bool y | ||
57 | |||
58 | config GENERIC_TIME | ||
59 | def_bool y | ||
60 | |||
61 | config SCHED_NO_NO_OMIT_FRAME_POINTER | ||
62 | def_bool y | ||
63 | |||
64 | config GENERIC_HARDIRQS_NO__DO_IRQ | ||
65 | def_bool y | ||
66 | |||
67 | config GENERIC_SYSCALL_TABLE | ||
68 | def_bool y | ||
69 | |||
70 | config SCORE_L1_CACHE_SHIFT | ||
71 | int | ||
72 | default "4" | ||
73 | |||
74 | menu "Kernel type" | ||
75 | |||
76 | config 32BIT | ||
77 | def_bool y | ||
78 | |||
79 | config GENERIC_HARDIRQS | ||
80 | def_bool y | ||
81 | |||
82 | config ARCH_FLATMEM_ENABLE | ||
83 | def_bool y | ||
84 | |||
85 | config ARCH_POPULATES_NODE_MAP | ||
86 | def_bool y | ||
87 | |||
88 | source "mm/Kconfig" | ||
89 | |||
90 | config MEMORY_START | ||
91 | hex | ||
92 | default 0xa0000000 | ||
93 | |||
94 | source "kernel/time/Kconfig" | ||
95 | source "kernel/Kconfig.hz" | ||
96 | source "kernel/Kconfig.preempt" | ||
97 | |||
98 | endmenu | ||
99 | |||
100 | config RWSEM_GENERIC_SPINLOCK | ||
101 | def_bool y | ||
102 | |||
103 | config LOCKDEP_SUPPORT | ||
104 | def_bool y | ||
105 | |||
106 | config STACKTRACE_SUPPORT | ||
107 | def_bool y | ||
108 | |||
109 | source "init/Kconfig" | ||
110 | |||
111 | config PROBE_INITRD_HEADER | ||
112 | bool "Probe initrd header created by addinitrd" | ||
113 | depends on BLK_DEV_INITRD | ||
114 | help | ||
115 | Probe initrd header at the last page of kernel image. | ||
116 | Say Y here if you are using arch/score/boot/addinitrd.c to | ||
117 | add initrd or initramfs image to the kernel image. | ||
118 | Otherwise, say N. | ||
119 | |||
120 | config MMU | ||
121 | def_bool y | ||
122 | |||
123 | menu "Executable file formats" | ||
124 | |||
125 | source "fs/Kconfig.binfmt" | ||
126 | |||
127 | endmenu | ||
128 | |||
129 | source "net/Kconfig" | ||
130 | |||
131 | source "drivers/Kconfig" | ||
132 | |||
133 | source "fs/Kconfig" | ||
134 | |||
135 | source "arch/score/Kconfig.debug" | ||
136 | |||
137 | source "security/Kconfig" | ||
138 | |||
139 | source "crypto/Kconfig" | ||
140 | |||
141 | source "lib/Kconfig" | ||
diff --git a/arch/score/Kconfig.debug b/arch/score/Kconfig.debug new file mode 100644 index 000000000000..451ed54ce646 --- /dev/null +++ b/arch/score/Kconfig.debug | |||
@@ -0,0 +1,37 @@ | |||
1 | menu "Kernel hacking" | ||
2 | |||
3 | config TRACE_IRQFLAGS_SUPPORT | ||
4 | bool | ||
5 | default y | ||
6 | |||
7 | source "lib/Kconfig.debug" | ||
8 | |||
9 | config CMDLINE | ||
10 | string "Default kernel command string" | ||
11 | default "" | ||
12 | help | ||
13 | On some platforms, there is currently no way for the boot loader to | ||
14 | pass arguments to the kernel. For these platforms, you can supply | ||
15 | some command-line options at build time by entering them here. In | ||
16 | other cases you can specify kernel args so that you don't have | ||
17 | to set them up in board prom initialization routines. | ||
18 | |||
19 | config DEBUG_STACK_USAGE | ||
20 | bool "Enable stack utilization instrumentation" | ||
21 | depends on DEBUG_KERNEL | ||
22 | help | ||
23 | Enables the display of the minimum amount of free stack which each | ||
24 | task has ever had available in the sysrq-T and sysrq-P debug output. | ||
25 | |||
26 | This option will slow down process creation somewhat. | ||
27 | |||
28 | config RUNTIME_DEBUG | ||
29 | bool "Enable run-time debugging" | ||
30 | depends on DEBUG_KERNEL | ||
31 | help | ||
32 | If you say Y here, some debugging macros will do run-time checking. | ||
33 | If you say N here, those macros will mostly turn to no-ops. See | ||
34 | include/asm-score/debug.h for debuging macros. | ||
35 | If unsure, say N. | ||
36 | |||
37 | endmenu | ||
diff --git a/arch/score/Makefile b/arch/score/Makefile new file mode 100644 index 000000000000..68e0cd06d5c9 --- /dev/null +++ b/arch/score/Makefile | |||
@@ -0,0 +1,43 @@ | |||
1 | # | ||
2 | # arch/score/Makefile | ||
3 | # | ||
4 | # This file is subject to the terms and conditions of the GNU General Public | ||
5 | # License. See the file "COPYING" in the main directory of this archive | ||
6 | # for more details. | ||
7 | # | ||
8 | |||
9 | KBUILD_DEFCONFIG := spct6600_defconfig | ||
10 | CROSS_COMPILE := score-linux- | ||
11 | |||
12 | # | ||
13 | # CPU-dependent compiler/assembler options for optimization. | ||
14 | # | ||
15 | cflags-y += -G0 -pipe -mel -mnhwloop -D__SCOREEL__ \ | ||
16 | -D__linux__ -ffunction-sections -ffreestanding | ||
17 | |||
18 | # | ||
19 | # Board-dependent options and extra files | ||
20 | # | ||
21 | KBUILD_AFLAGS += $(cflags-y) | ||
22 | KBUILD_CFLAGS += $(cflags-y) | ||
23 | MODFLAGS += -mlong-calls | ||
24 | LDFLAGS += --oformat elf32-littlescore | ||
25 | LDFLAGS_vmlinux += -G0 -static -nostdlib | ||
26 | |||
27 | head-y := arch/score/kernel/head.o | ||
28 | libs-y += arch/score/lib/ | ||
29 | core-y += arch/score/kernel/ arch/score/mm/ | ||
30 | |||
31 | boot := arch/score/boot | ||
32 | |||
33 | vmlinux.bin: vmlinux | ||
34 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ | ||
35 | |||
36 | archclean: | ||
37 | @$(MAKE) $(clean)=$(boot) | ||
38 | |||
39 | define archhelp | ||
40 | echo ' vmlinux.bin - Raw binary boot image' | ||
41 | echo | ||
42 | echo ' These will be default as apropriate for a configured platform.' | ||
43 | endef | ||
diff --git a/arch/score/boot/Makefile b/arch/score/boot/Makefile new file mode 100644 index 000000000000..0c5fbd0fb696 --- /dev/null +++ b/arch/score/boot/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | # | ||
2 | # arch/score/boot/Makefile | ||
3 | # | ||
4 | # This file is subject to the terms and conditions of the GNU General Public | ||
5 | # License. See the file "COPYING" in the main directory of this archive | ||
6 | # for more details. | ||
7 | # | ||
8 | |||
9 | targets := vmlinux.bin | ||
10 | |||
11 | $(obj)/vmlinux.bin: vmlinux FORCE | ||
12 | $(call if_changed,objcopy) | ||
13 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' | ||
14 | |||
15 | clean-files += vmlinux.bin | ||
diff --git a/arch/score/configs/spct6600_defconfig b/arch/score/configs/spct6600_defconfig new file mode 100644 index 000000000000..e064943b13d4 --- /dev/null +++ b/arch/score/configs/spct6600_defconfig | |||
@@ -0,0 +1,717 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.30-rc5 | ||
4 | # Fri Jun 12 18:57:07 2009 | ||
5 | # | ||
6 | |||
7 | # | ||
8 | # Machine selection | ||
9 | # | ||
10 | # CONFIG_ARCH_SCORE7 is not set | ||
11 | CONFIG_MACH_SPCT6600=y | ||
12 | # CONFIG_SCORE_SIM is not set | ||
13 | CONFIG_CPU_SCORE7=y | ||
14 | CONFIG_GENERIC_IOMAP=y | ||
15 | CONFIG_NO_DMA=y | ||
16 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
17 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
18 | CONFIG_GENERIC_HWEIGHT=y | ||
19 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
20 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
21 | CONFIG_GENERIC_TIME=y | ||
22 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | ||
23 | CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y | ||
24 | CONFIG_GENERIC_SYSCALL_TABLE=y | ||
25 | CONFIG_SCORE_L1_CACHE_SHIFT=4 | ||
26 | |||
27 | # | ||
28 | # Kernel type | ||
29 | # | ||
30 | CONFIG_32BIT=y | ||
31 | CONFIG_GENERIC_HARDIRQS=y | ||
32 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
33 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
34 | CONFIG_SELECT_MEMORY_MODEL=y | ||
35 | CONFIG_FLATMEM_MANUAL=y | ||
36 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
37 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
38 | CONFIG_FLATMEM=y | ||
39 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
40 | CONFIG_PAGEFLAGS_EXTENDED=y | ||
41 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
42 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
43 | CONFIG_ZONE_DMA_FLAG=0 | ||
44 | CONFIG_VIRT_TO_BUS=y | ||
45 | CONFIG_UNEVICTABLE_LRU=y | ||
46 | CONFIG_HAVE_MLOCK=y | ||
47 | CONFIG_HAVE_MLOCKED_PAGE_BIT=y | ||
48 | CONFIG_MEMORY_START=0xa0000000 | ||
49 | # CONFIG_NO_HZ is not set | ||
50 | # CONFIG_HIGH_RES_TIMERS is not set | ||
51 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
52 | CONFIG_HZ_100=y | ||
53 | # CONFIG_HZ_250 is not set | ||
54 | # CONFIG_HZ_300 is not set | ||
55 | # CONFIG_HZ_1000 is not set | ||
56 | CONFIG_HZ=100 | ||
57 | # CONFIG_SCHED_HRTICK is not set | ||
58 | # CONFIG_PREEMPT_NONE is not set | ||
59 | CONFIG_PREEMPT_VOLUNTARY=y | ||
60 | # CONFIG_PREEMPT is not set | ||
61 | CONFIG_LOCKDEP_SUPPORT=y | ||
62 | CONFIG_STACKTRACE_SUPPORT=y | ||
63 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
64 | |||
65 | # | ||
66 | # General setup | ||
67 | # | ||
68 | CONFIG_EXPERIMENTAL=y | ||
69 | CONFIG_BROKEN_ON_SMP=y | ||
70 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
71 | CONFIG_LOCALVERSION="" | ||
72 | # CONFIG_LOCALVERSION_AUTO is not set | ||
73 | CONFIG_SWAP=y | ||
74 | CONFIG_SYSVIPC=y | ||
75 | CONFIG_SYSVIPC_SYSCTL=y | ||
76 | CONFIG_POSIX_MQUEUE=y | ||
77 | CONFIG_POSIX_MQUEUE_SYSCTL=y | ||
78 | CONFIG_BSD_PROCESS_ACCT=y | ||
79 | # CONFIG_BSD_PROCESS_ACCT_V3 is not set | ||
80 | # CONFIG_TASKSTATS is not set | ||
81 | # CONFIG_AUDIT is not set | ||
82 | |||
83 | # | ||
84 | # RCU Subsystem | ||
85 | # | ||
86 | CONFIG_CLASSIC_RCU=y | ||
87 | # CONFIG_TREE_RCU is not set | ||
88 | # CONFIG_PREEMPT_RCU is not set | ||
89 | # CONFIG_TREE_RCU_TRACE is not set | ||
90 | # CONFIG_PREEMPT_RCU_TRACE is not set | ||
91 | # CONFIG_IKCONFIG is not set | ||
92 | CONFIG_LOG_BUF_SHIFT=12 | ||
93 | # CONFIG_GROUP_SCHED is not set | ||
94 | # CONFIG_CGROUPS is not set | ||
95 | CONFIG_SYSFS_DEPRECATED=y | ||
96 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
97 | # CONFIG_RELAY is not set | ||
98 | # CONFIG_NAMESPACES is not set | ||
99 | CONFIG_BLK_DEV_INITRD=y | ||
100 | CONFIG_INITRAMFS_SOURCE="" | ||
101 | CONFIG_RD_GZIP=y | ||
102 | # CONFIG_RD_BZIP2 is not set | ||
103 | # CONFIG_RD_LZMA is not set | ||
104 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
105 | CONFIG_SYSCTL=y | ||
106 | CONFIG_ANON_INODES=y | ||
107 | CONFIG_EMBEDDED=y | ||
108 | CONFIG_SYSCTL_SYSCALL=y | ||
109 | # CONFIG_KALLSYMS is not set | ||
110 | # CONFIG_STRIP_ASM_SYMS is not set | ||
111 | # CONFIG_HOTPLUG is not set | ||
112 | CONFIG_PRINTK=y | ||
113 | CONFIG_BUG=y | ||
114 | CONFIG_ELF_CORE=y | ||
115 | CONFIG_BASE_FULL=y | ||
116 | CONFIG_FUTEX=y | ||
117 | CONFIG_EPOLL=y | ||
118 | CONFIG_SIGNALFD=y | ||
119 | CONFIG_TIMERFD=y | ||
120 | CONFIG_EVENTFD=y | ||
121 | CONFIG_SHMEM=y | ||
122 | CONFIG_AIO=y | ||
123 | CONFIG_VM_EVENT_COUNTERS=y | ||
124 | CONFIG_COMPAT_BRK=y | ||
125 | CONFIG_SLAB=y | ||
126 | # CONFIG_SLUB is not set | ||
127 | # CONFIG_SLOB is not set | ||
128 | # CONFIG_PROFILING is not set | ||
129 | # CONFIG_MARKERS is not set | ||
130 | # CONFIG_SLOW_WORK is not set | ||
131 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | ||
132 | CONFIG_SLABINFO=y | ||
133 | CONFIG_RT_MUTEXES=y | ||
134 | CONFIG_BASE_SMALL=0 | ||
135 | CONFIG_MODULES=y | ||
136 | CONFIG_MODULE_FORCE_LOAD=y | ||
137 | CONFIG_MODULE_UNLOAD=y | ||
138 | CONFIG_MODULE_FORCE_UNLOAD=y | ||
139 | # CONFIG_MODVERSIONS is not set | ||
140 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
141 | CONFIG_BLOCK=y | ||
142 | CONFIG_LBD=y | ||
143 | # CONFIG_BLK_DEV_BSG is not set | ||
144 | # CONFIG_BLK_DEV_INTEGRITY is not set | ||
145 | |||
146 | # | ||
147 | # IO Schedulers | ||
148 | # | ||
149 | CONFIG_IOSCHED_NOOP=y | ||
150 | CONFIG_IOSCHED_AS=y | ||
151 | CONFIG_IOSCHED_DEADLINE=y | ||
152 | CONFIG_IOSCHED_CFQ=y | ||
153 | # CONFIG_DEFAULT_AS is not set | ||
154 | # CONFIG_DEFAULT_DEADLINE is not set | ||
155 | CONFIG_DEFAULT_CFQ=y | ||
156 | # CONFIG_DEFAULT_NOOP is not set | ||
157 | CONFIG_DEFAULT_IOSCHED="cfq" | ||
158 | # CONFIG_PROBE_INITRD_HEADER is not set | ||
159 | CONFIG_MMU=y | ||
160 | |||
161 | # | ||
162 | # Executable file formats | ||
163 | # | ||
164 | CONFIG_BINFMT_ELF=y | ||
165 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
166 | # CONFIG_HAVE_AOUT is not set | ||
167 | CONFIG_BINFMT_MISC=y | ||
168 | CONFIG_NET=y | ||
169 | |||
170 | # | ||
171 | # Networking options | ||
172 | # | ||
173 | # CONFIG_PACKET is not set | ||
174 | CONFIG_UNIX=y | ||
175 | CONFIG_XFRM=y | ||
176 | # CONFIG_XFRM_USER is not set | ||
177 | # CONFIG_XFRM_SUB_POLICY is not set | ||
178 | # CONFIG_XFRM_MIGRATE is not set | ||
179 | # CONFIG_XFRM_STATISTICS is not set | ||
180 | CONFIG_NET_KEY=y | ||
181 | # CONFIG_NET_KEY_MIGRATE is not set | ||
182 | CONFIG_INET=y | ||
183 | CONFIG_IP_MULTICAST=y | ||
184 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
185 | CONFIG_IP_FIB_HASH=y | ||
186 | # CONFIG_IP_PNP is not set | ||
187 | # CONFIG_NET_IPIP is not set | ||
188 | # CONFIG_NET_IPGRE is not set | ||
189 | # CONFIG_IP_MROUTE is not set | ||
190 | CONFIG_ARPD=y | ||
191 | # CONFIG_SYN_COOKIES is not set | ||
192 | # CONFIG_INET_AH is not set | ||
193 | # CONFIG_INET_ESP is not set | ||
194 | # CONFIG_INET_IPCOMP is not set | ||
195 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
196 | # CONFIG_INET_TUNNEL is not set | ||
197 | CONFIG_INET_XFRM_MODE_TRANSPORT=y | ||
198 | CONFIG_INET_XFRM_MODE_TUNNEL=y | ||
199 | CONFIG_INET_XFRM_MODE_BEET=y | ||
200 | # CONFIG_INET_LRO is not set | ||
201 | CONFIG_INET_DIAG=y | ||
202 | CONFIG_INET_TCP_DIAG=y | ||
203 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
204 | CONFIG_TCP_CONG_CUBIC=y | ||
205 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
206 | # CONFIG_TCP_MD5SIG is not set | ||
207 | # CONFIG_IPV6 is not set | ||
208 | # CONFIG_NETLABEL is not set | ||
209 | # CONFIG_NETWORK_SECMARK is not set | ||
210 | # CONFIG_NETFILTER is not set | ||
211 | # CONFIG_IP_DCCP is not set | ||
212 | # CONFIG_IP_SCTP is not set | ||
213 | # CONFIG_TIPC is not set | ||
214 | # CONFIG_ATM is not set | ||
215 | # CONFIG_BRIDGE is not set | ||
216 | # CONFIG_NET_DSA is not set | ||
217 | # CONFIG_VLAN_8021Q is not set | ||
218 | # CONFIG_DECNET is not set | ||
219 | # CONFIG_LLC2 is not set | ||
220 | # CONFIG_IPX is not set | ||
221 | # CONFIG_ATALK is not set | ||
222 | # CONFIG_X25 is not set | ||
223 | # CONFIG_LAPB is not set | ||
224 | # CONFIG_ECONET is not set | ||
225 | # CONFIG_WAN_ROUTER is not set | ||
226 | # CONFIG_PHONET is not set | ||
227 | # CONFIG_NET_SCHED is not set | ||
228 | # CONFIG_DCB is not set | ||
229 | |||
230 | # | ||
231 | # Network testing | ||
232 | # | ||
233 | # CONFIG_NET_PKTGEN is not set | ||
234 | # CONFIG_HAMRADIO is not set | ||
235 | # CONFIG_CAN is not set | ||
236 | # CONFIG_IRDA is not set | ||
237 | # CONFIG_BT is not set | ||
238 | # CONFIG_AF_RXRPC is not set | ||
239 | # CONFIG_WIRELESS is not set | ||
240 | # CONFIG_WIMAX is not set | ||
241 | # CONFIG_RFKILL is not set | ||
242 | # CONFIG_NET_9P is not set | ||
243 | |||
244 | # | ||
245 | # Device Drivers | ||
246 | # | ||
247 | |||
248 | # | ||
249 | # Generic Driver Options | ||
250 | # | ||
251 | # CONFIG_STANDALONE is not set | ||
252 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set | ||
253 | # CONFIG_SYS_HYPERVISOR is not set | ||
254 | # CONFIG_CONNECTOR is not set | ||
255 | # CONFIG_MTD is not set | ||
256 | # CONFIG_PARPORT is not set | ||
257 | CONFIG_BLK_DEV=y | ||
258 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
259 | CONFIG_BLK_DEV_LOOP=y | ||
260 | CONFIG_BLK_DEV_CRYPTOLOOP=y | ||
261 | # CONFIG_BLK_DEV_NBD is not set | ||
262 | CONFIG_BLK_DEV_RAM=y | ||
263 | CONFIG_BLK_DEV_RAM_COUNT=1 | ||
264 | CONFIG_BLK_DEV_RAM_SIZE=4096 | ||
265 | # CONFIG_BLK_DEV_XIP is not set | ||
266 | # CONFIG_CDROM_PKTCDVD is not set | ||
267 | # CONFIG_ATA_OVER_ETH is not set | ||
268 | # CONFIG_MISC_DEVICES is not set | ||
269 | |||
270 | # | ||
271 | # SCSI device support | ||
272 | # | ||
273 | # CONFIG_RAID_ATTRS is not set | ||
274 | # CONFIG_SCSI is not set | ||
275 | # CONFIG_SCSI_DMA is not set | ||
276 | # CONFIG_SCSI_NETLINK is not set | ||
277 | # CONFIG_MD is not set | ||
278 | CONFIG_NETDEVICES=y | ||
279 | CONFIG_COMPAT_NET_DEV_OPS=y | ||
280 | # CONFIG_DUMMY is not set | ||
281 | # CONFIG_BONDING is not set | ||
282 | # CONFIG_MACVLAN is not set | ||
283 | # CONFIG_EQUALIZER is not set | ||
284 | # CONFIG_TUN is not set | ||
285 | # CONFIG_VETH is not set | ||
286 | # CONFIG_NET_ETHERNET is not set | ||
287 | # CONFIG_NETDEV_1000 is not set | ||
288 | # CONFIG_NETDEV_10000 is not set | ||
289 | |||
290 | # | ||
291 | # Wireless LAN | ||
292 | # | ||
293 | # CONFIG_WLAN_PRE80211 is not set | ||
294 | # CONFIG_WLAN_80211 is not set | ||
295 | |||
296 | # | ||
297 | # Enable WiMAX (Networking options) to see the WiMAX drivers | ||
298 | # | ||
299 | # CONFIG_WAN is not set | ||
300 | # CONFIG_PPP is not set | ||
301 | # CONFIG_SLIP is not set | ||
302 | # CONFIG_NETCONSOLE is not set | ||
303 | # CONFIG_NETPOLL is not set | ||
304 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
305 | # CONFIG_ISDN is not set | ||
306 | # CONFIG_PHONE is not set | ||
307 | |||
308 | # | ||
309 | # Input device support | ||
310 | # | ||
311 | CONFIG_INPUT=y | ||
312 | # CONFIG_INPUT_FF_MEMLESS is not set | ||
313 | # CONFIG_INPUT_POLLDEV is not set | ||
314 | |||
315 | # | ||
316 | # Userland interfaces | ||
317 | # | ||
318 | # CONFIG_INPUT_MOUSEDEV is not set | ||
319 | # CONFIG_INPUT_JOYDEV is not set | ||
320 | # CONFIG_INPUT_EVDEV is not set | ||
321 | # CONFIG_INPUT_EVBUG is not set | ||
322 | |||
323 | # | ||
324 | # Input Device Drivers | ||
325 | # | ||
326 | # CONFIG_INPUT_KEYBOARD is not set | ||
327 | # CONFIG_INPUT_MOUSE is not set | ||
328 | # CONFIG_INPUT_JOYSTICK is not set | ||
329 | # CONFIG_INPUT_TABLET is not set | ||
330 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
331 | # CONFIG_INPUT_MISC is not set | ||
332 | |||
333 | # | ||
334 | # Hardware I/O ports | ||
335 | # | ||
336 | # CONFIG_SERIO is not set | ||
337 | # CONFIG_GAMEPORT is not set | ||
338 | |||
339 | # | ||
340 | # Character devices | ||
341 | # | ||
342 | CONFIG_VT=y | ||
343 | CONFIG_CONSOLE_TRANSLATIONS=y | ||
344 | CONFIG_VT_CONSOLE=y | ||
345 | CONFIG_HW_CONSOLE=y | ||
346 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | ||
347 | CONFIG_DEVKMEM=y | ||
348 | CONFIG_SERIAL_NONSTANDARD=y | ||
349 | # CONFIG_N_HDLC is not set | ||
350 | # CONFIG_RISCOM8 is not set | ||
351 | # CONFIG_SPECIALIX is not set | ||
352 | # CONFIG_RIO is not set | ||
353 | CONFIG_STALDRV=y | ||
354 | |||
355 | # | ||
356 | # Serial drivers | ||
357 | # | ||
358 | # CONFIG_SERIAL_8250 is not set | ||
359 | |||
360 | # | ||
361 | # Non-8250 serial port support | ||
362 | # | ||
363 | CONFIG_UNIX98_PTYS=y | ||
364 | # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set | ||
365 | CONFIG_LEGACY_PTYS=y | ||
366 | CONFIG_LEGACY_PTY_COUNT=256 | ||
367 | # CONFIG_IPMI_HANDLER is not set | ||
368 | # CONFIG_HW_RANDOM is not set | ||
369 | # CONFIG_RTC is not set | ||
370 | # CONFIG_GEN_RTC is not set | ||
371 | # CONFIG_R3964 is not set | ||
372 | CONFIG_RAW_DRIVER=y | ||
373 | CONFIG_MAX_RAW_DEVS=8192 | ||
374 | # CONFIG_TCG_TPM is not set | ||
375 | # CONFIG_I2C is not set | ||
376 | # CONFIG_SPI is not set | ||
377 | # CONFIG_W1 is not set | ||
378 | # CONFIG_POWER_SUPPLY is not set | ||
379 | # CONFIG_HWMON is not set | ||
380 | # CONFIG_THERMAL is not set | ||
381 | # CONFIG_THERMAL_HWMON is not set | ||
382 | # CONFIG_WATCHDOG is not set | ||
383 | |||
384 | # | ||
385 | # Multifunction device drivers | ||
386 | # | ||
387 | # CONFIG_MFD_CORE is not set | ||
388 | # CONFIG_MFD_SM501 is not set | ||
389 | # CONFIG_HTC_PASIC3 is not set | ||
390 | # CONFIG_MFD_TMIO is not set | ||
391 | # CONFIG_REGULATOR is not set | ||
392 | |||
393 | # | ||
394 | # Multimedia devices | ||
395 | # | ||
396 | |||
397 | # | ||
398 | # Multimedia core support | ||
399 | # | ||
400 | # CONFIG_VIDEO_DEV is not set | ||
401 | # CONFIG_DVB_CORE is not set | ||
402 | # CONFIG_VIDEO_MEDIA is not set | ||
403 | |||
404 | # | ||
405 | # Multimedia drivers | ||
406 | # | ||
407 | # CONFIG_DAB is not set | ||
408 | |||
409 | # | ||
410 | # Graphics support | ||
411 | # | ||
412 | # CONFIG_VGASTATE is not set | ||
413 | # CONFIG_VIDEO_OUTPUT_CONTROL is not set | ||
414 | # CONFIG_FB is not set | ||
415 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
416 | |||
417 | # | ||
418 | # Display device support | ||
419 | # | ||
420 | # CONFIG_DISPLAY_SUPPORT is not set | ||
421 | |||
422 | # | ||
423 | # Console display driver support | ||
424 | # | ||
425 | # CONFIG_VGA_CONSOLE is not set | ||
426 | CONFIG_DUMMY_CONSOLE=y | ||
427 | # CONFIG_SOUND is not set | ||
428 | # CONFIG_HID_SUPPORT is not set | ||
429 | # CONFIG_USB_SUPPORT is not set | ||
430 | # CONFIG_MMC is not set | ||
431 | # CONFIG_MEMSTICK is not set | ||
432 | # CONFIG_NEW_LEDS is not set | ||
433 | # CONFIG_ACCESSIBILITY is not set | ||
434 | # CONFIG_RTC_CLASS is not set | ||
435 | # CONFIG_AUXDISPLAY is not set | ||
436 | # CONFIG_UIO is not set | ||
437 | # CONFIG_STAGING is not set | ||
438 | |||
439 | # | ||
440 | # File systems | ||
441 | # | ||
442 | CONFIG_EXT2_FS=y | ||
443 | CONFIG_EXT2_FS_XATTR=y | ||
444 | CONFIG_EXT2_FS_POSIX_ACL=y | ||
445 | # CONFIG_EXT2_FS_SECURITY is not set | ||
446 | # CONFIG_EXT2_FS_XIP is not set | ||
447 | CONFIG_EXT3_FS=y | ||
448 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
449 | CONFIG_EXT3_FS_XATTR=y | ||
450 | CONFIG_EXT3_FS_POSIX_ACL=y | ||
451 | # CONFIG_EXT3_FS_SECURITY is not set | ||
452 | # CONFIG_EXT4_FS is not set | ||
453 | CONFIG_JBD=y | ||
454 | CONFIG_FS_MBCACHE=y | ||
455 | # CONFIG_REISERFS_FS is not set | ||
456 | # CONFIG_JFS_FS is not set | ||
457 | CONFIG_FS_POSIX_ACL=y | ||
458 | CONFIG_FILE_LOCKING=y | ||
459 | # CONFIG_XFS_FS is not set | ||
460 | # CONFIG_GFS2_FS is not set | ||
461 | # CONFIG_OCFS2_FS is not set | ||
462 | # CONFIG_BTRFS_FS is not set | ||
463 | CONFIG_DNOTIFY=y | ||
464 | CONFIG_INOTIFY=y | ||
465 | CONFIG_INOTIFY_USER=y | ||
466 | # CONFIG_QUOTA is not set | ||
467 | CONFIG_AUTOFS_FS=y | ||
468 | CONFIG_AUTOFS4_FS=y | ||
469 | # CONFIG_FUSE_FS is not set | ||
470 | CONFIG_GENERIC_ACL=y | ||
471 | |||
472 | # | ||
473 | # Caches | ||
474 | # | ||
475 | # CONFIG_FSCACHE is not set | ||
476 | |||
477 | # | ||
478 | # CD-ROM/DVD Filesystems | ||
479 | # | ||
480 | # CONFIG_ISO9660_FS is not set | ||
481 | # CONFIG_UDF_FS is not set | ||
482 | |||
483 | # | ||
484 | # DOS/FAT/NT Filesystems | ||
485 | # | ||
486 | # CONFIG_MSDOS_FS is not set | ||
487 | # CONFIG_VFAT_FS is not set | ||
488 | # CONFIG_NTFS_FS is not set | ||
489 | |||
490 | # | ||
491 | # Pseudo filesystems | ||
492 | # | ||
493 | CONFIG_PROC_FS=y | ||
494 | CONFIG_PROC_KCORE=y | ||
495 | CONFIG_PROC_SYSCTL=y | ||
496 | # CONFIG_PROC_PAGE_MONITOR is not set | ||
497 | CONFIG_SYSFS=y | ||
498 | CONFIG_TMPFS=y | ||
499 | CONFIG_TMPFS_POSIX_ACL=y | ||
500 | # CONFIG_HUGETLB_PAGE is not set | ||
501 | # CONFIG_CONFIGFS_FS is not set | ||
502 | CONFIG_MISC_FILESYSTEMS=y | ||
503 | # CONFIG_ADFS_FS is not set | ||
504 | # CONFIG_AFFS_FS is not set | ||
505 | # CONFIG_ECRYPT_FS is not set | ||
506 | # CONFIG_HFS_FS is not set | ||
507 | # CONFIG_HFSPLUS_FS is not set | ||
508 | # CONFIG_BEFS_FS is not set | ||
509 | # CONFIG_BFS_FS is not set | ||
510 | # CONFIG_EFS_FS is not set | ||
511 | # CONFIG_CRAMFS is not set | ||
512 | # CONFIG_SQUASHFS is not set | ||
513 | # CONFIG_VXFS_FS is not set | ||
514 | # CONFIG_MINIX_FS is not set | ||
515 | # CONFIG_OMFS_FS is not set | ||
516 | # CONFIG_HPFS_FS is not set | ||
517 | # CONFIG_QNX4FS_FS is not set | ||
518 | # CONFIG_ROMFS_FS is not set | ||
519 | # CONFIG_SYSV_FS is not set | ||
520 | # CONFIG_UFS_FS is not set | ||
521 | # CONFIG_NILFS2_FS is not set | ||
522 | CONFIG_NETWORK_FILESYSTEMS=y | ||
523 | CONFIG_NFS_FS=y | ||
524 | CONFIG_NFS_V3=y | ||
525 | CONFIG_NFS_V3_ACL=y | ||
526 | CONFIG_NFS_V4=y | ||
527 | CONFIG_NFSD=y | ||
528 | CONFIG_NFSD_V2_ACL=y | ||
529 | CONFIG_NFSD_V3=y | ||
530 | CONFIG_NFSD_V3_ACL=y | ||
531 | CONFIG_NFSD_V4=y | ||
532 | CONFIG_LOCKD=y | ||
533 | CONFIG_LOCKD_V4=y | ||
534 | CONFIG_EXPORTFS=y | ||
535 | CONFIG_NFS_ACL_SUPPORT=y | ||
536 | CONFIG_NFS_COMMON=y | ||
537 | CONFIG_SUNRPC=y | ||
538 | CONFIG_SUNRPC_GSS=y | ||
539 | CONFIG_RPCSEC_GSS_KRB5=y | ||
540 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
541 | # CONFIG_SMB_FS is not set | ||
542 | # CONFIG_CIFS is not set | ||
543 | # CONFIG_NCP_FS is not set | ||
544 | # CONFIG_CODA_FS is not set | ||
545 | # CONFIG_AFS_FS is not set | ||
546 | |||
547 | # | ||
548 | # Partition Types | ||
549 | # | ||
550 | # CONFIG_PARTITION_ADVANCED is not set | ||
551 | CONFIG_MSDOS_PARTITION=y | ||
552 | # CONFIG_NLS is not set | ||
553 | # CONFIG_DLM is not set | ||
554 | |||
555 | # | ||
556 | # Kernel hacking | ||
557 | # | ||
558 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
559 | # CONFIG_PRINTK_TIME is not set | ||
560 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
561 | CONFIG_ENABLE_MUST_CHECK=y | ||
562 | CONFIG_FRAME_WARN=1024 | ||
563 | # CONFIG_MAGIC_SYSRQ is not set | ||
564 | # CONFIG_UNUSED_SYMBOLS is not set | ||
565 | # CONFIG_DEBUG_FS is not set | ||
566 | # CONFIG_HEADERS_CHECK is not set | ||
567 | # CONFIG_DEBUG_KERNEL is not set | ||
568 | # CONFIG_DEBUG_MEMORY_INIT is not set | ||
569 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
570 | # CONFIG_SYSCTL_SYSCALL_CHECK is not set | ||
571 | CONFIG_TRACING_SUPPORT=y | ||
572 | |||
573 | # | ||
574 | # Tracers | ||
575 | # | ||
576 | # CONFIG_IRQSOFF_TRACER is not set | ||
577 | # CONFIG_SCHED_TRACER is not set | ||
578 | # CONFIG_CONTEXT_SWITCH_TRACER is not set | ||
579 | # CONFIG_EVENT_TRACER is not set | ||
580 | # CONFIG_BOOT_TRACER is not set | ||
581 | # CONFIG_TRACE_BRANCH_PROFILING is not set | ||
582 | # CONFIG_KMEMTRACE is not set | ||
583 | # CONFIG_WORKQUEUE_TRACER is not set | ||
584 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
585 | # CONFIG_SAMPLES is not set | ||
586 | CONFIG_CMDLINE="" | ||
587 | |||
588 | # | ||
589 | # Security options | ||
590 | # | ||
591 | CONFIG_KEYS=y | ||
592 | CONFIG_KEYS_DEBUG_PROC_KEYS=y | ||
593 | CONFIG_SECURITY=y | ||
594 | # CONFIG_SECURITYFS is not set | ||
595 | CONFIG_SECURITY_NETWORK=y | ||
596 | # CONFIG_SECURITY_NETWORK_XFRM is not set | ||
597 | # CONFIG_SECURITY_PATH is not set | ||
598 | CONFIG_SECURITY_FILE_CAPABILITIES=y | ||
599 | CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 | ||
600 | # CONFIG_SECURITY_TOMOYO is not set | ||
601 | CONFIG_CRYPTO=y | ||
602 | |||
603 | # | ||
604 | # Crypto core or helper | ||
605 | # | ||
606 | # CONFIG_CRYPTO_FIPS is not set | ||
607 | CONFIG_CRYPTO_ALGAPI=y | ||
608 | CONFIG_CRYPTO_ALGAPI2=y | ||
609 | CONFIG_CRYPTO_AEAD=y | ||
610 | CONFIG_CRYPTO_AEAD2=y | ||
611 | CONFIG_CRYPTO_BLKCIPHER=y | ||
612 | CONFIG_CRYPTO_BLKCIPHER2=y | ||
613 | CONFIG_CRYPTO_HASH=y | ||
614 | CONFIG_CRYPTO_HASH2=y | ||
615 | CONFIG_CRYPTO_RNG=y | ||
616 | CONFIG_CRYPTO_RNG2=y | ||
617 | CONFIG_CRYPTO_PCOMP=y | ||
618 | CONFIG_CRYPTO_MANAGER=y | ||
619 | CONFIG_CRYPTO_MANAGER2=y | ||
620 | # CONFIG_CRYPTO_GF128MUL is not set | ||
621 | CONFIG_CRYPTO_NULL=y | ||
622 | CONFIG_CRYPTO_WORKQUEUE=y | ||
623 | CONFIG_CRYPTO_CRYPTD=y | ||
624 | # CONFIG_CRYPTO_AUTHENC is not set | ||
625 | # CONFIG_CRYPTO_TEST is not set | ||
626 | |||
627 | # | ||
628 | # Authenticated Encryption with Associated Data | ||
629 | # | ||
630 | # CONFIG_CRYPTO_CCM is not set | ||
631 | # CONFIG_CRYPTO_GCM is not set | ||
632 | CONFIG_CRYPTO_SEQIV=y | ||
633 | |||
634 | # | ||
635 | # Block modes | ||
636 | # | ||
637 | CONFIG_CRYPTO_CBC=y | ||
638 | # CONFIG_CRYPTO_CTR is not set | ||
639 | # CONFIG_CRYPTO_CTS is not set | ||
640 | # CONFIG_CRYPTO_ECB is not set | ||
641 | # CONFIG_CRYPTO_LRW is not set | ||
642 | # CONFIG_CRYPTO_PCBC is not set | ||
643 | # CONFIG_CRYPTO_XTS is not set | ||
644 | |||
645 | # | ||
646 | # Hash modes | ||
647 | # | ||
648 | # CONFIG_CRYPTO_HMAC is not set | ||
649 | # CONFIG_CRYPTO_XCBC is not set | ||
650 | |||
651 | # | ||
652 | # Digest | ||
653 | # | ||
654 | CONFIG_CRYPTO_CRC32C=y | ||
655 | CONFIG_CRYPTO_MD4=y | ||
656 | CONFIG_CRYPTO_MD5=y | ||
657 | CONFIG_CRYPTO_MICHAEL_MIC=y | ||
658 | # CONFIG_CRYPTO_RMD128 is not set | ||
659 | # CONFIG_CRYPTO_RMD160 is not set | ||
660 | # CONFIG_CRYPTO_RMD256 is not set | ||
661 | # CONFIG_CRYPTO_RMD320 is not set | ||
662 | # CONFIG_CRYPTO_SHA1 is not set | ||
663 | # CONFIG_CRYPTO_SHA256 is not set | ||
664 | # CONFIG_CRYPTO_SHA512 is not set | ||
665 | # CONFIG_CRYPTO_TGR192 is not set | ||
666 | # CONFIG_CRYPTO_WP512 is not set | ||
667 | |||
668 | # | ||
669 | # Ciphers | ||
670 | # | ||
671 | # CONFIG_CRYPTO_AES is not set | ||
672 | # CONFIG_CRYPTO_ANUBIS is not set | ||
673 | # CONFIG_CRYPTO_ARC4 is not set | ||
674 | # CONFIG_CRYPTO_BLOWFISH is not set | ||
675 | # CONFIG_CRYPTO_CAMELLIA is not set | ||
676 | # CONFIG_CRYPTO_CAST5 is not set | ||
677 | # CONFIG_CRYPTO_CAST6 is not set | ||
678 | CONFIG_CRYPTO_DES=y | ||
679 | # CONFIG_CRYPTO_FCRYPT is not set | ||
680 | # CONFIG_CRYPTO_KHAZAD is not set | ||
681 | # CONFIG_CRYPTO_SALSA20 is not set | ||
682 | # CONFIG_CRYPTO_SEED is not set | ||
683 | # CONFIG_CRYPTO_SERPENT is not set | ||
684 | # CONFIG_CRYPTO_TEA is not set | ||
685 | # CONFIG_CRYPTO_TWOFISH is not set | ||
686 | |||
687 | # | ||
688 | # Compression | ||
689 | # | ||
690 | # CONFIG_CRYPTO_DEFLATE is not set | ||
691 | # CONFIG_CRYPTO_ZLIB is not set | ||
692 | # CONFIG_CRYPTO_LZO is not set | ||
693 | |||
694 | # | ||
695 | # Random Number Generation | ||
696 | # | ||
697 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | ||
698 | # CONFIG_CRYPTO_HW is not set | ||
699 | # CONFIG_BINARY_PRINTF is not set | ||
700 | |||
701 | # | ||
702 | # Library routines | ||
703 | # | ||
704 | CONFIG_BITREVERSE=y | ||
705 | CONFIG_GENERIC_FIND_LAST_BIT=y | ||
706 | CONFIG_CRC_CCITT=y | ||
707 | CONFIG_CRC16=y | ||
708 | # CONFIG_CRC_T10DIF is not set | ||
709 | # CONFIG_CRC_ITU_T is not set | ||
710 | CONFIG_CRC32=y | ||
711 | # CONFIG_CRC7 is not set | ||
712 | CONFIG_LIBCRC32C=y | ||
713 | CONFIG_ZLIB_INFLATE=y | ||
714 | CONFIG_DECOMPRESS_GZIP=y | ||
715 | CONFIG_HAS_IOMEM=y | ||
716 | CONFIG_HAS_IOPORT=y | ||
717 | CONFIG_NLATTR=y | ||
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild new file mode 100644 index 000000000000..b367abd4620f --- /dev/null +++ b/arch/score/include/asm/Kbuild | |||
@@ -0,0 +1,3 @@ | |||
1 | include include/asm-generic/Kbuild.asm | ||
2 | |||
3 | header-y += | ||
diff --git a/arch/score/include/asm/asmmacro.h b/arch/score/include/asm/asmmacro.h new file mode 100644 index 000000000000..a04a54cea25d --- /dev/null +++ b/arch/score/include/asm/asmmacro.h | |||
@@ -0,0 +1,161 @@ | |||
1 | #ifndef _ASM_SCORE_ASMMACRO_H | ||
2 | #define _ASM_SCORE_ASMMACRO_H | ||
3 | |||
4 | #include <asm/asm-offsets.h> | ||
5 | |||
6 | #ifdef __ASSEMBLY__ | ||
7 | |||
8 | .macro SAVE_ALL | ||
9 | mfcr r30, cr0 | ||
10 | mv r31, r0 | ||
11 | nop | ||
12 | /* if UMs == 1, change stack. */ | ||
13 | slli.c r30, r30, 28 | ||
14 | bpl 1f | ||
15 | la r31, kernelsp | ||
16 | lw r31, [r31] | ||
17 | 1: | ||
18 | mv r30, r0 | ||
19 | addri r0, r31, -PT_SIZE | ||
20 | |||
21 | sw r30, [r0, PT_R0] | ||
22 | .set r1 | ||
23 | sw r1, [r0, PT_R1] | ||
24 | .set nor1 | ||
25 | sw r2, [r0, PT_R2] | ||
26 | sw r3, [r0, PT_R3] | ||
27 | sw r4, [r0, PT_R4] | ||
28 | sw r5, [r0, PT_R5] | ||
29 | sw r6, [r0, PT_R6] | ||
30 | sw r7, [r0, PT_R7] | ||
31 | |||
32 | sw r8, [r0, PT_R8] | ||
33 | sw r9, [r0, PT_R9] | ||
34 | sw r10, [r0, PT_R10] | ||
35 | sw r11, [r0, PT_R11] | ||
36 | sw r12, [r0, PT_R12] | ||
37 | sw r13, [r0, PT_R13] | ||
38 | sw r14, [r0, PT_R14] | ||
39 | sw r15, [r0, PT_R15] | ||
40 | |||
41 | sw r16, [r0, PT_R16] | ||
42 | sw r17, [r0, PT_R17] | ||
43 | sw r18, [r0, PT_R18] | ||
44 | sw r19, [r0, PT_R19] | ||
45 | sw r20, [r0, PT_R20] | ||
46 | sw r21, [r0, PT_R21] | ||
47 | sw r22, [r0, PT_R22] | ||
48 | sw r23, [r0, PT_R23] | ||
49 | |||
50 | sw r24, [r0, PT_R24] | ||
51 | sw r25, [r0, PT_R25] | ||
52 | sw r25, [r0, PT_R25] | ||
53 | sw r26, [r0, PT_R26] | ||
54 | sw r27, [r0, PT_R27] | ||
55 | |||
56 | sw r28, [r0, PT_R28] | ||
57 | sw r29, [r0, PT_R29] | ||
58 | orri r28, r0, 0x1fff | ||
59 | li r31, 0x00001fff | ||
60 | xor r28, r28, r31 | ||
61 | |||
62 | mfcehl r30, r31 | ||
63 | sw r30, [r0, PT_CEH] | ||
64 | sw r31, [r0, PT_CEL] | ||
65 | |||
66 | mfcr r31, cr0 | ||
67 | sw r31, [r0, PT_PSR] | ||
68 | |||
69 | mfcr r31, cr1 | ||
70 | sw r31, [r0, PT_CONDITION] | ||
71 | |||
72 | mfcr r31, cr2 | ||
73 | sw r31, [r0, PT_ECR] | ||
74 | |||
75 | mfcr r31, cr5 | ||
76 | srli r31, r31, 1 | ||
77 | slli r31, r31, 1 | ||
78 | sw r31, [r0, PT_EPC] | ||
79 | .endm | ||
80 | |||
81 | .macro RESTORE_ALL_AND_RET | ||
82 | mfcr r30, cr0 | ||
83 | srli r30, r30, 1 | ||
84 | slli r30, r30, 1 | ||
85 | mtcr r30, cr0 | ||
86 | nop | ||
87 | nop | ||
88 | nop | ||
89 | nop | ||
90 | nop | ||
91 | |||
92 | .set r1 | ||
93 | ldis r1, 0x00ff | ||
94 | and r30, r30, r1 | ||
95 | not r1, r1 | ||
96 | lw r31, [r0, PT_PSR] | ||
97 | and r31, r31, r1 | ||
98 | .set nor1 | ||
99 | or r31, r31, r30 | ||
100 | mtcr r31, cr0 | ||
101 | nop | ||
102 | nop | ||
103 | nop | ||
104 | nop | ||
105 | nop | ||
106 | |||
107 | lw r30, [r0, PT_CONDITION] | ||
108 | mtcr r30, cr1 | ||
109 | nop | ||
110 | nop | ||
111 | nop | ||
112 | nop | ||
113 | nop | ||
114 | |||
115 | lw r30, [r0, PT_CEH] | ||
116 | lw r31, [r0, PT_CEL] | ||
117 | mtcehl r30, r31 | ||
118 | |||
119 | .set r1 | ||
120 | lw r1, [r0, PT_R1] | ||
121 | .set nor1 | ||
122 | lw r2, [r0, PT_R2] | ||
123 | lw r3, [r0, PT_R3] | ||
124 | lw r4, [r0, PT_R4] | ||
125 | lw r5, [r0, PT_R5] | ||
126 | lw r6, [r0, PT_R6] | ||
127 | lw r7, [r0, PT_R7] | ||
128 | |||
129 | lw r8, [r0, PT_R8] | ||
130 | lw r9, [r0, PT_R9] | ||
131 | lw r10, [r0, PT_R10] | ||
132 | lw r11, [r0, PT_R11] | ||
133 | lw r12, [r0, PT_R12] | ||
134 | lw r13, [r0, PT_R13] | ||
135 | lw r14, [r0, PT_R14] | ||
136 | lw r15, [r0, PT_R15] | ||
137 | |||
138 | lw r16, [r0, PT_R16] | ||
139 | lw r17, [r0, PT_R17] | ||
140 | lw r18, [r0, PT_R18] | ||
141 | lw r19, [r0, PT_R19] | ||
142 | lw r20, [r0, PT_R20] | ||
143 | lw r21, [r0, PT_R21] | ||
144 | lw r22, [r0, PT_R22] | ||
145 | lw r23, [r0, PT_R23] | ||
146 | |||
147 | lw r24, [r0, PT_R24] | ||
148 | lw r25, [r0, PT_R25] | ||
149 | lw r26, [r0, PT_R26] | ||
150 | lw r27, [r0, PT_R27] | ||
151 | lw r28, [r0, PT_R28] | ||
152 | lw r29, [r0, PT_R29] | ||
153 | |||
154 | lw r30, [r0, PT_EPC] | ||
155 | lw r0, [r0, PT_R0] | ||
156 | mtcr r30, cr5 | ||
157 | rte | ||
158 | .endm | ||
159 | |||
160 | #endif /* __ASSEMBLY__ */ | ||
161 | #endif /* _ASM_SCORE_ASMMACRO_H */ | ||
diff --git a/arch/score/include/asm/atomic.h b/arch/score/include/asm/atomic.h new file mode 100644 index 000000000000..84eb8ddf9f3f --- /dev/null +++ b/arch/score/include/asm/atomic.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_ATOMIC_H | ||
2 | #define _ASM_SCORE_ATOMIC_H | ||
3 | |||
4 | #include <asm-generic/atomic.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_ATOMIC_H */ | ||
diff --git a/arch/score/include/asm/auxvec.h b/arch/score/include/asm/auxvec.h new file mode 100644 index 000000000000..f69151565aee --- /dev/null +++ b/arch/score/include/asm/auxvec.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef _ASM_SCORE_AUXVEC_H | ||
2 | #define _ASM_SCORE_AUXVEC_H | ||
3 | |||
4 | #endif /* _ASM_SCORE_AUXVEC_H */ | ||
diff --git a/arch/score/include/asm/bitops.h b/arch/score/include/asm/bitops.h new file mode 100644 index 000000000000..2763b050fca8 --- /dev/null +++ b/arch/score/include/asm/bitops.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef _ASM_SCORE_BITOPS_H | ||
2 | #define _ASM_SCORE_BITOPS_H | ||
3 | |||
4 | #include <asm/byteorder.h> /* swab32 */ | ||
5 | #include <asm/system.h> /* save_flags */ | ||
6 | |||
7 | /* | ||
8 | * clear_bit() doesn't provide any barrier for the compiler. | ||
9 | */ | ||
10 | #define smp_mb__before_clear_bit() barrier() | ||
11 | #define smp_mb__after_clear_bit() barrier() | ||
12 | |||
13 | #include <asm-generic/bitops.h> | ||
14 | #include <asm-generic/bitops/__fls.h> | ||
15 | |||
16 | #endif /* _ASM_SCORE_BITOPS_H */ | ||
diff --git a/arch/score/include/asm/bitsperlong.h b/arch/score/include/asm/bitsperlong.h new file mode 100644 index 000000000000..86ff337aa459 --- /dev/null +++ b/arch/score/include/asm/bitsperlong.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_BITSPERLONG_H | ||
2 | #define _ASM_SCORE_BITSPERLONG_H | ||
3 | |||
4 | #include <asm-generic/bitsperlong.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_BITSPERLONG_H */ | ||
diff --git a/arch/score/include/asm/bug.h b/arch/score/include/asm/bug.h new file mode 100644 index 000000000000..bb76a330bcf1 --- /dev/null +++ b/arch/score/include/asm/bug.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_BUG_H | ||
2 | #define _ASM_SCORE_BUG_H | ||
3 | |||
4 | #include <asm-generic/bug.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_BUG_H */ | ||
diff --git a/arch/score/include/asm/bugs.h b/arch/score/include/asm/bugs.h new file mode 100644 index 000000000000..a062e1056bb3 --- /dev/null +++ b/arch/score/include/asm/bugs.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_BUGS_H | ||
2 | #define _ASM_SCORE_BUGS_H | ||
3 | |||
4 | #include <asm-generic/bugs.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_BUGS_H */ | ||
diff --git a/arch/score/include/asm/byteorder.h b/arch/score/include/asm/byteorder.h new file mode 100644 index 000000000000..88cbebc79212 --- /dev/null +++ b/arch/score/include/asm/byteorder.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_BYTEORDER_H | ||
2 | #define _ASM_SCORE_BYTEORDER_H | ||
3 | |||
4 | #include <linux/byteorder/little_endian.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_BYTEORDER_H */ | ||
diff --git a/arch/score/include/asm/cache.h b/arch/score/include/asm/cache.h new file mode 100644 index 000000000000..ae3d59f2d2c4 --- /dev/null +++ b/arch/score/include/asm/cache.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _ASM_SCORE_CACHE_H | ||
2 | #define _ASM_SCORE_CACHE_H | ||
3 | |||
4 | #define L1_CACHE_SHIFT 4 | ||
5 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | ||
6 | |||
7 | #endif /* _ASM_SCORE_CACHE_H */ | ||
diff --git a/arch/score/include/asm/cacheflush.h b/arch/score/include/asm/cacheflush.h new file mode 100644 index 000000000000..07cc8fc457cd --- /dev/null +++ b/arch/score/include/asm/cacheflush.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef _ASM_SCORE_CACHEFLUSH_H | ||
2 | #define _ASM_SCORE_CACHEFLUSH_H | ||
3 | |||
4 | /* Keep includes the same across arches. */ | ||
5 | #include <linux/mm.h> | ||
6 | |||
7 | extern void flush_cache_all(void); | ||
8 | extern void flush_cache_mm(struct mm_struct *mm); | ||
9 | extern void flush_cache_range(struct vm_area_struct *vma, | ||
10 | unsigned long start, unsigned long end); | ||
11 | extern void flush_cache_page(struct vm_area_struct *vma, | ||
12 | unsigned long page, unsigned long pfn); | ||
13 | extern void flush_cache_sigtramp(unsigned long addr); | ||
14 | extern void flush_icache_all(void); | ||
15 | extern void flush_icache_range(unsigned long start, unsigned long end); | ||
16 | extern void flush_dcache_range(unsigned long start, unsigned long end); | ||
17 | |||
18 | #define flush_cache_dup_mm(mm) do {} while (0) | ||
19 | #define flush_dcache_page(page) do {} while (0) | ||
20 | #define flush_dcache_mmap_lock(mapping) do {} while (0) | ||
21 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) | ||
22 | #define flush_cache_vmap(start, end) do {} while (0) | ||
23 | #define flush_cache_vunmap(start, end) do {} while (0) | ||
24 | |||
25 | static inline void flush_icache_page(struct vm_area_struct *vma, | ||
26 | struct page *page) | ||
27 | { | ||
28 | if (vma->vm_flags & VM_EXEC) { | ||
29 | void *v = page_address(page); | ||
30 | flush_icache_range((unsigned long) v, | ||
31 | (unsigned long) v + PAGE_SIZE); | ||
32 | } | ||
33 | } | ||
34 | |||
35 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | ||
36 | memcpy(dst, src, len) | ||
37 | |||
38 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | ||
39 | do { \ | ||
40 | memcpy(dst, src, len); \ | ||
41 | if ((vma->vm_flags & VM_EXEC)) \ | ||
42 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ | ||
43 | } while (0) | ||
44 | |||
45 | #endif /* _ASM_SCORE_CACHEFLUSH_H */ | ||
diff --git a/arch/score/include/asm/checksum.h b/arch/score/include/asm/checksum.h new file mode 100644 index 000000000000..f909ac3144a4 --- /dev/null +++ b/arch/score/include/asm/checksum.h | |||
@@ -0,0 +1,235 @@ | |||
1 | #ifndef _ASM_SCORE_CHECKSUM_H | ||
2 | #define _ASM_SCORE_CHECKSUM_H | ||
3 | |||
4 | #include <linux/in6.h> | ||
5 | #include <asm/uaccess.h> | ||
6 | |||
7 | /* | ||
8 | * computes the checksum of a memory block at buff, length len, | ||
9 | * and adds in "sum" (32-bit) | ||
10 | * | ||
11 | * returns a 32-bit number suitable for feeding into itself | ||
12 | * or csum_tcpudp_magic | ||
13 | * | ||
14 | * this function must be called with even lengths, except | ||
15 | * for the last fragment, which may be odd | ||
16 | * | ||
17 | * it's best to have buff aligned on a 32-bit boundary | ||
18 | */ | ||
19 | unsigned int csum_partial(const void *buff, int len, __wsum sum); | ||
20 | unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, | ||
21 | unsigned int sum, int *csum_err); | ||
22 | unsigned int csum_partial_copy(const char *src, char *dst, | ||
23 | int len, unsigned int sum); | ||
24 | |||
25 | /* | ||
26 | * this is a new version of the above that records errors it finds in *errp, | ||
27 | * but continues and zeros the rest of the buffer. | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Copy and checksum to user | ||
32 | */ | ||
33 | #define HAVE_CSUM_COPY_USER | ||
34 | static inline | ||
35 | __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, | ||
36 | __wsum sum, int *err_ptr) | ||
37 | { | ||
38 | sum = csum_partial(src, len, sum); | ||
39 | if (copy_to_user(dst, src, len)) { | ||
40 | *err_ptr = -EFAULT; | ||
41 | return (__force __wsum) -1; /* invalid checksum */ | ||
42 | } | ||
43 | return sum; | ||
44 | } | ||
45 | |||
46 | |||
47 | #define csum_partial_copy_nocheck csum_partial_copy | ||
48 | /* | ||
49 | * Fold a partial checksum without adding pseudo headers | ||
50 | */ | ||
51 | |||
52 | static inline __sum16 csum_fold(__wsum sum) | ||
53 | { | ||
54 | /* the while loop is unnecessary really, it's always enough with two | ||
55 | iterations */ | ||
56 | __asm__ __volatile__( | ||
57 | ".set volatile\n\t" | ||
58 | ".set\tr1\n\t" | ||
59 | "slli\tr1,%0, 16\n\t" | ||
60 | "add\t%0,%0, r1\n\t" | ||
61 | "cmp.c\tr1, %0\n\t" | ||
62 | "srli\t%0, %0, 16\n\t" | ||
63 | "bleu\t1f\n\t" | ||
64 | "addi\t%0, 0x1\n\t" | ||
65 | "1:ldi\tr30, 0xffff\n\t" | ||
66 | "xor\t%0, %0, r30\n\t" | ||
67 | "slli\t%0, %0, 16\n\t" | ||
68 | "srli\t%0, %0, 16\n\t" | ||
69 | ".set\tnor1\n\t" | ||
70 | ".set optimize\n\t" | ||
71 | : "=r" (sum) | ||
72 | : "0" (sum)); | ||
73 | return sum; | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * This is a version of ip_compute_csum() optimized for IP headers, | ||
78 | * which always checksum on 4 octet boundaries. | ||
79 | * | ||
80 | * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by | ||
81 | * Arnt Gulbrandsen. | ||
82 | */ | ||
83 | static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) | ||
84 | { | ||
85 | unsigned int sum; | ||
86 | unsigned long dummy; | ||
87 | |||
88 | __asm__ __volatile__( | ||
89 | ".set volatile\n\t" | ||
90 | ".set\tnor1\n\t" | ||
91 | "lw\t%0, [%1]\n\t" | ||
92 | "subri\t%2, %2, 4\n\t" | ||
93 | "slli\t%2, %2, 2\n\t" | ||
94 | "lw\t%3, [%1, 4]\n\t" | ||
95 | "add\t%2, %2, %1\n\t" | ||
96 | "add\t%0, %0, %3\n\t" | ||
97 | "cmp.c\t%3, %0\n\t" | ||
98 | "lw\t%3, [%1, 8]\n\t" | ||
99 | "bleu\t1f\n\t" | ||
100 | "addi\t%0, 0x1\n\t" | ||
101 | "1:\n\t" | ||
102 | "add\t%0, %0, %3\n\t" | ||
103 | "cmp.c\t%3, %0\n\t" | ||
104 | "lw\t%3, [%1, 12]\n\t" | ||
105 | "bleu\t1f\n\t" | ||
106 | "addi\t%0, 0x1\n\t" | ||
107 | "1:add\t%0, %0, %3\n\t" | ||
108 | "cmp.c\t%3, %0\n\t" | ||
109 | "bleu\t1f\n\t" | ||
110 | "addi\t%0, 0x1\n" | ||
111 | |||
112 | "1:\tlw\t%3, [%1, 16]\n\t" | ||
113 | "addi\t%1, 4\n\t" | ||
114 | "add\t%0, %0, %3\n\t" | ||
115 | "cmp.c\t%3, %0\n\t" | ||
116 | "bleu\t2f\n\t" | ||
117 | "addi\t%0, 0x1\n" | ||
118 | "2:cmp.c\t%2, %1\n\t" | ||
119 | "bne\t1b\n\t" | ||
120 | |||
121 | ".set\tr1\n\t" | ||
122 | ".set optimize\n\t" | ||
123 | : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy) | ||
124 | : "1" (iph), "2" (ihl)); | ||
125 | |||
126 | return csum_fold(sum); | ||
127 | } | ||
128 | |||
129 | static inline __wsum | ||
130 | csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, | ||
131 | unsigned short proto, __wsum sum) | ||
132 | { | ||
133 | unsigned long tmp = (ntohs(len) << 16) + proto * 256; | ||
134 | __asm__ __volatile__( | ||
135 | ".set volatile\n\t" | ||
136 | "add\t%0, %0, %2\n\t" | ||
137 | "cmp.c\t%2, %0\n\t" | ||
138 | "bleu\t1f\n\t" | ||
139 | "addi\t%0, 0x1\n\t" | ||
140 | "1:\n\t" | ||
141 | "add\t%0, %0, %3\n\t" | ||
142 | "cmp.c\t%3, %0\n\t" | ||
143 | "bleu\t1f\n\t" | ||
144 | "addi\t%0, 0x1\n\t" | ||
145 | "1:\n\t" | ||
146 | "add\t%0, %0, %4\n\t" | ||
147 | "cmp.c\t%4, %0\n\t" | ||
148 | "bleu\t1f\n\t" | ||
149 | "addi\t%0, 0x1\n\t" | ||
150 | "1:\n\t" | ||
151 | ".set optimize\n\t" | ||
152 | : "=r" (sum) | ||
153 | : "0" (daddr), "r"(saddr), | ||
154 | "r" (tmp), | ||
155 | "r" (sum)); | ||
156 | return sum; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * computes the checksum of the TCP/UDP pseudo-header | ||
161 | * returns a 16-bit checksum, already complemented | ||
162 | */ | ||
163 | static inline __sum16 | ||
164 | csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, | ||
165 | unsigned short proto, __wsum sum) | ||
166 | { | ||
167 | return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * this routine is used for miscellaneous IP-like checksums, mainly | ||
172 | * in icmp.c | ||
173 | */ | ||
174 | |||
175 | static inline unsigned short ip_compute_csum(const void *buff, int len) | ||
176 | { | ||
177 | return csum_fold(csum_partial(buff, len, 0)); | ||
178 | } | ||
179 | |||
180 | #define _HAVE_ARCH_IPV6_CSUM | ||
181 | static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, | ||
182 | const struct in6_addr *daddr, | ||
183 | __u32 len, unsigned short proto, | ||
184 | __wsum sum) | ||
185 | { | ||
186 | __asm__ __volatile__( | ||
187 | ".set\tnoreorder\t\t\t# csum_ipv6_magic\n\t" | ||
188 | ".set\tnoat\n\t" | ||
189 | "addu\t%0, %5\t\t\t# proto (long in network byte order)\n\t" | ||
190 | "sltu\t$1, %0, %5\n\t" | ||
191 | "addu\t%0, $1\n\t" | ||
192 | "addu\t%0, %6\t\t\t# csum\n\t" | ||
193 | "sltu\t$1, %0, %6\n\t" | ||
194 | "lw\t%1, 0(%2)\t\t\t# four words source address\n\t" | ||
195 | "addu\t%0, $1\n\t" | ||
196 | "addu\t%0, %1\n\t" | ||
197 | "sltu\t$1, %0, %1\n\t" | ||
198 | "lw\t%1, 4(%2)\n\t" | ||
199 | "addu\t%0, $1\n\t" | ||
200 | "addu\t%0, %1\n\t" | ||
201 | "sltu\t$1, %0, %1\n\t" | ||
202 | "lw\t%1, 8(%2)\n\t" | ||
203 | "addu\t%0, $1\n\t" | ||
204 | "addu\t%0, %1\n\t" | ||
205 | "sltu\t$1, %0, %1\n\t" | ||
206 | "lw\t%1, 12(%2)\n\t" | ||
207 | "addu\t%0, $1\n\t" | ||
208 | "addu\t%0, %1\n\t" | ||
209 | "sltu\t$1, %0, %1\n\t" | ||
210 | "lw\t%1, 0(%3)\n\t" | ||
211 | "addu\t%0, $1\n\t" | ||
212 | "addu\t%0, %1\n\t" | ||
213 | "sltu\t$1, %0, %1\n\t" | ||
214 | "lw\t%1, 4(%3)\n\t" | ||
215 | "addu\t%0, $1\n\t" | ||
216 | "addu\t%0, %1\n\t" | ||
217 | "sltu\t$1, %0, %1\n\t" | ||
218 | "lw\t%1, 8(%3)\n\t" | ||
219 | "addu\t%0, $1\n\t" | ||
220 | "addu\t%0, %1\n\t" | ||
221 | "sltu\t$1, %0, %1\n\t" | ||
222 | "lw\t%1, 12(%3)\n\t" | ||
223 | "addu\t%0, $1\n\t" | ||
224 | "addu\t%0, %1\n\t" | ||
225 | "sltu\t$1, %0, %1\n\t" | ||
226 | "addu\t%0, $1\t\t\t# Add final carry\n\t" | ||
227 | ".set\tnoat\n\t" | ||
228 | ".set\tnoreorder" | ||
229 | : "=r" (sum), "=r" (proto) | ||
230 | : "r" (saddr), "r" (daddr), | ||
231 | "0" (htonl(len)), "1" (htonl(proto)), "r" (sum)); | ||
232 | |||
233 | return csum_fold(sum); | ||
234 | } | ||
235 | #endif /* _ASM_SCORE_CHECKSUM_H */ | ||
diff --git a/arch/score/include/asm/cputime.h b/arch/score/include/asm/cputime.h new file mode 100644 index 000000000000..1fced99f0d67 --- /dev/null +++ b/arch/score/include/asm/cputime.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_CPUTIME_H | ||
2 | #define _ASM_SCORE_CPUTIME_H | ||
3 | |||
4 | #include <asm-generic/cputime.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_CPUTIME_H */ | ||
diff --git a/arch/score/include/asm/current.h b/arch/score/include/asm/current.h new file mode 100644 index 000000000000..16eae9cbaf1a --- /dev/null +++ b/arch/score/include/asm/current.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_CURRENT_H | ||
2 | #define _ASM_SCORE_CURRENT_H | ||
3 | |||
4 | #include <asm-generic/current.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_CURRENT_H */ | ||
diff --git a/arch/score/include/asm/delay.h b/arch/score/include/asm/delay.h new file mode 100644 index 000000000000..6726ec199dc0 --- /dev/null +++ b/arch/score/include/asm/delay.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef _ASM_SCORE_DELAY_H | ||
2 | #define _ASM_SCORE_DELAY_H | ||
3 | |||
4 | static inline void __delay(unsigned long loops) | ||
5 | { | ||
6 | /* 3 cycles per loop. */ | ||
7 | __asm__ __volatile__ ( | ||
8 | "1:\tsubi\t%0, 3\n\t" | ||
9 | "cmpz.c\t%0\n\t" | ||
10 | "ble\t1b\n\t" | ||
11 | : "=r" (loops) | ||
12 | : "0" (loops)); | ||
13 | } | ||
14 | |||
15 | static inline void __udelay(unsigned long usecs) | ||
16 | { | ||
17 | unsigned long loops_per_usec; | ||
18 | |||
19 | loops_per_usec = (loops_per_jiffy * HZ) / 1000000; | ||
20 | |||
21 | __delay(usecs * loops_per_usec); | ||
22 | } | ||
23 | |||
24 | #define udelay(usecs) __udelay(usecs) | ||
25 | |||
26 | #endif /* _ASM_SCORE_DELAY_H */ | ||
diff --git a/arch/score/include/asm/device.h b/arch/score/include/asm/device.h new file mode 100644 index 000000000000..2dc7cc5d5ef9 --- /dev/null +++ b/arch/score/include/asm/device.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_DEVICE_H | ||
2 | #define _ASM_SCORE_DEVICE_H | ||
3 | |||
4 | #include <asm-generic/device.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_DEVICE_H */ | ||
diff --git a/arch/score/include/asm/div64.h b/arch/score/include/asm/div64.h new file mode 100644 index 000000000000..75fae19824eb --- /dev/null +++ b/arch/score/include/asm/div64.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_DIV64_H | ||
2 | #define _ASM_SCORE_DIV64_H | ||
3 | |||
4 | #include <asm-generic/div64.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_DIV64_H */ | ||
diff --git a/arch/score/include/asm/dma-mapping.h b/arch/score/include/asm/dma-mapping.h new file mode 100644 index 000000000000..f9c0193c7a53 --- /dev/null +++ b/arch/score/include/asm/dma-mapping.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_DMA_MAPPING_H | ||
2 | #define _ASM_SCORE_DMA_MAPPING_H | ||
3 | |||
4 | #include <asm-generic/dma-mapping-broken.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_DMA_MAPPING_H */ | ||
diff --git a/arch/score/include/asm/dma.h b/arch/score/include/asm/dma.h new file mode 100644 index 000000000000..9f44185298bf --- /dev/null +++ b/arch/score/include/asm/dma.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _ASM_SCORE_DMA_H | ||
2 | #define _ASM_SCORE_DMA_H | ||
3 | |||
4 | #include <asm/io.h> | ||
5 | |||
6 | #define MAX_DMA_ADDRESS (0) | ||
7 | |||
8 | #endif /* _ASM_SCORE_DMA_H */ | ||
diff --git a/arch/score/include/asm/elf.h b/arch/score/include/asm/elf.h new file mode 100644 index 000000000000..43526d9fda93 --- /dev/null +++ b/arch/score/include/asm/elf.h | |||
@@ -0,0 +1,103 @@ | |||
1 | #ifndef _ASM_SCORE_ELF_H | ||
2 | #define _ASM_SCORE_ELF_H | ||
3 | |||
4 | #include <linux/ptrace.h> | ||
5 | |||
6 | #define EM_SCORE7 135 | ||
7 | |||
8 | /* Relocation types. */ | ||
9 | #define R_SCORE_NONE 0 | ||
10 | #define R_SCORE_HI16 1 | ||
11 | #define R_SCORE_LO16 2 | ||
12 | #define R_SCORE_BCMP 3 | ||
13 | #define R_SCORE_24 4 | ||
14 | #define R_SCORE_PC19 5 | ||
15 | #define R_SCORE16_11 6 | ||
16 | #define R_SCORE16_PC8 7 | ||
17 | #define R_SCORE_ABS32 8 | ||
18 | #define R_SCORE_ABS16 9 | ||
19 | #define R_SCORE_DUMMY2 10 | ||
20 | #define R_SCORE_GP15 11 | ||
21 | #define R_SCORE_GNU_VTINHERIT 12 | ||
22 | #define R_SCORE_GNU_VTENTRY 13 | ||
23 | #define R_SCORE_GOT15 14 | ||
24 | #define R_SCORE_GOT_LO16 15 | ||
25 | #define R_SCORE_CALL15 16 | ||
26 | #define R_SCORE_GPREL32 17 | ||
27 | #define R_SCORE_REL32 18 | ||
28 | #define R_SCORE_DUMMY_HI16 19 | ||
29 | #define R_SCORE_IMM30 20 | ||
30 | #define R_SCORE_IMM32 21 | ||
31 | |||
32 | /* ELF register definitions */ | ||
33 | typedef unsigned long elf_greg_t; | ||
34 | |||
35 | #define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t)) | ||
36 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | ||
37 | |||
38 | /* Score does not have fp regs. */ | ||
39 | typedef double elf_fpreg_t; | ||
40 | typedef elf_fpreg_t elf_fpregset_t; | ||
41 | |||
42 | #define elf_check_arch(x) ((x)->e_machine == EM_SCORE7) | ||
43 | |||
44 | /* | ||
45 | * These are used to set parameters in the core dumps. | ||
46 | */ | ||
47 | #define ELF_CLASS ELFCLASS32 | ||
48 | |||
49 | /* | ||
50 | * These are used to set parameters in the core dumps. | ||
51 | */ | ||
52 | #define ELF_DATA ELFDATA2LSB | ||
53 | #define ELF_ARCH EM_SCORE7 | ||
54 | |||
55 | #define SET_PERSONALITY(ex) \ | ||
56 | do { \ | ||
57 | set_personality(PER_LINUX); \ | ||
58 | } while (0) | ||
59 | |||
60 | struct task_struct; | ||
61 | struct pt_regs; | ||
62 | |||
63 | #define CORE_DUMP_USE_REGSET | ||
64 | #define USE_ELF_CORE_DUMP | ||
65 | #define ELF_EXEC_PAGESIZE PAGE_SIZE | ||
66 | |||
67 | /* This yields a mask that user programs can use to figure out what | ||
68 | instruction set this cpu supports. This could be done in userspace, | ||
69 | but it's not easy, and we've already done it here. */ | ||
70 | |||
71 | #define ELF_HWCAP (0) | ||
72 | |||
73 | /* This yields a string that ld.so will use to load implementation | ||
74 | specific libraries for optimization. This is more specific in | ||
75 | intent than poking at uname or /proc/cpuinfo. | ||
76 | |||
77 | For the moment, we have only optimizations for the Intel generations, | ||
78 | but that could change... */ | ||
79 | |||
80 | #define ELF_PLATFORM (NULL) | ||
81 | |||
82 | #define ELF_PLAT_INIT(_r, load_addr) \ | ||
83 | do { \ | ||
84 | _r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0; \ | ||
85 | _r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \ | ||
86 | _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \ | ||
87 | _r->regs[13] = _r->regs[14] = _r->regs[15] = _r->regs[16] = 0; \ | ||
88 | _r->regs[17] = _r->regs[18] = _r->regs[19] = _r->regs[20] = 0; \ | ||
89 | _r->regs[21] = _r->regs[22] = _r->regs[23] = _r->regs[24] = 0; \ | ||
90 | _r->regs[25] = _r->regs[26] = _r->regs[27] = _r->regs[28] = 0; \ | ||
91 | _r->regs[30] = _r->regs[31] = 0; \ | ||
92 | } while (0) | ||
93 | |||
94 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical | ||
95 | use of this is to invoke "./ld.so someprog" to test out a new version of | ||
96 | the loader. We need to make sure that it is out of the way of the program | ||
97 | that it will "exec", and that there is sufficient room for the brk. */ | ||
98 | |||
99 | #ifndef ELF_ET_DYN_BASE | ||
100 | #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) | ||
101 | #endif | ||
102 | |||
103 | #endif /* _ASM_SCORE_ELF_H */ | ||
diff --git a/arch/score/include/asm/emergency-restart.h b/arch/score/include/asm/emergency-restart.h new file mode 100644 index 000000000000..ca31e9803a8a --- /dev/null +++ b/arch/score/include/asm/emergency-restart.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_EMERGENCY_RESTART_H | ||
2 | #define _ASM_SCORE_EMERGENCY_RESTART_H | ||
3 | |||
4 | #include <asm-generic/emergency-restart.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_EMERGENCY_RESTART_H */ | ||
diff --git a/arch/score/include/asm/errno.h b/arch/score/include/asm/errno.h new file mode 100644 index 000000000000..29ff39d5ab47 --- /dev/null +++ b/arch/score/include/asm/errno.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_ERRNO_H | ||
2 | #define _ASM_SCORE_ERRNO_H | ||
3 | |||
4 | #include <asm-generic/errno.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_ERRNO_H */ | ||
diff --git a/arch/score/include/asm/fcntl.h b/arch/score/include/asm/fcntl.h new file mode 100644 index 000000000000..03968a3103a4 --- /dev/null +++ b/arch/score/include/asm/fcntl.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_FCNTL_H | ||
2 | #define _ASM_SCORE_FCNTL_H | ||
3 | |||
4 | #include <asm-generic/fcntl.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_FCNTL_H */ | ||
diff --git a/arch/score/include/asm/fixmap.h b/arch/score/include/asm/fixmap.h new file mode 100644 index 000000000000..ee1676694024 --- /dev/null +++ b/arch/score/include/asm/fixmap.h | |||
@@ -0,0 +1,82 @@ | |||
1 | #ifndef _ASM_SCORE_FIXMAP_H | ||
2 | #define _ASM_SCORE_FIXMAP_H | ||
3 | |||
4 | #include <asm/page.h> | ||
5 | |||
6 | #define PHY_RAM_BASE 0x00000000 | ||
7 | #define PHY_IO_BASE 0x10000000 | ||
8 | |||
9 | #define VIRTUAL_RAM_BASE 0xa0000000 | ||
10 | #define VIRTUAL_IO_BASE 0xb0000000 | ||
11 | |||
12 | #define RAM_SPACE_SIZE 0x10000000 | ||
13 | #define IO_SPACE_SIZE 0x10000000 | ||
14 | |||
15 | /* Kernel unmapped, cached 512MB */ | ||
16 | #define KSEG1 0xa0000000 | ||
17 | |||
18 | /* | ||
19 | * Here we define all the compile-time 'special' virtual | ||
20 | * addresses. The point is to have a constant address at | ||
21 | * compile time, but to set the physical address only | ||
22 | * in the boot process. We allocate these special addresses | ||
23 | * from the end of virtual memory (0xfffff000) backwards. | ||
24 | * Also this lets us do fail-safe vmalloc(), we | ||
25 | * can guarantee that these special addresses and | ||
26 | * vmalloc()-ed addresses never overlap. | ||
27 | * | ||
28 | * these 'compile-time allocated' memory buffers are | ||
29 | * fixed-size 4k pages. (or larger if used with an increment | ||
30 | * highger than 1) use fixmap_set(idx,phys) to associate | ||
31 | * physical memory with fixmap indices. | ||
32 | * | ||
33 | * TLB entries of such buffers will not be flushed across | ||
34 | * task switches. | ||
35 | */ | ||
36 | |||
37 | /* | ||
38 | * on UP currently we will have no trace of the fixmap mechanizm, | ||
39 | * no page table allocations, etc. This might change in the | ||
40 | * future, say framebuffers for the console driver(s) could be | ||
41 | * fix-mapped? | ||
42 | */ | ||
43 | enum fixed_addresses { | ||
44 | #define FIX_N_COLOURS 8 | ||
45 | FIX_CMAP_BEGIN, | ||
46 | FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS, | ||
47 | __end_of_fixed_addresses | ||
48 | }; | ||
49 | |||
50 | /* | ||
51 | * used by vmalloc.c. | ||
52 | * | ||
53 | * Leave one empty page between vmalloc'ed areas and | ||
54 | * the start of the fixmap, and leave one page empty | ||
55 | * at the top of mem.. | ||
56 | */ | ||
57 | #define FIXADDR_TOP ((unsigned long)(long)(int)0xfefe0000) | ||
58 | #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | ||
59 | #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) | ||
60 | |||
61 | #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) | ||
62 | #define __virt_to_fix(x) \ | ||
63 | ((FIXADDR_TOP - ((x) & PAGE_MASK)) >> PAGE_SHIFT) | ||
64 | |||
65 | extern void __this_fixmap_does_not_exist(void); | ||
66 | |||
67 | /* | ||
68 | * 'index to address' translation. If anyone tries to use the idx | ||
69 | * directly without tranlation, we catch the bug with a NULL-deference | ||
70 | * kernel oops. Illegal ranges of incoming indices are caught too. | ||
71 | */ | ||
72 | static inline unsigned long fix_to_virt(const unsigned int idx) | ||
73 | { | ||
74 | return __fix_to_virt(idx); | ||
75 | } | ||
76 | |||
77 | static inline unsigned long virt_to_fix(const unsigned long vaddr) | ||
78 | { | ||
79 | return __virt_to_fix(vaddr); | ||
80 | } | ||
81 | |||
82 | #endif /* _ASM_SCORE_FIXMAP_H */ | ||
diff --git a/arch/score/include/asm/ftrace.h b/arch/score/include/asm/ftrace.h new file mode 100644 index 000000000000..79d6f10e1f5b --- /dev/null +++ b/arch/score/include/asm/ftrace.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef _ASM_SCORE_FTRACE_H | ||
2 | #define _ASM_SCORE_FTRACE_H | ||
3 | |||
4 | #endif /* _ASM_SCORE_FTRACE_H */ | ||
diff --git a/arch/score/include/asm/futex.h b/arch/score/include/asm/futex.h new file mode 100644 index 000000000000..1dca2420f8db --- /dev/null +++ b/arch/score/include/asm/futex.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_FUTEX_H | ||
2 | #define _ASM_SCORE_FUTEX_H | ||
3 | |||
4 | #include <asm-generic/futex.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_FUTEX_H */ | ||
diff --git a/arch/score/include/asm/hardirq.h b/arch/score/include/asm/hardirq.h new file mode 100644 index 000000000000..dc932c50d3ee --- /dev/null +++ b/arch/score/include/asm/hardirq.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_HARDIRQ_H | ||
2 | #define _ASM_SCORE_HARDIRQ_H | ||
3 | |||
4 | #include <asm-generic/hardirq.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_HARDIRQ_H */ | ||
diff --git a/arch/score/include/asm/hw_irq.h b/arch/score/include/asm/hw_irq.h new file mode 100644 index 000000000000..4caafb2b509a --- /dev/null +++ b/arch/score/include/asm/hw_irq.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef _ASM_SCORE_HW_IRQ_H | ||
2 | #define _ASM_SCORE_HW_IRQ_H | ||
3 | |||
4 | #endif /* _ASM_SCORE_HW_IRQ_H */ | ||
diff --git a/arch/score/include/asm/io.h b/arch/score/include/asm/io.h new file mode 100644 index 000000000000..fbbfd7132e3b --- /dev/null +++ b/arch/score/include/asm/io.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _ASM_SCORE_IO_H | ||
2 | #define _ASM_SCORE_IO_H | ||
3 | |||
4 | #include <asm-generic/io.h> | ||
5 | |||
6 | #define virt_to_bus virt_to_phys | ||
7 | #define bus_to_virt phys_to_virt | ||
8 | |||
9 | #endif /* _ASM_SCORE_IO_H */ | ||
diff --git a/arch/score/include/asm/ioctl.h b/arch/score/include/asm/ioctl.h new file mode 100644 index 000000000000..a351d2194bfd --- /dev/null +++ b/arch/score/include/asm/ioctl.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_IOCTL_H | ||
2 | #define _ASM_SCORE_IOCTL_H | ||
3 | |||
4 | #include <asm-generic/ioctl.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_IOCTL_H */ | ||
diff --git a/arch/score/include/asm/ioctls.h b/arch/score/include/asm/ioctls.h new file mode 100644 index 000000000000..ed01d2b9aeab --- /dev/null +++ b/arch/score/include/asm/ioctls.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_IOCTLS_H | ||
2 | #define _ASM_SCORE_IOCTLS_H | ||
3 | |||
4 | #include <asm-generic/ioctls.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_IOCTLS_H */ | ||
diff --git a/arch/score/include/asm/ipcbuf.h b/arch/score/include/asm/ipcbuf.h new file mode 100644 index 000000000000..e082ceff1818 --- /dev/null +++ b/arch/score/include/asm/ipcbuf.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_IPCBUF_H | ||
2 | #define _ASM_SCORE_IPCBUF_H | ||
3 | |||
4 | #include <asm-generic/ipcbuf.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_IPCBUF_H */ | ||
diff --git a/arch/score/include/asm/irq.h b/arch/score/include/asm/irq.h new file mode 100644 index 000000000000..c883f3df33fa --- /dev/null +++ b/arch/score/include/asm/irq.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _ASM_SCORE_IRQ_H | ||
2 | #define _ASM_SCORE_IRQ_H | ||
3 | |||
4 | #define EXCEPTION_VECTOR_BASE_ADDR 0xa0000000 | ||
5 | #define VECTOR_ADDRESS_OFFSET_MODE4 0 | ||
6 | #define VECTOR_ADDRESS_OFFSET_MODE16 1 | ||
7 | |||
8 | #define DEBUG_VECTOR_SIZE (0x4) | ||
9 | #define DEBUG_VECTOR_BASE_ADDR ((EXCEPTION_VECTOR_BASE_ADDR) + 0x1fc) | ||
10 | |||
11 | #define GENERAL_VECTOR_SIZE (0x10) | ||
12 | #define GENERAL_VECTOR_BASE_ADDR ((EXCEPTION_VECTOR_BASE_ADDR) + 0x200) | ||
13 | |||
14 | #define NR_IRQS 64 | ||
15 | #define IRQ_VECTOR_SIZE (0x10) | ||
16 | #define IRQ_VECTOR_BASE_ADDR ((EXCEPTION_VECTOR_BASE_ADDR) + 0x210) | ||
17 | #define IRQ_VECTOR_END_ADDR ((EXCEPTION_VECTOR_BASE_ADDR) + 0x5f0) | ||
18 | |||
19 | #define irq_canonicalize(irq) (irq) | ||
20 | |||
21 | #define IRQ_TIMER (7) /* Timer IRQ number of SPCT6600 */ | ||
22 | |||
23 | extern void interrupt_exception_vector(void); | ||
24 | |||
25 | #endif /* _ASM_SCORE_IRQ_H */ | ||
diff --git a/arch/score/include/asm/irq_regs.h b/arch/score/include/asm/irq_regs.h new file mode 100644 index 000000000000..b8e881c9a69f --- /dev/null +++ b/arch/score/include/asm/irq_regs.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _ASM_SCORE_IRQ_REGS_H | ||
2 | #define _ASM_SCORE_IRQ_REGS_H | ||
3 | |||
4 | #include <linux/thread_info.h> | ||
5 | |||
6 | static inline struct pt_regs *get_irq_regs(void) | ||
7 | { | ||
8 | return current_thread_info()->regs; | ||
9 | } | ||
10 | |||
11 | #endif /* _ASM_SCORE_IRQ_REGS_H */ | ||
diff --git a/arch/score/include/asm/irqflags.h b/arch/score/include/asm/irqflags.h new file mode 100644 index 000000000000..690a6cae7294 --- /dev/null +++ b/arch/score/include/asm/irqflags.h | |||
@@ -0,0 +1,109 @@ | |||
1 | #ifndef _ASM_SCORE_IRQFLAGS_H | ||
2 | #define _ASM_SCORE_IRQFLAGS_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | |||
6 | #define raw_local_irq_save(x) \ | ||
7 | { \ | ||
8 | __asm__ __volatile__( \ | ||
9 | "mfcr r8, cr0;" \ | ||
10 | "li r9, 0xfffffffe;" \ | ||
11 | "nop;" \ | ||
12 | "mv %0, r8;" \ | ||
13 | "and r8, r8, r9;" \ | ||
14 | "mtcr r8, cr0;" \ | ||
15 | "nop;" \ | ||
16 | "nop;" \ | ||
17 | "nop;" \ | ||
18 | "nop;" \ | ||
19 | "nop;" \ | ||
20 | : "=r" (x) \ | ||
21 | : \ | ||
22 | : "r8", "r9" \ | ||
23 | ); \ | ||
24 | } | ||
25 | |||
26 | #define raw_local_irq_restore(x) \ | ||
27 | { \ | ||
28 | __asm__ __volatile__( \ | ||
29 | "mfcr r8, cr0;" \ | ||
30 | "ldi r9, 0x1;" \ | ||
31 | "and %0, %0, r9;" \ | ||
32 | "or r8, r8, %0;" \ | ||
33 | "mtcr r8, cr0;" \ | ||
34 | "nop;" \ | ||
35 | "nop;" \ | ||
36 | "nop;" \ | ||
37 | "nop;" \ | ||
38 | "nop;" \ | ||
39 | : \ | ||
40 | : "r"(x) \ | ||
41 | : "r8", "r9" \ | ||
42 | ); \ | ||
43 | } | ||
44 | |||
45 | #define raw_local_irq_enable(void) \ | ||
46 | { \ | ||
47 | __asm__ __volatile__( \ | ||
48 | "mfcr\tr8,cr0;" \ | ||
49 | "nop;" \ | ||
50 | "nop;" \ | ||
51 | "ori\tr8,0x1;" \ | ||
52 | "mtcr\tr8,cr0;" \ | ||
53 | "nop;" \ | ||
54 | "nop;" \ | ||
55 | "nop;" \ | ||
56 | "nop;" \ | ||
57 | "nop;" \ | ||
58 | : \ | ||
59 | : \ | ||
60 | : "r8"); \ | ||
61 | } | ||
62 | |||
63 | #define raw_local_irq_disable(void) \ | ||
64 | { \ | ||
65 | __asm__ __volatile__( \ | ||
66 | "mfcr\tr8,cr0;" \ | ||
67 | "nop;" \ | ||
68 | "nop;" \ | ||
69 | "srli\tr8,r8,1;" \ | ||
70 | "slli\tr8,r8,1;" \ | ||
71 | "mtcr\tr8,cr0;" \ | ||
72 | "nop;" \ | ||
73 | "nop;" \ | ||
74 | "nop;" \ | ||
75 | "nop;" \ | ||
76 | "nop;" \ | ||
77 | : \ | ||
78 | : \ | ||
79 | : "r8"); \ | ||
80 | } | ||
81 | |||
82 | #define raw_local_save_flags(x) \ | ||
83 | { \ | ||
84 | __asm__ __volatile__( \ | ||
85 | "mfcr r8, cr0;" \ | ||
86 | "nop;" \ | ||
87 | "nop;" \ | ||
88 | "mv %0, r8;" \ | ||
89 | "nop;" \ | ||
90 | "nop;" \ | ||
91 | "nop;" \ | ||
92 | "nop;" \ | ||
93 | "nop;" \ | ||
94 | "ldi r9, 0x1;" \ | ||
95 | "and %0, %0, r9;" \ | ||
96 | : "=r" (x) \ | ||
97 | : \ | ||
98 | : "r8", "r9" \ | ||
99 | ); \ | ||
100 | } | ||
101 | |||
102 | static inline int raw_irqs_disabled_flags(unsigned long flags) | ||
103 | { | ||
104 | return !(flags & 1); | ||
105 | } | ||
106 | |||
107 | #endif | ||
108 | |||
109 | #endif /* _ASM_SCORE_IRQFLAGS_H */ | ||
diff --git a/arch/score/include/asm/kdebug.h b/arch/score/include/asm/kdebug.h new file mode 100644 index 000000000000..a666e513f747 --- /dev/null +++ b/arch/score/include/asm/kdebug.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_KDEBUG_H | ||
2 | #define _ASM_SCORE_KDEBUG_H | ||
3 | |||
4 | #include <asm-generic/kdebug.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_KDEBUG_H */ | ||
diff --git a/arch/score/include/asm/kmap_types.h b/arch/score/include/asm/kmap_types.h new file mode 100644 index 000000000000..6c46eb5077d3 --- /dev/null +++ b/arch/score/include/asm/kmap_types.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_KMAP_TYPES_H | ||
2 | #define _ASM_SCORE_KMAP_TYPES_H | ||
3 | |||
4 | #include <asm-generic/kmap_types.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_KMAP_TYPES_H */ | ||
diff --git a/arch/score/include/asm/linkage.h b/arch/score/include/asm/linkage.h new file mode 100644 index 000000000000..2323a8ecf445 --- /dev/null +++ b/arch/score/include/asm/linkage.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef _ASM_SCORE_LINKAGE_H | ||
2 | #define _ASM_SCORE_LINKAGE_H | ||
3 | |||
4 | #define __ALIGN .align 2 | ||
5 | #define __ALIGN_STR ".align 2" | ||
6 | |||
7 | #endif /* _ASM_SCORE_LINKAGE_H */ | ||
diff --git a/arch/score/include/asm/local.h b/arch/score/include/asm/local.h new file mode 100644 index 000000000000..7e02f13dbba8 --- /dev/null +++ b/arch/score/include/asm/local.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_LOCAL_H | ||
2 | #define _ASM_SCORE_LOCAL_H | ||
3 | |||
4 | #include <asm-generic/local.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_LOCAL_H */ | ||
diff --git a/arch/score/include/asm/mman.h b/arch/score/include/asm/mman.h new file mode 100644 index 000000000000..84d85ddfed8d --- /dev/null +++ b/arch/score/include/asm/mman.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_MMAN_H | ||
2 | #define _ASM_SCORE_MMAN_H | ||
3 | |||
4 | #include <asm-generic/mman.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_MMAN_H */ | ||
diff --git a/arch/score/include/asm/mmu.h b/arch/score/include/asm/mmu.h new file mode 100644 index 000000000000..676828e4c10a --- /dev/null +++ b/arch/score/include/asm/mmu.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_MMU_H | ||
2 | #define _ASM_SCORE_MMU_H | ||
3 | |||
4 | typedef unsigned long mm_context_t; | ||
5 | |||
6 | #endif /* _ASM_SCORE_MMU_H */ | ||
diff --git a/arch/score/include/asm/mmu_context.h b/arch/score/include/asm/mmu_context.h new file mode 100644 index 000000000000..2644577c96e8 --- /dev/null +++ b/arch/score/include/asm/mmu_context.h | |||
@@ -0,0 +1,113 @@ | |||
1 | #ifndef _ASM_SCORE_MMU_CONTEXT_H | ||
2 | #define _ASM_SCORE_MMU_CONTEXT_H | ||
3 | |||
4 | #include <linux/errno.h> | ||
5 | #include <linux/sched.h> | ||
6 | #include <linux/slab.h> | ||
7 | #include <asm-generic/mm_hooks.h> | ||
8 | |||
9 | #include <asm/cacheflush.h> | ||
10 | #include <asm/tlbflush.h> | ||
11 | #include <asm/scoreregs.h> | ||
12 | |||
13 | /* | ||
14 | * For the fast tlb miss handlers, we keep a per cpu array of pointers | ||
15 | * to the current pgd for each processor. Also, the proc. id is stuffed | ||
16 | * into the context register. | ||
17 | */ | ||
18 | extern unsigned long asid_cache; | ||
19 | extern unsigned long pgd_current; | ||
20 | |||
21 | #define TLBMISS_HANDLER_SETUP_PGD(pgd) (pgd_current = (unsigned long)(pgd)) | ||
22 | |||
23 | #define TLBMISS_HANDLER_SETUP() \ | ||
24 | do { \ | ||
25 | write_c0_context(0); \ | ||
26 | TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) \ | ||
27 | } while (0) | ||
28 | |||
29 | /* | ||
30 | * All unused by hardware upper bits will be considered | ||
31 | * as a software asid extension. | ||
32 | */ | ||
33 | #define ASID_VERSION_MASK 0xfffff000 | ||
34 | #define ASID_FIRST_VERSION 0x1000 | ||
35 | |||
36 | /* PEVN --------- VPN ---------- --ASID--- -NA- */ | ||
37 | /* binary: 0000 0000 0000 0000 0000 0000 0001 0000 */ | ||
38 | /* binary: 0000 0000 0000 0000 0000 1111 1111 0000 */ | ||
39 | #define ASID_INC 0x10 | ||
40 | #define ASID_MASK 0xff0 | ||
41 | |||
42 | static inline void enter_lazy_tlb(struct mm_struct *mm, | ||
43 | struct task_struct *tsk) | ||
44 | {} | ||
45 | |||
46 | static inline void | ||
47 | get_new_mmu_context(struct mm_struct *mm) | ||
48 | { | ||
49 | unsigned long asid = asid_cache + ASID_INC; | ||
50 | |||
51 | if (!(asid & ASID_MASK)) { | ||
52 | local_flush_tlb_all(); /* start new asid cycle */ | ||
53 | if (!asid) /* fix version if needed */ | ||
54 | asid = ASID_FIRST_VERSION; | ||
55 | } | ||
56 | |||
57 | mm->context = asid; | ||
58 | asid_cache = asid; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Initialize the context related info for a new mm_struct | ||
63 | * instance. | ||
64 | */ | ||
65 | static inline int | ||
66 | init_new_context(struct task_struct *tsk, struct mm_struct *mm) | ||
67 | { | ||
68 | mm->context = 0; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | ||
73 | struct task_struct *tsk) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | |||
77 | local_irq_save(flags); | ||
78 | if ((next->context ^ asid_cache) & ASID_VERSION_MASK) | ||
79 | get_new_mmu_context(next); | ||
80 | |||
81 | pevn_set(next->context); | ||
82 | TLBMISS_HANDLER_SETUP_PGD(next->pgd); | ||
83 | local_irq_restore(flags); | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * Destroy context related info for an mm_struct that is about | ||
88 | * to be put to rest. | ||
89 | */ | ||
90 | static inline void destroy_context(struct mm_struct *mm) | ||
91 | {} | ||
92 | |||
93 | static inline void | ||
94 | deactivate_mm(struct task_struct *task, struct mm_struct *mm) | ||
95 | {} | ||
96 | |||
97 | /* | ||
98 | * After we have set current->mm to a new value, this activates | ||
99 | * the context for the new mm so we see the new mappings. | ||
100 | */ | ||
101 | static inline void | ||
102 | activate_mm(struct mm_struct *prev, struct mm_struct *next) | ||
103 | { | ||
104 | unsigned long flags; | ||
105 | |||
106 | local_irq_save(flags); | ||
107 | get_new_mmu_context(next); | ||
108 | pevn_set(next->context); | ||
109 | TLBMISS_HANDLER_SETUP_PGD(next->pgd); | ||
110 | local_irq_restore(flags); | ||
111 | } | ||
112 | |||
113 | #endif /* _ASM_SCORE_MMU_CONTEXT_H */ | ||
diff --git a/arch/score/include/asm/module.h b/arch/score/include/asm/module.h new file mode 100644 index 000000000000..f0b5dc0bd023 --- /dev/null +++ b/arch/score/include/asm/module.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef _ASM_SCORE_MODULE_H | ||
2 | #define _ASM_SCORE_MODULE_H | ||
3 | |||
4 | #include <linux/list.h> | ||
5 | #include <asm/uaccess.h> | ||
6 | |||
7 | struct mod_arch_specific { | ||
8 | /* Data Bus Error exception tables */ | ||
9 | struct list_head dbe_list; | ||
10 | const struct exception_table_entry *dbe_start; | ||
11 | const struct exception_table_entry *dbe_end; | ||
12 | }; | ||
13 | |||
14 | typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ | ||
15 | |||
16 | #define Elf_Shdr Elf32_Shdr | ||
17 | #define Elf_Sym Elf32_Sym | ||
18 | #define Elf_Ehdr Elf32_Ehdr | ||
19 | #define Elf_Addr Elf32_Addr | ||
20 | |||
21 | /* Given an address, look for it in the exception tables. */ | ||
22 | #ifdef CONFIG_MODULES | ||
23 | const struct exception_table_entry *search_module_dbetables(unsigned long addr); | ||
24 | #else | ||
25 | static inline const struct exception_table_entry | ||
26 | *search_module_dbetables(unsigned long addr) | ||
27 | { | ||
28 | return NULL; | ||
29 | } | ||
30 | #endif | ||
31 | |||
32 | #define MODULE_PROC_FAMILY "SCORE7" | ||
33 | #define MODULE_KERNEL_TYPE "32BIT " | ||
34 | #define MODULE_KERNEL_SMTC "" | ||
35 | |||
36 | #define MODULE_ARCH_VERMAGIC \ | ||
37 | MODULE_PROC_FAMILY MODULE_KERNEL_TYPE MODULE_KERNEL_SMTC | ||
38 | |||
39 | #endif /* _ASM_SCORE_MODULE_H */ | ||
diff --git a/arch/score/include/asm/msgbuf.h b/arch/score/include/asm/msgbuf.h new file mode 100644 index 000000000000..7506721e29fa --- /dev/null +++ b/arch/score/include/asm/msgbuf.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_MSGBUF_H | ||
2 | #define _ASM_SCORE_MSGBUF_H | ||
3 | |||
4 | #include <asm-generic/msgbuf.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_MSGBUF_H */ | ||
diff --git a/arch/score/include/asm/mutex.h b/arch/score/include/asm/mutex.h new file mode 100644 index 000000000000..10d48fe4db97 --- /dev/null +++ b/arch/score/include/asm/mutex.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_MUTEX_H | ||
2 | #define _ASM_SCORE_MUTEX_H | ||
3 | |||
4 | #include <asm-generic/mutex-dec.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_MUTEX_H */ | ||
diff --git a/arch/score/include/asm/page.h b/arch/score/include/asm/page.h new file mode 100644 index 000000000000..ee5821042fcc --- /dev/null +++ b/arch/score/include/asm/page.h | |||
@@ -0,0 +1,92 @@ | |||
1 | #ifndef _ASM_SCORE_PAGE_H | ||
2 | #define _ASM_SCORE_PAGE_H | ||
3 | |||
4 | #include <linux/pfn.h> | ||
5 | |||
6 | /* PAGE_SHIFT determines the page size */ | ||
7 | #define PAGE_SHIFT (12) | ||
8 | #define PAGE_SIZE (1UL << PAGE_SHIFT) | ||
9 | #define PAGE_MASK (~(PAGE_SIZE-1)) | ||
10 | |||
11 | #ifdef __KERNEL__ | ||
12 | |||
13 | #ifndef __ASSEMBLY__ | ||
14 | |||
15 | #define PAGE_UP(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1))) | ||
16 | #define PAGE_DOWN(addr) ((addr)&(~((PAGE_SIZE)-1))) | ||
17 | |||
18 | /* align addr on a size boundary - adjust address up/down if needed */ | ||
19 | #define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1))) | ||
20 | #define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) | ||
21 | |||
22 | /* align addr on a size boundary - adjust address up if needed */ | ||
23 | #define _ALIGN(addr, size) _ALIGN_UP(addr, size) | ||
24 | |||
25 | /* | ||
26 | * PAGE_OFFSET -- the first address of the first page of memory. When not | ||
27 | * using MMU this corresponds to the first free page in physical memory (aligned | ||
28 | * on a page boundary). | ||
29 | */ | ||
30 | #define PAGE_OFFSET (0xA0000000UL) | ||
31 | |||
32 | #define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE) | ||
33 | #define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) | ||
34 | |||
35 | #define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE) | ||
36 | #define copy_user_page(vto, vfrom, vaddr, topg) \ | ||
37 | memcpy((vto), (vfrom), PAGE_SIZE) | ||
38 | |||
39 | /* | ||
40 | * These are used to make use of C type-checking.. | ||
41 | */ | ||
42 | |||
43 | typedef struct { unsigned long pte; } pte_t; /* page table entry */ | ||
44 | typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */ | ||
45 | typedef struct { unsigned long pgprot; } pgprot_t; | ||
46 | typedef struct page *pgtable_t; | ||
47 | |||
48 | #define pte_val(x) ((x).pte) | ||
49 | #define pgd_val(x) ((x).pgd) | ||
50 | #define pgprot_val(x) ((x).pgprot) | ||
51 | |||
52 | #define __pte(x) ((pte_t) { (x) }) | ||
53 | #define __pgd(x) ((pgd_t) { (x) }) | ||
54 | #define __pgprot(x) ((pgprot_t) { (x) }) | ||
55 | |||
56 | extern unsigned long max_low_pfn; | ||
57 | extern unsigned long min_low_pfn; | ||
58 | extern unsigned long max_pfn; | ||
59 | |||
60 | #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET) | ||
61 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) | ||
62 | |||
63 | #define phys_to_pfn(phys) (PFN_DOWN(phys)) | ||
64 | #define pfn_to_phys(pfn) (PFN_PHYS(pfn)) | ||
65 | |||
66 | #define virt_to_pfn(vaddr) (phys_to_pfn((__pa(vaddr)))) | ||
67 | #define pfn_to_virt(pfn) __va(pfn_to_phys((pfn))) | ||
68 | |||
69 | #define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr))) | ||
70 | #define page_to_virt(page) (pfn_to_virt(page_to_pfn(page))) | ||
71 | |||
72 | #define page_to_phys(page) (pfn_to_phys(page_to_pfn(page))) | ||
73 | #define page_to_bus(page) (page_to_phys(page)) | ||
74 | #define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr))) | ||
75 | |||
76 | #define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_mapnr) | ||
77 | |||
78 | #define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) | ||
79 | |||
80 | #endif /* __ASSEMBLY__ */ | ||
81 | |||
82 | #define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) | ||
83 | |||
84 | #endif /* __KERNEL__ */ | ||
85 | |||
86 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ | ||
87 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
88 | |||
89 | #include <asm-generic/memory_model.h> | ||
90 | #include <asm-generic/getorder.h> | ||
91 | |||
92 | #endif /* _ASM_SCORE_PAGE_H */ | ||
diff --git a/arch/score/include/asm/param.h b/arch/score/include/asm/param.h new file mode 100644 index 000000000000..916b8690b6aa --- /dev/null +++ b/arch/score/include/asm/param.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_PARAM_H | ||
2 | #define _ASM_SCORE_PARAM_H | ||
3 | |||
4 | #include <asm-generic/param.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_PARAM_H */ | ||
diff --git a/arch/score/include/asm/pci.h b/arch/score/include/asm/pci.h new file mode 100644 index 000000000000..3f3cfd82549c --- /dev/null +++ b/arch/score/include/asm/pci.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef _ASM_SCORE_PCI_H | ||
2 | #define _ASM_SCORE_PCI_H | ||
3 | |||
4 | #endif /* _ASM_SCORE_PCI_H */ | ||
diff --git a/arch/score/include/asm/percpu.h b/arch/score/include/asm/percpu.h new file mode 100644 index 000000000000..e7bd4e05b475 --- /dev/null +++ b/arch/score/include/asm/percpu.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_PERCPU_H | ||
2 | #define _ASM_SCORE_PERCPU_H | ||
3 | |||
4 | #include <asm-generic/percpu.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_PERCPU_H */ | ||
diff --git a/arch/score/include/asm/pgalloc.h b/arch/score/include/asm/pgalloc.h new file mode 100644 index 000000000000..059a61b7071b --- /dev/null +++ b/arch/score/include/asm/pgalloc.h | |||
@@ -0,0 +1,83 @@ | |||
1 | #ifndef _ASM_SCORE_PGALLOC_H | ||
2 | #define _ASM_SCORE_PGALLOC_H | ||
3 | |||
4 | #include <linux/mm.h> | ||
5 | |||
6 | static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, | ||
7 | pte_t *pte) | ||
8 | { | ||
9 | set_pmd(pmd, __pmd((unsigned long)pte)); | ||
10 | } | ||
11 | |||
12 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | ||
13 | pgtable_t pte) | ||
14 | { | ||
15 | set_pmd(pmd, __pmd((unsigned long)page_address(pte))); | ||
16 | } | ||
17 | |||
18 | #define pmd_pgtable(pmd) pmd_page(pmd) | ||
19 | |||
20 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | ||
21 | { | ||
22 | pgd_t *ret, *init; | ||
23 | |||
24 | ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER); | ||
25 | if (ret) { | ||
26 | init = pgd_offset(&init_mm, 0UL); | ||
27 | pgd_init((unsigned long)ret); | ||
28 | memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, | ||
29 | (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); | ||
30 | } | ||
31 | |||
32 | return ret; | ||
33 | } | ||
34 | |||
35 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | ||
36 | { | ||
37 | free_pages((unsigned long)pgd, PGD_ORDER); | ||
38 | } | ||
39 | |||
40 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | ||
41 | unsigned long address) | ||
42 | { | ||
43 | pte_t *pte; | ||
44 | |||
45 | pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, | ||
46 | PTE_ORDER); | ||
47 | |||
48 | return pte; | ||
49 | } | ||
50 | |||
51 | static inline struct page *pte_alloc_one(struct mm_struct *mm, | ||
52 | unsigned long address) | ||
53 | { | ||
54 | struct page *pte; | ||
55 | |||
56 | pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER); | ||
57 | if (pte) { | ||
58 | clear_highpage(pte); | ||
59 | pgtable_page_ctor(pte); | ||
60 | } | ||
61 | return pte; | ||
62 | } | ||
63 | |||
64 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | ||
65 | { | ||
66 | free_pages((unsigned long)pte, PTE_ORDER); | ||
67 | } | ||
68 | |||
69 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | ||
70 | { | ||
71 | pgtable_page_dtor(pte); | ||
72 | __free_pages(pte, PTE_ORDER); | ||
73 | } | ||
74 | |||
75 | #define __pte_free_tlb(tlb, pte, buf) \ | ||
76 | do { \ | ||
77 | pgtable_page_dtor(pte); \ | ||
78 | tlb_remove_page((tlb), pte); \ | ||
79 | } while (0) | ||
80 | |||
81 | #define check_pgt_cache() do {} while (0) | ||
82 | |||
83 | #endif /* _ASM_SCORE_PGALLOC_H */ | ||
diff --git a/arch/score/include/asm/pgtable-bits.h b/arch/score/include/asm/pgtable-bits.h new file mode 100644 index 000000000000..7d65a96a82e5 --- /dev/null +++ b/arch/score/include/asm/pgtable-bits.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _ASM_SCORE_PGTABLE_BITS_H | ||
2 | #define _ASM_SCORE_PGTABLE_BITS_H | ||
3 | |||
4 | #define _PAGE_ACCESSED (1<<5) /* implemented in software */ | ||
5 | #define _PAGE_READ (1<<6) /* implemented in software */ | ||
6 | #define _PAGE_WRITE (1<<7) /* implemented in software */ | ||
7 | #define _PAGE_PRESENT (1<<9) /* implemented in software */ | ||
8 | #define _PAGE_MODIFIED (1<<10) /* implemented in software */ | ||
9 | #define _PAGE_FILE (1<<10) | ||
10 | |||
11 | #define _PAGE_GLOBAL (1<<0) | ||
12 | #define _PAGE_VALID (1<<1) | ||
13 | #define _PAGE_SILENT_READ (1<<1) /* synonym */ | ||
14 | #define _PAGE_DIRTY (1<<2) /* Write bit */ | ||
15 | #define _PAGE_SILENT_WRITE (1<<2) | ||
16 | #define _PAGE_CACHE (1<<3) /* cache */ | ||
17 | #define _CACHE_MASK (1<<3) | ||
18 | #define _PAGE_BUFFERABLE (1<<4) /*Fallow Spec. */ | ||
19 | |||
20 | #define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED) | ||
21 | #define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED) | ||
22 | #define _PAGE_CHG_MASK \ | ||
23 | (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_CACHE) | ||
24 | |||
25 | #endif /* _ASM_SCORE_PGTABLE_BITS_H */ | ||
diff --git a/arch/score/include/asm/pgtable.h b/arch/score/include/asm/pgtable.h new file mode 100644 index 000000000000..674934b40170 --- /dev/null +++ b/arch/score/include/asm/pgtable.h | |||
@@ -0,0 +1,287 @@ | |||
1 | #ifndef _ASM_SCORE_PGTABLE_H | ||
2 | #define _ASM_SCORE_PGTABLE_H | ||
3 | |||
4 | #include <linux/const.h> | ||
5 | #include <asm-generic/pgtable-nopmd.h> | ||
6 | |||
7 | #include <asm/fixmap.h> | ||
8 | #include <asm/setup.h> | ||
9 | #include <asm/pgtable-bits.h> | ||
10 | |||
11 | extern void load_pgd(unsigned long pg_dir); | ||
12 | extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)]; | ||
13 | |||
14 | /* PGDIR_SHIFT determines what a third-level page table entry can map */ | ||
15 | #define PGDIR_SHIFT 22 | ||
16 | #define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) | ||
17 | #define PGDIR_MASK (~(PGDIR_SIZE - 1)) | ||
18 | |||
19 | /* | ||
20 | * Entries per page directory level: we use two-level, so | ||
21 | * we don't really have any PUD/PMD directory physically. | ||
22 | */ | ||
23 | #define PGD_ORDER 0 | ||
24 | #define PTE_ORDER 0 | ||
25 | |||
26 | #define PTRS_PER_PGD 1024 | ||
27 | #define PTRS_PER_PTE 1024 | ||
28 | |||
29 | #define USER_PTRS_PER_PGD (0x80000000UL/PGDIR_SIZE) | ||
30 | #define FIRST_USER_ADDRESS 0 | ||
31 | |||
32 | #define VMALLOC_START (0xc0000000UL) | ||
33 | |||
34 | #define PKMAP_BASE (0xfd000000UL) | ||
35 | |||
36 | #define VMALLOC_END (FIXADDR_START - 2*PAGE_SIZE) | ||
37 | |||
38 | #define pte_ERROR(e) \ | ||
39 | printk(KERN_ERR "%s:%d: bad pte %08lx.\n", \ | ||
40 | __FILE__, __LINE__, pte_val(e)) | ||
41 | #define pgd_ERROR(e) \ | ||
42 | printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", \ | ||
43 | __FILE__, __LINE__, pgd_val(e)) | ||
44 | |||
45 | /* | ||
46 | * Empty pgd/pmd entries point to the invalid_pte_table. | ||
47 | */ | ||
48 | static inline int pmd_none(pmd_t pmd) | ||
49 | { | ||
50 | return pmd_val(pmd) == (unsigned long) invalid_pte_table; | ||
51 | } | ||
52 | |||
53 | #define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) | ||
54 | |||
55 | static inline int pmd_present(pmd_t pmd) | ||
56 | { | ||
57 | return pmd_val(pmd) != (unsigned long) invalid_pte_table; | ||
58 | } | ||
59 | |||
60 | static inline void pmd_clear(pmd_t *pmdp) | ||
61 | { | ||
62 | pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); | ||
63 | } | ||
64 | |||
65 | #define pte_page(x) pfn_to_page(pte_pfn(x)) | ||
66 | #define pte_pfn(x) ((unsigned long)((x).pte >> PAGE_SHIFT)) | ||
67 | #define pfn_pte(pfn, prot) \ | ||
68 | __pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) | ||
69 | |||
70 | #define __pgd_offset(address) pgd_index(address) | ||
71 | #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) | ||
72 | #define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) | ||
73 | |||
74 | /* to find an entry in a kernel page-table-directory */ | ||
75 | #define pgd_offset_k(address) pgd_offset(&init_mm, address) | ||
76 | #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) | ||
77 | |||
78 | /* to find an entry in a page-table-directory */ | ||
79 | #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) | ||
80 | |||
81 | /* Find an entry in the third-level page table.. */ | ||
82 | #define __pte_offset(address) \ | ||
83 | (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | ||
84 | #define pte_offset(dir, address) \ | ||
85 | ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) | ||
86 | #define pte_offset_kernel(dir, address) \ | ||
87 | ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) | ||
88 | |||
89 | #define pte_offset_map(dir, address) \ | ||
90 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | ||
91 | #define pte_offset_map_nested(dir, address) \ | ||
92 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | ||
93 | #define pte_unmap(pte) ((void)(pte)) | ||
94 | #define pte_unmap_nested(pte) ((void)(pte)) | ||
95 | |||
96 | /* | ||
97 | * Bits 9(_PAGE_PRESENT) and 10(_PAGE_FILE)are taken, | ||
98 | * split up 30 bits of offset into this range: | ||
99 | */ | ||
100 | #define PTE_FILE_MAX_BITS 30 | ||
101 | #define pte_to_pgoff(_pte) \ | ||
102 | (((_pte).pte & 0x1ff) | (((_pte).pte >> 11) << 9)) | ||
103 | #define pgoff_to_pte(off) \ | ||
104 | ((pte_t) {((off) & 0x1ff) | (((off) >> 9) << 11) | _PAGE_FILE}) | ||
105 | #define __pte_to_swp_entry(pte) \ | ||
106 | ((swp_entry_t) { pte_val(pte)}) | ||
107 | #define __swp_entry_to_pte(x) ((pte_t) {(x).val}) | ||
108 | |||
109 | #define pmd_phys(pmd) __pa((void *)pmd_val(pmd)) | ||
110 | #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) | ||
111 | #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) | ||
112 | static inline pte_t pte_mkspecial(pte_t pte) { return pte; } | ||
113 | |||
114 | #define set_pte(pteptr, pteval) (*(pteptr) = pteval) | ||
115 | #define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) | ||
116 | #define pte_clear(mm, addr, xp) \ | ||
117 | do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) | ||
118 | |||
119 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | ||
120 | remap_pfn_range(vma, vaddr, pfn, size, prot) | ||
121 | |||
122 | /* | ||
123 | * The "pgd_xxx()" functions here are trivial for a folded two-level | ||
124 | * setup: the pgd is never bad, and a pmd always exists (as it's folded | ||
125 | * into the pgd entry) | ||
126 | */ | ||
127 | #define pgd_present(pgd) (1) | ||
128 | #define pgd_none(pgd) (0) | ||
129 | #define pgd_bad(pgd) (0) | ||
130 | #define pgd_clear(pgdp) do { } while (0) | ||
131 | |||
132 | #define kern_addr_valid(addr) (1) | ||
133 | #define pmd_page_vaddr(pmd) pmd_val(pmd) | ||
134 | |||
135 | #define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) | ||
136 | #define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) | ||
137 | |||
138 | #define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_CACHE) | ||
139 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ | ||
140 | _PAGE_CACHE) | ||
141 | #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_CACHE) | ||
142 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_CACHE) | ||
143 | #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ | ||
144 | _PAGE_GLOBAL | _PAGE_CACHE) | ||
145 | #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \ | ||
146 | __WRITEABLE | _PAGE_GLOBAL & ~_PAGE_CACHE) | ||
147 | |||
148 | #define __P000 PAGE_NONE | ||
149 | #define __P001 PAGE_READONLY | ||
150 | #define __P010 PAGE_COPY | ||
151 | #define __P011 PAGE_COPY | ||
152 | #define __P100 PAGE_READONLY | ||
153 | #define __P101 PAGE_READONLY | ||
154 | #define __P110 PAGE_COPY | ||
155 | #define __P111 PAGE_COPY | ||
156 | |||
157 | #define __S000 PAGE_NONE | ||
158 | #define __S001 PAGE_READONLY | ||
159 | #define __S010 PAGE_SHARED | ||
160 | #define __S011 PAGE_SHARED | ||
161 | #define __S100 PAGE_READONLY | ||
162 | #define __S101 PAGE_READONLY | ||
163 | #define __S110 PAGE_SHARED | ||
164 | #define __S111 PAGE_SHARED | ||
165 | |||
166 | #define pgprot_noncached pgprot_noncached | ||
167 | |||
168 | static inline pgprot_t pgprot_noncached(pgprot_t _prot) | ||
169 | { | ||
170 | unsigned long prot = pgprot_val(_prot); | ||
171 | |||
172 | prot = (prot & ~_CACHE_MASK); | ||
173 | |||
174 | return __pgprot(prot); | ||
175 | } | ||
176 | |||
177 | #define __swp_type(x) ((x).val & 0x1f) | ||
178 | #define __swp_offset(x) ((x).val >> 11) | ||
179 | #define __swp_entry(type, offset) ((swp_entry_t){(type) | ((offset) << 11)}) | ||
180 | |||
181 | extern unsigned long empty_zero_page; | ||
182 | extern unsigned long zero_page_mask; | ||
183 | |||
184 | #define ZERO_PAGE(vaddr) \ | ||
185 | (virt_to_page((void *)(empty_zero_page + \ | ||
186 | (((unsigned long)(vaddr)) & zero_page_mask)))) | ||
187 | |||
188 | #define pgtable_cache_init() do {} while (0) | ||
189 | |||
190 | #define arch_enter_lazy_cpu_mode() do {} while (0) | ||
191 | |||
192 | static inline int pte_write(pte_t pte) | ||
193 | { | ||
194 | return pte_val(pte) & _PAGE_WRITE; | ||
195 | } | ||
196 | |||
197 | static inline int pte_dirty(pte_t pte) | ||
198 | { | ||
199 | return pte_val(pte) & _PAGE_MODIFIED; | ||
200 | } | ||
201 | |||
202 | static inline int pte_young(pte_t pte) | ||
203 | { | ||
204 | return pte_val(pte) & _PAGE_ACCESSED; | ||
205 | } | ||
206 | |||
207 | static inline int pte_file(pte_t pte) | ||
208 | { | ||
209 | return pte_val(pte) & _PAGE_FILE; | ||
210 | } | ||
211 | |||
212 | #define pte_special(pte) (0) | ||
213 | |||
214 | static inline pte_t pte_wrprotect(pte_t pte) | ||
215 | { | ||
216 | pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); | ||
217 | return pte; | ||
218 | } | ||
219 | |||
220 | static inline pte_t pte_mkclean(pte_t pte) | ||
221 | { | ||
222 | pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); | ||
223 | return pte; | ||
224 | } | ||
225 | |||
226 | static inline pte_t pte_mkold(pte_t pte) | ||
227 | { | ||
228 | pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); | ||
229 | return pte; | ||
230 | } | ||
231 | |||
232 | static inline pte_t pte_mkwrite(pte_t pte) | ||
233 | { | ||
234 | pte_val(pte) |= _PAGE_WRITE; | ||
235 | if (pte_val(pte) & _PAGE_MODIFIED) | ||
236 | pte_val(pte) |= _PAGE_SILENT_WRITE; | ||
237 | return pte; | ||
238 | } | ||
239 | |||
240 | static inline pte_t pte_mkdirty(pte_t pte) | ||
241 | { | ||
242 | pte_val(pte) |= _PAGE_MODIFIED; | ||
243 | if (pte_val(pte) & _PAGE_WRITE) | ||
244 | pte_val(pte) |= _PAGE_SILENT_WRITE; | ||
245 | return pte; | ||
246 | } | ||
247 | |||
248 | static inline pte_t pte_mkyoung(pte_t pte) | ||
249 | { | ||
250 | pte_val(pte) |= _PAGE_ACCESSED; | ||
251 | if (pte_val(pte) & _PAGE_READ) | ||
252 | pte_val(pte) |= _PAGE_SILENT_READ; | ||
253 | return pte; | ||
254 | } | ||
255 | |||
256 | #define set_pmd(pmdptr, pmdval) \ | ||
257 | do { *(pmdptr) = (pmdval); } while (0) | ||
258 | #define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) | ||
259 | |||
260 | extern unsigned long pgd_current; | ||
261 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||
262 | extern void paging_init(void); | ||
263 | |||
264 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | ||
265 | { | ||
266 | return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); | ||
267 | } | ||
268 | |||
269 | extern void __update_tlb(struct vm_area_struct *vma, | ||
270 | unsigned long address, pte_t pte); | ||
271 | extern void __update_cache(struct vm_area_struct *vma, | ||
272 | unsigned long address, pte_t pte); | ||
273 | |||
274 | static inline void update_mmu_cache(struct vm_area_struct *vma, | ||
275 | unsigned long address, pte_t pte) | ||
276 | { | ||
277 | __update_tlb(vma, address, pte); | ||
278 | __update_cache(vma, address, pte); | ||
279 | } | ||
280 | |||
281 | #ifndef __ASSEMBLY__ | ||
282 | #include <asm-generic/pgtable.h> | ||
283 | |||
284 | void setup_memory(void); | ||
285 | #endif /* __ASSEMBLY__ */ | ||
286 | |||
287 | #endif /* _ASM_SCORE_PGTABLE_H */ | ||
diff --git a/arch/score/include/asm/poll.h b/arch/score/include/asm/poll.h new file mode 100644 index 000000000000..18532db02861 --- /dev/null +++ b/arch/score/include/asm/poll.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_POLL_H | ||
2 | #define _ASM_SCORE_POLL_H | ||
3 | |||
4 | #include <asm-generic/poll.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_POLL_H */ | ||
diff --git a/arch/score/include/asm/posix_types.h b/arch/score/include/asm/posix_types.h new file mode 100644 index 000000000000..b88acf80048a --- /dev/null +++ b/arch/score/include/asm/posix_types.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_POSIX_TYPES_H | ||
2 | #define _ASM_SCORE_POSIX_TYPES_H | ||
3 | |||
4 | #include <asm-generic/posix_types.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_POSIX_TYPES_H */ | ||
diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h new file mode 100644 index 000000000000..7e22f216d771 --- /dev/null +++ b/arch/score/include/asm/processor.h | |||
@@ -0,0 +1,106 @@ | |||
1 | #ifndef _ASM_SCORE_PROCESSOR_H | ||
2 | #define _ASM_SCORE_PROCESSOR_H | ||
3 | |||
4 | #include <linux/cpumask.h> | ||
5 | #include <linux/threads.h> | ||
6 | |||
7 | #include <asm/segment.h> | ||
8 | |||
9 | struct task_struct; | ||
10 | |||
11 | /* | ||
12 | * System setup and hardware flags.. | ||
13 | */ | ||
14 | extern void (*cpu_wait)(void); | ||
15 | |||
16 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
17 | extern unsigned long thread_saved_pc(struct task_struct *tsk); | ||
18 | extern void start_thread(struct pt_regs *regs, | ||
19 | unsigned long pc, unsigned long sp); | ||
20 | extern unsigned long get_wchan(struct task_struct *p); | ||
21 | |||
22 | /* | ||
23 | * Return current * instruction pointer ("program counter"). | ||
24 | */ | ||
25 | #define current_text_addr() ({ __label__ _l; _l: &&_l; }) | ||
26 | |||
27 | #define cpu_relax() barrier() | ||
28 | #define release_thread(thread) do {} while (0) | ||
29 | #define prepare_to_copy(tsk) do {} while (0) | ||
30 | |||
31 | /* | ||
32 | * User space process size: 2GB. This is hardcoded into a few places, | ||
33 | * so don't change it unless you know what you are doing. | ||
34 | */ | ||
35 | #define TASK_SIZE 0x7fff8000UL | ||
36 | |||
37 | /* | ||
38 | * This decides where the kernel will search for a free chunk of vm | ||
39 | * space during mmap's. | ||
40 | */ | ||
41 | #define TASK_UNMAPPED_BASE ((TASK_SIZE / 3) & ~(PAGE_SIZE)) | ||
42 | |||
43 | #ifdef __KERNEL__ | ||
44 | #define STACK_TOP TASK_SIZE | ||
45 | #define STACK_TOP_MAX TASK_SIZE | ||
46 | #endif | ||
47 | |||
48 | /* | ||
49 | * If you change thread_struct remember to change the #defines below too! | ||
50 | */ | ||
51 | struct thread_struct { | ||
52 | unsigned long reg0, reg2, reg3; | ||
53 | unsigned long reg12, reg13, reg14, reg15, reg16; | ||
54 | unsigned long reg17, reg18, reg19, reg20, reg21; | ||
55 | |||
56 | unsigned long cp0_psr; | ||
57 | unsigned long cp0_ema; /* Last user fault */ | ||
58 | unsigned long cp0_badvaddr; /* Last user fault */ | ||
59 | unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ | ||
60 | unsigned long error_code; | ||
61 | unsigned long trap_no; | ||
62 | |||
63 | unsigned long mflags; | ||
64 | unsigned long reg29; | ||
65 | |||
66 | unsigned long single_step; | ||
67 | unsigned long ss_nextcnt; | ||
68 | |||
69 | unsigned long insn1_type; | ||
70 | unsigned long addr1; | ||
71 | unsigned long insn1; | ||
72 | |||
73 | unsigned long insn2_type; | ||
74 | unsigned long addr2; | ||
75 | unsigned long insn2; | ||
76 | |||
77 | mm_segment_t current_ds; | ||
78 | }; | ||
79 | |||
80 | #define INIT_THREAD { \ | ||
81 | .reg0 = 0, \ | ||
82 | .reg2 = 0, \ | ||
83 | .reg3 = 0, \ | ||
84 | .reg12 = 0, \ | ||
85 | .reg13 = 0, \ | ||
86 | .reg14 = 0, \ | ||
87 | .reg15 = 0, \ | ||
88 | .reg16 = 0, \ | ||
89 | .reg17 = 0, \ | ||
90 | .reg18 = 0, \ | ||
91 | .reg19 = 0, \ | ||
92 | .reg20 = 0, \ | ||
93 | .reg21 = 0, \ | ||
94 | .cp0_psr = 0, \ | ||
95 | .error_code = 0, \ | ||
96 | .trap_no = 0, \ | ||
97 | } | ||
98 | |||
99 | #define kstk_tos(tsk) \ | ||
100 | ((unsigned long)task_stack_page(tsk) + THREAD_SIZE - 32) | ||
101 | #define task_pt_regs(tsk) ((struct pt_regs *)kstk_tos(tsk) - 1) | ||
102 | |||
103 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->cp0_epc) | ||
104 | #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29]) | ||
105 | |||
106 | #endif /* _ASM_SCORE_PROCESSOR_H */ | ||
diff --git a/arch/score/include/asm/ptrace.h b/arch/score/include/asm/ptrace.h new file mode 100644 index 000000000000..d40e691f23e2 --- /dev/null +++ b/arch/score/include/asm/ptrace.h | |||
@@ -0,0 +1,97 @@ | |||
1 | #ifndef _ASM_SCORE_PTRACE_H | ||
2 | #define _ASM_SCORE_PTRACE_H | ||
3 | |||
4 | #define PTRACE_GETREGS 12 | ||
5 | #define PTRACE_SETREGS 13 | ||
6 | |||
7 | #define PC 32 | ||
8 | #define CONDITION 33 | ||
9 | #define ECR 34 | ||
10 | #define EMA 35 | ||
11 | #define CEH 36 | ||
12 | #define CEL 37 | ||
13 | #define COUNTER 38 | ||
14 | #define LDCR 39 | ||
15 | #define STCR 40 | ||
16 | #define PSR 41 | ||
17 | |||
18 | #define SINGLESTEP16_INSN 0x7006 | ||
19 | #define SINGLESTEP32_INSN 0x840C8000 | ||
20 | #define BREAKPOINT16_INSN 0x7002 /* work on SPG300 */ | ||
21 | #define BREAKPOINT32_INSN 0x84048000 /* work on SPG300 */ | ||
22 | |||
23 | /* Define instruction mask */ | ||
24 | #define INSN32_MASK 0x80008000 | ||
25 | |||
26 | #define J32 0x88008000 /* 1_00010_0000000000_1_000000000000000 */ | ||
27 | #define J32M 0xFC008000 /* 1_11111_0000000000_1_000000000000000 */ | ||
28 | |||
29 | #define B32 0x90008000 /* 1_00100_0000000000_1_000000000000000 */ | ||
30 | #define B32M 0xFC008000 | ||
31 | #define BL32 0x90008001 /* 1_00100_0000000000_1_000000000000001 */ | ||
32 | #define BL32M B32 | ||
33 | #define BR32 0x80008008 /* 1_00000_0000000000_1_00000000_000100_0 */ | ||
34 | #define BR32M 0xFFE0807E | ||
35 | #define BRL32 0x80008009 /* 1_00000_0000000000_1_00000000_000100_1 */ | ||
36 | #define BRL32M BR32M | ||
37 | |||
38 | #define B32_SET (J32 | B32 | BL32 | BR32 | BRL32) | ||
39 | |||
40 | #define J16 0x3000 /* 0_011_....... */ | ||
41 | #define J16M 0xF000 | ||
42 | #define B16 0x4000 /* 0_100_....... */ | ||
43 | #define B16M 0xF000 | ||
44 | #define BR16 0x0004 /* 0_000.......0100 */ | ||
45 | #define BR16M 0xF00F | ||
46 | #define B16_SET (J16 | B16 | BR16) | ||
47 | |||
48 | |||
49 | /* | ||
50 | * This struct defines the way the registers are stored on the stack during a | ||
51 | * system call/exception. As usual the registers k0/k1 aren't being saved. | ||
52 | */ | ||
53 | struct pt_regs { | ||
54 | unsigned long pad0[6]; /* stack arguments */ | ||
55 | unsigned long orig_r4; | ||
56 | unsigned long orig_r7; | ||
57 | long is_syscall; | ||
58 | |||
59 | unsigned long regs[32]; | ||
60 | |||
61 | unsigned long cel; | ||
62 | unsigned long ceh; | ||
63 | |||
64 | unsigned long sr0; /* cnt */ | ||
65 | unsigned long sr1; /* lcr */ | ||
66 | unsigned long sr2; /* scr */ | ||
67 | |||
68 | unsigned long cp0_epc; | ||
69 | unsigned long cp0_ema; | ||
70 | unsigned long cp0_psr; | ||
71 | unsigned long cp0_ecr; | ||
72 | unsigned long cp0_condition; | ||
73 | }; | ||
74 | |||
75 | #ifdef __KERNEL__ | ||
76 | |||
77 | struct task_struct; | ||
78 | |||
79 | /* | ||
80 | * Does the process account for user or for system time? | ||
81 | */ | ||
82 | #define user_mode(regs) ((regs->cp0_psr & 8) == 8) | ||
83 | |||
84 | #define instruction_pointer(regs) ((unsigned long)(regs)->cp0_epc) | ||
85 | #define profile_pc(regs) instruction_pointer(regs) | ||
86 | |||
87 | extern void do_syscall_trace(struct pt_regs *regs, int entryexit); | ||
88 | extern int read_tsk_long(struct task_struct *, unsigned long, unsigned long *); | ||
89 | extern int read_tsk_short(struct task_struct *, unsigned long, | ||
90 | unsigned short *); | ||
91 | |||
92 | #define arch_has_single_step() (1) | ||
93 | extern void user_enable_single_step(struct task_struct *); | ||
94 | extern void user_disable_single_step(struct task_struct *); | ||
95 | #endif /* __KERNEL__ */ | ||
96 | |||
97 | #endif /* _ASM_SCORE_PTRACE_H */ | ||
diff --git a/arch/score/include/asm/resource.h b/arch/score/include/asm/resource.h new file mode 100644 index 000000000000..9ce22bc7b475 --- /dev/null +++ b/arch/score/include/asm/resource.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_RESOURCE_H | ||
2 | #define _ASM_SCORE_RESOURCE_H | ||
3 | |||
4 | #include <asm-generic/resource.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_RESOURCE_H */ | ||
diff --git a/arch/score/include/asm/scatterlist.h b/arch/score/include/asm/scatterlist.h new file mode 100644 index 000000000000..9f533b8362c7 --- /dev/null +++ b/arch/score/include/asm/scatterlist.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SCATTERLIST_H | ||
2 | #define _ASM_SCORE_SCATTERLIST_H | ||
3 | |||
4 | #include <asm-generic/scatterlist.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SCATTERLIST_H */ | ||
diff --git a/arch/score/include/asm/scoreregs.h b/arch/score/include/asm/scoreregs.h new file mode 100644 index 000000000000..d0ad29204518 --- /dev/null +++ b/arch/score/include/asm/scoreregs.h | |||
@@ -0,0 +1,51 @@ | |||
1 | #ifndef _ASM_SCORE_SCOREREGS_H | ||
2 | #define _ASM_SCORE_SCOREREGS_H | ||
3 | |||
4 | #include <linux/linkage.h> | ||
5 | |||
6 | /* TIMER register */ | ||
7 | #define TIME0BASE 0x96080000 | ||
8 | #define P_TIMER0_CTRL (TIME0BASE + 0x00) | ||
9 | #define P_TIMER0_CPP_CTRL (TIME0BASE + 0x04) | ||
10 | #define P_TIMER0_PRELOAD (TIME0BASE + 0x08) | ||
11 | #define P_TIMER0_CPP_REG (TIME0BASE + 0x0C) | ||
12 | #define P_TIMER0_UPCNT (TIME0BASE + 0x10) | ||
13 | |||
14 | /* Timer Controller Register */ | ||
15 | /* bit 0 Timer enable */ | ||
16 | #define TMR_DISABLE 0x0000 | ||
17 | #define TMR_ENABLE 0x0001 | ||
18 | |||
19 | /* bit 1 Interrupt enable */ | ||
20 | #define TMR_IE_DISABLE 0x0000 | ||
21 | #define TMR_IE_ENABLE 0x0002 | ||
22 | |||
23 | /* bit 2 Output enable */ | ||
24 | #define TMR_OE_DISABLE 0x0004 | ||
25 | #define TMR_OE_ENABLE 0x0000 | ||
26 | |||
27 | /* bit4 Up/Down counting selection */ | ||
28 | #define TMR_UD_DOWN 0x0000 | ||
29 | #define TMR_UD_UP 0x0010 | ||
30 | |||
31 | /* bit5 Up/Down counting control selection */ | ||
32 | #define TMR_UDS_UD 0x0000 | ||
33 | #define TMR_UDS_EXTUD 0x0020 | ||
34 | |||
35 | /* bit6 Time output mode */ | ||
36 | #define TMR_OM_TOGGLE 0x0000 | ||
37 | #define TMR_OM_PILSE 0x0040 | ||
38 | |||
39 | /* bit 8..9 External input active edge selection */ | ||
40 | #define TMR_ES_PE 0x0000 | ||
41 | #define TMR_ES_NE 0x0100 | ||
42 | #define TMR_ES_BOTH 0x0200 | ||
43 | |||
44 | /* bit 10..11 Operating mode */ | ||
45 | #define TMR_M_FREE 0x0000 /* free running timer mode */ | ||
46 | #define TMR_M_PERIODIC 0x0400 /* periodic timer mode */ | ||
47 | #define TMR_M_FC 0x0800 /* free running counter mode */ | ||
48 | #define TMR_M_PC 0x0c00 /* periodic counter mode */ | ||
49 | |||
50 | #define SYSTEM_CLOCK (27*1000000/4) /* 27 MHz */ | ||
51 | #endif /* _ASM_SCORE_SCOREREGS_H */ | ||
diff --git a/arch/score/include/asm/sections.h b/arch/score/include/asm/sections.h new file mode 100644 index 000000000000..9441d23af005 --- /dev/null +++ b/arch/score/include/asm/sections.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SECTIONS_H | ||
2 | #define _ASM_SCORE_SECTIONS_H | ||
3 | |||
4 | #include <asm-generic/sections.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SECTIONS_H */ | ||
diff --git a/arch/score/include/asm/segment.h b/arch/score/include/asm/segment.h new file mode 100644 index 000000000000..e16cf6afb495 --- /dev/null +++ b/arch/score/include/asm/segment.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _ASM_SCORE_SEGMENT_H | ||
2 | #define _ASM_SCORE_SEGMENT_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | |||
6 | typedef struct { | ||
7 | unsigned long seg; | ||
8 | } mm_segment_t; | ||
9 | |||
10 | #define KERNEL_DS ((mm_segment_t){0}) | ||
11 | #define USER_DS KERNEL_DS | ||
12 | |||
13 | # define get_ds() (KERNEL_DS) | ||
14 | # define get_fs() (current_thread_info()->addr_limit) | ||
15 | # define set_fs(x) \ | ||
16 | do { current_thread_info()->addr_limit = (x); } while (0) | ||
17 | |||
18 | # define segment_eq(a, b) ((a).seg == (b).seg) | ||
19 | |||
20 | # endif /* __ASSEMBLY__ */ | ||
21 | #endif /* _ASM_SCORE_SEGMENT_H */ | ||
diff --git a/arch/score/include/asm/sembuf.h b/arch/score/include/asm/sembuf.h new file mode 100644 index 000000000000..dae5e835ce9e --- /dev/null +++ b/arch/score/include/asm/sembuf.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SEMBUF_H | ||
2 | #define _ASM_SCORE_SEMBUF_H | ||
3 | |||
4 | #include <asm-generic/sembuf.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SEMBUF_H */ | ||
diff --git a/arch/score/include/asm/setup.h b/arch/score/include/asm/setup.h new file mode 100644 index 000000000000..3cb944dc68dc --- /dev/null +++ b/arch/score/include/asm/setup.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef _ASM_SCORE_SETUP_H | ||
2 | #define _ASM_SCORE_SETUP_H | ||
3 | |||
4 | #define COMMAND_LINE_SIZE 256 | ||
5 | #define MEMORY_START 0 | ||
6 | #define MEMORY_SIZE 0x2000000 | ||
7 | |||
8 | #ifdef __KERNEL__ | ||
9 | |||
10 | extern void pagetable_init(void); | ||
11 | extern void pgd_init(unsigned long page); | ||
12 | |||
13 | extern void setup_early_printk(void); | ||
14 | extern void cpu_cache_init(void); | ||
15 | extern void tlb_init(void); | ||
16 | |||
17 | extern void handle_nmi(void); | ||
18 | extern void handle_adelinsn(void); | ||
19 | extern void handle_adedata(void); | ||
20 | extern void handle_ibe(void); | ||
21 | extern void handle_pel(void); | ||
22 | extern void handle_sys(void); | ||
23 | extern void handle_ccu(void); | ||
24 | extern void handle_ri(void); | ||
25 | extern void handle_tr(void); | ||
26 | extern void handle_ades(void); | ||
27 | extern void handle_cee(void); | ||
28 | extern void handle_cpe(void); | ||
29 | extern void handle_dve(void); | ||
30 | extern void handle_dbe(void); | ||
31 | extern void handle_reserved(void); | ||
32 | extern void handle_tlb_refill(void); | ||
33 | extern void handle_tlb_invaild(void); | ||
34 | extern void handle_mod(void); | ||
35 | extern void debug_exception_vector(void); | ||
36 | extern void general_exception_vector(void); | ||
37 | extern void interrupt_exception_vector(void); | ||
38 | |||
39 | #endif /* __KERNEL__ */ | ||
40 | |||
41 | #endif /* _ASM_SCORE_SETUP_H */ | ||
diff --git a/arch/score/include/asm/shmbuf.h b/arch/score/include/asm/shmbuf.h new file mode 100644 index 000000000000..c85b2429ba21 --- /dev/null +++ b/arch/score/include/asm/shmbuf.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SHMBUF_H | ||
2 | #define _ASM_SCORE_SHMBUF_H | ||
3 | |||
4 | #include <asm-generic/shmbuf.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SHMBUF_H */ | ||
diff --git a/arch/score/include/asm/shmparam.h b/arch/score/include/asm/shmparam.h new file mode 100644 index 000000000000..1d60813141b6 --- /dev/null +++ b/arch/score/include/asm/shmparam.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SHMPARAM_H | ||
2 | #define _ASM_SCORE_SHMPARAM_H | ||
3 | |||
4 | #include <asm-generic/shmparam.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SHMPARAM_H */ | ||
diff --git a/arch/score/include/asm/sigcontext.h b/arch/score/include/asm/sigcontext.h new file mode 100644 index 000000000000..5ffda39ddb90 --- /dev/null +++ b/arch/score/include/asm/sigcontext.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef _ASM_SCORE_SIGCONTEXT_H | ||
2 | #define _ASM_SCORE_SIGCONTEXT_H | ||
3 | |||
4 | /* | ||
5 | * Keep this struct definition in sync with the sigcontext fragment | ||
6 | * in arch/score/tools/offset.c | ||
7 | */ | ||
8 | struct sigcontext { | ||
9 | unsigned int sc_regmask; | ||
10 | unsigned int sc_psr; | ||
11 | unsigned int sc_condition; | ||
12 | unsigned long sc_pc; | ||
13 | unsigned long sc_regs[32]; | ||
14 | unsigned int sc_ssflags; | ||
15 | unsigned int sc_mdceh; | ||
16 | unsigned int sc_mdcel; | ||
17 | unsigned int sc_ecr; | ||
18 | unsigned long sc_ema; | ||
19 | unsigned long sc_sigset[4]; | ||
20 | }; | ||
21 | |||
22 | #endif /* _ASM_SCORE_SIGCONTEXT_H */ | ||
diff --git a/arch/score/include/asm/siginfo.h b/arch/score/include/asm/siginfo.h new file mode 100644 index 000000000000..87ca35607a28 --- /dev/null +++ b/arch/score/include/asm/siginfo.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SIGINFO_H | ||
2 | #define _ASM_SCORE_SIGINFO_H | ||
3 | |||
4 | #include <asm-generic/siginfo.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SIGINFO_H */ | ||
diff --git a/arch/score/include/asm/signal.h b/arch/score/include/asm/signal.h new file mode 100644 index 000000000000..2605bc06b64f --- /dev/null +++ b/arch/score/include/asm/signal.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SIGNAL_H | ||
2 | #define _ASM_SCORE_SIGNAL_H | ||
3 | |||
4 | #include <asm-generic/signal.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SIGNAL_H */ | ||
diff --git a/arch/score/include/asm/socket.h b/arch/score/include/asm/socket.h new file mode 100644 index 000000000000..612a70e385ba --- /dev/null +++ b/arch/score/include/asm/socket.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SOCKET_H | ||
2 | #define _ASM_SCORE_SOCKET_H | ||
3 | |||
4 | #include <asm-generic/socket.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SOCKET_H */ | ||
diff --git a/arch/score/include/asm/sockios.h b/arch/score/include/asm/sockios.h new file mode 100644 index 000000000000..ba8256480189 --- /dev/null +++ b/arch/score/include/asm/sockios.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SOCKIOS_H | ||
2 | #define _ASM_SCORE_SOCKIOS_H | ||
3 | |||
4 | #include <asm-generic/sockios.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SOCKIOS_H */ | ||
diff --git a/arch/score/include/asm/stat.h b/arch/score/include/asm/stat.h new file mode 100644 index 000000000000..5037055500a2 --- /dev/null +++ b/arch/score/include/asm/stat.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_STAT_H | ||
2 | #define _ASM_SCORE_STAT_H | ||
3 | |||
4 | #include <asm-generic/stat.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_STAT_H */ | ||
diff --git a/arch/score/include/asm/statfs.h b/arch/score/include/asm/statfs.h new file mode 100644 index 000000000000..36e41004e996 --- /dev/null +++ b/arch/score/include/asm/statfs.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_STATFS_H | ||
2 | #define _ASM_SCORE_STATFS_H | ||
3 | |||
4 | #include <asm-generic/statfs.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_STATFS_H */ | ||
diff --git a/arch/score/include/asm/string.h b/arch/score/include/asm/string.h new file mode 100644 index 000000000000..8a6bf5063aa5 --- /dev/null +++ b/arch/score/include/asm/string.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _ASM_SCORE_STRING_H | ||
2 | #define _ASM_SCORE_STRING_H | ||
3 | |||
4 | extern void *memset(void *__s, int __c, size_t __count); | ||
5 | extern void *memcpy(void *__to, __const__ void *__from, size_t __n); | ||
6 | extern void *memmove(void *__dest, __const__ void *__src, size_t __n); | ||
7 | |||
8 | #endif /* _ASM_SCORE_STRING_H */ | ||
diff --git a/arch/score/include/asm/swab.h b/arch/score/include/asm/swab.h new file mode 100644 index 000000000000..fadc3cc6d8a2 --- /dev/null +++ b/arch/score/include/asm/swab.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SWAB_H | ||
2 | #define _ASM_SCORE_SWAB_H | ||
3 | |||
4 | #include <asm-generic/swab.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_SWAB_H */ | ||
diff --git a/arch/score/include/asm/syscalls.h b/arch/score/include/asm/syscalls.h new file mode 100644 index 000000000000..1dd5e0d6b0c3 --- /dev/null +++ b/arch/score/include/asm/syscalls.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _ASM_SCORE_SYSCALLS_H | ||
2 | #define _ASM_SCORE_SYSCALLS_H | ||
3 | |||
4 | asmlinkage long score_clone(struct pt_regs *regs); | ||
5 | asmlinkage long score_execve(struct pt_regs *regs); | ||
6 | asmlinkage long score_sigaltstack(struct pt_regs *regs); | ||
7 | asmlinkage long score_rt_sigreturn(struct pt_regs *regs); | ||
8 | |||
9 | #include <asm-generic/syscalls.h> | ||
10 | |||
11 | #endif /* _ASM_SCORE_SYSCALLS_H */ | ||
diff --git a/arch/score/include/asm/system.h b/arch/score/include/asm/system.h new file mode 100644 index 000000000000..589d5c7e171c --- /dev/null +++ b/arch/score/include/asm/system.h | |||
@@ -0,0 +1,90 @@ | |||
1 | #ifndef _ASM_SCORE_SYSTEM_H | ||
2 | #define _ASM_SCORE_SYSTEM_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <linux/irqflags.h> | ||
6 | |||
7 | struct pt_regs; | ||
8 | struct task_struct; | ||
9 | |||
10 | extern void *resume(void *last, void *next, void *next_ti); | ||
11 | |||
12 | #define switch_to(prev, next, last) \ | ||
13 | do { \ | ||
14 | (last) = resume(prev, next, task_thread_info(next)); \ | ||
15 | } while (0) | ||
16 | |||
17 | #define finish_arch_switch(prev) do {} while (0) | ||
18 | |||
19 | typedef void (*vi_handler_t)(void); | ||
20 | extern unsigned long arch_align_stack(unsigned long sp); | ||
21 | |||
22 | #define mb() barrier() | ||
23 | #define rmb() barrier() | ||
24 | #define wmb() barrier() | ||
25 | #define smp_mb() barrier() | ||
26 | #define smp_rmb() barrier() | ||
27 | #define smp_wmb() barrier() | ||
28 | |||
29 | #define read_barrier_depends() do {} while (0) | ||
30 | #define smp_read_barrier_depends() do {} while (0) | ||
31 | |||
32 | #define set_mb(var, value) do {var = value; wmb(); } while (0) | ||
33 | |||
34 | #define __HAVE_ARCH_CMPXCHG 1 | ||
35 | |||
36 | #include <asm-generic/cmpxchg-local.h> | ||
37 | |||
38 | #ifndef __ASSEMBLY__ | ||
39 | |||
40 | struct __xchg_dummy { unsigned long a[100]; }; | ||
41 | #define __xg(x) ((struct __xchg_dummy *)(x)) | ||
42 | |||
43 | static inline | ||
44 | unsigned long __xchg(volatile unsigned long *m, unsigned long val) | ||
45 | { | ||
46 | unsigned long retval; | ||
47 | unsigned long flags; | ||
48 | |||
49 | local_irq_save(flags); | ||
50 | retval = *m; | ||
51 | *m = val; | ||
52 | local_irq_restore(flags); | ||
53 | return retval; | ||
54 | } | ||
55 | |||
56 | #define xchg(ptr, v) \ | ||
57 | ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr), \ | ||
58 | (unsigned long)(v))) | ||
59 | |||
60 | static inline unsigned long __cmpxchg(volatile unsigned long *m, | ||
61 | unsigned long old, unsigned long new) | ||
62 | { | ||
63 | unsigned long retval; | ||
64 | unsigned long flags; | ||
65 | |||
66 | local_irq_save(flags); | ||
67 | retval = *m; | ||
68 | if (retval == old) | ||
69 | *m = new; | ||
70 | local_irq_restore(flags); | ||
71 | return retval; | ||
72 | } | ||
73 | |||
74 | #define cmpxchg(ptr, o, n) \ | ||
75 | ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \ | ||
76 | (unsigned long)(o), \ | ||
77 | (unsigned long)(n))) | ||
78 | |||
79 | extern void __die(const char *, struct pt_regs *, const char *, | ||
80 | const char *, unsigned long) __attribute__((noreturn)); | ||
81 | extern void __die_if_kernel(const char *, struct pt_regs *, const char *, | ||
82 | const char *, unsigned long); | ||
83 | |||
84 | #define die(msg, regs) \ | ||
85 | __die(msg, regs, __FILE__ ":", __func__, __LINE__) | ||
86 | #define die_if_kernel(msg, regs) \ | ||
87 | __die_if_kernel(msg, regs, __FILE__ ":", __func__, __LINE__) | ||
88 | |||
89 | #endif /* !__ASSEMBLY__ */ | ||
90 | #endif /* _ASM_SCORE_SYSTEM_H */ | ||
diff --git a/arch/score/include/asm/termbits.h b/arch/score/include/asm/termbits.h new file mode 100644 index 000000000000..9a95c1412437 --- /dev/null +++ b/arch/score/include/asm/termbits.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_TERMBITS_H | ||
2 | #define _ASM_SCORE_TERMBITS_H | ||
3 | |||
4 | #include <asm-generic/termbits.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_TERMBITS_H */ | ||
diff --git a/arch/score/include/asm/termios.h b/arch/score/include/asm/termios.h new file mode 100644 index 000000000000..40984e811ad6 --- /dev/null +++ b/arch/score/include/asm/termios.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_TERMIOS_H | ||
2 | #define _ASM_SCORE_TERMIOS_H | ||
3 | |||
4 | #include <asm-generic/termios.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_TERMIOS_H */ | ||
diff --git a/arch/score/include/asm/thread_info.h b/arch/score/include/asm/thread_info.h new file mode 100644 index 000000000000..3a1122885528 --- /dev/null +++ b/arch/score/include/asm/thread_info.h | |||
@@ -0,0 +1,105 @@ | |||
1 | #ifndef _ASM_SCORE_THREAD_INFO_H | ||
2 | #define _ASM_SCORE_THREAD_INFO_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | |||
6 | #define KU_MASK 0x08 | ||
7 | #define KU_USER 0x08 | ||
8 | #define KU_KERN 0x00 | ||
9 | |||
10 | #ifndef __ASSEMBLY__ | ||
11 | |||
12 | #include <asm/processor.h> | ||
13 | |||
14 | /* | ||
15 | * low level task data that entry.S needs immediate access to | ||
16 | * - this struct should fit entirely inside of one cache line | ||
17 | * - this struct shares the supervisor stack pages | ||
18 | * - if the contents of this structure are changed, the assembly constants | ||
19 | * must also be changed | ||
20 | */ | ||
21 | struct thread_info { | ||
22 | struct task_struct *task; /* main task structure */ | ||
23 | struct exec_domain *exec_domain; /* execution domain */ | ||
24 | unsigned long flags; /* low level flags */ | ||
25 | unsigned long tp_value; /* thread pointer */ | ||
26 | __u32 cpu; /* current CPU */ | ||
27 | |||
28 | /* 0 => preemptable, < 0 => BUG */ | ||
29 | int preempt_count; | ||
30 | |||
31 | /* | ||
32 | * thread address space: | ||
33 | * 0-0xBFFFFFFF for user-thead | ||
34 | * 0-0xFFFFFFFF for kernel-thread | ||
35 | */ | ||
36 | mm_segment_t addr_limit; | ||
37 | struct restart_block restart_block; | ||
38 | struct pt_regs *regs; | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | * macros/functions for gaining access to the thread information structure | ||
43 | * | ||
44 | * preempt_count needs to be 1 initially, until the scheduler is functional. | ||
45 | */ | ||
46 | #define INIT_THREAD_INFO(tsk) \ | ||
47 | { \ | ||
48 | .task = &tsk, \ | ||
49 | .exec_domain = &default_exec_domain, \ | ||
50 | .cpu = 0, \ | ||
51 | .preempt_count = 1, \ | ||
52 | .addr_limit = KERNEL_DS, \ | ||
53 | .restart_block = { \ | ||
54 | .fn = do_no_restart_syscall, \ | ||
55 | }, \ | ||
56 | } | ||
57 | |||
58 | #define init_thread_info (init_thread_union.thread_info) | ||
59 | #define init_stack (init_thread_union.stack) | ||
60 | |||
61 | /* How to get the thread information struct from C. */ | ||
62 | register struct thread_info *__current_thread_info __asm__("r28"); | ||
63 | #define current_thread_info() __current_thread_info | ||
64 | |||
65 | /* thread information allocation */ | ||
66 | #define THREAD_SIZE_ORDER (1) | ||
67 | #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) | ||
68 | #define THREAD_MASK (THREAD_SIZE - 1UL) | ||
69 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | ||
70 | |||
71 | #define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) | ||
72 | #define free_thread_info(info) kfree(info) | ||
73 | |||
74 | #endif /* !__ASSEMBLY__ */ | ||
75 | |||
76 | #define PREEMPT_ACTIVE 0x10000000 | ||
77 | |||
78 | /* | ||
79 | * thread information flags | ||
80 | * - these are process state flags that various assembly files may need to | ||
81 | * access | ||
82 | * - pending work-to-be-done flags are in LSW | ||
83 | * - other flags in MSW | ||
84 | */ | ||
85 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ | ||
86 | #define TIF_SIGPENDING 1 /* signal pending */ | ||
87 | #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ | ||
88 | #define TIF_NOTIFY_RESUME 5 /* callback before returning to user */ | ||
89 | #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ | ||
90 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling | ||
91 | TIF_NEED_RESCHED */ | ||
92 | #define TIF_MEMDIE 18 | ||
93 | |||
94 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | ||
95 | #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) | ||
96 | #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) | ||
97 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) | ||
98 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) | ||
99 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | ||
100 | |||
101 | #define _TIF_WORK_MASK (0x0000ffff) | ||
102 | |||
103 | #endif /* __KERNEL__ */ | ||
104 | |||
105 | #endif /* _ASM_SCORE_THREAD_INFO_H */ | ||
diff --git a/arch/score/include/asm/timex.h b/arch/score/include/asm/timex.h new file mode 100644 index 000000000000..a524ae0c5e7b --- /dev/null +++ b/arch/score/include/asm/timex.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _ASM_SCORE_TIMEX_H | ||
2 | #define _ASM_SCORE_TIMEX_H | ||
3 | |||
4 | #define CLOCK_TICK_RATE 27000000 /* Timer input freq. */ | ||
5 | |||
6 | #include <asm-generic/timex.h> | ||
7 | |||
8 | #endif /* _ASM_SCORE_TIMEX_H */ | ||
diff --git a/arch/score/include/asm/tlb.h b/arch/score/include/asm/tlb.h new file mode 100644 index 000000000000..46882ed524e6 --- /dev/null +++ b/arch/score/include/asm/tlb.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef _ASM_SCORE_TLB_H | ||
2 | #define _ASM_SCORE_TLB_H | ||
3 | |||
4 | /* | ||
5 | * SCORE doesn't need any special per-pte or per-vma handling, except | ||
6 | * we need to flush cache for area to be unmapped. | ||
7 | */ | ||
8 | #define tlb_start_vma(tlb, vma) do {} while (0) | ||
9 | #define tlb_end_vma(tlb, vma) do {} while (0) | ||
10 | #define __tlb_remove_tlb_entry(tlb, ptep, address) do {} while (0) | ||
11 | #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) | ||
12 | |||
13 | extern void score7_FTLB_refill_Handler(void); | ||
14 | |||
15 | #include <asm-generic/tlb.h> | ||
16 | |||
17 | #endif /* _ASM_SCORE_TLB_H */ | ||
diff --git a/arch/score/include/asm/tlbflush.h b/arch/score/include/asm/tlbflush.h new file mode 100644 index 000000000000..9cce978367d5 --- /dev/null +++ b/arch/score/include/asm/tlbflush.h | |||
@@ -0,0 +1,142 @@ | |||
1 | #ifndef _ASM_SCORE_TLBFLUSH_H | ||
2 | #define _ASM_SCORE_TLBFLUSH_H | ||
3 | |||
4 | #include <linux/mm.h> | ||
5 | |||
6 | /* | ||
7 | * TLB flushing: | ||
8 | * | ||
9 | * - flush_tlb_all() flushes all processes TLB entries | ||
10 | * - flush_tlb_mm(mm) flushes the specified mm context TLB entries | ||
11 | * - flush_tlb_page(vma, vmaddr) flushes one page | ||
12 | * - flush_tlb_range(vma, start, end) flushes a range of pages | ||
13 | * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages | ||
14 | */ | ||
15 | extern void local_flush_tlb_all(void); | ||
16 | extern void local_flush_tlb_mm(struct mm_struct *mm); | ||
17 | extern void local_flush_tlb_range(struct vm_area_struct *vma, | ||
18 | unsigned long start, unsigned long end); | ||
19 | extern void local_flush_tlb_kernel_range(unsigned long start, | ||
20 | unsigned long end); | ||
21 | extern void local_flush_tlb_page(struct vm_area_struct *vma, | ||
22 | unsigned long page); | ||
23 | extern void local_flush_tlb_one(unsigned long vaddr); | ||
24 | |||
25 | #define flush_tlb_all() local_flush_tlb_all() | ||
26 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) | ||
27 | #define flush_tlb_range(vma, vmaddr, end) \ | ||
28 | local_flush_tlb_range(vma, vmaddr, end) | ||
29 | #define flush_tlb_kernel_range(vmaddr, end) \ | ||
30 | local_flush_tlb_kernel_range(vmaddr, end) | ||
31 | #define flush_tlb_page(vma, page) local_flush_tlb_page(vma, page) | ||
32 | #define flush_tlb_one(vaddr) local_flush_tlb_one(vaddr) | ||
33 | |||
34 | #ifndef __ASSEMBLY__ | ||
35 | |||
36 | static inline unsigned long pevn_get(void) | ||
37 | { | ||
38 | unsigned long val; | ||
39 | |||
40 | __asm__ __volatile__( | ||
41 | "mfcr %0, cr11\n" | ||
42 | "nop\nnop\n" | ||
43 | : "=r" (val)); | ||
44 | |||
45 | return val; | ||
46 | } | ||
47 | |||
48 | static inline void pevn_set(unsigned long val) | ||
49 | { | ||
50 | __asm__ __volatile__( | ||
51 | "mtcr %0, cr11\n" | ||
52 | "nop\nnop\nnop\nnop\nnop\n" | ||
53 | : : "r" (val)); | ||
54 | } | ||
55 | |||
56 | static inline void pectx_set(unsigned long val) | ||
57 | { | ||
58 | __asm__ __volatile__( | ||
59 | "mtcr %0, cr12\n" | ||
60 | "nop\nnop\nnop\nnop\nnop\n" | ||
61 | : : "r" (val)); | ||
62 | } | ||
63 | |||
64 | static inline unsigned long pectx_get(void) | ||
65 | { | ||
66 | unsigned long val; | ||
67 | __asm__ __volatile__( | ||
68 | "mfcr %0, cr12\n" | ||
69 | "nop\nnop\n" | ||
70 | : "=r" (val)); | ||
71 | return val; | ||
72 | } | ||
73 | static inline unsigned long tlblock_get(void) | ||
74 | { | ||
75 | unsigned long val; | ||
76 | |||
77 | __asm__ __volatile__( | ||
78 | "mfcr %0, cr7\n" | ||
79 | "nop\nnop\n" | ||
80 | : "=r" (val)); | ||
81 | return val; | ||
82 | } | ||
83 | static inline void tlblock_set(unsigned long val) | ||
84 | { | ||
85 | __asm__ __volatile__( | ||
86 | "mtcr %0, cr7\n" | ||
87 | "nop\nnop\nnop\nnop\nnop\n" | ||
88 | : : "r" (val)); | ||
89 | } | ||
90 | |||
91 | static inline void tlbpt_set(unsigned long val) | ||
92 | { | ||
93 | __asm__ __volatile__( | ||
94 | "mtcr %0, cr8\n" | ||
95 | "nop\nnop\nnop\nnop\nnop\n" | ||
96 | : : "r" (val)); | ||
97 | } | ||
98 | |||
99 | static inline long tlbpt_get(void) | ||
100 | { | ||
101 | long val; | ||
102 | |||
103 | __asm__ __volatile__( | ||
104 | "mfcr %0, cr8\n" | ||
105 | "nop\nnop\n" | ||
106 | : "=r" (val)); | ||
107 | |||
108 | return val; | ||
109 | } | ||
110 | |||
111 | static inline void peaddr_set(unsigned long val) | ||
112 | { | ||
113 | __asm__ __volatile__( | ||
114 | "mtcr %0, cr9\n" | ||
115 | "nop\nnop\nnop\nnop\nnop\n" | ||
116 | : : "r" (val)); | ||
117 | } | ||
118 | |||
119 | /* TLB operations. */ | ||
120 | static inline void tlb_probe(void) | ||
121 | { | ||
122 | __asm__ __volatile__("stlb;nop;nop;nop;nop;nop"); | ||
123 | } | ||
124 | |||
125 | static inline void tlb_read(void) | ||
126 | { | ||
127 | __asm__ __volatile__("mftlb;nop;nop;nop;nop;nop"); | ||
128 | } | ||
129 | |||
130 | static inline void tlb_write_indexed(void) | ||
131 | { | ||
132 | __asm__ __volatile__("mtptlb;nop;nop;nop;nop;nop"); | ||
133 | } | ||
134 | |||
135 | static inline void tlb_write_random(void) | ||
136 | { | ||
137 | __asm__ __volatile__("mtrtlb;nop;nop;nop;nop;nop"); | ||
138 | } | ||
139 | |||
140 | #endif /* Not __ASSEMBLY__ */ | ||
141 | |||
142 | #endif /* _ASM_SCORE_TLBFLUSH_H */ | ||
diff --git a/arch/score/include/asm/topology.h b/arch/score/include/asm/topology.h new file mode 100644 index 000000000000..425fba381f88 --- /dev/null +++ b/arch/score/include/asm/topology.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_TOPOLOGY_H | ||
2 | #define _ASM_SCORE_TOPOLOGY_H | ||
3 | |||
4 | #include <asm-generic/topology.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_TOPOLOGY_H */ | ||
diff --git a/arch/score/include/asm/types.h b/arch/score/include/asm/types.h new file mode 100644 index 000000000000..2140032778ee --- /dev/null +++ b/arch/score/include/asm/types.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_TYPES_H | ||
2 | #define _ASM_SCORE_TYPES_H | ||
3 | |||
4 | #include <asm-generic/types.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_TYPES_H */ | ||
diff --git a/arch/score/include/asm/uaccess.h b/arch/score/include/asm/uaccess.h new file mode 100644 index 000000000000..ab66ddde777b --- /dev/null +++ b/arch/score/include/asm/uaccess.h | |||
@@ -0,0 +1,424 @@ | |||
1 | #ifndef __SCORE_UACCESS_H | ||
2 | #define __SCORE_UACCESS_H | ||
3 | |||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/errno.h> | ||
6 | #include <linux/thread_info.h> | ||
7 | |||
8 | #define VERIFY_READ 0 | ||
9 | #define VERIFY_WRITE 1 | ||
10 | |||
11 | #define get_ds() (KERNEL_DS) | ||
12 | #define get_fs() (current_thread_info()->addr_limit) | ||
13 | #define segment_eq(a, b) ((a).seg == (b).seg) | ||
14 | |||
15 | /* | ||
16 | * Is a address valid? This does a straighforward calculation rather | ||
17 | * than tests. | ||
18 | * | ||
19 | * Address valid if: | ||
20 | * - "addr" doesn't have any high-bits set | ||
21 | * - AND "size" doesn't have any high-bits set | ||
22 | * - AND "addr+size" doesn't have any high-bits set | ||
23 | * - OR we are in kernel mode. | ||
24 | * | ||
25 | * __ua_size() is a trick to avoid runtime checking of positive constant | ||
26 | * sizes; for those we already know at compile time that the size is ok. | ||
27 | */ | ||
28 | #define __ua_size(size) \ | ||
29 | ((__builtin_constant_p(size) && (signed long) (size) > 0) ? 0 : (size)) | ||
30 | |||
31 | /* | ||
32 | * access_ok: - Checks if a user space pointer is valid | ||
33 | * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that | ||
34 | * %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe | ||
35 | * to write to a block, it is always safe to read from it. | ||
36 | * @addr: User space pointer to start of block to check | ||
37 | * @size: Size of block to check | ||
38 | * | ||
39 | * Context: User context only. This function may sleep. | ||
40 | * | ||
41 | * Checks if a pointer to a block of memory in user space is valid. | ||
42 | * | ||
43 | * Returns true (nonzero) if the memory block may be valid, false (zero) | ||
44 | * if it is definitely invalid. | ||
45 | * | ||
46 | * Note that, depending on architecture, this function probably just | ||
47 | * checks that the pointer is in the user space range - after calling | ||
48 | * this function, memory access functions may still return -EFAULT. | ||
49 | */ | ||
50 | |||
51 | #define __access_ok(addr, size) \ | ||
52 | (((long)((get_fs().seg) & \ | ||
53 | ((addr) | ((addr) + (size)) | \ | ||
54 | __ua_size(size)))) == 0) | ||
55 | |||
56 | #define access_ok(type, addr, size) \ | ||
57 | likely(__access_ok((unsigned long)(addr), (size))) | ||
58 | |||
59 | /* | ||
60 | * put_user: - Write a simple value into user space. | ||
61 | * @x: Value to copy to user space. | ||
62 | * @ptr: Destination address, in user space. | ||
63 | * | ||
64 | * Context: User context only. This function may sleep. | ||
65 | * | ||
66 | * This macro copies a single simple value from kernel space to user | ||
67 | * space. It supports simple types like char and int, but not larger | ||
68 | * data types like structures or arrays. | ||
69 | * | ||
70 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
71 | * to the result of dereferencing @ptr. | ||
72 | * | ||
73 | * Returns zero on success, or -EFAULT on error. | ||
74 | */ | ||
75 | #define put_user(x, ptr) __put_user_check((x), (ptr), sizeof(*(ptr))) | ||
76 | |||
77 | /* | ||
78 | * get_user: - Get a simple variable from user space. | ||
79 | * @x: Variable to store result. | ||
80 | * @ptr: Source address, in user space. | ||
81 | * | ||
82 | * Context: User context only. This function may sleep. | ||
83 | * | ||
84 | * This macro copies a single simple variable from user space to kernel | ||
85 | * space. It supports simple types like char and int, but not larger | ||
86 | * data types like structures or arrays. | ||
87 | * | ||
88 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
89 | * dereferencing @ptr must be assignable to @x without a cast. | ||
90 | * | ||
91 | * Returns zero on success, or -EFAULT on error. | ||
92 | * On error, the variable @x is set to zero. | ||
93 | */ | ||
94 | #define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr))) | ||
95 | |||
96 | /* | ||
97 | * __put_user: - Write a simple value into user space, with less checking. | ||
98 | * @x: Value to copy to user space. | ||
99 | * @ptr: Destination address, in user space. | ||
100 | * | ||
101 | * Context: User context only. This function may sleep. | ||
102 | * | ||
103 | * This macro copies a single simple value from kernel space to user | ||
104 | * space. It supports simple types like char and int, but not larger | ||
105 | * data types like structures or arrays. | ||
106 | * | ||
107 | * @ptr must have pointer-to-simple-variable type, and @x must be assignable | ||
108 | * to the result of dereferencing @ptr. | ||
109 | * | ||
110 | * Caller must check the pointer with access_ok() before calling this | ||
111 | * function. | ||
112 | * | ||
113 | * Returns zero on success, or -EFAULT on error. | ||
114 | */ | ||
115 | #define __put_user(x, ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr))) | ||
116 | |||
117 | /* | ||
118 | * __get_user: - Get a simple variable from user space, with less checking. | ||
119 | * @x: Variable to store result. | ||
120 | * @ptr: Source address, in user space. | ||
121 | * | ||
122 | * Context: User context only. This function may sleep. | ||
123 | * | ||
124 | * This macro copies a single simple variable from user space to kernel | ||
125 | * space. It supports simple types like char and int, but not larger | ||
126 | * data types like structures or arrays. | ||
127 | * | ||
128 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
129 | * dereferencing @ptr must be assignable to @x without a cast. | ||
130 | * | ||
131 | * Caller must check the pointer with access_ok() before calling this | ||
132 | * function. | ||
133 | * | ||
134 | * Returns zero on success, or -EFAULT on error. | ||
135 | * On error, the variable @x is set to zero. | ||
136 | */ | ||
137 | #define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr))) | ||
138 | |||
139 | struct __large_struct { unsigned long buf[100]; }; | ||
140 | #define __m(x) (*(struct __large_struct __user *)(x)) | ||
141 | |||
142 | /* | ||
143 | * Yuck. We need two variants, one for 64bit operation and one | ||
144 | * for 32 bit mode and old iron. | ||
145 | */ | ||
146 | extern void __get_user_unknown(void); | ||
147 | |||
148 | #define __get_user_common(val, size, ptr) \ | ||
149 | do { \ | ||
150 | switch (size) { \ | ||
151 | case 1: \ | ||
152 | __get_user_asm(val, "lb", ptr); \ | ||
153 | break; \ | ||
154 | case 2: \ | ||
155 | __get_user_asm(val, "lh", ptr); \ | ||
156 | break; \ | ||
157 | case 4: \ | ||
158 | __get_user_asm(val, "lw", ptr); \ | ||
159 | break; \ | ||
160 | case 8: \ | ||
161 | if ((copy_from_user((void *)&val, ptr, 8)) == 0) \ | ||
162 | __gu_err = 0; \ | ||
163 | else \ | ||
164 | __gu_err = -EFAULT; \ | ||
165 | break; \ | ||
166 | default: \ | ||
167 | __get_user_unknown(); \ | ||
168 | break; \ | ||
169 | } \ | ||
170 | } while (0) | ||
171 | |||
172 | #define __get_user_nocheck(x, ptr, size) \ | ||
173 | ({ \ | ||
174 | long __gu_err = 0; \ | ||
175 | __get_user_common((x), size, ptr); \ | ||
176 | __gu_err; \ | ||
177 | }) | ||
178 | |||
179 | #define __get_user_check(x, ptr, size) \ | ||
180 | ({ \ | ||
181 | long __gu_err = -EFAULT; \ | ||
182 | const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ | ||
183 | \ | ||
184 | if (likely(access_ok(VERIFY_READ, __gu_ptr, size))) \ | ||
185 | __get_user_common((x), size, __gu_ptr); \ | ||
186 | \ | ||
187 | __gu_err; \ | ||
188 | }) | ||
189 | |||
190 | #define __get_user_asm(val, insn, addr) \ | ||
191 | { \ | ||
192 | long __gu_tmp; \ | ||
193 | \ | ||
194 | __asm__ __volatile__( \ | ||
195 | "1:" insn " %1, %3\n" \ | ||
196 | "2:\n" \ | ||
197 | ".section .fixup,\"ax\"\n" \ | ||
198 | "3:li %0, %4\n" \ | ||
199 | "j 2b\n" \ | ||
200 | ".previous\n" \ | ||
201 | ".section __ex_table,\"a\"\n" \ | ||
202 | ".word 1b, 3b\n" \ | ||
203 | ".previous\n" \ | ||
204 | : "=r" (__gu_err), "=r" (__gu_tmp) \ | ||
205 | : "0" (0), "o" (__m(addr)), "i" (-EFAULT)); \ | ||
206 | \ | ||
207 | (val) = (__typeof__(*(addr))) __gu_tmp; \ | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * Yuck. We need two variants, one for 64bit operation and one | ||
212 | * for 32 bit mode and old iron. | ||
213 | */ | ||
214 | #define __put_user_nocheck(val, ptr, size) \ | ||
215 | ({ \ | ||
216 | __typeof__(*(ptr)) __pu_val; \ | ||
217 | long __pu_err = 0; \ | ||
218 | \ | ||
219 | __pu_val = (val); \ | ||
220 | switch (size) { \ | ||
221 | case 1: \ | ||
222 | __put_user_asm("sb", ptr); \ | ||
223 | break; \ | ||
224 | case 2: \ | ||
225 | __put_user_asm("sh", ptr); \ | ||
226 | break; \ | ||
227 | case 4: \ | ||
228 | __put_user_asm("sw", ptr); \ | ||
229 | break; \ | ||
230 | case 8: \ | ||
231 | if ((__copy_to_user((void *)ptr, &__pu_val, 8)) == 0) \ | ||
232 | __pu_err = 0; \ | ||
233 | else \ | ||
234 | __pu_err = -EFAULT; \ | ||
235 | break; \ | ||
236 | default: \ | ||
237 | __put_user_unknown(); \ | ||
238 | break; \ | ||
239 | } \ | ||
240 | __pu_err; \ | ||
241 | }) | ||
242 | |||
243 | |||
244 | #define __put_user_check(val, ptr, size) \ | ||
245 | ({ \ | ||
246 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ | ||
247 | __typeof__(*(ptr)) __pu_val = (val); \ | ||
248 | long __pu_err = -EFAULT; \ | ||
249 | \ | ||
250 | if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) { \ | ||
251 | switch (size) { \ | ||
252 | case 1: \ | ||
253 | __put_user_asm("sb", __pu_addr); \ | ||
254 | break; \ | ||
255 | case 2: \ | ||
256 | __put_user_asm("sh", __pu_addr); \ | ||
257 | break; \ | ||
258 | case 4: \ | ||
259 | __put_user_asm("sw", __pu_addr); \ | ||
260 | break; \ | ||
261 | case 8: \ | ||
262 | if ((__copy_to_user((void *)__pu_addr, &__pu_val, 8)) == 0)\ | ||
263 | __pu_err = 0; \ | ||
264 | else \ | ||
265 | __pu_err = -EFAULT; \ | ||
266 | break; \ | ||
267 | default: \ | ||
268 | __put_user_unknown(); \ | ||
269 | break; \ | ||
270 | } \ | ||
271 | } \ | ||
272 | __pu_err; \ | ||
273 | }) | ||
274 | |||
275 | #define __put_user_asm(insn, ptr) \ | ||
276 | __asm__ __volatile__( \ | ||
277 | "1:" insn " %2, %3\n" \ | ||
278 | "2:\n" \ | ||
279 | ".section .fixup,\"ax\"\n" \ | ||
280 | "3:li %0, %4\n" \ | ||
281 | "j 2b\n" \ | ||
282 | ".previous\n" \ | ||
283 | ".section __ex_table,\"a\"\n" \ | ||
284 | ".word 1b, 3b\n" \ | ||
285 | ".previous\n" \ | ||
286 | : "=r" (__pu_err) \ | ||
287 | : "0" (0), "r" (__pu_val), "o" (__m(ptr)), \ | ||
288 | "i" (-EFAULT)); | ||
289 | |||
290 | extern void __put_user_unknown(void); | ||
291 | extern int __copy_tofrom_user(void *to, const void *from, unsigned long len); | ||
292 | |||
293 | static inline unsigned long | ||
294 | copy_from_user(void *to, const void *from, unsigned long len) | ||
295 | { | ||
296 | unsigned long over; | ||
297 | |||
298 | if (access_ok(VERIFY_READ, from, len)) | ||
299 | return __copy_tofrom_user(to, from, len); | ||
300 | |||
301 | if ((unsigned long)from < TASK_SIZE) { | ||
302 | over = (unsigned long)from + len - TASK_SIZE; | ||
303 | return __copy_tofrom_user(to, from, len - over) + over; | ||
304 | } | ||
305 | return len; | ||
306 | } | ||
307 | |||
308 | static inline unsigned long | ||
309 | copy_to_user(void *to, const void *from, unsigned long len) | ||
310 | { | ||
311 | unsigned long over; | ||
312 | |||
313 | if (access_ok(VERIFY_WRITE, to, len)) | ||
314 | return __copy_tofrom_user(to, from, len); | ||
315 | |||
316 | if ((unsigned long)to < TASK_SIZE) { | ||
317 | over = (unsigned long)to + len - TASK_SIZE; | ||
318 | return __copy_tofrom_user(to, from, len - over) + over; | ||
319 | } | ||
320 | return len; | ||
321 | } | ||
322 | |||
323 | #define __copy_from_user(to, from, len) \ | ||
324 | __copy_tofrom_user((to), (from), (len)) | ||
325 | |||
326 | #define __copy_to_user(to, from, len) \ | ||
327 | __copy_tofrom_user((to), (from), (len)) | ||
328 | |||
329 | static inline unsigned long | ||
330 | __copy_to_user_inatomic(void *to, const void *from, unsigned long len) | ||
331 | { | ||
332 | return __copy_to_user(to, from, len); | ||
333 | } | ||
334 | |||
335 | static inline unsigned long | ||
336 | __copy_from_user_inatomic(void *to, const void *from, unsigned long len) | ||
337 | { | ||
338 | return __copy_from_user(to, from, len); | ||
339 | } | ||
340 | |||
341 | #define __copy_in_user(to, from, len) __copy_from_user(to, from, len) | ||
342 | |||
343 | static inline unsigned long | ||
344 | copy_in_user(void *to, const void *from, unsigned long len) | ||
345 | { | ||
346 | if (access_ok(VERIFY_READ, from, len) && | ||
347 | access_ok(VERFITY_WRITE, to, len)) | ||
348 | return copy_from_user(to, from, len); | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * __clear_user: - Zero a block of memory in user space, with less checking. | ||
353 | * @to: Destination address, in user space. | ||
354 | * @n: Number of bytes to zero. | ||
355 | * | ||
356 | * Zero a block of memory in user space. Caller must check | ||
357 | * the specified block with access_ok() before calling this function. | ||
358 | * | ||
359 | * Returns number of bytes that could not be cleared. | ||
360 | * On success, this will be zero. | ||
361 | */ | ||
362 | extern unsigned long __clear_user(void __user *src, unsigned long size); | ||
363 | |||
364 | static inline unsigned long clear_user(char *src, unsigned long size) | ||
365 | { | ||
366 | if (access_ok(VERIFY_WRITE, src, size)) | ||
367 | return __clear_user(src, size); | ||
368 | |||
369 | return -EFAULT; | ||
370 | } | ||
371 | /* | ||
372 | * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. | ||
373 | * @dst: Destination address, in kernel space. This buffer must be at | ||
374 | * least @count bytes long. | ||
375 | * @src: Source address, in user space. | ||
376 | * @count: Maximum number of bytes to copy, including the trailing NUL. | ||
377 | * | ||
378 | * Copies a NUL-terminated string from userspace to kernel space. | ||
379 | * Caller must check the specified block with access_ok() before calling | ||
380 | * this function. | ||
381 | * | ||
382 | * On success, returns the length of the string (not including the trailing | ||
383 | * NUL). | ||
384 | * | ||
385 | * If access to userspace fails, returns -EFAULT (some data may have been | ||
386 | * copied). | ||
387 | * | ||
388 | * If @count is smaller than the length of the string, copies @count bytes | ||
389 | * and returns @count. | ||
390 | */ | ||
391 | extern int __strncpy_from_user(char *dst, const char *src, long len); | ||
392 | |||
393 | static inline int strncpy_from_user(char *dst, const char *src, long len) | ||
394 | { | ||
395 | if (access_ok(VERIFY_READ, src, 1)) | ||
396 | return __strncpy_from_user(dst, src, len); | ||
397 | |||
398 | return -EFAULT; | ||
399 | } | ||
400 | |||
401 | extern int __strlen_user(const char *src); | ||
402 | static inline long strlen_user(const char __user *src) | ||
403 | { | ||
404 | return __strlen_user(src); | ||
405 | } | ||
406 | |||
407 | extern int __strnlen_user(const char *str, long len); | ||
408 | static inline long strnlen_user(const char __user *str, long len) | ||
409 | { | ||
410 | if (!access_ok(VERIFY_READ, str, 0)) | ||
411 | return 0; | ||
412 | else | ||
413 | return __strnlen_user(str, len); | ||
414 | } | ||
415 | |||
416 | struct exception_table_entry { | ||
417 | unsigned long insn; | ||
418 | unsigned long fixup; | ||
419 | }; | ||
420 | |||
421 | extern int fixup_exception(struct pt_regs *regs); | ||
422 | |||
423 | #endif /* __SCORE_UACCESS_H */ | ||
424 | |||
diff --git a/arch/score/include/asm/ucontext.h b/arch/score/include/asm/ucontext.h new file mode 100644 index 000000000000..9bc07b9f30fb --- /dev/null +++ b/arch/score/include/asm/ucontext.h | |||
@@ -0,0 +1 @@ | |||
#include <asm-generic/ucontext.h> | |||
diff --git a/arch/score/include/asm/unaligned.h b/arch/score/include/asm/unaligned.h new file mode 100644 index 000000000000..2fc06de51c62 --- /dev/null +++ b/arch/score/include/asm/unaligned.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_UNALIGNED_H | ||
2 | #define _ASM_SCORE_UNALIGNED_H | ||
3 | |||
4 | #include <asm-generic/unaligned.h> | ||
5 | |||
6 | #endif /* _ASM_SCORE_UNALIGNED_H */ | ||
diff --git a/arch/score/include/asm/unistd.h b/arch/score/include/asm/unistd.h new file mode 100644 index 000000000000..4aa957364d4d --- /dev/null +++ b/arch/score/include/asm/unistd.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #if !defined(_ASM_SCORE_UNISTD_H) || defined(__SYSCALL) | ||
2 | #define _ASM_SCORE_UNISTD_H | ||
3 | |||
4 | #define __ARCH_HAVE_MMU | ||
5 | |||
6 | #define __ARCH_WANT_SYSCALL_NO_AT | ||
7 | #define __ARCH_WANT_SYSCALL_NO_FLAGS | ||
8 | #define __ARCH_WANT_SYSCALL_OFF_T | ||
9 | #define __ARCH_WANT_SYSCALL_DEPRECATED | ||
10 | |||
11 | #include <asm-generic/unistd.h> | ||
12 | |||
13 | #endif /* _ASM_SCORE_UNISTD_H */ | ||
diff --git a/arch/score/include/asm/user.h b/arch/score/include/asm/user.h new file mode 100644 index 000000000000..7bfb8e2c8054 --- /dev/null +++ b/arch/score/include/asm/user.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _ASM_SCORE_USER_H | ||
2 | #define _ASM_SCORE_USER_H | ||
3 | |||
4 | struct user_regs_struct { | ||
5 | unsigned long regs[32]; | ||
6 | |||
7 | unsigned long cel; | ||
8 | unsigned long ceh; | ||
9 | |||
10 | unsigned long sr0; /* cnt */ | ||
11 | unsigned long sr1; /* lcr */ | ||
12 | unsigned long sr2; /* scr */ | ||
13 | |||
14 | unsigned long cp0_epc; | ||
15 | unsigned long cp0_ema; | ||
16 | unsigned long cp0_psr; | ||
17 | unsigned long cp0_ecr; | ||
18 | unsigned long cp0_condition; | ||
19 | }; | ||
20 | |||
21 | #endif /* _ASM_SCORE_USER_H */ | ||
diff --git a/arch/score/kernel/Makefile b/arch/score/kernel/Makefile new file mode 100644 index 000000000000..f218673b5d3d --- /dev/null +++ b/arch/score/kernel/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Makefile for the Linux/SCORE kernel. | ||
3 | # | ||
4 | |||
5 | extra-y := head.o vmlinux.lds | ||
6 | |||
7 | obj-y += entry.o init_task.o irq.o process.o ptrace.o \ | ||
8 | setup.o signal.o sys_score.o time.o traps.o \ | ||
9 | sys_call_table.o | ||
10 | |||
11 | obj-$(CONFIG_MODULES) += module.o | ||
diff --git a/arch/score/kernel/asm-offsets.c b/arch/score/kernel/asm-offsets.c new file mode 100644 index 000000000000..57788f44c6fb --- /dev/null +++ b/arch/score/kernel/asm-offsets.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/asm-offsets.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kbuild.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/sched.h> | ||
30 | |||
31 | #include <asm-generic/cmpxchg-local.h> | ||
32 | |||
33 | void output_ptreg_defines(void) | ||
34 | { | ||
35 | COMMENT("SCORE pt_regs offsets."); | ||
36 | OFFSET(PT_R0, pt_regs, regs[0]); | ||
37 | OFFSET(PT_R1, pt_regs, regs[1]); | ||
38 | OFFSET(PT_R2, pt_regs, regs[2]); | ||
39 | OFFSET(PT_R3, pt_regs, regs[3]); | ||
40 | OFFSET(PT_R4, pt_regs, regs[4]); | ||
41 | OFFSET(PT_R5, pt_regs, regs[5]); | ||
42 | OFFSET(PT_R6, pt_regs, regs[6]); | ||
43 | OFFSET(PT_R7, pt_regs, regs[7]); | ||
44 | OFFSET(PT_R8, pt_regs, regs[8]); | ||
45 | OFFSET(PT_R9, pt_regs, regs[9]); | ||
46 | OFFSET(PT_R10, pt_regs, regs[10]); | ||
47 | OFFSET(PT_R11, pt_regs, regs[11]); | ||
48 | OFFSET(PT_R12, pt_regs, regs[12]); | ||
49 | OFFSET(PT_R13, pt_regs, regs[13]); | ||
50 | OFFSET(PT_R14, pt_regs, regs[14]); | ||
51 | OFFSET(PT_R15, pt_regs, regs[15]); | ||
52 | OFFSET(PT_R16, pt_regs, regs[16]); | ||
53 | OFFSET(PT_R17, pt_regs, regs[17]); | ||
54 | OFFSET(PT_R18, pt_regs, regs[18]); | ||
55 | OFFSET(PT_R19, pt_regs, regs[19]); | ||
56 | OFFSET(PT_R20, pt_regs, regs[20]); | ||
57 | OFFSET(PT_R21, pt_regs, regs[21]); | ||
58 | OFFSET(PT_R22, pt_regs, regs[22]); | ||
59 | OFFSET(PT_R23, pt_regs, regs[23]); | ||
60 | OFFSET(PT_R24, pt_regs, regs[24]); | ||
61 | OFFSET(PT_R25, pt_regs, regs[25]); | ||
62 | OFFSET(PT_R26, pt_regs, regs[26]); | ||
63 | OFFSET(PT_R27, pt_regs, regs[27]); | ||
64 | OFFSET(PT_R28, pt_regs, regs[28]); | ||
65 | OFFSET(PT_R29, pt_regs, regs[29]); | ||
66 | OFFSET(PT_R30, pt_regs, regs[30]); | ||
67 | OFFSET(PT_R31, pt_regs, regs[31]); | ||
68 | |||
69 | OFFSET(PT_ORIG_R4, pt_regs, orig_r4); | ||
70 | OFFSET(PT_ORIG_R7, pt_regs, orig_r7); | ||
71 | OFFSET(PT_CEL, pt_regs, cel); | ||
72 | OFFSET(PT_CEH, pt_regs, ceh); | ||
73 | OFFSET(PT_SR0, pt_regs, sr0); | ||
74 | OFFSET(PT_SR1, pt_regs, sr1); | ||
75 | OFFSET(PT_SR2, pt_regs, sr2); | ||
76 | OFFSET(PT_EPC, pt_regs, cp0_epc); | ||
77 | OFFSET(PT_EMA, pt_regs, cp0_ema); | ||
78 | OFFSET(PT_PSR, pt_regs, cp0_psr); | ||
79 | OFFSET(PT_ECR, pt_regs, cp0_ecr); | ||
80 | OFFSET(PT_CONDITION, pt_regs, cp0_condition); | ||
81 | OFFSET(PT_IS_SYSCALL, pt_regs, is_syscall); | ||
82 | |||
83 | DEFINE(PT_SIZE, sizeof(struct pt_regs)); | ||
84 | BLANK(); | ||
85 | } | ||
86 | |||
87 | void output_task_defines(void) | ||
88 | { | ||
89 | COMMENT("SCORE task_struct offsets."); | ||
90 | OFFSET(TASK_STATE, task_struct, state); | ||
91 | OFFSET(TASK_THREAD_INFO, task_struct, stack); | ||
92 | OFFSET(TASK_FLAGS, task_struct, flags); | ||
93 | OFFSET(TASK_MM, task_struct, mm); | ||
94 | OFFSET(TASK_PID, task_struct, pid); | ||
95 | DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct)); | ||
96 | BLANK(); | ||
97 | } | ||
98 | |||
99 | void output_thread_info_defines(void) | ||
100 | { | ||
101 | COMMENT("SCORE thread_info offsets."); | ||
102 | OFFSET(TI_TASK, thread_info, task); | ||
103 | OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain); | ||
104 | OFFSET(TI_FLAGS, thread_info, flags); | ||
105 | OFFSET(TI_TP_VALUE, thread_info, tp_value); | ||
106 | OFFSET(TI_CPU, thread_info, cpu); | ||
107 | OFFSET(TI_PRE_COUNT, thread_info, preempt_count); | ||
108 | OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit); | ||
109 | OFFSET(TI_RESTART_BLOCK, thread_info, restart_block); | ||
110 | OFFSET(TI_REGS, thread_info, regs); | ||
111 | DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); | ||
112 | DEFINE(KERNEL_STACK_MASK, THREAD_MASK); | ||
113 | BLANK(); | ||
114 | } | ||
115 | |||
116 | void output_thread_defines(void) | ||
117 | { | ||
118 | COMMENT("SCORE specific thread_struct offsets."); | ||
119 | OFFSET(THREAD_REG0, task_struct, thread.reg0); | ||
120 | OFFSET(THREAD_REG2, task_struct, thread.reg2); | ||
121 | OFFSET(THREAD_REG3, task_struct, thread.reg3); | ||
122 | OFFSET(THREAD_REG12, task_struct, thread.reg12); | ||
123 | OFFSET(THREAD_REG13, task_struct, thread.reg13); | ||
124 | OFFSET(THREAD_REG14, task_struct, thread.reg14); | ||
125 | OFFSET(THREAD_REG15, task_struct, thread.reg15); | ||
126 | OFFSET(THREAD_REG16, task_struct, thread.reg16); | ||
127 | OFFSET(THREAD_REG17, task_struct, thread.reg17); | ||
128 | OFFSET(THREAD_REG18, task_struct, thread.reg18); | ||
129 | OFFSET(THREAD_REG19, task_struct, thread.reg19); | ||
130 | OFFSET(THREAD_REG20, task_struct, thread.reg20); | ||
131 | OFFSET(THREAD_REG21, task_struct, thread.reg21); | ||
132 | OFFSET(THREAD_REG29, task_struct, thread.reg29); | ||
133 | |||
134 | OFFSET(THREAD_PSR, task_struct, thread.cp0_psr); | ||
135 | OFFSET(THREAD_EMA, task_struct, thread.cp0_ema); | ||
136 | OFFSET(THREAD_BADUADDR, task_struct, thread.cp0_baduaddr); | ||
137 | OFFSET(THREAD_ECODE, task_struct, thread.error_code); | ||
138 | OFFSET(THREAD_TRAPNO, task_struct, thread.trap_no); | ||
139 | BLANK(); | ||
140 | } | ||
141 | |||
142 | void output_mm_defines(void) | ||
143 | { | ||
144 | COMMENT("Size of struct page"); | ||
145 | DEFINE(STRUCT_PAGE_SIZE, sizeof(struct page)); | ||
146 | BLANK(); | ||
147 | COMMENT("Linux mm_struct offsets."); | ||
148 | OFFSET(MM_USERS, mm_struct, mm_users); | ||
149 | OFFSET(MM_PGD, mm_struct, pgd); | ||
150 | OFFSET(MM_CONTEXT, mm_struct, context); | ||
151 | BLANK(); | ||
152 | DEFINE(_PAGE_SIZE, PAGE_SIZE); | ||
153 | DEFINE(_PAGE_SHIFT, PAGE_SHIFT); | ||
154 | BLANK(); | ||
155 | DEFINE(_PGD_T_SIZE, sizeof(pgd_t)); | ||
156 | DEFINE(_PTE_T_SIZE, sizeof(pte_t)); | ||
157 | BLANK(); | ||
158 | DEFINE(_PGD_ORDER, PGD_ORDER); | ||
159 | DEFINE(_PTE_ORDER, PTE_ORDER); | ||
160 | BLANK(); | ||
161 | DEFINE(_PGDIR_SHIFT, PGDIR_SHIFT); | ||
162 | BLANK(); | ||
163 | DEFINE(_PTRS_PER_PGD, PTRS_PER_PGD); | ||
164 | DEFINE(_PTRS_PER_PTE, PTRS_PER_PTE); | ||
165 | BLANK(); | ||
166 | } | ||
167 | |||
168 | void output_sc_defines(void) | ||
169 | { | ||
170 | COMMENT("Linux sigcontext offsets."); | ||
171 | OFFSET(SC_REGS, sigcontext, sc_regs); | ||
172 | OFFSET(SC_MDCEH, sigcontext, sc_mdceh); | ||
173 | OFFSET(SC_MDCEL, sigcontext, sc_mdcel); | ||
174 | OFFSET(SC_PC, sigcontext, sc_pc); | ||
175 | OFFSET(SC_PSR, sigcontext, sc_psr); | ||
176 | OFFSET(SC_ECR, sigcontext, sc_ecr); | ||
177 | OFFSET(SC_EMA, sigcontext, sc_ema); | ||
178 | BLANK(); | ||
179 | } | ||
180 | |||
181 | void output_signal_defined(void) | ||
182 | { | ||
183 | COMMENT("Linux signal numbers."); | ||
184 | DEFINE(_SIGHUP, SIGHUP); | ||
185 | DEFINE(_SIGINT, SIGINT); | ||
186 | DEFINE(_SIGQUIT, SIGQUIT); | ||
187 | DEFINE(_SIGILL, SIGILL); | ||
188 | DEFINE(_SIGTRAP, SIGTRAP); | ||
189 | DEFINE(_SIGIOT, SIGIOT); | ||
190 | DEFINE(_SIGABRT, SIGABRT); | ||
191 | DEFINE(_SIGFPE, SIGFPE); | ||
192 | DEFINE(_SIGKILL, SIGKILL); | ||
193 | DEFINE(_SIGBUS, SIGBUS); | ||
194 | DEFINE(_SIGSEGV, SIGSEGV); | ||
195 | DEFINE(_SIGSYS, SIGSYS); | ||
196 | DEFINE(_SIGPIPE, SIGPIPE); | ||
197 | DEFINE(_SIGALRM, SIGALRM); | ||
198 | DEFINE(_SIGTERM, SIGTERM); | ||
199 | DEFINE(_SIGUSR1, SIGUSR1); | ||
200 | DEFINE(_SIGUSR2, SIGUSR2); | ||
201 | DEFINE(_SIGCHLD, SIGCHLD); | ||
202 | DEFINE(_SIGPWR, SIGPWR); | ||
203 | DEFINE(_SIGWINCH, SIGWINCH); | ||
204 | DEFINE(_SIGURG, SIGURG); | ||
205 | DEFINE(_SIGIO, SIGIO); | ||
206 | DEFINE(_SIGSTOP, SIGSTOP); | ||
207 | DEFINE(_SIGTSTP, SIGTSTP); | ||
208 | DEFINE(_SIGCONT, SIGCONT); | ||
209 | DEFINE(_SIGTTIN, SIGTTIN); | ||
210 | DEFINE(_SIGTTOU, SIGTTOU); | ||
211 | DEFINE(_SIGVTALRM, SIGVTALRM); | ||
212 | DEFINE(_SIGPROF, SIGPROF); | ||
213 | DEFINE(_SIGXCPU, SIGXCPU); | ||
214 | DEFINE(_SIGXFSZ, SIGXFSZ); | ||
215 | BLANK(); | ||
216 | } | ||
diff --git a/arch/score/kernel/entry.S b/arch/score/kernel/entry.S new file mode 100644 index 000000000000..577abba3fac6 --- /dev/null +++ b/arch/score/kernel/entry.S | |||
@@ -0,0 +1,514 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/entry.S | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/err.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/linkage.h> | ||
29 | |||
30 | #include <asm/asmmacro.h> | ||
31 | #include <asm/thread_info.h> | ||
32 | #include <asm/unistd.h> | ||
33 | |||
34 | /* | ||
35 | * disable interrupts. | ||
36 | */ | ||
37 | .macro disable_irq | ||
38 | mfcr r8, cr0 | ||
39 | srli r8, r8, 1 | ||
40 | slli r8, r8, 1 | ||
41 | mtcr r8, cr0 | ||
42 | nop | ||
43 | nop | ||
44 | nop | ||
45 | nop | ||
46 | nop | ||
47 | .endm | ||
48 | |||
49 | /* | ||
50 | * enable interrupts. | ||
51 | */ | ||
52 | .macro enable_irq | ||
53 | mfcr r8, cr0 | ||
54 | ori r8, 1 | ||
55 | mtcr r8, cr0 | ||
56 | nop | ||
57 | nop | ||
58 | nop | ||
59 | nop | ||
60 | nop | ||
61 | .endm | ||
62 | |||
63 | __INIT | ||
64 | ENTRY(debug_exception_vector) | ||
65 | nop! | ||
66 | nop! | ||
67 | nop! | ||
68 | nop! | ||
69 | nop! | ||
70 | nop! | ||
71 | nop! | ||
72 | nop! | ||
73 | |||
74 | ENTRY(general_exception_vector) # should move to addr 0x200 | ||
75 | j general_exception | ||
76 | nop! | ||
77 | nop! | ||
78 | nop! | ||
79 | nop! | ||
80 | nop! | ||
81 | nop! | ||
82 | |||
83 | ENTRY(interrupt_exception_vector) # should move to addr 0x210 | ||
84 | j interrupt_exception | ||
85 | nop! | ||
86 | nop! | ||
87 | nop! | ||
88 | nop! | ||
89 | nop! | ||
90 | nop! | ||
91 | |||
92 | .section ".text", "ax" | ||
93 | .align 2; | ||
94 | general_exception: | ||
95 | mfcr r31, cr2 | ||
96 | nop | ||
97 | la r30, exception_handlers | ||
98 | andi r31, 0x1f # get ecr.exc_code | ||
99 | slli r31, r31, 2 | ||
100 | add r30, r30, r31 | ||
101 | lw r30, [r30] | ||
102 | br r30 | ||
103 | |||
104 | interrupt_exception: | ||
105 | SAVE_ALL | ||
106 | mfcr r4, cr2 | ||
107 | nop | ||
108 | lw r16, [r28, TI_REGS] | ||
109 | sw r0, [r28, TI_REGS] | ||
110 | la r3, ret_from_irq | ||
111 | srli r4, r4, 18 # get ecr.ip[7:2], interrupt No. | ||
112 | mv r5, r0 | ||
113 | j do_IRQ | ||
114 | |||
115 | ENTRY(handle_nmi) # NMI #1 | ||
116 | SAVE_ALL | ||
117 | mv r4, r0 | ||
118 | la r8, nmi_exception_handler | ||
119 | brl r8 | ||
120 | j restore_all | ||
121 | |||
122 | ENTRY(handle_adelinsn) # AdEL-instruction #2 | ||
123 | SAVE_ALL | ||
124 | mfcr r8, cr6 | ||
125 | nop | ||
126 | nop | ||
127 | sw r8, [r0, PT_EMA] | ||
128 | mv r4, r0 | ||
129 | la r8, do_adelinsn | ||
130 | brl r8 | ||
131 | mv r4, r0 | ||
132 | j ret_from_exception | ||
133 | nop | ||
134 | |||
135 | ENTRY(handle_ibe) # BusEL-instruction #5 | ||
136 | SAVE_ALL | ||
137 | mv r4, r0 | ||
138 | la r8, do_be | ||
139 | brl r8 | ||
140 | mv r4, r0 | ||
141 | j ret_from_exception | ||
142 | nop | ||
143 | |||
144 | ENTRY(handle_pel) # P-EL #6 | ||
145 | SAVE_ALL | ||
146 | mv r4, r0 | ||
147 | la r8, do_pel | ||
148 | brl r8 | ||
149 | mv r4, r0 | ||
150 | j ret_from_exception | ||
151 | nop | ||
152 | |||
153 | ENTRY(handle_ccu) # CCU #8 | ||
154 | SAVE_ALL | ||
155 | mv r4, r0 | ||
156 | la r8, do_ccu | ||
157 | brl r8 | ||
158 | mv r4, r0 | ||
159 | j ret_from_exception | ||
160 | nop | ||
161 | |||
162 | ENTRY(handle_ri) # RI #9 | ||
163 | SAVE_ALL | ||
164 | mv r4, r0 | ||
165 | la r8, do_ri | ||
166 | brl r8 | ||
167 | mv r4, r0 | ||
168 | j ret_from_exception | ||
169 | nop | ||
170 | |||
171 | ENTRY(handle_tr) # Trap #10 | ||
172 | SAVE_ALL | ||
173 | mv r4, r0 | ||
174 | la r8, do_tr | ||
175 | brl r8 | ||
176 | mv r4, r0 | ||
177 | j ret_from_exception | ||
178 | nop | ||
179 | |||
180 | ENTRY(handle_adedata) # AdES-instruction #12 | ||
181 | SAVE_ALL | ||
182 | mfcr r8, cr6 | ||
183 | nop | ||
184 | nop | ||
185 | sw r8, [r0, PT_EMA] | ||
186 | mv r4, r0 | ||
187 | la r8, do_adedata | ||
188 | brl r8 | ||
189 | mv r4, r0 | ||
190 | j ret_from_exception | ||
191 | nop | ||
192 | |||
193 | ENTRY(handle_cee) # CeE #16 | ||
194 | SAVE_ALL | ||
195 | mv r4, r0 | ||
196 | la r8, do_cee | ||
197 | brl r8 | ||
198 | mv r4, r0 | ||
199 | j ret_from_exception | ||
200 | nop | ||
201 | |||
202 | ENTRY(handle_cpe) # CpE #17 | ||
203 | SAVE_ALL | ||
204 | mv r4, r0 | ||
205 | la r8, do_cpe | ||
206 | brl r8 | ||
207 | mv r4, r0 | ||
208 | j ret_from_exception | ||
209 | nop | ||
210 | |||
211 | ENTRY(handle_dbe) # BusEL-data #18 | ||
212 | SAVE_ALL | ||
213 | mv r4, r0 | ||
214 | la r8, do_be | ||
215 | brl r8 | ||
216 | mv r4, r0 | ||
217 | j ret_from_exception | ||
218 | nop | ||
219 | |||
220 | ENTRY(handle_reserved) # others | ||
221 | SAVE_ALL | ||
222 | mv r4, r0 | ||
223 | la r8, do_reserved | ||
224 | brl r8 | ||
225 | mv r4, r0 | ||
226 | j ret_from_exception | ||
227 | nop | ||
228 | |||
229 | #ifndef CONFIG_PREEMPT | ||
230 | #define resume_kernel restore_all | ||
231 | #else | ||
232 | #define __ret_from_irq ret_from_exception | ||
233 | #endif | ||
234 | |||
235 | .align 2 | ||
236 | #ifndef CONFIG_PREEMPT | ||
237 | ENTRY(ret_from_exception) | ||
238 | disable_irq # preempt stop | ||
239 | nop | ||
240 | j __ret_from_irq | ||
241 | nop | ||
242 | #endif | ||
243 | |||
244 | ENTRY(ret_from_irq) | ||
245 | sw r16, [r28, TI_REGS] | ||
246 | |||
247 | ENTRY(__ret_from_irq) | ||
248 | lw r8, [r0, PT_PSR] # returning to kernel mode? | ||
249 | andri.c r8, r8, KU_USER | ||
250 | beq resume_kernel | ||
251 | |||
252 | resume_userspace: | ||
253 | disable_irq | ||
254 | lw r6, [r28, TI_FLAGS] # current->work | ||
255 | li r8, _TIF_WORK_MASK | ||
256 | and.c r8, r8, r6 # ignoring syscall_trace | ||
257 | bne work_pending | ||
258 | nop | ||
259 | j restore_all | ||
260 | nop | ||
261 | |||
262 | #ifdef CONFIG_PREEMPT | ||
263 | resume_kernel: | ||
264 | disable_irq | ||
265 | lw r8, [r28, TI_PRE_COUNT] | ||
266 | cmpz.c r8 | ||
267 | bne r8, restore_all | ||
268 | need_resched: | ||
269 | lw r8, [r28, TI_FLAGS] | ||
270 | andri.c r9, r8, _TIF_NEED_RESCHED | ||
271 | beq restore_all | ||
272 | lw r8, [r28, PT_PSR] # Interrupts off? | ||
273 | andri.c r8, r8, 1 | ||
274 | beq restore_all | ||
275 | bl preempt_schedule_irq | ||
276 | nop | ||
277 | j need_resched | ||
278 | nop | ||
279 | #endif | ||
280 | |||
281 | ENTRY(ret_from_fork) | ||
282 | bl schedule_tail # r4=struct task_struct *prev | ||
283 | |||
284 | ENTRY(syscall_exit) | ||
285 | nop | ||
286 | disable_irq | ||
287 | lw r6, [r28, TI_FLAGS] # current->work | ||
288 | li r8, _TIF_WORK_MASK | ||
289 | and.c r8, r6, r8 | ||
290 | bne syscall_exit_work | ||
291 | |||
292 | ENTRY(restore_all) # restore full frame | ||
293 | RESTORE_ALL_AND_RET | ||
294 | |||
295 | work_pending: | ||
296 | andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS | ||
297 | beq work_notifysig | ||
298 | work_resched: | ||
299 | bl schedule | ||
300 | nop | ||
301 | disable_irq | ||
302 | lw r6, [r28, TI_FLAGS] | ||
303 | li r8, _TIF_WORK_MASK | ||
304 | and.c r8, r6, r8 # is there any work to be done | ||
305 | # other than syscall tracing? | ||
306 | beq restore_all | ||
307 | andri.c r8, r6, _TIF_NEED_RESCHED | ||
308 | bne work_resched | ||
309 | |||
310 | work_notifysig: | ||
311 | mv r4, r0 | ||
312 | li r5, 0 | ||
313 | bl do_notify_resume # r6 already loaded | ||
314 | nop | ||
315 | j resume_userspace | ||
316 | nop | ||
317 | |||
318 | ENTRY(syscall_exit_work) | ||
319 | li r8, _TIF_SYSCALL_TRACE | ||
320 | and.c r8, r8, r6 # r6 is preloaded with TI_FLAGS | ||
321 | beq work_pending # trace bit set? | ||
322 | nop | ||
323 | enable_irq | ||
324 | mv r4, r0 | ||
325 | li r5, 1 | ||
326 | bl do_syscall_trace | ||
327 | nop | ||
328 | b resume_userspace | ||
329 | nop | ||
330 | |||
331 | .macro save_context reg | ||
332 | sw r12, [\reg, THREAD_REG12]; | ||
333 | sw r13, [\reg, THREAD_REG13]; | ||
334 | sw r14, [\reg, THREAD_REG14]; | ||
335 | sw r15, [\reg, THREAD_REG15]; | ||
336 | sw r16, [\reg, THREAD_REG16]; | ||
337 | sw r17, [\reg, THREAD_REG17]; | ||
338 | sw r18, [\reg, THREAD_REG18]; | ||
339 | sw r19, [\reg, THREAD_REG19]; | ||
340 | sw r20, [\reg, THREAD_REG20]; | ||
341 | sw r21, [\reg, THREAD_REG21]; | ||
342 | sw r29, [\reg, THREAD_REG29]; | ||
343 | sw r2, [\reg, THREAD_REG2]; | ||
344 | sw r0, [\reg, THREAD_REG0] | ||
345 | .endm | ||
346 | |||
347 | .macro restore_context reg | ||
348 | lw r12, [\reg, THREAD_REG12]; | ||
349 | lw r13, [\reg, THREAD_REG13]; | ||
350 | lw r14, [\reg, THREAD_REG14]; | ||
351 | lw r15, [\reg, THREAD_REG15]; | ||
352 | lw r16, [\reg, THREAD_REG16]; | ||
353 | lw r17, [\reg, THREAD_REG17]; | ||
354 | lw r18, [\reg, THREAD_REG18]; | ||
355 | lw r19, [\reg, THREAD_REG19]; | ||
356 | lw r20, [\reg, THREAD_REG20]; | ||
357 | lw r21, [\reg, THREAD_REG21]; | ||
358 | lw r29, [\reg, THREAD_REG29]; | ||
359 | lw r0, [\reg, THREAD_REG0]; | ||
360 | lw r2, [\reg, THREAD_REG2]; | ||
361 | lw r3, [\reg, THREAD_REG3] | ||
362 | .endm | ||
363 | |||
364 | /* | ||
365 | * task_struct *resume(task_struct *prev, task_struct *next, | ||
366 | * struct thread_info *next_ti) | ||
367 | */ | ||
368 | ENTRY(resume) | ||
369 | mfcr r9, cr0 | ||
370 | nop | ||
371 | nop | ||
372 | sw r9, [r4, THREAD_PSR] | ||
373 | save_context r4 | ||
374 | sw r3, [r4, THREAD_REG3] | ||
375 | |||
376 | mv r28, r6 | ||
377 | restore_context r5 | ||
378 | mv r8, r6 | ||
379 | addi r8, KERNEL_STACK_SIZE | ||
380 | subi r8, 32 | ||
381 | la r9, kernelsp; | ||
382 | sw r8, [r9]; | ||
383 | |||
384 | mfcr r9, cr0 | ||
385 | ldis r7, 0x00ff | ||
386 | nop | ||
387 | and r9, r9, r7 | ||
388 | lw r6, [r5, THREAD_PSR] | ||
389 | not r7, r7 | ||
390 | and r6, r6, r7 | ||
391 | or r6, r6, r9 | ||
392 | mtcr r6, cr0 | ||
393 | nop; nop; nop; nop; nop | ||
394 | br r3 | ||
395 | |||
396 | ENTRY(handle_sys) | ||
397 | SAVE_ALL | ||
398 | sw r8, [r0, 16] # argument 5 from user r8 | ||
399 | sw r9, [r0, 20] # argument 6 from user r9 | ||
400 | enable_irq | ||
401 | |||
402 | sw r4, [r0, PT_ORIG_R4] #for restart syscall | ||
403 | sw r7, [r0, PT_ORIG_R7] #for restart syscall | ||
404 | sw r27, [r0, PT_IS_SYSCALL] # it from syscall | ||
405 | |||
406 | lw r9, [r0, PT_EPC] # skip syscall on return | ||
407 | addi r9, 4 | ||
408 | sw r9, [r0, PT_EPC] | ||
409 | |||
410 | cmpi.c r27, __NR_syscalls # check syscall number | ||
411 | bgtu illegal_syscall | ||
412 | |||
413 | slli r8, r27, 2 # get syscall routine | ||
414 | la r11, sys_call_table | ||
415 | add r11, r11, r8 | ||
416 | lw r10, [r11] # get syscall entry | ||
417 | |||
418 | cmpz.c r10 | ||
419 | beq illegal_syscall | ||
420 | |||
421 | lw r8, [r28, TI_FLAGS] | ||
422 | li r9, _TIF_SYSCALL_TRACE | ||
423 | and.c r8, r8, r9 | ||
424 | bne syscall_trace_entry | ||
425 | |||
426 | brl r10 # Do The Real system call | ||
427 | |||
428 | cmpi.c r4, 0 | ||
429 | blt 1f | ||
430 | ldi r8, 0 | ||
431 | sw r8, [r0, PT_R7] | ||
432 | b 2f | ||
433 | 1: | ||
434 | cmpi.c r4, -MAX_ERRNO - 1 | ||
435 | ble 2f | ||
436 | ldi r8, 0x1; | ||
437 | sw r8, [r0, PT_R7] | ||
438 | neg r4, r4 | ||
439 | 2: | ||
440 | sw r4, [r0, PT_R4] # save result | ||
441 | |||
442 | syscall_return: | ||
443 | disable_irq | ||
444 | lw r6, [r28, TI_FLAGS] # current->work | ||
445 | li r8, _TIF_WORK_MASK | ||
446 | and.c r8, r6, r8 | ||
447 | bne syscall_return_work | ||
448 | j restore_all | ||
449 | |||
450 | syscall_return_work: | ||
451 | j syscall_exit_work | ||
452 | |||
453 | syscall_trace_entry: | ||
454 | mv r16, r10 | ||
455 | mv r4, r0 | ||
456 | li r5, 0 | ||
457 | bl do_syscall_trace | ||
458 | |||
459 | mv r8, r16 | ||
460 | lw r4, [r0, PT_R4] # Restore argument registers | ||
461 | lw r5, [r0, PT_R5] | ||
462 | lw r6, [r0, PT_R6] | ||
463 | lw r7, [r0, PT_R7] | ||
464 | brl r8 | ||
465 | |||
466 | li r8, -MAX_ERRNO - 1 | ||
467 | sw r8, [r0, PT_R7] # set error flag | ||
468 | |||
469 | neg r4, r4 # error | ||
470 | sw r4, [r0, PT_R0] # set flag for syscall | ||
471 | # restarting | ||
472 | 1: sw r4, [r0, PT_R2] # result | ||
473 | j syscall_exit | ||
474 | |||
475 | illegal_syscall: | ||
476 | ldi r4, -ENOSYS # error | ||
477 | sw r4, [r0, PT_ORIG_R4] | ||
478 | sw r4, [r0, PT_R4] | ||
479 | ldi r9, 1 # set error flag | ||
480 | sw r9, [r0, PT_R7] | ||
481 | j syscall_return | ||
482 | |||
483 | ENTRY(sys_execve) | ||
484 | mv r4, r0 | ||
485 | la r8, score_execve | ||
486 | br r8 | ||
487 | |||
488 | ENTRY(sys_clone) | ||
489 | mv r4, r0 | ||
490 | la r8, score_clone | ||
491 | br r8 | ||
492 | |||
493 | ENTRY(sys_rt_sigreturn) | ||
494 | mv r4, r0 | ||
495 | la r8, score_rt_sigreturn | ||
496 | br r8 | ||
497 | |||
498 | ENTRY(sys_sigaltstack) | ||
499 | mv r4, r0 | ||
500 | la r8, score_sigaltstack | ||
501 | br r8 | ||
502 | |||
503 | #ifdef __ARCH_WANT_SYSCALL_DEPRECATED | ||
504 | ENTRY(sys_fork) | ||
505 | mv r4, r0 | ||
506 | la r8, score_fork | ||
507 | br r8 | ||
508 | |||
509 | ENTRY(sys_vfork) | ||
510 | mv r4, r0 | ||
511 | la r8, score_vfork | ||
512 | br r8 | ||
513 | #endif /* __ARCH_WANT_SYSCALL_DEPRECATED */ | ||
514 | |||
diff --git a/arch/score/kernel/head.S b/arch/score/kernel/head.S new file mode 100644 index 000000000000..22a7e3c7292b --- /dev/null +++ b/arch/score/kernel/head.S | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/head.S | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/linkage.h> | ||
27 | |||
28 | #include <asm/asm-offsets.h> | ||
29 | |||
30 | .extern start_kernel | ||
31 | .global init_thread_union | ||
32 | .global kernelsp | ||
33 | |||
34 | __INIT | ||
35 | ENTRY(_stext) | ||
36 | la r30, __bss_start /* initialize BSS segment. */ | ||
37 | la r31, _end | ||
38 | xor r8, r8, r8 | ||
39 | |||
40 | 1: cmp.c r31, r30 | ||
41 | beq 2f | ||
42 | |||
43 | sw r8, [r30] /* clean memory. */ | ||
44 | addi r30, 4 | ||
45 | b 1b | ||
46 | |||
47 | 2: la r28, init_thread_union /* set kernel stack. */ | ||
48 | mv r0, r28 | ||
49 | addi r0, KERNEL_STACK_SIZE - 32 | ||
50 | la r30, kernelsp | ||
51 | sw r0, [r30] | ||
52 | subi r0, 4*4 | ||
53 | xor r30, r30, r30 | ||
54 | ori r30, 0x02 /* enable MMU. */ | ||
55 | mtcr r30, cr4 | ||
56 | nop | ||
57 | nop | ||
58 | nop | ||
59 | nop | ||
60 | nop | ||
61 | nop | ||
62 | nop | ||
63 | |||
64 | /* there is no parameter */ | ||
65 | xor r4, r4, r4 | ||
66 | xor r5, r5, r5 | ||
67 | xor r6, r6, r6 | ||
68 | xor r7, r7, r7 | ||
69 | la r30, start_kernel /* jump to init_arch */ | ||
70 | br r30 | ||
diff --git a/arch/score/kernel/init_task.c b/arch/score/kernel/init_task.c new file mode 100644 index 000000000000..ff952f6c63fd --- /dev/null +++ b/arch/score/kernel/init_task.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/init_task.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, see the file COPYING, or write | ||
20 | * to the Free Software Foundation, Inc., | ||
21 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/init_task.h> | ||
25 | #include <linux/mqueue.h> | ||
26 | |||
27 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | ||
28 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | ||
29 | |||
30 | /* | ||
31 | * Initial thread structure. | ||
32 | * | ||
33 | * We need to make sure that this is THREAD_SIZE aligned due to the | ||
34 | * way process stacks are handled. This is done by having a special | ||
35 | * "init_task" linker map entry.. | ||
36 | */ | ||
37 | union thread_union init_thread_union | ||
38 | __attribute__((__section__(".data.init_task"), __aligned__(THREAD_SIZE))) = | ||
39 | { INIT_THREAD_INFO(init_task) }; | ||
40 | |||
41 | /* | ||
42 | * Initial task structure. | ||
43 | * | ||
44 | * All other task structs will be allocated on slabs in fork.c | ||
45 | */ | ||
46 | struct task_struct init_task = INIT_TASK(init_task); | ||
47 | EXPORT_SYMBOL(init_task); | ||
diff --git a/arch/score/kernel/irq.c b/arch/score/kernel/irq.c new file mode 100644 index 000000000000..47647dde09ca --- /dev/null +++ b/arch/score/kernel/irq.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/irq.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/kernel_stat.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | |||
30 | #include <asm/io.h> | ||
31 | |||
32 | /* the interrupt controller is hardcoded at this address */ | ||
33 | #define SCORE_PIC ((u32 __iomem __force *)0x95F50000) | ||
34 | |||
35 | #define INT_PNDL 0 | ||
36 | #define INT_PNDH 1 | ||
37 | #define INT_PRIORITY_M 2 | ||
38 | #define INT_PRIORITY_SG0 4 | ||
39 | #define INT_PRIORITY_SG1 5 | ||
40 | #define INT_PRIORITY_SG2 6 | ||
41 | #define INT_PRIORITY_SG3 7 | ||
42 | #define INT_MASKL 8 | ||
43 | #define INT_MASKH 9 | ||
44 | |||
45 | /* | ||
46 | * handles all normal device IRQs | ||
47 | */ | ||
48 | asmlinkage void do_IRQ(int irq) | ||
49 | { | ||
50 | irq_enter(); | ||
51 | generic_handle_irq(irq); | ||
52 | irq_exit(); | ||
53 | } | ||
54 | |||
55 | static void score_mask(unsigned int irq_nr) | ||
56 | { | ||
57 | unsigned int irq_source = 63 - irq_nr; | ||
58 | |||
59 | if (irq_source < 32) | ||
60 | __raw_writel((__raw_readl(SCORE_PIC + INT_MASKL) | \ | ||
61 | (1 << irq_source)), SCORE_PIC + INT_MASKL); | ||
62 | else | ||
63 | __raw_writel((__raw_readl(SCORE_PIC + INT_MASKH) | \ | ||
64 | (1 << (irq_source - 32))), SCORE_PIC + INT_MASKH); | ||
65 | } | ||
66 | |||
67 | static void score_unmask(unsigned int irq_nr) | ||
68 | { | ||
69 | unsigned int irq_source = 63 - irq_nr; | ||
70 | |||
71 | if (irq_source < 32) | ||
72 | __raw_writel((__raw_readl(SCORE_PIC + INT_MASKL) & \ | ||
73 | ~(1 << irq_source)), SCORE_PIC + INT_MASKL); | ||
74 | else | ||
75 | __raw_writel((__raw_readl(SCORE_PIC + INT_MASKH) & \ | ||
76 | ~(1 << (irq_source - 32))), SCORE_PIC + INT_MASKH); | ||
77 | } | ||
78 | |||
79 | struct irq_chip score_irq_chip = { | ||
80 | .name = "Score7-level", | ||
81 | .mask = score_mask, | ||
82 | .mask_ack = score_mask, | ||
83 | .unmask = score_unmask, | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * initialise the interrupt system | ||
88 | */ | ||
89 | void __init init_IRQ(void) | ||
90 | { | ||
91 | int index; | ||
92 | unsigned long target_addr; | ||
93 | |||
94 | for (index = 0; index < NR_IRQS; ++index) | ||
95 | set_irq_chip_and_handler(index, &score_irq_chip, | ||
96 | handle_level_irq); | ||
97 | |||
98 | for (target_addr = IRQ_VECTOR_BASE_ADDR; | ||
99 | target_addr <= IRQ_VECTOR_END_ADDR; | ||
100 | target_addr += IRQ_VECTOR_SIZE) | ||
101 | memcpy((void *)target_addr, \ | ||
102 | interrupt_exception_vector, IRQ_VECTOR_SIZE); | ||
103 | |||
104 | __raw_writel(0xffffffff, SCORE_PIC + INT_MASKL); | ||
105 | __raw_writel(0xffffffff, SCORE_PIC + INT_MASKH); | ||
106 | |||
107 | __asm__ __volatile__( | ||
108 | "mtcr %0, cr3\n\t" | ||
109 | : : "r" (EXCEPTION_VECTOR_BASE_ADDR | \ | ||
110 | VECTOR_ADDRESS_OFFSET_MODE16)); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Generic, controller-independent functions: | ||
115 | */ | ||
116 | int show_interrupts(struct seq_file *p, void *v) | ||
117 | { | ||
118 | int i = *(loff_t *)v, cpu; | ||
119 | struct irqaction *action; | ||
120 | unsigned long flags; | ||
121 | |||
122 | if (i == 0) { | ||
123 | seq_puts(p, " "); | ||
124 | for_each_online_cpu(cpu) | ||
125 | seq_printf(p, "CPU%d ", cpu); | ||
126 | seq_putc(p, '\n'); | ||
127 | } | ||
128 | |||
129 | if (i < NR_IRQS) { | ||
130 | spin_lock_irqsave(&irq_desc[i].lock, flags); | ||
131 | action = irq_desc[i].action; | ||
132 | if (!action) | ||
133 | goto unlock; | ||
134 | |||
135 | seq_printf(p, "%3d: ", i); | ||
136 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
137 | seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-"); | ||
138 | seq_printf(p, " %s", action->name); | ||
139 | for (action = action->next; action; action = action->next) | ||
140 | seq_printf(p, ", %s", action->name); | ||
141 | |||
142 | seq_putc(p, '\n'); | ||
143 | unlock: | ||
144 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
diff --git a/arch/score/kernel/module.c b/arch/score/kernel/module.c new file mode 100644 index 000000000000..4de8d47becd3 --- /dev/null +++ b/arch/score/kernel/module.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/module.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/moduleloader.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | |||
30 | void *module_alloc(unsigned long size) | ||
31 | { | ||
32 | return size ? vmalloc(size) : NULL; | ||
33 | } | ||
34 | |||
35 | /* Free memory returned from module_alloc */ | ||
36 | void module_free(struct module *mod, void *module_region) | ||
37 | { | ||
38 | vfree(module_region); | ||
39 | } | ||
40 | |||
41 | int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, | ||
42 | char *secstrings, struct module *mod) | ||
43 | { | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, | ||
48 | unsigned int symindex, unsigned int relindex, | ||
49 | struct module *me) | ||
50 | { | ||
51 | Elf32_Shdr *symsec = sechdrs + symindex; | ||
52 | Elf32_Shdr *relsec = sechdrs + relindex; | ||
53 | Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; | ||
54 | Elf32_Rel *rel = (void *)relsec->sh_addr; | ||
55 | unsigned int i; | ||
56 | |||
57 | for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { | ||
58 | unsigned long loc; | ||
59 | Elf32_Sym *sym; | ||
60 | s32 r_offset; | ||
61 | |||
62 | r_offset = ELF32_R_SYM(rel->r_info); | ||
63 | if ((r_offset < 0) || | ||
64 | (r_offset > (symsec->sh_size / sizeof(Elf32_Sym)))) { | ||
65 | printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n", | ||
66 | me->name, relindex, i); | ||
67 | return -ENOEXEC; | ||
68 | } | ||
69 | |||
70 | sym = ((Elf32_Sym *)symsec->sh_addr) + r_offset; | ||
71 | |||
72 | if ((rel->r_offset < 0) || | ||
73 | (rel->r_offset > dstsec->sh_size - sizeof(u32))) { | ||
74 | printk(KERN_ERR "%s: out of bounds relocation, " | ||
75 | "section %d reloc %d offset %d size %d\n", | ||
76 | me->name, relindex, i, rel->r_offset, | ||
77 | dstsec->sh_size); | ||
78 | return -ENOEXEC; | ||
79 | } | ||
80 | |||
81 | loc = dstsec->sh_addr + rel->r_offset; | ||
82 | switch (ELF32_R_TYPE(rel->r_info)) { | ||
83 | case R_SCORE_NONE: | ||
84 | break; | ||
85 | case R_SCORE_ABS32: | ||
86 | *(unsigned long *)loc += sym->st_value; | ||
87 | break; | ||
88 | case R_SCORE_HI16: | ||
89 | break; | ||
90 | case R_SCORE_LO16: { | ||
91 | unsigned long hi16_offset, offset; | ||
92 | unsigned long uvalue; | ||
93 | unsigned long temp, temp_hi; | ||
94 | temp_hi = *((unsigned long *)loc - 1); | ||
95 | temp = *(unsigned long *)loc; | ||
96 | |||
97 | hi16_offset = (((((temp_hi) >> 16) & 0x3) << 15) | | ||
98 | ((temp_hi) & 0x7fff)) >> 1; | ||
99 | offset = ((temp >> 16 & 0x03) << 15) | | ||
100 | ((temp & 0x7fff) >> 1); | ||
101 | offset = (hi16_offset << 16) | (offset & 0xffff); | ||
102 | uvalue = sym->st_value + offset; | ||
103 | hi16_offset = (uvalue >> 16) << 1; | ||
104 | |||
105 | temp_hi = ((temp_hi) & (~(0x37fff))) | | ||
106 | (hi16_offset & 0x7fff) | | ||
107 | ((hi16_offset << 1) & 0x30000); | ||
108 | *((unsigned long *)loc - 1) = temp_hi; | ||
109 | |||
110 | offset = (uvalue & 0xffff) << 1; | ||
111 | temp = (temp & (~(0x37fff))) | (offset & 0x7fff) | | ||
112 | ((offset << 1) & 0x30000); | ||
113 | *(unsigned long *)loc = temp; | ||
114 | break; | ||
115 | } | ||
116 | case R_SCORE_24: { | ||
117 | unsigned long hi16_offset, offset; | ||
118 | unsigned long uvalue; | ||
119 | unsigned long temp; | ||
120 | |||
121 | temp = *(unsigned long *)loc; | ||
122 | offset = (temp & 0x03FF7FFE); | ||
123 | hi16_offset = (offset & 0xFFFF0000); | ||
124 | offset = (hi16_offset | ((offset & 0xFFFF) << 1)) >> 2; | ||
125 | |||
126 | uvalue = (sym->st_value + offset) >> 1; | ||
127 | uvalue = uvalue & 0x00ffffff; | ||
128 | |||
129 | temp = (temp & 0xfc008001) | | ||
130 | ((uvalue << 2) & 0x3ff0000) | | ||
131 | ((uvalue & 0x3fff) << 1); | ||
132 | *(unsigned long *)loc = temp; | ||
133 | break; | ||
134 | } | ||
135 | default: | ||
136 | printk(KERN_ERR "%s: unknown relocation: %u\n", | ||
137 | me->name, ELF32_R_TYPE(rel->r_info)); | ||
138 | return -ENOEXEC; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, | ||
146 | unsigned int symindex, unsigned int relsec, | ||
147 | struct module *me) | ||
148 | { | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | /* Given an address, look for it in the module exception tables. */ | ||
153 | const struct exception_table_entry *search_module_dbetables(unsigned long addr) | ||
154 | { | ||
155 | return NULL; | ||
156 | } | ||
157 | |||
158 | /* Put in dbe list if necessary. */ | ||
159 | int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, | ||
160 | struct module *me) | ||
161 | { | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | void module_arch_cleanup(struct module *mod) {} | ||
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c new file mode 100644 index 000000000000..25d08030a883 --- /dev/null +++ b/arch/score/kernel/process.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/process.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/reboot.h> | ||
28 | #include <linux/elfcore.h> | ||
29 | #include <linux/pm.h> | ||
30 | |||
31 | void (*pm_power_off)(void); | ||
32 | EXPORT_SYMBOL(pm_power_off); | ||
33 | |||
34 | /* If or when software machine-restart is implemented, add code here. */ | ||
35 | void machine_restart(char *command) {} | ||
36 | |||
37 | /* If or when software machine-halt is implemented, add code here. */ | ||
38 | void machine_halt(void) {} | ||
39 | |||
40 | /* If or when software machine-power-off is implemented, add code here. */ | ||
41 | void machine_power_off(void) {} | ||
42 | |||
43 | /* | ||
44 | * The idle thread. There's no useful work to be | ||
45 | * done, so just try to conserve power and have a | ||
46 | * low exit latency (ie sit in a loop waiting for | ||
47 | * somebody to say that they'd like to reschedule) | ||
48 | */ | ||
49 | void __noreturn cpu_idle(void) | ||
50 | { | ||
51 | /* endless idle loop with no priority at all */ | ||
52 | while (1) { | ||
53 | while (!need_resched()) | ||
54 | barrier(); | ||
55 | |||
56 | preempt_enable_no_resched(); | ||
57 | schedule(); | ||
58 | preempt_disable(); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | void ret_from_fork(void); | ||
63 | |||
64 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) | ||
65 | { | ||
66 | unsigned long status; | ||
67 | |||
68 | /* New thread loses kernel privileges. */ | ||
69 | status = regs->cp0_psr & ~(KU_MASK); | ||
70 | status |= KU_USER; | ||
71 | regs->cp0_psr = status; | ||
72 | regs->cp0_epc = pc; | ||
73 | regs->regs[0] = sp; | ||
74 | } | ||
75 | |||
76 | void exit_thread(void) {} | ||
77 | |||
78 | /* | ||
79 | * When a process does an "exec", machine state like FPU and debug | ||
80 | * registers need to be reset. This is a hook function for that. | ||
81 | * Currently we don't have any such state to reset, so this is empty. | ||
82 | */ | ||
83 | void flush_thread(void) {} | ||
84 | |||
85 | /* | ||
86 | * set up the kernel stack and exception frames for a new process | ||
87 | */ | ||
88 | int copy_thread(unsigned long clone_flags, unsigned long usp, | ||
89 | unsigned long unused, | ||
90 | struct task_struct *p, struct pt_regs *regs) | ||
91 | { | ||
92 | struct thread_info *ti = task_thread_info(p); | ||
93 | struct pt_regs *childregs = task_pt_regs(p); | ||
94 | |||
95 | p->set_child_tid = NULL; | ||
96 | p->clear_child_tid = NULL; | ||
97 | |||
98 | *childregs = *regs; | ||
99 | childregs->regs[7] = 0; /* Clear error flag */ | ||
100 | childregs->regs[4] = 0; /* Child gets zero as return value */ | ||
101 | regs->regs[4] = p->pid; | ||
102 | |||
103 | if (childregs->cp0_psr & 0x8) { /* test kernel fork or user fork */ | ||
104 | childregs->regs[0] = usp; /* user fork */ | ||
105 | } else { | ||
106 | childregs->regs[28] = (unsigned long) ti; /* kernel fork */ | ||
107 | childregs->regs[0] = (unsigned long) childregs; | ||
108 | } | ||
109 | |||
110 | p->thread.reg0 = (unsigned long) childregs; | ||
111 | p->thread.reg3 = (unsigned long) ret_from_fork; | ||
112 | p->thread.cp0_psr = 0; | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /* Fill in the fpu structure for a core dump. */ | ||
118 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) | ||
119 | { | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | static void __noreturn | ||
124 | kernel_thread_helper(void *unused0, int (*fn)(void *), | ||
125 | void *arg, void *unused1) | ||
126 | { | ||
127 | do_exit(fn(arg)); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Create a kernel thread. | ||
132 | */ | ||
133 | long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
134 | { | ||
135 | struct pt_regs regs; | ||
136 | |||
137 | memset(®s, 0, sizeof(regs)); | ||
138 | |||
139 | regs.regs[6] = (unsigned long) arg; | ||
140 | regs.regs[5] = (unsigned long) fn; | ||
141 | regs.cp0_epc = (unsigned long) kernel_thread_helper; | ||
142 | regs.cp0_psr = (regs.cp0_psr & ~(0x1|0x4|0x8)) | \ | ||
143 | ((regs.cp0_psr & 0x3) << 2); | ||
144 | |||
145 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, \ | ||
146 | 0, ®s, 0, NULL, NULL); | ||
147 | } | ||
148 | |||
149 | unsigned long thread_saved_pc(struct task_struct *tsk) | ||
150 | { | ||
151 | return task_pt_regs(tsk)->cp0_epc; | ||
152 | } | ||
153 | |||
154 | unsigned long get_wchan(struct task_struct *task) | ||
155 | { | ||
156 | if (!task || task == current || task->state == TASK_RUNNING) | ||
157 | return 0; | ||
158 | |||
159 | if (!task_stack_page(task)) | ||
160 | return 0; | ||
161 | |||
162 | return task_pt_regs(task)->cp0_epc; | ||
163 | } | ||
164 | |||
165 | unsigned long arch_align_stack(unsigned long sp) | ||
166 | { | ||
167 | return sp; | ||
168 | } | ||
diff --git a/arch/score/kernel/ptrace.c b/arch/score/kernel/ptrace.c new file mode 100644 index 000000000000..174c6422b096 --- /dev/null +++ b/arch/score/kernel/ptrace.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/ptrace.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/elf.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/ptrace.h> | ||
30 | #include <linux/regset.h> | ||
31 | |||
32 | #include <asm/uaccess.h> | ||
33 | |||
34 | /* | ||
35 | * retrieve the contents of SCORE userspace general registers | ||
36 | */ | ||
37 | static int genregs_get(struct task_struct *target, | ||
38 | const struct user_regset *regset, | ||
39 | unsigned int pos, unsigned int count, | ||
40 | void *kbuf, void __user *ubuf) | ||
41 | { | ||
42 | const struct pt_regs *regs = task_pt_regs(target); | ||
43 | int ret; | ||
44 | |||
45 | /* skip 9 * sizeof(unsigned long) not use for pt_regs */ | ||
46 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
47 | 0, offsetof(struct pt_regs, regs)); | ||
48 | |||
49 | /* r0 - r31, cel, ceh, sr0, sr1, sr2, epc, ema, psr, ecr, condition */ | ||
50 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
51 | regs->regs, | ||
52 | offsetof(struct pt_regs, regs), | ||
53 | offsetof(struct pt_regs, cp0_condition)); | ||
54 | |||
55 | if (!ret) | ||
56 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
57 | sizeof(struct pt_regs), -1); | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * update the contents of the SCORE userspace general registers | ||
64 | */ | ||
65 | static int genregs_set(struct task_struct *target, | ||
66 | const struct user_regset *regset, | ||
67 | unsigned int pos, unsigned int count, | ||
68 | const void *kbuf, const void __user *ubuf) | ||
69 | { | ||
70 | struct pt_regs *regs = task_pt_regs(target); | ||
71 | int ret; | ||
72 | |||
73 | /* skip 9 * sizeof(unsigned long) */ | ||
74 | ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, | ||
75 | 0, offsetof(struct pt_regs, regs)); | ||
76 | |||
77 | /* r0 - r31, cel, ceh, sr0, sr1, sr2, epc, ema, psr, ecr, condition */ | ||
78 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
79 | regs->regs, | ||
80 | offsetof(struct pt_regs, regs), | ||
81 | offsetof(struct pt_regs, cp0_condition)); | ||
82 | |||
83 | if (!ret) | ||
84 | ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, | ||
85 | sizeof(struct pt_regs), -1); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * Define the register sets available on the score7 under Linux | ||
92 | */ | ||
93 | enum score7_regset { | ||
94 | REGSET_GENERAL, | ||
95 | }; | ||
96 | |||
97 | static const struct user_regset score7_regsets[] = { | ||
98 | [REGSET_GENERAL] = { | ||
99 | .core_note_type = NT_PRSTATUS, | ||
100 | .n = ELF_NGREG, | ||
101 | .size = sizeof(long), | ||
102 | .align = sizeof(long), | ||
103 | .get = genregs_get, | ||
104 | .set = genregs_set, | ||
105 | }, | ||
106 | }; | ||
107 | |||
108 | static const struct user_regset_view user_score_native_view = { | ||
109 | .name = "score7", | ||
110 | .e_machine = EM_SCORE7, | ||
111 | .regsets = score7_regsets, | ||
112 | .n = ARRAY_SIZE(score7_regsets), | ||
113 | }; | ||
114 | |||
115 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | ||
116 | { | ||
117 | return &user_score_native_view; | ||
118 | } | ||
119 | |||
120 | static int is_16bitinsn(unsigned long insn) | ||
121 | { | ||
122 | if ((insn & INSN32_MASK) == INSN32_MASK) | ||
123 | return 0; | ||
124 | else | ||
125 | return 1; | ||
126 | } | ||
127 | |||
128 | int | ||
129 | read_tsk_long(struct task_struct *child, | ||
130 | unsigned long addr, unsigned long *res) | ||
131 | { | ||
132 | int copied; | ||
133 | |||
134 | copied = access_process_vm(child, addr, res, sizeof(*res), 0); | ||
135 | |||
136 | return copied != sizeof(*res) ? -EIO : 0; | ||
137 | } | ||
138 | |||
139 | int | ||
140 | read_tsk_short(struct task_struct *child, | ||
141 | unsigned long addr, unsigned short *res) | ||
142 | { | ||
143 | int copied; | ||
144 | |||
145 | copied = access_process_vm(child, addr, res, sizeof(*res), 0); | ||
146 | |||
147 | return copied != sizeof(*res) ? -EIO : 0; | ||
148 | } | ||
149 | |||
150 | static int | ||
151 | write_tsk_short(struct task_struct *child, | ||
152 | unsigned long addr, unsigned short val) | ||
153 | { | ||
154 | int copied; | ||
155 | |||
156 | copied = access_process_vm(child, addr, &val, sizeof(val), 1); | ||
157 | |||
158 | return copied != sizeof(val) ? -EIO : 0; | ||
159 | } | ||
160 | |||
161 | static int | ||
162 | write_tsk_long(struct task_struct *child, | ||
163 | unsigned long addr, unsigned long val) | ||
164 | { | ||
165 | int copied; | ||
166 | |||
167 | copied = access_process_vm(child, addr, &val, sizeof(val), 1); | ||
168 | |||
169 | return copied != sizeof(val) ? -EIO : 0; | ||
170 | } | ||
171 | |||
172 | void user_enable_single_step(struct task_struct *child) | ||
173 | { | ||
174 | /* far_epc is the target of branch */ | ||
175 | unsigned int epc, far_epc = 0; | ||
176 | unsigned long epc_insn, far_epc_insn; | ||
177 | int ninsn_type; /* next insn type 0=16b, 1=32b */ | ||
178 | unsigned int tmp, tmp2; | ||
179 | struct pt_regs *regs = task_pt_regs(child); | ||
180 | child->thread.single_step = 1; | ||
181 | child->thread.ss_nextcnt = 1; | ||
182 | epc = regs->cp0_epc; | ||
183 | |||
184 | read_tsk_long(child, epc, &epc_insn); | ||
185 | |||
186 | if (is_16bitinsn(epc_insn)) { | ||
187 | if ((epc_insn & J16M) == J16) { | ||
188 | tmp = epc_insn & 0xFFE; | ||
189 | epc = (epc & 0xFFFFF000) | tmp; | ||
190 | } else if ((epc_insn & B16M) == B16) { | ||
191 | child->thread.ss_nextcnt = 2; | ||
192 | tmp = (epc_insn & 0xFF) << 1; | ||
193 | tmp = tmp << 23; | ||
194 | tmp = (unsigned int)((int) tmp >> 23); | ||
195 | far_epc = epc + tmp; | ||
196 | epc += 2; | ||
197 | } else if ((epc_insn & BR16M) == BR16) { | ||
198 | child->thread.ss_nextcnt = 2; | ||
199 | tmp = (epc_insn >> 4) & 0xF; | ||
200 | far_epc = regs->regs[tmp]; | ||
201 | epc += 2; | ||
202 | } else | ||
203 | epc += 2; | ||
204 | } else { | ||
205 | if ((epc_insn & J32M) == J32) { | ||
206 | tmp = epc_insn & 0x03FFFFFE; | ||
207 | tmp2 = tmp & 0x7FFF; | ||
208 | tmp = (((tmp >> 16) & 0x3FF) << 15) | tmp2; | ||
209 | epc = (epc & 0xFFC00000) | tmp; | ||
210 | } else if ((epc_insn & B32M) == B32) { | ||
211 | child->thread.ss_nextcnt = 2; | ||
212 | tmp = epc_insn & 0x03FFFFFE; /* discard LK bit */ | ||
213 | tmp2 = tmp & 0x3FF; | ||
214 | tmp = (((tmp >> 16) & 0x3FF) << 10) | tmp2; /* 20bit */ | ||
215 | tmp = tmp << 12; | ||
216 | tmp = (unsigned int)((int) tmp >> 12); | ||
217 | far_epc = epc + tmp; | ||
218 | epc += 4; | ||
219 | } else if ((epc_insn & BR32M) == BR32) { | ||
220 | child->thread.ss_nextcnt = 2; | ||
221 | tmp = (epc_insn >> 16) & 0x1F; | ||
222 | far_epc = regs->regs[tmp]; | ||
223 | epc += 4; | ||
224 | } else | ||
225 | epc += 4; | ||
226 | } | ||
227 | |||
228 | if (child->thread.ss_nextcnt == 1) { | ||
229 | read_tsk_long(child, epc, &epc_insn); | ||
230 | |||
231 | if (is_16bitinsn(epc_insn)) { | ||
232 | write_tsk_short(child, epc, SINGLESTEP16_INSN); | ||
233 | ninsn_type = 0; | ||
234 | } else { | ||
235 | write_tsk_long(child, epc, SINGLESTEP32_INSN); | ||
236 | ninsn_type = 1; | ||
237 | } | ||
238 | |||
239 | if (ninsn_type == 0) { /* 16bits */ | ||
240 | child->thread.insn1_type = 0; | ||
241 | child->thread.addr1 = epc; | ||
242 | /* the insn may have 32bit data */ | ||
243 | child->thread.insn1 = (short)epc_insn; | ||
244 | } else { | ||
245 | child->thread.insn1_type = 1; | ||
246 | child->thread.addr1 = epc; | ||
247 | child->thread.insn1 = epc_insn; | ||
248 | } | ||
249 | } else { | ||
250 | /* branch! have two target child->thread.ss_nextcnt=2 */ | ||
251 | read_tsk_long(child, epc, &epc_insn); | ||
252 | read_tsk_long(child, far_epc, &far_epc_insn); | ||
253 | if (is_16bitinsn(epc_insn)) { | ||
254 | write_tsk_short(child, epc, SINGLESTEP16_INSN); | ||
255 | ninsn_type = 0; | ||
256 | } else { | ||
257 | write_tsk_long(child, epc, SINGLESTEP32_INSN); | ||
258 | ninsn_type = 1; | ||
259 | } | ||
260 | |||
261 | if (ninsn_type == 0) { /* 16bits */ | ||
262 | child->thread.insn1_type = 0; | ||
263 | child->thread.addr1 = epc; | ||
264 | /* the insn may have 32bit data */ | ||
265 | child->thread.insn1 = (short)epc_insn; | ||
266 | } else { | ||
267 | child->thread.insn1_type = 1; | ||
268 | child->thread.addr1 = epc; | ||
269 | child->thread.insn1 = epc_insn; | ||
270 | } | ||
271 | |||
272 | if (is_16bitinsn(far_epc_insn)) { | ||
273 | write_tsk_short(child, far_epc, SINGLESTEP16_INSN); | ||
274 | ninsn_type = 0; | ||
275 | } else { | ||
276 | write_tsk_long(child, far_epc, SINGLESTEP32_INSN); | ||
277 | ninsn_type = 1; | ||
278 | } | ||
279 | |||
280 | if (ninsn_type == 0) { /* 16bits */ | ||
281 | child->thread.insn2_type = 0; | ||
282 | child->thread.addr2 = far_epc; | ||
283 | /* the insn may have 32bit data */ | ||
284 | child->thread.insn2 = (short)far_epc_insn; | ||
285 | } else { | ||
286 | child->thread.insn2_type = 1; | ||
287 | child->thread.addr2 = far_epc; | ||
288 | child->thread.insn2 = far_epc_insn; | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | |||
293 | void user_disable_single_step(struct task_struct *child) | ||
294 | { | ||
295 | if (child->thread.insn1_type == 0) | ||
296 | write_tsk_short(child, child->thread.addr1, | ||
297 | child->thread.insn1); | ||
298 | |||
299 | if (child->thread.insn1_type == 1) | ||
300 | write_tsk_long(child, child->thread.addr1, | ||
301 | child->thread.insn1); | ||
302 | |||
303 | if (child->thread.ss_nextcnt == 2) { /* branch */ | ||
304 | if (child->thread.insn1_type == 0) | ||
305 | write_tsk_short(child, child->thread.addr1, | ||
306 | child->thread.insn1); | ||
307 | if (child->thread.insn1_type == 1) | ||
308 | write_tsk_long(child, child->thread.addr1, | ||
309 | child->thread.insn1); | ||
310 | if (child->thread.insn2_type == 0) | ||
311 | write_tsk_short(child, child->thread.addr2, | ||
312 | child->thread.insn2); | ||
313 | if (child->thread.insn2_type == 1) | ||
314 | write_tsk_long(child, child->thread.addr2, | ||
315 | child->thread.insn2); | ||
316 | } | ||
317 | |||
318 | child->thread.single_step = 0; | ||
319 | child->thread.ss_nextcnt = 0; | ||
320 | } | ||
321 | |||
322 | void ptrace_disable(struct task_struct *child) | ||
323 | { | ||
324 | user_disable_single_step(child); | ||
325 | } | ||
326 | |||
327 | long | ||
328 | arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||
329 | { | ||
330 | int ret; | ||
331 | unsigned long __user *datap = (void __user *)data; | ||
332 | |||
333 | switch (request) { | ||
334 | case PTRACE_GETREGS: | ||
335 | ret = copy_regset_to_user(child, &user_score_native_view, | ||
336 | REGSET_GENERAL, | ||
337 | 0, sizeof(struct pt_regs), | ||
338 | (void __user *)datap); | ||
339 | break; | ||
340 | |||
341 | case PTRACE_SETREGS: | ||
342 | ret = copy_regset_from_user(child, &user_score_native_view, | ||
343 | REGSET_GENERAL, | ||
344 | 0, sizeof(struct pt_regs), | ||
345 | (const void __user *)datap); | ||
346 | break; | ||
347 | |||
348 | default: | ||
349 | ret = ptrace_request(child, request, addr, data); | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * Notification of system call entry/exit | ||
358 | * - triggered by current->work.syscall_trace | ||
359 | */ | ||
360 | asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) | ||
361 | { | ||
362 | if (!(current->ptrace & PT_PTRACED)) | ||
363 | return; | ||
364 | |||
365 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
366 | return; | ||
367 | |||
368 | /* The 0x80 provides a way for the tracing parent to distinguish | ||
369 | between a syscall stop and SIGTRAP delivery. */ | ||
370 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? | ||
371 | 0x80 : 0)); | ||
372 | |||
373 | /* | ||
374 | * this isn't the same as continuing with a signal, but it will do | ||
375 | * for normal use. strace only continues with a signal if the | ||
376 | * stopping signal is not SIGTRAP. -brl | ||
377 | */ | ||
378 | if (current->exit_code) { | ||
379 | send_sig(current->exit_code, current, 1); | ||
380 | current->exit_code = 0; | ||
381 | } | ||
382 | } | ||
diff --git a/arch/score/kernel/setup.c b/arch/score/kernel/setup.c new file mode 100644 index 000000000000..6a2503c75c4e --- /dev/null +++ b/arch/score/kernel/setup.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/setup.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/bootmem.h> | ||
27 | #include <linux/initrd.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/seq_file.h> | ||
31 | #include <linux/screen_info.h> | ||
32 | |||
33 | #include <asm-generic/sections.h> | ||
34 | #include <asm/setup.h> | ||
35 | |||
36 | struct screen_info screen_info; | ||
37 | unsigned long kernelsp; | ||
38 | |||
39 | static char command_line[COMMAND_LINE_SIZE]; | ||
40 | static struct resource code_resource = { .name = "Kernel code",}; | ||
41 | static struct resource data_resource = { .name = "Kernel data",}; | ||
42 | |||
43 | static void __init bootmem_init(void) | ||
44 | { | ||
45 | unsigned long start_pfn, bootmap_size; | ||
46 | unsigned long size = initrd_end - initrd_start; | ||
47 | |||
48 | start_pfn = PFN_UP(__pa(&_end)); | ||
49 | |||
50 | min_low_pfn = PFN_UP(MEMORY_START); | ||
51 | max_low_pfn = PFN_UP(MEMORY_START + MEMORY_SIZE); | ||
52 | |||
53 | /* Initialize the boot-time allocator with low memory only. */ | ||
54 | bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, | ||
55 | min_low_pfn, max_low_pfn); | ||
56 | add_active_range(0, min_low_pfn, max_low_pfn); | ||
57 | |||
58 | free_bootmem(PFN_PHYS(start_pfn), | ||
59 | (max_low_pfn - start_pfn) << PAGE_SHIFT); | ||
60 | memory_present(0, start_pfn, max_low_pfn); | ||
61 | |||
62 | /* Reserve space for the bootmem bitmap. */ | ||
63 | reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size, BOOTMEM_DEFAULT); | ||
64 | |||
65 | if (size == 0) { | ||
66 | printk(KERN_INFO "Initrd not found or empty"); | ||
67 | goto disable; | ||
68 | } | ||
69 | |||
70 | if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { | ||
71 | printk(KERN_ERR "Initrd extends beyond end of memory"); | ||
72 | goto disable; | ||
73 | } | ||
74 | |||
75 | /* Reserve space for the initrd bitmap. */ | ||
76 | reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT); | ||
77 | initrd_below_start_ok = 1; | ||
78 | |||
79 | pr_info("Initial ramdisk at: 0x%lx (%lu bytes)\n", | ||
80 | initrd_start, size); | ||
81 | return; | ||
82 | disable: | ||
83 | printk(KERN_CONT " - disabling initrd\n"); | ||
84 | initrd_start = 0; | ||
85 | initrd_end = 0; | ||
86 | } | ||
87 | |||
88 | static void __init resource_init(void) | ||
89 | { | ||
90 | struct resource *res; | ||
91 | |||
92 | code_resource.start = __pa(&_text); | ||
93 | code_resource.end = __pa(&_etext) - 1; | ||
94 | data_resource.start = __pa(&_etext); | ||
95 | data_resource.end = __pa(&_edata) - 1; | ||
96 | |||
97 | res = alloc_bootmem(sizeof(struct resource)); | ||
98 | res->name = "System RAM"; | ||
99 | res->start = MEMORY_START; | ||
100 | res->end = MEMORY_START + MEMORY_SIZE - 1; | ||
101 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
102 | request_resource(&iomem_resource, res); | ||
103 | |||
104 | request_resource(res, &code_resource); | ||
105 | request_resource(res, &data_resource); | ||
106 | } | ||
107 | |||
108 | void __init setup_arch(char **cmdline_p) | ||
109 | { | ||
110 | randomize_va_space = 0; | ||
111 | *cmdline_p = command_line; | ||
112 | |||
113 | cpu_cache_init(); | ||
114 | tlb_init(); | ||
115 | bootmem_init(); | ||
116 | paging_init(); | ||
117 | resource_init(); | ||
118 | } | ||
119 | |||
120 | static int show_cpuinfo(struct seq_file *m, void *v) | ||
121 | { | ||
122 | unsigned long n = (unsigned long) v - 1; | ||
123 | |||
124 | seq_printf(m, "processor\t\t: %ld\n", n); | ||
125 | seq_printf(m, "\n"); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
131 | { | ||
132 | unsigned long i = *pos; | ||
133 | |||
134 | return i < 1 ? (void *) (i + 1) : NULL; | ||
135 | } | ||
136 | |||
137 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
138 | { | ||
139 | ++*pos; | ||
140 | return c_start(m, pos); | ||
141 | } | ||
142 | |||
143 | static void c_stop(struct seq_file *m, void *v) | ||
144 | { | ||
145 | } | ||
146 | |||
147 | const struct seq_operations cpuinfo_op = { | ||
148 | .start = c_start, | ||
149 | .next = c_next, | ||
150 | .stop = c_stop, | ||
151 | .show = show_cpuinfo, | ||
152 | }; | ||
153 | |||
154 | static int __init topology_init(void) | ||
155 | { | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | subsys_initcall(topology_init); | ||
diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c new file mode 100644 index 000000000000..aa57440e4973 --- /dev/null +++ b/arch/score/kernel/signal.c | |||
@@ -0,0 +1,361 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/signal.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/errno.h> | ||
27 | #include <linux/signal.h> | ||
28 | #include <linux/ptrace.h> | ||
29 | #include <linux/unistd.h> | ||
30 | #include <linux/uaccess.h> | ||
31 | |||
32 | #include <asm/cacheflush.h> | ||
33 | #include <asm/syscalls.h> | ||
34 | #include <asm/ucontext.h> | ||
35 | |||
36 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
37 | |||
38 | struct rt_sigframe { | ||
39 | u32 rs_ass[4]; /* argument save space */ | ||
40 | u32 rs_code[2]; /* signal trampoline */ | ||
41 | struct siginfo rs_info; | ||
42 | struct ucontext rs_uc; | ||
43 | }; | ||
44 | |||
45 | static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | ||
46 | { | ||
47 | int err = 0; | ||
48 | unsigned long reg; | ||
49 | |||
50 | reg = regs->cp0_epc; err |= __put_user(reg, &sc->sc_pc); | ||
51 | err |= __put_user(regs->cp0_psr, &sc->sc_psr); | ||
52 | err |= __put_user(regs->cp0_condition, &sc->sc_condition); | ||
53 | |||
54 | |||
55 | #define save_gp_reg(i) { \ | ||
56 | reg = regs->regs[i]; \ | ||
57 | err |= __put_user(reg, &sc->sc_regs[i]); \ | ||
58 | } while (0) | ||
59 | save_gp_reg(0); save_gp_reg(1); save_gp_reg(2); | ||
60 | save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); | ||
61 | save_gp_reg(6); save_gp_reg(7); save_gp_reg(8); | ||
62 | save_gp_reg(9); save_gp_reg(10); save_gp_reg(11); | ||
63 | save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); | ||
64 | save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); | ||
65 | save_gp_reg(18); save_gp_reg(19); save_gp_reg(20); | ||
66 | save_gp_reg(21); save_gp_reg(22); save_gp_reg(23); | ||
67 | save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); | ||
68 | save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); | ||
69 | #undef save_gp_reg | ||
70 | |||
71 | reg = regs->ceh; err |= __put_user(reg, &sc->sc_mdceh); | ||
72 | reg = regs->cel; err |= __put_user(reg, &sc->sc_mdcel); | ||
73 | err |= __put_user(regs->cp0_ecr, &sc->sc_ecr); | ||
74 | err |= __put_user(regs->cp0_ema, &sc->sc_ema); | ||
75 | |||
76 | return err; | ||
77 | } | ||
78 | |||
79 | static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | ||
80 | { | ||
81 | int err = 0; | ||
82 | u32 reg; | ||
83 | |||
84 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); | ||
85 | err |= __get_user(regs->cp0_condition, &sc->sc_condition); | ||
86 | |||
87 | err |= __get_user(reg, &sc->sc_mdceh); | ||
88 | regs->ceh = (int) reg; | ||
89 | err |= __get_user(reg, &sc->sc_mdcel); | ||
90 | regs->cel = (int) reg; | ||
91 | |||
92 | err |= __get_user(reg, &sc->sc_psr); | ||
93 | regs->cp0_psr = (int) reg; | ||
94 | err |= __get_user(reg, &sc->sc_ecr); | ||
95 | regs->cp0_ecr = (int) reg; | ||
96 | err |= __get_user(reg, &sc->sc_ema); | ||
97 | regs->cp0_ema = (int) reg; | ||
98 | |||
99 | #define restore_gp_reg(i) do { \ | ||
100 | err |= __get_user(reg, &sc->sc_regs[i]); \ | ||
101 | regs->regs[i] = reg; \ | ||
102 | } while (0) | ||
103 | restore_gp_reg(0); restore_gp_reg(1); restore_gp_reg(2); | ||
104 | restore_gp_reg(3); restore_gp_reg(4); restore_gp_reg(5); | ||
105 | restore_gp_reg(6); restore_gp_reg(7); restore_gp_reg(8); | ||
106 | restore_gp_reg(9); restore_gp_reg(10); restore_gp_reg(11); | ||
107 | restore_gp_reg(12); restore_gp_reg(13); restore_gp_reg(14); | ||
108 | restore_gp_reg(15); restore_gp_reg(16); restore_gp_reg(17); | ||
109 | restore_gp_reg(18); restore_gp_reg(19); restore_gp_reg(20); | ||
110 | restore_gp_reg(21); restore_gp_reg(22); restore_gp_reg(23); | ||
111 | restore_gp_reg(24); restore_gp_reg(25); restore_gp_reg(26); | ||
112 | restore_gp_reg(27); restore_gp_reg(28); restore_gp_reg(29); | ||
113 | #undef restore_gp_reg | ||
114 | |||
115 | return err; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Determine which stack to use.. | ||
120 | */ | ||
121 | static void __user *get_sigframe(struct k_sigaction *ka, | ||
122 | struct pt_regs *regs, size_t frame_size) | ||
123 | { | ||
124 | unsigned long sp; | ||
125 | |||
126 | /* Default to using normal stack */ | ||
127 | sp = regs->regs[0]; | ||
128 | sp -= 32; | ||
129 | |||
130 | /* This is the X/Open sanctioned signal stack switching. */ | ||
131 | if ((ka->sa.sa_flags & SA_ONSTACK) && (!on_sig_stack(sp))) | ||
132 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
133 | |||
134 | return (void __user*)((sp - frame_size) & ~7); | ||
135 | } | ||
136 | |||
137 | asmlinkage long | ||
138 | score_sigaltstack(struct pt_regs *regs) | ||
139 | { | ||
140 | const stack_t __user *uss = (const stack_t __user *) regs->regs[4]; | ||
141 | stack_t __user *uoss = (stack_t __user *) regs->regs[5]; | ||
142 | unsigned long usp = regs->regs[0]; | ||
143 | |||
144 | return do_sigaltstack(uss, uoss, usp); | ||
145 | } | ||
146 | |||
147 | asmlinkage long | ||
148 | score_rt_sigreturn(struct pt_regs *regs) | ||
149 | { | ||
150 | struct rt_sigframe __user *frame; | ||
151 | sigset_t set; | ||
152 | stack_t st; | ||
153 | int sig; | ||
154 | |||
155 | frame = (struct rt_sigframe __user *) regs->regs[0]; | ||
156 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
157 | goto badframe; | ||
158 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) | ||
159 | goto badframe; | ||
160 | |||
161 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
162 | spin_lock_irq(¤t->sighand->siglock); | ||
163 | current->blocked = set; | ||
164 | recalc_sigpending(); | ||
165 | spin_unlock_irq(¤t->sighand->siglock); | ||
166 | |||
167 | sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); | ||
168 | if (sig < 0) | ||
169 | goto badframe; | ||
170 | else if (sig) | ||
171 | force_sig(sig, current); | ||
172 | |||
173 | if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) | ||
174 | goto badframe; | ||
175 | |||
176 | /* It is more difficult to avoid calling this function than to | ||
177 | call it and ignore errors. */ | ||
178 | do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]); | ||
179 | |||
180 | __asm__ __volatile__( | ||
181 | "mv\tr0, %0\n\t" | ||
182 | "la\tr8, syscall_exit\n\t" | ||
183 | "br\tr8\n\t" | ||
184 | : : "r" (regs) : "r8"); | ||
185 | |||
186 | badframe: | ||
187 | force_sig(SIGSEGV, current); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, | ||
193 | int signr, sigset_t *set, siginfo_t *info) | ||
194 | { | ||
195 | struct rt_sigframe __user *frame; | ||
196 | int err = 0; | ||
197 | |||
198 | frame = get_sigframe(ka, regs, sizeof(*frame)); | ||
199 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
200 | goto give_sigsegv; | ||
201 | |||
202 | /* | ||
203 | * Set up the return code ... | ||
204 | * | ||
205 | * li v0, __NR_rt_sigreturn | ||
206 | * syscall | ||
207 | */ | ||
208 | err |= __put_user(0x87788000 + __NR_rt_sigreturn*2, | ||
209 | frame->rs_code + 0); | ||
210 | err |= __put_user(0x80008002, frame->rs_code + 1); | ||
211 | flush_cache_sigtramp((unsigned long) frame->rs_code); | ||
212 | |||
213 | err |= copy_siginfo_to_user(&frame->rs_info, info); | ||
214 | err |= __put_user(0, &frame->rs_uc.uc_flags); | ||
215 | err |= __put_user(NULL, &frame->rs_uc.uc_link); | ||
216 | err |= __put_user((void __user *)current->sas_ss_sp, | ||
217 | &frame->rs_uc.uc_stack.ss_sp); | ||
218 | err |= __put_user(sas_ss_flags(regs->regs[0]), | ||
219 | &frame->rs_uc.uc_stack.ss_flags); | ||
220 | err |= __put_user(current->sas_ss_size, | ||
221 | &frame->rs_uc.uc_stack.ss_size); | ||
222 | err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); | ||
223 | err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); | ||
224 | |||
225 | if (err) | ||
226 | goto give_sigsegv; | ||
227 | |||
228 | regs->regs[0] = (unsigned long) frame; | ||
229 | regs->regs[3] = (unsigned long) frame->rs_code; | ||
230 | regs->regs[4] = signr; | ||
231 | regs->regs[5] = (unsigned long) &frame->rs_info; | ||
232 | regs->regs[6] = (unsigned long) &frame->rs_uc; | ||
233 | regs->regs[29] = (unsigned long) ka->sa.sa_handler; | ||
234 | regs->cp0_epc = (unsigned long) ka->sa.sa_handler; | ||
235 | |||
236 | return 0; | ||
237 | |||
238 | give_sigsegv: | ||
239 | if (signr == SIGSEGV) | ||
240 | ka->sa.sa_handler = SIG_DFL; | ||
241 | force_sig(SIGSEGV, current); | ||
242 | return -EFAULT; | ||
243 | } | ||
244 | |||
245 | static int handle_signal(unsigned long sig, siginfo_t *info, | ||
246 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) | ||
247 | { | ||
248 | int ret; | ||
249 | |||
250 | if (regs->is_syscall) { | ||
251 | switch (regs->regs[4]) { | ||
252 | case ERESTART_RESTARTBLOCK: | ||
253 | case ERESTARTNOHAND: | ||
254 | regs->regs[4] = EINTR; | ||
255 | break; | ||
256 | case ERESTARTSYS: | ||
257 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
258 | regs->regs[4] = EINTR; | ||
259 | break; | ||
260 | } | ||
261 | case ERESTARTNOINTR: | ||
262 | regs->regs[4] = regs->orig_r4; | ||
263 | regs->regs[7] = regs->orig_r7; | ||
264 | regs->cp0_epc -= 8; | ||
265 | } | ||
266 | |||
267 | regs->is_syscall = 0; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * Set up the stack frame | ||
272 | */ | ||
273 | ret = setup_rt_frame(ka, regs, sig, oldset, info); | ||
274 | |||
275 | spin_lock_irq(¤t->sighand->siglock); | ||
276 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
277 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
278 | sigaddset(¤t->blocked, sig); | ||
279 | recalc_sigpending(); | ||
280 | spin_unlock_irq(¤t->sighand->siglock); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static void do_signal(struct pt_regs *regs) | ||
286 | { | ||
287 | struct k_sigaction ka; | ||
288 | sigset_t *oldset; | ||
289 | siginfo_t info; | ||
290 | int signr; | ||
291 | |||
292 | /* | ||
293 | * We want the common case to go fast, which is why we may in certain | ||
294 | * cases get here from kernel mode. Just return without doing anything | ||
295 | * if so. | ||
296 | */ | ||
297 | if (!user_mode(regs)) | ||
298 | return; | ||
299 | |||
300 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
301 | oldset = ¤t->saved_sigmask; | ||
302 | else | ||
303 | oldset = ¤t->blocked; | ||
304 | |||
305 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
306 | if (signr > 0) { | ||
307 | /* Actually deliver the signal. */ | ||
308 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | ||
309 | /* | ||
310 | * A signal was successfully delivered; the saved | ||
311 | * sigmask will have been stored in the signal frame, | ||
312 | * and will be restored by sigreturn, so we can simply | ||
313 | * clear the TIF_RESTORE_SIGMASK flag. | ||
314 | */ | ||
315 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
316 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
317 | } | ||
318 | |||
319 | return; | ||
320 | } | ||
321 | |||
322 | if (regs->is_syscall) { | ||
323 | if (regs->regs[4] == ERESTARTNOHAND || | ||
324 | regs->regs[4] == ERESTARTSYS || | ||
325 | regs->regs[4] == ERESTARTNOINTR) { | ||
326 | regs->regs[4] = regs->orig_r4; | ||
327 | regs->regs[7] = regs->orig_r7; | ||
328 | regs->cp0_epc -= 8; | ||
329 | } | ||
330 | |||
331 | if (regs->regs[4] == ERESTART_RESTARTBLOCK) { | ||
332 | regs->regs[27] = __NR_restart_syscall; | ||
333 | regs->regs[4] = regs->orig_r4; | ||
334 | regs->regs[7] = regs->orig_r7; | ||
335 | regs->cp0_epc -= 8; | ||
336 | } | ||
337 | |||
338 | regs->is_syscall = 0; /* Don't deal with this again. */ | ||
339 | } | ||
340 | |||
341 | /* | ||
342 | * If there's no signal to deliver, we just put the saved sigmask | ||
343 | * back | ||
344 | */ | ||
345 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
346 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
347 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * notification of userspace execution resumption | ||
353 | * - triggered by the TIF_WORK_MASK flags | ||
354 | */ | ||
355 | asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, | ||
356 | __u32 thread_info_flags) | ||
357 | { | ||
358 | /* deal with pending signal delivery */ | ||
359 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | ||
360 | do_signal(regs); | ||
361 | } | ||
diff --git a/arch/score/kernel/sys_call_table.c b/arch/score/kernel/sys_call_table.c new file mode 100644 index 000000000000..287369b88c43 --- /dev/null +++ b/arch/score/kernel/sys_call_table.c | |||
@@ -0,0 +1,12 @@ | |||
1 | #include <linux/syscalls.h> | ||
2 | #include <linux/signal.h> | ||
3 | #include <linux/unistd.h> | ||
4 | |||
5 | #include <asm/syscalls.h> | ||
6 | |||
7 | #undef __SYSCALL | ||
8 | #define __SYSCALL(nr, call) [nr] = (call), | ||
9 | |||
10 | void *sys_call_table[__NR_syscalls] = { | ||
11 | #include <asm/unistd.h> | ||
12 | }; | ||
diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c new file mode 100644 index 000000000000..001249469866 --- /dev/null +++ b/arch/score/kernel/sys_score.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/syscall.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/file.h> | ||
27 | #include <linux/fs.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/mman.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/unistd.h> | ||
32 | #include <linux/syscalls.h> | ||
33 | #include <asm/syscalls.h> | ||
34 | |||
35 | asmlinkage long | ||
36 | sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | ||
37 | unsigned long flags, unsigned long fd, unsigned long pgoff) | ||
38 | { | ||
39 | int error = -EBADF; | ||
40 | struct file *file = NULL; | ||
41 | |||
42 | if (pgoff & (~PAGE_MASK >> 12)) | ||
43 | return -EINVAL; | ||
44 | |||
45 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
46 | if (!(flags & MAP_ANONYMOUS)) { | ||
47 | file = fget(fd); | ||
48 | if (!file) | ||
49 | return error; | ||
50 | } | ||
51 | |||
52 | down_write(¤t->mm->mmap_sem); | ||
53 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
54 | up_write(¤t->mm->mmap_sem); | ||
55 | |||
56 | if (file) | ||
57 | fput(file); | ||
58 | |||
59 | return error; | ||
60 | } | ||
61 | |||
62 | asmlinkage long | ||
63 | sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, | ||
64 | unsigned long flags, unsigned long fd, off_t pgoff) | ||
65 | { | ||
66 | return sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); | ||
67 | } | ||
68 | |||
69 | asmlinkage long | ||
70 | score_fork(struct pt_regs *regs) | ||
71 | { | ||
72 | return do_fork(SIGCHLD, regs->regs[0], regs, 0, NULL, NULL); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * Clone a task - this clones the calling program thread. | ||
77 | * This is called indirectly via a small wrapper | ||
78 | */ | ||
79 | asmlinkage long | ||
80 | score_clone(struct pt_regs *regs) | ||
81 | { | ||
82 | unsigned long clone_flags; | ||
83 | unsigned long newsp; | ||
84 | int __user *parent_tidptr, *child_tidptr; | ||
85 | |||
86 | clone_flags = regs->regs[4]; | ||
87 | newsp = regs->regs[5]; | ||
88 | if (!newsp) | ||
89 | newsp = regs->regs[0]; | ||
90 | parent_tidptr = (int __user *)regs->regs[6]; | ||
91 | child_tidptr = (int __user *)regs->regs[8]; | ||
92 | |||
93 | return do_fork(clone_flags, newsp, regs, 0, | ||
94 | parent_tidptr, child_tidptr); | ||
95 | } | ||
96 | |||
97 | asmlinkage long | ||
98 | score_vfork(struct pt_regs *regs) | ||
99 | { | ||
100 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
101 | regs->regs[0], regs, 0, NULL, NULL); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * sys_execve() executes a new program. | ||
106 | * This is called indirectly via a small wrapper | ||
107 | */ | ||
108 | asmlinkage long | ||
109 | score_execve(struct pt_regs *regs) | ||
110 | { | ||
111 | int error; | ||
112 | char *filename; | ||
113 | |||
114 | filename = getname((char __user*)regs->regs[4]); | ||
115 | error = PTR_ERR(filename); | ||
116 | if (IS_ERR(filename)) | ||
117 | return error; | ||
118 | |||
119 | error = do_execve(filename, (char __user *__user*)regs->regs[5], | ||
120 | (char __user *__user *) regs->regs[6], regs); | ||
121 | |||
122 | putname(filename); | ||
123 | return error; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Do a system call from kernel instead of calling sys_execve so we | ||
128 | * end up with proper pt_regs. | ||
129 | */ | ||
130 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]) | ||
131 | { | ||
132 | register unsigned long __r4 asm("r4") = (unsigned long) filename; | ||
133 | register unsigned long __r5 asm("r5") = (unsigned long) argv; | ||
134 | register unsigned long __r6 asm("r6") = (unsigned long) envp; | ||
135 | register unsigned long __r7 asm("r7"); | ||
136 | |||
137 | __asm__ __volatile__ (" \n" | ||
138 | "ldi r27, %5 \n" | ||
139 | "syscall \n" | ||
140 | "mv %0, r4 \n" | ||
141 | "mv %1, r7 \n" | ||
142 | : "=&r" (__r4), "=r" (__r7) | ||
143 | : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve) | ||
144 | : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25", | ||
145 | "r26", "r27", "memory"); | ||
146 | |||
147 | if (__r7 == 0) | ||
148 | return __r4; | ||
149 | |||
150 | return -__r4; | ||
151 | } | ||
diff --git a/arch/score/kernel/time.c b/arch/score/kernel/time.c new file mode 100644 index 000000000000..f0a43affb201 --- /dev/null +++ b/arch/score/kernel/time.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/time.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/clockchips.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | |||
29 | #include <asm/scoreregs.h> | ||
30 | |||
31 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
32 | { | ||
33 | struct clock_event_device *evdev = dev_id; | ||
34 | |||
35 | /* clear timer interrupt flag */ | ||
36 | outl(1, P_TIMER0_CPP_REG); | ||
37 | evdev->event_handler(evdev); | ||
38 | |||
39 | return IRQ_HANDLED; | ||
40 | } | ||
41 | |||
42 | static struct irqaction timer_irq = { | ||
43 | .handler = timer_interrupt, | ||
44 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
45 | .name = "timer", | ||
46 | }; | ||
47 | |||
48 | static int score_timer_set_next_event(unsigned long delta, | ||
49 | struct clock_event_device *evdev) | ||
50 | { | ||
51 | outl((TMR_M_PERIODIC | TMR_IE_ENABLE), P_TIMER0_CTRL); | ||
52 | outl(delta, P_TIMER0_PRELOAD); | ||
53 | outl(inl(P_TIMER0_CTRL) | TMR_ENABLE, P_TIMER0_CTRL); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static void score_timer_set_mode(enum clock_event_mode mode, | ||
59 | struct clock_event_device *evdev) | ||
60 | { | ||
61 | switch (mode) { | ||
62 | case CLOCK_EVT_MODE_PERIODIC: | ||
63 | outl((TMR_M_PERIODIC | TMR_IE_ENABLE), P_TIMER0_CTRL); | ||
64 | outl(SYSTEM_CLOCK/HZ, P_TIMER0_PRELOAD); | ||
65 | outl(inl(P_TIMER0_CTRL) | TMR_ENABLE, P_TIMER0_CTRL); | ||
66 | break; | ||
67 | case CLOCK_EVT_MODE_ONESHOT: | ||
68 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
69 | case CLOCK_EVT_MODE_RESUME: | ||
70 | case CLOCK_EVT_MODE_UNUSED: | ||
71 | break; | ||
72 | default: | ||
73 | BUG(); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | static struct clock_event_device score_clockevent = { | ||
78 | .name = "score_clockevent", | ||
79 | .features = CLOCK_EVT_FEAT_PERIODIC, | ||
80 | .shift = 16, | ||
81 | .set_next_event = score_timer_set_next_event, | ||
82 | .set_mode = score_timer_set_mode, | ||
83 | }; | ||
84 | |||
85 | void __init time_init(void) | ||
86 | { | ||
87 | timer_irq.dev_id = &score_clockevent; | ||
88 | setup_irq(IRQ_TIMER , &timer_irq); | ||
89 | |||
90 | /* setup COMPARE clockevent */ | ||
91 | score_clockevent.mult = div_sc(SYSTEM_CLOCK, NSEC_PER_SEC, | ||
92 | score_clockevent.shift); | ||
93 | score_clockevent.max_delta_ns = clockevent_delta2ns((u32)~0, | ||
94 | &score_clockevent); | ||
95 | score_clockevent.min_delta_ns = clockevent_delta2ns(50, | ||
96 | &score_clockevent) + 1; | ||
97 | score_clockevent.cpumask = cpumask_of(0); | ||
98 | clockevents_register_device(&score_clockevent); | ||
99 | } | ||
diff --git a/arch/score/kernel/traps.c b/arch/score/kernel/traps.c new file mode 100644 index 000000000000..0e46fb19a848 --- /dev/null +++ b/arch/score/kernel/traps.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/traps.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/sched.h> | ||
28 | |||
29 | #include <asm/cacheflush.h> | ||
30 | #include <asm/irq.h> | ||
31 | #include <asm/irq_regs.h> | ||
32 | |||
33 | unsigned long exception_handlers[32]; | ||
34 | |||
35 | /* | ||
36 | * The architecture-independent show_stack generator | ||
37 | */ | ||
38 | void show_stack(struct task_struct *task, unsigned long *sp) | ||
39 | { | ||
40 | int i; | ||
41 | long stackdata; | ||
42 | |||
43 | sp = sp ? sp : (unsigned long *)&sp; | ||
44 | |||
45 | printk(KERN_NOTICE "Stack: "); | ||
46 | i = 1; | ||
47 | while ((long) sp & (PAGE_SIZE - 1)) { | ||
48 | if (i && ((i % 8) == 0)) | ||
49 | printk(KERN_NOTICE "\n"); | ||
50 | if (i > 40) { | ||
51 | printk(KERN_NOTICE " ..."); | ||
52 | break; | ||
53 | } | ||
54 | |||
55 | if (__get_user(stackdata, sp++)) { | ||
56 | printk(KERN_NOTICE " (Bad stack address)"); | ||
57 | break; | ||
58 | } | ||
59 | |||
60 | printk(KERN_NOTICE " %08lx", stackdata); | ||
61 | i++; | ||
62 | } | ||
63 | printk(KERN_NOTICE "\n"); | ||
64 | } | ||
65 | |||
66 | static void show_trace(long *sp) | ||
67 | { | ||
68 | int i; | ||
69 | long addr; | ||
70 | |||
71 | sp = sp ? sp : (long *) &sp; | ||
72 | |||
73 | printk(KERN_NOTICE "Call Trace: "); | ||
74 | i = 1; | ||
75 | while ((long) sp & (PAGE_SIZE - 1)) { | ||
76 | if (__get_user(addr, sp++)) { | ||
77 | if (i && ((i % 6) == 0)) | ||
78 | printk(KERN_NOTICE "\n"); | ||
79 | printk(KERN_NOTICE " (Bad stack address)\n"); | ||
80 | break; | ||
81 | } | ||
82 | |||
83 | if (kernel_text_address(addr)) { | ||
84 | if (i && ((i % 6) == 0)) | ||
85 | printk(KERN_NOTICE "\n"); | ||
86 | if (i > 40) { | ||
87 | printk(KERN_NOTICE " ..."); | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | printk(KERN_NOTICE " [<%08lx>]", addr); | ||
92 | i++; | ||
93 | } | ||
94 | } | ||
95 | printk(KERN_NOTICE "\n"); | ||
96 | } | ||
97 | |||
98 | static void show_code(unsigned int *pc) | ||
99 | { | ||
100 | long i; | ||
101 | |||
102 | printk(KERN_NOTICE "\nCode:"); | ||
103 | |||
104 | for (i = -3; i < 6; i++) { | ||
105 | unsigned long insn; | ||
106 | if (__get_user(insn, pc + i)) { | ||
107 | printk(KERN_NOTICE " (Bad address in epc)\n"); | ||
108 | break; | ||
109 | } | ||
110 | printk(KERN_NOTICE "%c%08lx%c", (i ? ' ' : '<'), | ||
111 | insn, (i ? ' ' : '>')); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * FIXME: really the generic show_regs should take a const pointer argument. | ||
117 | */ | ||
118 | void show_regs(struct pt_regs *regs) | ||
119 | { | ||
120 | printk("r0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
121 | regs->regs[0], regs->regs[1], regs->regs[2], regs->regs[3], | ||
122 | regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); | ||
123 | printk("r8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
124 | regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11], | ||
125 | regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); | ||
126 | printk("r16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
127 | regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19], | ||
128 | regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); | ||
129 | printk("r24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", | ||
130 | regs->regs[24], regs->regs[25], regs->regs[26], regs->regs[27], | ||
131 | regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); | ||
132 | |||
133 | printk("CEH : %08lx\n", regs->ceh); | ||
134 | printk("CEL : %08lx\n", regs->cel); | ||
135 | |||
136 | printk("EMA:%08lx, epc:%08lx %s\nPSR: %08lx\nECR:%08lx\nCondition : %08lx\n", | ||
137 | regs->cp0_ema, regs->cp0_epc, print_tainted(), regs->cp0_psr, | ||
138 | regs->cp0_ecr, regs->cp0_condition); | ||
139 | } | ||
140 | |||
141 | static void show_registers(struct pt_regs *regs) | ||
142 | { | ||
143 | show_regs(regs); | ||
144 | printk(KERN_NOTICE "Process %s (pid: %d, stackpage=%08lx)\n", | ||
145 | current->comm, current->pid, (unsigned long) current); | ||
146 | show_stack(current_thread_info()->task, (long *) regs->regs[0]); | ||
147 | show_trace((long *) regs->regs[0]); | ||
148 | show_code((unsigned int *) regs->cp0_epc); | ||
149 | printk(KERN_NOTICE "\n"); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * The architecture-independent dump_stack generator | ||
154 | */ | ||
155 | void dump_stack(void) | ||
156 | { | ||
157 | show_stack(current_thread_info()->task, | ||
158 | (long *) get_irq_regs()->regs[0]); | ||
159 | } | ||
160 | EXPORT_SYMBOL(dump_stack); | ||
161 | |||
162 | void __die(const char *str, struct pt_regs *regs, const char *file, | ||
163 | const char *func, unsigned long line) | ||
164 | { | ||
165 | console_verbose(); | ||
166 | printk("%s", str); | ||
167 | if (file && func) | ||
168 | printk(" in %s:%s, line %ld", file, func, line); | ||
169 | printk(":\n"); | ||
170 | show_registers(regs); | ||
171 | do_exit(SIGSEGV); | ||
172 | } | ||
173 | |||
174 | void __die_if_kernel(const char *str, struct pt_regs *regs, | ||
175 | const char *file, const char *func, unsigned long line) | ||
176 | { | ||
177 | if (!user_mode(regs)) | ||
178 | __die(str, regs, file, func, line); | ||
179 | } | ||
180 | |||
181 | asmlinkage void do_adelinsn(struct pt_regs *regs) | ||
182 | { | ||
183 | printk("do_ADE-linsn:ema:0x%08lx:epc:0x%08lx\n", | ||
184 | regs->cp0_ema, regs->cp0_epc); | ||
185 | die_if_kernel("do_ade execution Exception\n", regs); | ||
186 | force_sig(SIGBUS, current); | ||
187 | } | ||
188 | |||
189 | asmlinkage void do_adedata(struct pt_regs *regs) | ||
190 | { | ||
191 | const struct exception_table_entry *fixup; | ||
192 | fixup = search_exception_tables(regs->cp0_epc); | ||
193 | if (fixup) { | ||
194 | regs->cp0_epc = fixup->fixup; | ||
195 | return; | ||
196 | } | ||
197 | printk("do_ADE-data:ema:0x%08lx:epc:0x%08lx\n", | ||
198 | regs->cp0_ema, regs->cp0_epc); | ||
199 | die_if_kernel("do_ade execution Exception\n", regs); | ||
200 | force_sig(SIGBUS, current); | ||
201 | } | ||
202 | |||
203 | asmlinkage void do_pel(struct pt_regs *regs) | ||
204 | { | ||
205 | die_if_kernel("do_pel execution Exception", regs); | ||
206 | force_sig(SIGFPE, current); | ||
207 | } | ||
208 | |||
209 | asmlinkage void do_cee(struct pt_regs *regs) | ||
210 | { | ||
211 | die_if_kernel("do_cee execution Exception", regs); | ||
212 | force_sig(SIGFPE, current); | ||
213 | } | ||
214 | |||
215 | asmlinkage void do_cpe(struct pt_regs *regs) | ||
216 | { | ||
217 | die_if_kernel("do_cpe execution Exception", regs); | ||
218 | force_sig(SIGFPE, current); | ||
219 | } | ||
220 | |||
221 | asmlinkage void do_be(struct pt_regs *regs) | ||
222 | { | ||
223 | die_if_kernel("do_be execution Exception", regs); | ||
224 | force_sig(SIGBUS, current); | ||
225 | } | ||
226 | |||
227 | asmlinkage void do_ov(struct pt_regs *regs) | ||
228 | { | ||
229 | siginfo_t info; | ||
230 | |||
231 | die_if_kernel("do_ov execution Exception", regs); | ||
232 | |||
233 | info.si_code = FPE_INTOVF; | ||
234 | info.si_signo = SIGFPE; | ||
235 | info.si_errno = 0; | ||
236 | info.si_addr = (void *)regs->cp0_epc; | ||
237 | force_sig_info(SIGFPE, &info, current); | ||
238 | } | ||
239 | |||
240 | asmlinkage void do_tr(struct pt_regs *regs) | ||
241 | { | ||
242 | die_if_kernel("do_tr execution Exception", regs); | ||
243 | force_sig(SIGTRAP, current); | ||
244 | } | ||
245 | |||
246 | asmlinkage void do_ri(struct pt_regs *regs) | ||
247 | { | ||
248 | unsigned long epc_insn; | ||
249 | unsigned long epc = regs->cp0_epc; | ||
250 | |||
251 | read_tsk_long(current, epc, &epc_insn); | ||
252 | if (current->thread.single_step == 1) { | ||
253 | if ((epc == current->thread.addr1) || | ||
254 | (epc == current->thread.addr2)) { | ||
255 | user_disable_single_step(current); | ||
256 | force_sig(SIGTRAP, current); | ||
257 | return; | ||
258 | } else | ||
259 | BUG(); | ||
260 | } else if ((epc_insn == BREAKPOINT32_INSN) || | ||
261 | ((epc_insn & 0x0000FFFF) == 0x7002) || | ||
262 | ((epc_insn & 0xFFFF0000) == 0x70020000)) { | ||
263 | force_sig(SIGTRAP, current); | ||
264 | return; | ||
265 | } else { | ||
266 | die_if_kernel("do_ri execution Exception", regs); | ||
267 | force_sig(SIGILL, current); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | asmlinkage void do_ccu(struct pt_regs *regs) | ||
272 | { | ||
273 | die_if_kernel("do_ccu execution Exception", regs); | ||
274 | force_sig(SIGILL, current); | ||
275 | } | ||
276 | |||
277 | asmlinkage void do_reserved(struct pt_regs *regs) | ||
278 | { | ||
279 | /* | ||
280 | * Game over - no way to handle this if it ever occurs. Most probably | ||
281 | * caused by a new unknown cpu type or after another deadly | ||
282 | * hard/software error. | ||
283 | */ | ||
284 | die_if_kernel("do_reserved execution Exception", regs); | ||
285 | show_regs(regs); | ||
286 | panic("Caught reserved exception - should not happen."); | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * NMI exception handler. | ||
291 | */ | ||
292 | void nmi_exception_handler(struct pt_regs *regs) | ||
293 | { | ||
294 | die_if_kernel("nmi_exception_handler execution Exception", regs); | ||
295 | die("NMI", regs); | ||
296 | } | ||
297 | |||
298 | /* Install CPU exception handler */ | ||
299 | void *set_except_vector(int n, void *addr) | ||
300 | { | ||
301 | unsigned long handler = (unsigned long) addr; | ||
302 | unsigned long old_handler = exception_handlers[n]; | ||
303 | |||
304 | exception_handlers[n] = handler; | ||
305 | return (void *)old_handler; | ||
306 | } | ||
307 | |||
308 | void __init trap_init(void) | ||
309 | { | ||
310 | int i; | ||
311 | |||
312 | pgd_current = (unsigned long)init_mm.pgd; | ||
313 | /* DEBUG EXCEPTION */ | ||
314 | memcpy((void *)DEBUG_VECTOR_BASE_ADDR, | ||
315 | &debug_exception_vector, DEBUG_VECTOR_SIZE); | ||
316 | /* NMI EXCEPTION */ | ||
317 | memcpy((void *)GENERAL_VECTOR_BASE_ADDR, | ||
318 | &general_exception_vector, GENERAL_VECTOR_SIZE); | ||
319 | |||
320 | /* | ||
321 | * Initialise exception handlers | ||
322 | */ | ||
323 | for (i = 0; i <= 31; i++) | ||
324 | set_except_vector(i, handle_reserved); | ||
325 | |||
326 | set_except_vector(1, handle_nmi); | ||
327 | set_except_vector(2, handle_adelinsn); | ||
328 | set_except_vector(3, handle_tlb_refill); | ||
329 | set_except_vector(4, handle_tlb_invaild); | ||
330 | set_except_vector(5, handle_ibe); | ||
331 | set_except_vector(6, handle_pel); | ||
332 | set_except_vector(7, handle_sys); | ||
333 | set_except_vector(8, handle_ccu); | ||
334 | set_except_vector(9, handle_ri); | ||
335 | set_except_vector(10, handle_tr); | ||
336 | set_except_vector(11, handle_adedata); | ||
337 | set_except_vector(12, handle_adedata); | ||
338 | set_except_vector(13, handle_tlb_refill); | ||
339 | set_except_vector(14, handle_tlb_invaild); | ||
340 | set_except_vector(15, handle_mod); | ||
341 | set_except_vector(16, handle_cee); | ||
342 | set_except_vector(17, handle_cpe); | ||
343 | set_except_vector(18, handle_dbe); | ||
344 | flush_icache_range(DEBUG_VECTOR_BASE_ADDR, IRQ_VECTOR_BASE_ADDR); | ||
345 | |||
346 | atomic_inc(&init_mm.mm_count); | ||
347 | current->active_mm = &init_mm; | ||
348 | cpu_cache_init(); | ||
349 | } | ||
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..f85569831d5c --- /dev/null +++ b/arch/score/kernel/vmlinux.lds.S | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * arch/score/kernel/vmlinux.lds.S | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <asm-generic/vmlinux.lds.h> | ||
27 | |||
28 | OUTPUT_ARCH(score) | ||
29 | ENTRY(_stext) | ||
30 | |||
31 | jiffies = jiffies_64; | ||
32 | |||
33 | SECTIONS | ||
34 | { | ||
35 | . = CONFIG_MEMORY_START + 0x2000; | ||
36 | /* read-only */ | ||
37 | .text : { | ||
38 | _text = .; /* Text and read-only data */ | ||
39 | TEXT_TEXT | ||
40 | SCHED_TEXT | ||
41 | LOCK_TEXT | ||
42 | KPROBES_TEXT | ||
43 | *(.text.*) | ||
44 | *(.fixup) | ||
45 | . = ALIGN (4) ; | ||
46 | _etext = .; /* End of text section */ | ||
47 | } | ||
48 | |||
49 | . = ALIGN(16); | ||
50 | RODATA | ||
51 | |||
52 | /* Exception table */ | ||
53 | . = ALIGN(16); | ||
54 | __ex_table : { | ||
55 | __start___ex_table = .; | ||
56 | *(__ex_table) | ||
57 | __stop___ex_table = .; | ||
58 | } | ||
59 | |||
60 | /* writeable */ | ||
61 | .data ALIGN (4096): { | ||
62 | *(.data.init_task) | ||
63 | |||
64 | DATA_DATA | ||
65 | CONSTRUCTORS | ||
66 | } | ||
67 | |||
68 | /* We want the small data sections together, so single-instruction offsets | ||
69 | can access them all, and initialized data all before uninitialized, so | ||
70 | we can shorten the on-disk segment size. */ | ||
71 | . = ALIGN(8); | ||
72 | .sdata : { | ||
73 | *(.sdata) | ||
74 | } | ||
75 | |||
76 | . = ALIGN(32); | ||
77 | .data.cacheline_aligned : { | ||
78 | *(.data.cacheline_aligned) | ||
79 | } | ||
80 | _edata = .; /* End of data section */ | ||
81 | |||
82 | /* will be freed after init */ | ||
83 | . = ALIGN(4096); /* Init code and data */ | ||
84 | __init_begin = .; | ||
85 | |||
86 | . = ALIGN(4096); | ||
87 | .init.text : { | ||
88 | _sinittext = .; | ||
89 | INIT_TEXT | ||
90 | _einittext = .; | ||
91 | } | ||
92 | .init.data : { | ||
93 | INIT_DATA | ||
94 | } | ||
95 | . = ALIGN(16); | ||
96 | .init.setup : { | ||
97 | __setup_start = .; | ||
98 | *(.init.setup) | ||
99 | __setup_end = .; | ||
100 | } | ||
101 | |||
102 | .initcall.init : { | ||
103 | __initcall_start = .; | ||
104 | INITCALLS | ||
105 | __initcall_end = .; | ||
106 | } | ||
107 | |||
108 | .con_initcall.init : { | ||
109 | __con_initcall_start = .; | ||
110 | *(.con_initcall.init) | ||
111 | __con_initcall_end = .; | ||
112 | } | ||
113 | SECURITY_INIT | ||
114 | |||
115 | /* .exit.text is discarded at runtime, not link time, to deal with | ||
116 | * references from .rodata | ||
117 | */ | ||
118 | .exit.text : { | ||
119 | EXIT_TEXT | ||
120 | } | ||
121 | .exit.data : { | ||
122 | EXIT_DATA | ||
123 | } | ||
124 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
125 | .init.ramfs ALIGN(4096): { | ||
126 | __initramfs_start = .; | ||
127 | *(.init.ramfs) | ||
128 | __initramfs_end = .; | ||
129 | . = ALIGN(4); | ||
130 | LONG(0); | ||
131 | } | ||
132 | #endif | ||
133 | . = ALIGN(4096); | ||
134 | __init_end = .; | ||
135 | /* freed after init ends here */ | ||
136 | |||
137 | __bss_start = .; /* BSS */ | ||
138 | .sbss : { | ||
139 | *(.sbss) | ||
140 | *(.scommon) | ||
141 | } | ||
142 | .bss : { | ||
143 | *(.bss) | ||
144 | *(COMMON) | ||
145 | } | ||
146 | __bss_stop = .; | ||
147 | _end = .; | ||
148 | } | ||
diff --git a/arch/score/lib/Makefile b/arch/score/lib/Makefile new file mode 100644 index 000000000000..553e30e81faf --- /dev/null +++ b/arch/score/lib/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for SCORE-specific library files.. | ||
3 | # | ||
4 | |||
5 | lib-y += string.o checksum.o checksum_copy.o | ||
6 | |||
7 | # libgcc-style stuff needed in the kernel | ||
8 | obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o | ||
diff --git a/arch/score/lib/ashldi3.c b/arch/score/lib/ashldi3.c new file mode 100644 index 000000000000..15691a910431 --- /dev/null +++ b/arch/score/lib/ashldi3.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * arch/score/lib/ashldi3.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see the file COPYING, or write | ||
16 | * to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include "libgcc.h" | ||
22 | |||
23 | long long __ashldi3(long long u, word_type b) | ||
24 | { | ||
25 | DWunion uu, w; | ||
26 | word_type bm; | ||
27 | |||
28 | if (b == 0) | ||
29 | return u; | ||
30 | |||
31 | uu.ll = u; | ||
32 | bm = 32 - b; | ||
33 | |||
34 | if (bm <= 0) { | ||
35 | w.s.low = 0; | ||
36 | w.s.high = (unsigned int) uu.s.low << -bm; | ||
37 | } else { | ||
38 | const unsigned int carries = (unsigned int) uu.s.low >> bm; | ||
39 | |||
40 | w.s.low = (unsigned int) uu.s.low << b; | ||
41 | w.s.high = ((unsigned int) uu.s.high << b) | carries; | ||
42 | } | ||
43 | |||
44 | return w.ll; | ||
45 | } | ||
46 | EXPORT_SYMBOL(__ashldi3); | ||
diff --git a/arch/score/lib/ashrdi3.c b/arch/score/lib/ashrdi3.c new file mode 100644 index 000000000000..d9814a5d8d30 --- /dev/null +++ b/arch/score/lib/ashrdi3.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * arch/score/lib/ashrdi3.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see the file COPYING, or write | ||
16 | * to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include "libgcc.h" | ||
22 | |||
23 | long long __ashrdi3(long long u, word_type b) | ||
24 | { | ||
25 | DWunion uu, w; | ||
26 | word_type bm; | ||
27 | |||
28 | if (b == 0) | ||
29 | return u; | ||
30 | |||
31 | uu.ll = u; | ||
32 | bm = 32 - b; | ||
33 | |||
34 | if (bm <= 0) { | ||
35 | /* w.s.high = 1..1 or 0..0 */ | ||
36 | w.s.high = | ||
37 | uu.s.high >> 31; | ||
38 | w.s.low = uu.s.high >> -bm; | ||
39 | } else { | ||
40 | const unsigned int carries = (unsigned int) uu.s.high << bm; | ||
41 | |||
42 | w.s.high = uu.s.high >> b; | ||
43 | w.s.low = ((unsigned int) uu.s.low >> b) | carries; | ||
44 | } | ||
45 | |||
46 | return w.ll; | ||
47 | } | ||
48 | EXPORT_SYMBOL(__ashrdi3); | ||
diff --git a/arch/score/lib/checksum.S b/arch/score/lib/checksum.S new file mode 100644 index 000000000000..706157edc7d5 --- /dev/null +++ b/arch/score/lib/checksum.S | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * arch/score/lib/csum_partial.S | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | #include <linux/linkage.h> | ||
26 | |||
27 | #define ADDC(sum,reg) \ | ||
28 | add sum, sum, reg; \ | ||
29 | cmp.c reg, sum; \ | ||
30 | bleu 9f; \ | ||
31 | addi sum, 0x1; \ | ||
32 | 9: | ||
33 | |||
34 | #define CSUM_BIGCHUNK(src, offset, sum) \ | ||
35 | lw r8, [src, offset + 0x00]; \ | ||
36 | lw r9, [src, offset + 0x04]; \ | ||
37 | lw r10, [src, offset + 0x08]; \ | ||
38 | lw r11, [src, offset + 0x0c]; \ | ||
39 | ADDC(sum, r8); \ | ||
40 | ADDC(sum, r9); \ | ||
41 | ADDC(sum, r10); \ | ||
42 | ADDC(sum, r11); \ | ||
43 | lw r8, [src, offset + 0x10]; \ | ||
44 | lw r9, [src, offset + 0x14]; \ | ||
45 | lw r10, [src, offset + 0x18]; \ | ||
46 | lw r11, [src, offset + 0x1c]; \ | ||
47 | ADDC(sum, r8); \ | ||
48 | ADDC(sum, r9); \ | ||
49 | ADDC(sum, r10); \ | ||
50 | ADDC(sum, r11); \ | ||
51 | |||
52 | #define src r4 | ||
53 | #define dest r5 | ||
54 | #define sum r27 | ||
55 | |||
56 | .text | ||
57 | /* unknown src alignment and < 8 bytes to go */ | ||
58 | small_csumcpy: | ||
59 | mv r5, r10 | ||
60 | ldi r9, 0x0 | ||
61 | cmpi.c r25, 0x1 | ||
62 | beq pass_small_set_t7 /*already set, jump to pass_small_set_t7*/ | ||
63 | andri.c r25,r4 , 0x1 /*Is src 2 bytes aligned?*/ | ||
64 | |||
65 | pass_small_set_t7: | ||
66 | beq aligned | ||
67 | cmpi.c r5, 0x0 | ||
68 | beq fold | ||
69 | lbu r9, [src] | ||
70 | slli r9,r9, 0x8 /*Little endian*/ | ||
71 | ADDC(sum, r9) | ||
72 | addi src, 0x1 | ||
73 | subi.c r5, 0x1 | ||
74 | |||
75 | /*len still a full word */ | ||
76 | aligned: | ||
77 | andri.c r8, r5, 0x4 /*Len >= 4?*/ | ||
78 | beq len_less_4bytes | ||
79 | |||
80 | /* Still a full word (4byte) to go,and the src is word aligned.*/ | ||
81 | andri.c r8, src, 0x3 /*src is 4bytes aligned, so use LW!!*/ | ||
82 | beq four_byte_aligned | ||
83 | lhu r9, [src] | ||
84 | addi src, 2 | ||
85 | ADDC(sum, r9) | ||
86 | lhu r9, [src] | ||
87 | addi src, 2 | ||
88 | ADDC(sum, r9) | ||
89 | b len_less_4bytes | ||
90 | |||
91 | four_byte_aligned: /* Len >=4 and four byte aligned */ | ||
92 | lw r9, [src] | ||
93 | addi src, 4 | ||
94 | ADDC(sum, r9) | ||
95 | |||
96 | len_less_4bytes: /* 2 byte aligned aligned and length<4B */ | ||
97 | andri.c r8, r5, 0x2 | ||
98 | beq len_less_2bytes | ||
99 | lhu r9, [src] | ||
100 | addi src, 0x2 /* src+=2 */ | ||
101 | ADDC(sum, r9) | ||
102 | |||
103 | len_less_2bytes: /* len = 1 */ | ||
104 | andri.c r8, r5, 0x1 | ||
105 | beq fold /* less than 2 and not equal 1--> len=0 -> fold */ | ||
106 | lbu r9, [src] | ||
107 | |||
108 | fold_ADDC: | ||
109 | ADDC(sum, r9) | ||
110 | fold: | ||
111 | /* fold checksum */ | ||
112 | slli r26, sum, 16 | ||
113 | add sum, sum, r26 | ||
114 | cmp.c r26, sum | ||
115 | srli sum, sum, 16 | ||
116 | bleu 1f /* if r26<=sum */ | ||
117 | addi sum, 0x1 /* r26>sum */ | ||
118 | 1: | ||
119 | /* odd buffer alignment? r25 was set in csum_partial */ | ||
120 | cmpi.c r25, 0x0 | ||
121 | beq 1f | ||
122 | slli r26, sum, 8 | ||
123 | srli sum, sum, 8 | ||
124 | or sum, sum, r26 | ||
125 | andi sum, 0xffff | ||
126 | 1: | ||
127 | .set optimize | ||
128 | /* Add the passed partial csum. */ | ||
129 | ADDC(sum, r6) | ||
130 | mv r4, sum | ||
131 | br r3 | ||
132 | .set volatile | ||
133 | |||
134 | .align 5 | ||
135 | ENTRY(csum_partial) | ||
136 | ldi sum, 0 | ||
137 | ldi r25, 0 | ||
138 | mv r10, r5 | ||
139 | cmpi.c r5, 0x8 | ||
140 | blt small_csumcpy /* < 8(singed) bytes to copy */ | ||
141 | cmpi.c r5, 0x0 | ||
142 | beq out | ||
143 | andri.c r25, src, 0x1 /* odd buffer? */ | ||
144 | |||
145 | beq word_align | ||
146 | hword_align: /* 1 byte */ | ||
147 | lbu r8, [src] | ||
148 | subi r5, 0x1 | ||
149 | slli r8, r8, 8 | ||
150 | ADDC(sum, r8) | ||
151 | addi src, 0x1 | ||
152 | |||
153 | word_align: /* 2 bytes */ | ||
154 | andri.c r8, src, 0x2 /* 4bytes(dword)_aligned? */ | ||
155 | beq dword_align /* not, maybe dword_align */ | ||
156 | lhu r8, [src] | ||
157 | subi r5, 0x2 | ||
158 | ADDC(sum, r8) | ||
159 | addi src, 0x2 | ||
160 | |||
161 | dword_align: /* 4bytes */ | ||
162 | mv r26, r5 /* maybe useless when len >=56 */ | ||
163 | ldi r8, 56 | ||
164 | cmp.c r8, r5 | ||
165 | bgtu do_end_words /* if a1(len)<t0(56) ,unsigned */ | ||
166 | andri.c r26, src, 0x4 | ||
167 | beq qword_align | ||
168 | lw r8, [src] | ||
169 | subi r5, 0x4 | ||
170 | ADDC(sum, r8) | ||
171 | addi src, 0x4 | ||
172 | |||
173 | qword_align: /* 8 bytes */ | ||
174 | andri.c r26, src, 0x8 | ||
175 | beq oword_align | ||
176 | lw r8, [src, 0x0] | ||
177 | lw r9, [src, 0x4] | ||
178 | subi r5, 0x8 /* len-=0x8 */ | ||
179 | ADDC(sum, r8) | ||
180 | ADDC(sum, r9) | ||
181 | addi src, 0x8 | ||
182 | |||
183 | oword_align: /* 16bytes */ | ||
184 | andri.c r26, src, 0x10 | ||
185 | beq begin_movement | ||
186 | lw r10, [src, 0x08] | ||
187 | lw r11, [src, 0x0c] | ||
188 | lw r8, [src, 0x00] | ||
189 | lw r9, [src, 0x04] | ||
190 | ADDC(sum, r10) | ||
191 | ADDC(sum, r11) | ||
192 | ADDC(sum, r8) | ||
193 | ADDC(sum, r9) | ||
194 | subi r5, 0x10 | ||
195 | addi src, 0x10 | ||
196 | |||
197 | begin_movement: | ||
198 | srli.c r26, r5, 0x7 /* len>=128? */ | ||
199 | beq 1f /* len<128 */ | ||
200 | |||
201 | /* r26 is the result that computed in oword_align */ | ||
202 | move_128bytes: | ||
203 | CSUM_BIGCHUNK(src, 0x00, sum) | ||
204 | CSUM_BIGCHUNK(src, 0x20, sum) | ||
205 | CSUM_BIGCHUNK(src, 0x40, sum) | ||
206 | CSUM_BIGCHUNK(src, 0x60, sum) | ||
207 | subi.c r26, 0x01 /* r26 equals len/128 */ | ||
208 | addi src, 0x80 | ||
209 | bne move_128bytes | ||
210 | |||
211 | 1: /* len<128,we process 64byte here */ | ||
212 | andri.c r10, r5, 0x40 | ||
213 | beq 1f | ||
214 | |||
215 | move_64bytes: | ||
216 | CSUM_BIGCHUNK(src, 0x00, sum) | ||
217 | CSUM_BIGCHUNK(src, 0x20, sum) | ||
218 | addi src, 0x40 | ||
219 | |||
220 | 1: /* len<64 */ | ||
221 | andri r26, r5, 0x1c /* 0x1c=28 */ | ||
222 | andri.c r10, r5, 0x20 | ||
223 | beq do_end_words /* decided by andri */ | ||
224 | |||
225 | move_32bytes: | ||
226 | CSUM_BIGCHUNK(src, 0x00, sum) | ||
227 | andri r26, r5, 0x1c | ||
228 | addri src, src, 0x20 | ||
229 | |||
230 | do_end_words: /* len<32 */ | ||
231 | /* r26 was set already in dword_align */ | ||
232 | cmpi.c r26, 0x0 | ||
233 | beq maybe_end_cruft /* len<28 or len<56 */ | ||
234 | srli r26, r26, 0x2 | ||
235 | |||
236 | end_words: | ||
237 | lw r8, [src] | ||
238 | subi.c r26, 0x1 /* unit is 4 byte */ | ||
239 | ADDC(sum, r8) | ||
240 | addi src, 0x4 | ||
241 | cmpi.c r26, 0x0 | ||
242 | bne end_words /* r26!=0 */ | ||
243 | |||
244 | maybe_end_cruft: /* len<4 */ | ||
245 | andri r10, r5, 0x3 | ||
246 | |||
247 | small_memcpy: | ||
248 | mv r5, r10 | ||
249 | j small_csumcpy | ||
250 | |||
251 | out: | ||
252 | mv r4, sum | ||
253 | br r3 | ||
254 | |||
255 | END(csum_partial) | ||
diff --git a/arch/score/lib/checksum_copy.c b/arch/score/lib/checksum_copy.c new file mode 100644 index 000000000000..04565dd3ded8 --- /dev/null +++ b/arch/score/lib/checksum_copy.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * arch/score/lib/csum_partial_copy.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <net/checksum.h> | ||
27 | |||
28 | #include <asm/uaccess.h> | ||
29 | |||
30 | unsigned int csum_partial_copy(const char *src, char *dst, | ||
31 | int len, unsigned int sum) | ||
32 | { | ||
33 | sum = csum_partial(src, len, sum); | ||
34 | memcpy(dst, src, len); | ||
35 | |||
36 | return sum; | ||
37 | } | ||
38 | |||
39 | unsigned int csum_partial_copy_from_user(const char *src, char *dst, | ||
40 | int len, unsigned int sum, | ||
41 | int *err_ptr) | ||
42 | { | ||
43 | int missing; | ||
44 | |||
45 | missing = copy_from_user(dst, src, len); | ||
46 | if (missing) { | ||
47 | memset(dst + len - missing, 0, missing); | ||
48 | *err_ptr = -EFAULT; | ||
49 | } | ||
50 | |||
51 | return csum_partial(dst, len, sum); | ||
52 | } | ||
diff --git a/arch/score/lib/cmpdi2.c b/arch/score/lib/cmpdi2.c new file mode 100644 index 000000000000..1ed5290c66ed --- /dev/null +++ b/arch/score/lib/cmpdi2.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * arch/score/lib/cmpdi2.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see the file COPYING, or write | ||
16 | * to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include "libgcc.h" | ||
22 | |||
23 | word_type __cmpdi2(long long a, long long b) | ||
24 | { | ||
25 | const DWunion au = { | ||
26 | .ll = a | ||
27 | }; | ||
28 | const DWunion bu = { | ||
29 | .ll = b | ||
30 | }; | ||
31 | |||
32 | if (au.s.high < bu.s.high) | ||
33 | return 0; | ||
34 | else if (au.s.high > bu.s.high) | ||
35 | return 2; | ||
36 | |||
37 | if ((unsigned int) au.s.low < (unsigned int) bu.s.low) | ||
38 | return 0; | ||
39 | else if ((unsigned int) au.s.low > (unsigned int) bu.s.low) | ||
40 | return 2; | ||
41 | |||
42 | return 1; | ||
43 | } | ||
44 | EXPORT_SYMBOL(__cmpdi2); | ||
diff --git a/arch/score/lib/libgcc.h b/arch/score/lib/libgcc.h new file mode 100644 index 000000000000..0f12543d9f31 --- /dev/null +++ b/arch/score/lib/libgcc.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * arch/score/lib/libgcc.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see the file COPYING, or write | ||
16 | * to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | |||
21 | #ifndef __ASM_LIBGCC_H | ||
22 | #define __ASM_LIBGCC_H | ||
23 | |||
24 | #include <asm/byteorder.h> | ||
25 | |||
26 | typedef int word_type __attribute__((mode(__word__))); | ||
27 | |||
28 | struct DWstruct { | ||
29 | int low, high; | ||
30 | }; | ||
31 | |||
32 | typedef union { | ||
33 | struct DWstruct s; | ||
34 | long long ll; | ||
35 | } DWunion; | ||
36 | |||
37 | #endif /* __ASM_LIBGCC_H */ | ||
diff --git a/arch/score/lib/lshrdi3.c b/arch/score/lib/lshrdi3.c new file mode 100644 index 000000000000..ce21175fd791 --- /dev/null +++ b/arch/score/lib/lshrdi3.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * arch/score/lib/lshrdi3.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see the file COPYING, or write | ||
16 | * to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include "libgcc.h" | ||
23 | |||
24 | long long __lshrdi3(long long u, word_type b) | ||
25 | { | ||
26 | DWunion uu, w; | ||
27 | word_type bm; | ||
28 | |||
29 | if (b == 0) | ||
30 | return u; | ||
31 | |||
32 | uu.ll = u; | ||
33 | bm = 32 - b; | ||
34 | |||
35 | if (bm <= 0) { | ||
36 | w.s.high = 0; | ||
37 | w.s.low = (unsigned int) uu.s.high >> -bm; | ||
38 | } else { | ||
39 | const unsigned int carries = (unsigned int) uu.s.high << bm; | ||
40 | |||
41 | w.s.high = (unsigned int) uu.s.high >> b; | ||
42 | w.s.low = ((unsigned int) uu.s.low >> b) | carries; | ||
43 | } | ||
44 | |||
45 | return w.ll; | ||
46 | } | ||
47 | EXPORT_SYMBOL(__lshrdi3); | ||
diff --git a/arch/score/lib/string.S b/arch/score/lib/string.S new file mode 100644 index 000000000000..00b7d3a2fc60 --- /dev/null +++ b/arch/score/lib/string.S | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * arch/score/lib/string.S | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
8 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/linkage.h> | ||
27 | #include <asm-generic/errno.h> | ||
28 | |||
29 | .text | ||
30 | .align 2 | ||
31 | ENTRY(__strncpy_from_user) | ||
32 | cmpi.c r6, 0 | ||
33 | mv r9, r6 | ||
34 | ble .L2 | ||
35 | 0: lbu r7, [r5] | ||
36 | ldi r8, 0 | ||
37 | 1: sb r7, [r4] | ||
38 | 2: lb r6, [r5] | ||
39 | cmp.c r6, r8 | ||
40 | beq .L2 | ||
41 | |||
42 | .L5: | ||
43 | addi r8, 1 | ||
44 | cmp.c r8, r9 | ||
45 | beq .L7 | ||
46 | 3: lbu r6, [r5, 1]+ | ||
47 | 4: sb r6, [r4, 1]+ | ||
48 | 5: lb r7, [r5] | ||
49 | cmpi.c r7, 0 | ||
50 | bne .L5 | ||
51 | .L7: | ||
52 | mv r4, r8 | ||
53 | br r3 | ||
54 | .L2: | ||
55 | ldi r8, 0 | ||
56 | mv r4, r8 | ||
57 | br r3 | ||
58 | .section .fixup, "ax" | ||
59 | 99: | ||
60 | ldi r4, -EFAULT | ||
61 | br r3 | ||
62 | .previous | ||
63 | .section __ex_table, "a" | ||
64 | .align 2 | ||
65 | .word 0b ,99b | ||
66 | .word 1b ,99b | ||
67 | .word 2b ,99b | ||
68 | .word 3b ,99b | ||
69 | .word 4b ,99b | ||
70 | .word 5b ,99b | ||
71 | .previous | ||
72 | |||
73 | .align 2 | ||
74 | ENTRY(__strnlen_user) | ||
75 | cmpi.c r5, 0 | ||
76 | ble .L11 | ||
77 | 0: lb r6, [r4] | ||
78 | ldi r7, 0 | ||
79 | cmp.c r6, r7 | ||
80 | beq .L11 | ||
81 | .L15: | ||
82 | addi r7, 1 | ||
83 | cmp.c r7, r5 | ||
84 | beq .L23 | ||
85 | 1: lb r6, [r4,1]+ | ||
86 | cmpi.c r6, 0 | ||
87 | bne .L15 | ||
88 | .L23: | ||
89 | addri r4, r7, 1 | ||
90 | br r3 | ||
91 | |||
92 | .L11: | ||
93 | ldi r4, 1 | ||
94 | br r3 | ||
95 | .section .fixup, "ax" | ||
96 | 99: | ||
97 | ldi r4, 0 | ||
98 | br r3 | ||
99 | |||
100 | .section __ex_table,"a" | ||
101 | .align 2 | ||
102 | .word 0b, 99b | ||
103 | .word 1b, 99b | ||
104 | .previous | ||
105 | |||
106 | .align 2 | ||
107 | ENTRY(__strlen_user) | ||
108 | 0: lb r6, [r4] | ||
109 | mv r7, r4 | ||
110 | extsb r6, r6 | ||
111 | cmpi.c r6, 0 | ||
112 | mv r4, r6 | ||
113 | beq .L27 | ||
114 | .L28: | ||
115 | 1: lb r6, [r7, 1]+ | ||
116 | addi r6, 1 | ||
117 | cmpi.c r6, 0 | ||
118 | bne .L28 | ||
119 | .L27: | ||
120 | br r3 | ||
121 | .section .fixup, "ax" | ||
122 | ldi r4, 0x0 | ||
123 | br r3 | ||
124 | 99: | ||
125 | ldi r4, 0 | ||
126 | br r3 | ||
127 | .previous | ||
128 | .section __ex_table, "a" | ||
129 | .align 2 | ||
130 | .word 0b ,99b | ||
131 | .word 1b ,99b | ||
132 | .previous | ||
133 | |||
134 | .align 2 | ||
135 | ENTRY(__copy_tofrom_user) | ||
136 | cmpi.c r6, 0 | ||
137 | mv r10,r6 | ||
138 | beq .L32 | ||
139 | ldi r9, 0 | ||
140 | .L34: | ||
141 | add r6, r5, r9 | ||
142 | 0: lbu r8, [r6] | ||
143 | add r7, r4, r9 | ||
144 | 1: sb r8, [r7] | ||
145 | addi r9, 1 | ||
146 | cmp.c r9, r10 | ||
147 | bne .L34 | ||
148 | .L32: | ||
149 | ldi r4, 0 | ||
150 | br r3 | ||
151 | .section .fixup, "ax" | ||
152 | 99: | ||
153 | sub r4, r10, r9 | ||
154 | br r3 | ||
155 | .previous | ||
156 | .section __ex_table, "a" | ||
157 | .align 2 | ||
158 | .word 0b, 99b | ||
159 | .word 1b, 99b | ||
160 | .previous | ||
161 | |||
162 | .align 2 | ||
163 | ENTRY(__clear_user) | ||
164 | cmpi.c r5, 0 | ||
165 | beq .L38 | ||
166 | ldi r6, 0 | ||
167 | mv r7, r6 | ||
168 | .L40: | ||
169 | addi r6, 1 | ||
170 | 0: sb r7, [r4]+, 1 | ||
171 | cmp.c r6, r5 | ||
172 | bne .L40 | ||
173 | .L38: | ||
174 | ldi r4, 0 | ||
175 | br r3 | ||
176 | |||
177 | .section .fixup, "ax" | ||
178 | br r3 | ||
179 | .previous | ||
180 | .section __ex_table, "a" | ||
181 | .align 2 | ||
182 | 99: | ||
183 | .word 0b, 99b | ||
184 | .previous | ||
diff --git a/arch/score/lib/ucmpdi2.c b/arch/score/lib/ucmpdi2.c new file mode 100644 index 000000000000..b15241e0b079 --- /dev/null +++ b/arch/score/lib/ucmpdi2.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * arch/score/lib/ucmpdi2.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see the file COPYING, or write | ||
16 | * to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include "libgcc.h" | ||
22 | |||
23 | word_type __ucmpdi2(unsigned long long a, unsigned long long b) | ||
24 | { | ||
25 | const DWunion au = {.ll = a}; | ||
26 | const DWunion bu = {.ll = b}; | ||
27 | |||
28 | if ((unsigned int) au.s.high < (unsigned int) bu.s.high) | ||
29 | return 0; | ||
30 | else if ((unsigned int) au.s.high > (unsigned int) bu.s.high) | ||
31 | return 2; | ||
32 | if ((unsigned int) au.s.low < (unsigned int) bu.s.low) | ||
33 | return 0; | ||
34 | else if ((unsigned int) au.s.low > (unsigned int) bu.s.low) | ||
35 | return 2; | ||
36 | return 1; | ||
37 | } | ||
38 | EXPORT_SYMBOL(__ucmpdi2); | ||
diff --git a/arch/score/mm/Makefile b/arch/score/mm/Makefile new file mode 100644 index 000000000000..7b1e29b1f8cd --- /dev/null +++ b/arch/score/mm/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the Linux/SCORE-specific parts of the memory manager. | ||
3 | # | ||
4 | |||
5 | obj-y += cache.o extable.o fault.o init.o \ | ||
6 | tlb-miss.o tlb-score.o pgtable.o | ||
diff --git a/arch/score/mm/cache.c b/arch/score/mm/cache.c new file mode 100644 index 000000000000..dbac9d9dfddd --- /dev/null +++ b/arch/score/mm/cache.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * arch/score/mm/cache.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/linkage.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/sched.h> | ||
32 | |||
33 | #include <asm/mmu_context.h> | ||
34 | |||
35 | /* | ||
36 | Just flush entire Dcache!! | ||
37 | You must ensure the page doesn't include instructions, because | ||
38 | the function will not flush the Icache. | ||
39 | The addr must be cache aligned. | ||
40 | */ | ||
41 | static void flush_data_cache_page(unsigned long addr) | ||
42 | { | ||
43 | unsigned int i; | ||
44 | for (i = 0; i < (PAGE_SIZE / L1_CACHE_BYTES); i += L1_CACHE_BYTES) { | ||
45 | __asm__ __volatile__( | ||
46 | "cache 0x0e, [%0, 0]\n" | ||
47 | "cache 0x1a, [%0, 0]\n" | ||
48 | "nop\n" | ||
49 | : : "r" (addr)); | ||
50 | addr += L1_CACHE_BYTES; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* called by update_mmu_cache. */ | ||
55 | void __update_cache(struct vm_area_struct *vma, unsigned long address, | ||
56 | pte_t pte) | ||
57 | { | ||
58 | struct page *page; | ||
59 | unsigned long pfn, addr; | ||
60 | int exec = (vma->vm_flags & VM_EXEC); | ||
61 | |||
62 | pfn = pte_pfn(pte); | ||
63 | if (unlikely(!pfn_valid(pfn))) | ||
64 | return; | ||
65 | page = pfn_to_page(pfn); | ||
66 | if (page_mapping(page) && test_bit(PG_arch_1, &page->flags)) { | ||
67 | addr = (unsigned long) page_address(page); | ||
68 | if (exec) | ||
69 | flush_data_cache_page(addr); | ||
70 | clear_bit(PG_arch_1, &page->flags); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static inline void setup_protection_map(void) | ||
75 | { | ||
76 | protection_map[0] = PAGE_NONE; | ||
77 | protection_map[1] = PAGE_READONLY; | ||
78 | protection_map[2] = PAGE_COPY; | ||
79 | protection_map[3] = PAGE_COPY; | ||
80 | protection_map[4] = PAGE_READONLY; | ||
81 | protection_map[5] = PAGE_READONLY; | ||
82 | protection_map[6] = PAGE_COPY; | ||
83 | protection_map[7] = PAGE_COPY; | ||
84 | protection_map[8] = PAGE_NONE; | ||
85 | protection_map[9] = PAGE_READONLY; | ||
86 | protection_map[10] = PAGE_SHARED; | ||
87 | protection_map[11] = PAGE_SHARED; | ||
88 | protection_map[12] = PAGE_READONLY; | ||
89 | protection_map[13] = PAGE_READONLY; | ||
90 | protection_map[14] = PAGE_SHARED; | ||
91 | protection_map[15] = PAGE_SHARED; | ||
92 | } | ||
93 | |||
94 | void __devinit cpu_cache_init(void) | ||
95 | { | ||
96 | setup_protection_map(); | ||
97 | } | ||
98 | |||
99 | void flush_icache_all(void) | ||
100 | { | ||
101 | __asm__ __volatile__( | ||
102 | "la r8, flush_icache_all\n" | ||
103 | "cache 0x10, [r8, 0]\n" | ||
104 | "nop\nnop\nnop\nnop\nnop\nnop\n" | ||
105 | : : : "r8"); | ||
106 | } | ||
107 | |||
108 | void flush_dcache_all(void) | ||
109 | { | ||
110 | __asm__ __volatile__( | ||
111 | "la r8, flush_dcache_all\n" | ||
112 | "cache 0x1f, [r8, 0]\n" | ||
113 | "nop\nnop\nnop\nnop\nnop\nnop\n" | ||
114 | "cache 0x1a, [r8, 0]\n" | ||
115 | "nop\nnop\nnop\nnop\nnop\nnop\n" | ||
116 | : : : "r8"); | ||
117 | } | ||
118 | |||
119 | void flush_cache_all(void) | ||
120 | { | ||
121 | __asm__ __volatile__( | ||
122 | "la r8, flush_cache_all\n" | ||
123 | "cache 0x10, [r8, 0]\n" | ||
124 | "nop\nnop\nnop\nnop\nnop\nnop\n" | ||
125 | "cache 0x1f, [r8, 0]\n" | ||
126 | "nop\nnop\nnop\nnop\nnop\nnop\n" | ||
127 | "cache 0x1a, [r8, 0]\n" | ||
128 | "nop\nnop\nnop\nnop\nnop\nnop\n" | ||
129 | : : : "r8"); | ||
130 | } | ||
131 | |||
132 | void flush_cache_mm(struct mm_struct *mm) | ||
133 | { | ||
134 | if (!(mm->context)) | ||
135 | return; | ||
136 | flush_cache_all(); | ||
137 | } | ||
138 | |||
139 | /*if we flush a range precisely , the processing may be very long. | ||
140 | We must check each page in the range whether present. If the page is present, | ||
141 | we can flush the range in the page. Be careful, the range may be cross two | ||
142 | page, a page is present and another is not present. | ||
143 | */ | ||
144 | /* | ||
145 | The interface is provided in hopes that the port can find | ||
146 | a suitably efficient method for removing multiple page | ||
147 | sized regions from the cache. | ||
148 | */ | ||
149 | void flush_cache_range(struct vm_area_struct *vma, | ||
150 | unsigned long start, unsigned long end) | ||
151 | { | ||
152 | struct mm_struct *mm = vma->vm_mm; | ||
153 | int exec = vma->vm_flags & VM_EXEC; | ||
154 | pgd_t *pgdp; | ||
155 | pud_t *pudp; | ||
156 | pmd_t *pmdp; | ||
157 | pte_t *ptep; | ||
158 | |||
159 | if (!(mm->context)) | ||
160 | return; | ||
161 | |||
162 | pgdp = pgd_offset(mm, start); | ||
163 | pudp = pud_offset(pgdp, start); | ||
164 | pmdp = pmd_offset(pudp, start); | ||
165 | ptep = pte_offset(pmdp, start); | ||
166 | |||
167 | while (start <= end) { | ||
168 | unsigned long tmpend; | ||
169 | pgdp = pgd_offset(mm, start); | ||
170 | pudp = pud_offset(pgdp, start); | ||
171 | pmdp = pmd_offset(pudp, start); | ||
172 | ptep = pte_offset(pmdp, start); | ||
173 | |||
174 | if (!(pte_val(*ptep) & _PAGE_PRESENT)) { | ||
175 | start = (start + PAGE_SIZE) & ~(PAGE_SIZE - 1); | ||
176 | continue; | ||
177 | } | ||
178 | tmpend = (start | (PAGE_SIZE-1)) > end ? | ||
179 | end : (start | (PAGE_SIZE-1)); | ||
180 | |||
181 | flush_dcache_range(start, tmpend); | ||
182 | if (exec) | ||
183 | flush_icache_range(start, tmpend); | ||
184 | start = (start + PAGE_SIZE) & ~(PAGE_SIZE - 1); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | void flush_cache_page(struct vm_area_struct *vma, | ||
189 | unsigned long addr, unsigned long pfn) | ||
190 | { | ||
191 | int exec = vma->vm_flags & VM_EXEC; | ||
192 | unsigned long kaddr = 0xa0000000 | (pfn << PAGE_SHIFT); | ||
193 | |||
194 | flush_dcache_range(kaddr, kaddr + PAGE_SIZE); | ||
195 | |||
196 | if (exec) | ||
197 | flush_icache_range(kaddr, kaddr + PAGE_SIZE); | ||
198 | } | ||
199 | |||
200 | void flush_cache_sigtramp(unsigned long addr) | ||
201 | { | ||
202 | __asm__ __volatile__( | ||
203 | "cache 0x02, [%0, 0]\n" | ||
204 | "nop\nnop\nnop\nnop\nnop\n" | ||
205 | "cache 0x02, [%0, 0x4]\n" | ||
206 | "nop\nnop\nnop\nnop\nnop\n" | ||
207 | |||
208 | "cache 0x0d, [%0, 0]\n" | ||
209 | "nop\nnop\nnop\nnop\nnop\n" | ||
210 | "cache 0x0d, [%0, 0x4]\n" | ||
211 | "nop\nnop\nnop\nnop\nnop\n" | ||
212 | |||
213 | "cache 0x1a, [%0, 0]\n" | ||
214 | "nop\nnop\nnop\nnop\nnop\n" | ||
215 | : : "r" (addr)); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | 1. WB and invalid a cache line of Dcache | ||
220 | 2. Drain Write Buffer | ||
221 | the range must be smaller than PAGE_SIZE | ||
222 | */ | ||
223 | void flush_dcache_range(unsigned long start, unsigned long end) | ||
224 | { | ||
225 | int size, i; | ||
226 | |||
227 | start = start & ~(L1_CACHE_BYTES - 1); | ||
228 | end = end & ~(L1_CACHE_BYTES - 1); | ||
229 | size = end - start; | ||
230 | /* flush dcache to ram, and invalidate dcache lines. */ | ||
231 | for (i = 0; i < size; i += L1_CACHE_BYTES) { | ||
232 | __asm__ __volatile__( | ||
233 | "cache 0x0e, [%0, 0]\n" | ||
234 | "nop\nnop\nnop\nnop\nnop\n" | ||
235 | "cache 0x1a, [%0, 0]\n" | ||
236 | "nop\nnop\nnop\nnop\nnop\n" | ||
237 | : : "r" (start)); | ||
238 | start += L1_CACHE_BYTES; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | void flush_icache_range(unsigned long start, unsigned long end) | ||
243 | { | ||
244 | int size, i; | ||
245 | start = start & ~(L1_CACHE_BYTES - 1); | ||
246 | end = end & ~(L1_CACHE_BYTES - 1); | ||
247 | |||
248 | size = end - start; | ||
249 | /* invalidate icache lines. */ | ||
250 | for (i = 0; i < size; i += L1_CACHE_BYTES) { | ||
251 | __asm__ __volatile__( | ||
252 | "cache 0x02, [%0, 0]\n" | ||
253 | "nop\nnop\nnop\nnop\nnop\n" | ||
254 | : : "r" (start)); | ||
255 | start += L1_CACHE_BYTES; | ||
256 | } | ||
257 | } | ||
diff --git a/arch/score/mm/extable.c b/arch/score/mm/extable.c new file mode 100644 index 000000000000..01ff6445171c --- /dev/null +++ b/arch/score/mm/extable.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * arch/score/mm/extable.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | |||
28 | int fixup_exception(struct pt_regs *regs) | ||
29 | { | ||
30 | const struct exception_table_entry *fixup; | ||
31 | |||
32 | fixup = search_exception_tables(regs->cp0_epc); | ||
33 | if (fixup) { | ||
34 | regs->cp0_epc = fixup->fixup; | ||
35 | return 1; | ||
36 | } | ||
37 | return 0; | ||
38 | } | ||
diff --git a/arch/score/mm/fault.c b/arch/score/mm/fault.c new file mode 100644 index 000000000000..47b600e4b2c5 --- /dev/null +++ b/arch/score/mm/fault.c | |||
@@ -0,0 +1,235 @@ | |||
1 | /* | ||
2 | * arch/score/mm/fault.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/errno.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/mman.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/signal.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/ptrace.h> | ||
37 | |||
38 | /* | ||
39 | * This routine handles page faults. It determines the address, | ||
40 | * and the problem, and then passes it off to one of the appropriate | ||
41 | * routines. | ||
42 | */ | ||
43 | asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, | ||
44 | unsigned long address) | ||
45 | { | ||
46 | struct vm_area_struct *vma = NULL; | ||
47 | struct task_struct *tsk = current; | ||
48 | struct mm_struct *mm = tsk->mm; | ||
49 | const int field = sizeof(unsigned long) * 2; | ||
50 | siginfo_t info; | ||
51 | int fault; | ||
52 | |||
53 | info.si_code = SEGV_MAPERR; | ||
54 | |||
55 | /* | ||
56 | * We fault-in kernel-space virtual memory on-demand. The | ||
57 | * 'reference' page table is init_mm.pgd. | ||
58 | * | ||
59 | * NOTE! We MUST NOT take any locks for this case. We may | ||
60 | * be in an interrupt or a critical region, and should | ||
61 | * only copy the information from the master page table, | ||
62 | * nothing more. | ||
63 | */ | ||
64 | if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END)) | ||
65 | goto vmalloc_fault; | ||
66 | #ifdef MODULE_START | ||
67 | if (unlikely(address >= MODULE_START && address < MODULE_END)) | ||
68 | goto vmalloc_fault; | ||
69 | #endif | ||
70 | |||
71 | /* | ||
72 | * If we're in an interrupt or have no user | ||
73 | * context, we must not take the fault.. | ||
74 | */ | ||
75 | if (in_atomic() || !mm) | ||
76 | goto bad_area_nosemaphore; | ||
77 | |||
78 | down_read(&mm->mmap_sem); | ||
79 | vma = find_vma(mm, address); | ||
80 | if (!vma) | ||
81 | goto bad_area; | ||
82 | if (vma->vm_start <= address) | ||
83 | goto good_area; | ||
84 | if (!(vma->vm_flags & VM_GROWSDOWN)) | ||
85 | goto bad_area; | ||
86 | if (expand_stack(vma, address)) | ||
87 | goto bad_area; | ||
88 | /* | ||
89 | * Ok, we have a good vm_area for this memory access, so | ||
90 | * we can handle it.. | ||
91 | */ | ||
92 | good_area: | ||
93 | info.si_code = SEGV_ACCERR; | ||
94 | |||
95 | if (write) { | ||
96 | if (!(vma->vm_flags & VM_WRITE)) | ||
97 | goto bad_area; | ||
98 | } else { | ||
99 | if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))) | ||
100 | goto bad_area; | ||
101 | } | ||
102 | |||
103 | survive: | ||
104 | /* | ||
105 | * If for any reason at all we couldn't handle the fault, | ||
106 | * make sure we exit gracefully rather than endlessly redo | ||
107 | * the fault. | ||
108 | */ | ||
109 | fault = handle_mm_fault(mm, vma, address, write); | ||
110 | if (unlikely(fault & VM_FAULT_ERROR)) { | ||
111 | if (fault & VM_FAULT_OOM) | ||
112 | goto out_of_memory; | ||
113 | else if (fault & VM_FAULT_SIGBUS) | ||
114 | goto do_sigbus; | ||
115 | BUG(); | ||
116 | } | ||
117 | if (fault & VM_FAULT_MAJOR) | ||
118 | tsk->maj_flt++; | ||
119 | else | ||
120 | tsk->min_flt++; | ||
121 | |||
122 | up_read(&mm->mmap_sem); | ||
123 | return; | ||
124 | |||
125 | /* | ||
126 | * Something tried to access memory that isn't in our memory map.. | ||
127 | * Fix it, but check if it's kernel or user first.. | ||
128 | */ | ||
129 | bad_area: | ||
130 | up_read(&mm->mmap_sem); | ||
131 | |||
132 | bad_area_nosemaphore: | ||
133 | /* User mode accesses just cause a SIGSEGV */ | ||
134 | if (user_mode(regs)) { | ||
135 | tsk->thread.cp0_badvaddr = address; | ||
136 | tsk->thread.error_code = write; | ||
137 | info.si_signo = SIGSEGV; | ||
138 | info.si_errno = 0; | ||
139 | /* info.si_code has been set above */ | ||
140 | info.si_addr = (void __user *) address; | ||
141 | force_sig_info(SIGSEGV, &info, tsk); | ||
142 | return; | ||
143 | } | ||
144 | |||
145 | no_context: | ||
146 | /* Are we prepared to handle this kernel fault? */ | ||
147 | if (fixup_exception(regs)) { | ||
148 | current->thread.cp0_baduaddr = address; | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Oops. The kernel tried to access some bad page. We'll have to | ||
154 | * terminate things with extreme prejudice. | ||
155 | */ | ||
156 | bust_spinlocks(1); | ||
157 | |||
158 | printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " | ||
159 | "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n", | ||
160 | 0, field, address, field, regs->cp0_epc, | ||
161 | field, regs->regs[3]); | ||
162 | die("Oops", regs); | ||
163 | |||
164 | /* | ||
165 | * We ran out of memory, or some other thing happened to us that made | ||
166 | * us unable to handle the page fault gracefully. | ||
167 | */ | ||
168 | out_of_memory: | ||
169 | up_read(&mm->mmap_sem); | ||
170 | if (is_global_init(tsk)) { | ||
171 | yield(); | ||
172 | down_read(&mm->mmap_sem); | ||
173 | goto survive; | ||
174 | } | ||
175 | printk("VM: killing process %s\n", tsk->comm); | ||
176 | if (user_mode(regs)) | ||
177 | do_group_exit(SIGKILL); | ||
178 | goto no_context; | ||
179 | |||
180 | do_sigbus: | ||
181 | up_read(&mm->mmap_sem); | ||
182 | /* Kernel mode? Handle exceptions or die */ | ||
183 | if (!user_mode(regs)) | ||
184 | goto no_context; | ||
185 | else | ||
186 | /* | ||
187 | * Send a sigbus, regardless of whether we were in kernel | ||
188 | * or user mode. | ||
189 | */ | ||
190 | tsk->thread.cp0_badvaddr = address; | ||
191 | info.si_signo = SIGBUS; | ||
192 | info.si_errno = 0; | ||
193 | info.si_code = BUS_ADRERR; | ||
194 | info.si_addr = (void __user *) address; | ||
195 | force_sig_info(SIGBUS, &info, tsk); | ||
196 | return; | ||
197 | vmalloc_fault: | ||
198 | { | ||
199 | /* | ||
200 | * Synchronize this task's top level page-table | ||
201 | * with the 'reference' page table. | ||
202 | * | ||
203 | * Do _not_ use "tsk" here. We might be inside | ||
204 | * an interrupt in the middle of a task switch.. | ||
205 | */ | ||
206 | int offset = __pgd_offset(address); | ||
207 | pgd_t *pgd, *pgd_k; | ||
208 | pud_t *pud, *pud_k; | ||
209 | pmd_t *pmd, *pmd_k; | ||
210 | pte_t *pte_k; | ||
211 | |||
212 | pgd = (pgd_t *) pgd_current + offset; | ||
213 | pgd_k = init_mm.pgd + offset; | ||
214 | |||
215 | if (!pgd_present(*pgd_k)) | ||
216 | goto no_context; | ||
217 | set_pgd(pgd, *pgd_k); | ||
218 | |||
219 | pud = pud_offset(pgd, address); | ||
220 | pud_k = pud_offset(pgd_k, address); | ||
221 | if (!pud_present(*pud_k)) | ||
222 | goto no_context; | ||
223 | |||
224 | pmd = pmd_offset(pud, address); | ||
225 | pmd_k = pmd_offset(pud_k, address); | ||
226 | if (!pmd_present(*pmd_k)) | ||
227 | goto no_context; | ||
228 | set_pmd(pmd, *pmd_k); | ||
229 | |||
230 | pte_k = pte_offset_kernel(pmd_k, address); | ||
231 | if (!pte_present(*pte_k)) | ||
232 | goto no_context; | ||
233 | return; | ||
234 | } | ||
235 | } | ||
diff --git a/arch/score/mm/init.c b/arch/score/mm/init.c new file mode 100644 index 000000000000..4e3dcd0c4716 --- /dev/null +++ b/arch/score/mm/init.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * arch/score/mm/init.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/errno.h> | ||
27 | #include <linux/bootmem.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/mman.h> | ||
32 | #include <linux/pagemap.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/initrd.h> | ||
36 | |||
37 | #include <asm/sections.h> | ||
38 | #include <asm/tlb.h> | ||
39 | |||
40 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
41 | |||
42 | unsigned long empty_zero_page; | ||
43 | EXPORT_SYMBOL_GPL(empty_zero_page); | ||
44 | |||
45 | static struct kcore_list kcore_mem, kcore_vmalloc; | ||
46 | |||
47 | static unsigned long setup_zero_page(void) | ||
48 | { | ||
49 | struct page *page; | ||
50 | |||
51 | empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, 0); | ||
52 | if (!empty_zero_page) | ||
53 | panic("Oh boy, that early out of memory?"); | ||
54 | |||
55 | page = virt_to_page((void *) empty_zero_page); | ||
56 | SetPageReserved(page); | ||
57 | |||
58 | return 1UL; | ||
59 | } | ||
60 | |||
61 | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||
62 | static int __init page_is_ram(unsigned long pagenr) | ||
63 | { | ||
64 | if (pagenr >= min_low_pfn && pagenr < max_low_pfn) | ||
65 | return 1; | ||
66 | else | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | void __init paging_init(void) | ||
71 | { | ||
72 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | ||
73 | unsigned long lastpfn; | ||
74 | |||
75 | pagetable_init(); | ||
76 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; | ||
77 | lastpfn = max_low_pfn; | ||
78 | free_area_init_nodes(max_zone_pfns); | ||
79 | } | ||
80 | |||
81 | void __init mem_init(void) | ||
82 | { | ||
83 | unsigned long codesize, reservedpages, datasize, initsize; | ||
84 | unsigned long tmp, ram = 0; | ||
85 | |||
86 | max_mapnr = max_low_pfn; | ||
87 | high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); | ||
88 | totalram_pages += free_all_bootmem(); | ||
89 | totalram_pages -= setup_zero_page(); /* Setup zeroed pages. */ | ||
90 | reservedpages = 0; | ||
91 | |||
92 | for (tmp = 0; tmp < max_low_pfn; tmp++) | ||
93 | if (page_is_ram(tmp)) { | ||
94 | ram++; | ||
95 | if (PageReserved(pfn_to_page(tmp))) | ||
96 | reservedpages++; | ||
97 | } | ||
98 | |||
99 | num_physpages = ram; | ||
100 | codesize = (unsigned long) &_etext - (unsigned long) &_text; | ||
101 | datasize = (unsigned long) &_edata - (unsigned long) &_etext; | ||
102 | initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; | ||
103 | |||
104 | kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); | ||
105 | kclist_add(&kcore_vmalloc, (void *) VMALLOC_START, | ||
106 | VMALLOC_END - VMALLOC_START); | ||
107 | |||
108 | printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " | ||
109 | "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", | ||
110 | (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), | ||
111 | ram << (PAGE_SHIFT-10), codesize >> 10, | ||
112 | reservedpages << (PAGE_SHIFT-10), datasize >> 10, | ||
113 | initsize >> 10, | ||
114 | (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); | ||
115 | } | ||
116 | #endif /* !CONFIG_NEED_MULTIPLE_NODES */ | ||
117 | |||
118 | static void free_init_pages(const char *what, unsigned long begin, unsigned long end) | ||
119 | { | ||
120 | unsigned long pfn; | ||
121 | |||
122 | for (pfn = PFN_UP(begin); pfn < PFN_DOWN(end); pfn++) { | ||
123 | struct page *page = pfn_to_page(pfn); | ||
124 | void *addr = phys_to_virt(PFN_PHYS(pfn)); | ||
125 | |||
126 | ClearPageReserved(page); | ||
127 | init_page_count(page); | ||
128 | memset(addr, POISON_FREE_INITMEM, PAGE_SIZE); | ||
129 | __free_page(page); | ||
130 | totalram_pages++; | ||
131 | } | ||
132 | printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); | ||
133 | } | ||
134 | |||
135 | #ifdef CONFIG_BLK_DEV_INITRD | ||
136 | void free_initrd_mem(unsigned long start, unsigned long end) | ||
137 | { | ||
138 | free_init_pages("initrd memory", | ||
139 | virt_to_phys((void *) start), | ||
140 | virt_to_phys((void *) end)); | ||
141 | } | ||
142 | #endif | ||
143 | |||
144 | void __init_refok free_initmem(void) | ||
145 | { | ||
146 | free_init_pages("unused kernel memory", | ||
147 | __pa(&__init_begin), | ||
148 | __pa(&__init_end)); | ||
149 | } | ||
150 | |||
151 | unsigned long pgd_current; | ||
152 | |||
153 | #define __page_aligned(order) __attribute__((__aligned__(PAGE_SIZE<<order))) | ||
154 | |||
155 | /* | ||
156 | * gcc 3.3 and older have trouble determining that PTRS_PER_PGD and PGD_ORDER | ||
157 | * are constants. So we use the variants from asm-offset.h until that gcc | ||
158 | * will officially be retired. | ||
159 | */ | ||
160 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned(PTE_ORDER); | ||
161 | pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned(PTE_ORDER); | ||
diff --git a/arch/score/mm/pgtable.c b/arch/score/mm/pgtable.c new file mode 100644 index 000000000000..6408bb73d3cc --- /dev/null +++ b/arch/score/mm/pgtable.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * arch/score/mm/pgtable-32.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/bootmem.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/pfn.h> | ||
29 | #include <linux/mm.h> | ||
30 | |||
31 | void pgd_init(unsigned long page) | ||
32 | { | ||
33 | unsigned long *p = (unsigned long *) page; | ||
34 | int i; | ||
35 | |||
36 | for (i = 0; i < USER_PTRS_PER_PGD; i += 8) { | ||
37 | p[i + 0] = (unsigned long) invalid_pte_table; | ||
38 | p[i + 1] = (unsigned long) invalid_pte_table; | ||
39 | p[i + 2] = (unsigned long) invalid_pte_table; | ||
40 | p[i + 3] = (unsigned long) invalid_pte_table; | ||
41 | p[i + 4] = (unsigned long) invalid_pte_table; | ||
42 | p[i + 5] = (unsigned long) invalid_pte_table; | ||
43 | p[i + 6] = (unsigned long) invalid_pte_table; | ||
44 | p[i + 7] = (unsigned long) invalid_pte_table; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | void __init pagetable_init(void) | ||
49 | { | ||
50 | /* Initialize the entire pgd. */ | ||
51 | pgd_init((unsigned long)swapper_pg_dir); | ||
52 | } | ||
diff --git a/arch/score/mm/tlb-miss.S b/arch/score/mm/tlb-miss.S new file mode 100644 index 000000000000..f27651914e8d --- /dev/null +++ b/arch/score/mm/tlb-miss.S | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * arch/score/mm/tlbex.S | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <asm/asmmacro.h> | ||
27 | #include <asm/pgtable-bits.h> | ||
28 | #include <asm/scoreregs.h> | ||
29 | |||
30 | /* | ||
31 | * After this macro runs, the pte faulted on is | ||
32 | * in register PTE, a ptr into the table in which | ||
33 | * the pte belongs is in PTR. | ||
34 | */ | ||
35 | .macro load_pte, pte, ptr | ||
36 | la \ptr, pgd_current | ||
37 | lw \ptr, [\ptr, 0] | ||
38 | mfcr \pte, cr6 | ||
39 | srli \pte, \pte, 22 | ||
40 | slli \pte, \pte, 2 | ||
41 | add \ptr, \ptr, \pte | ||
42 | lw \ptr, [\ptr, 0] | ||
43 | mfcr \pte, cr6 | ||
44 | srli \pte, \pte, 10 | ||
45 | andi \pte, 0xffc | ||
46 | add \ptr, \ptr, \pte | ||
47 | lw \pte, [\ptr, 0] | ||
48 | .endm | ||
49 | |||
50 | .macro pte_reload, ptr | ||
51 | lw \ptr, [\ptr, 0] | ||
52 | mtcr \ptr, cr12 | ||
53 | nop | ||
54 | nop | ||
55 | nop | ||
56 | nop | ||
57 | nop | ||
58 | .endm | ||
59 | |||
60 | .macro do_fault, write | ||
61 | SAVE_ALL | ||
62 | mfcr r6, cr6 | ||
63 | mv r4, r0 | ||
64 | ldi r5, \write | ||
65 | la r8, do_page_fault | ||
66 | brl r8 | ||
67 | j ret_from_exception | ||
68 | .endm | ||
69 | |||
70 | .macro pte_writable, pte, ptr, label | ||
71 | andi \pte, 0x280 | ||
72 | cmpi.c \pte, 0x280 | ||
73 | bne \label | ||
74 | lw \pte, [\ptr, 0] /*reload PTE*/ | ||
75 | .endm | ||
76 | |||
77 | /* | ||
78 | * Make PTE writable, update software status bits as well, | ||
79 | * then store at PTR. | ||
80 | */ | ||
81 | .macro pte_makewrite, pte, ptr | ||
82 | ori \pte, 0x426 | ||
83 | sw \pte, [\ptr, 0] | ||
84 | .endm | ||
85 | |||
86 | .text | ||
87 | ENTRY(score7_FTLB_refill_Handler) | ||
88 | la r31, pgd_current /* get pgd pointer */ | ||
89 | lw r31, [r31, 0] /* get the address of PGD */ | ||
90 | mfcr r30, cr6 | ||
91 | srli r30, r30, 22 /* PGDIR_SHIFT = 22*/ | ||
92 | slli r30, r30, 2 | ||
93 | add r31, r31, r30 | ||
94 | lw r31, [r31, 0] /* get the address of the start address of PTE table */ | ||
95 | |||
96 | mfcr r30, cr9 | ||
97 | andi r30, 0xfff /* equivalent to get PET index and right shift 2 bits */ | ||
98 | add r31, r31, r30 | ||
99 | lw r30, [r31, 0] /* load pte entry */ | ||
100 | mtcr r30, cr12 | ||
101 | nop | ||
102 | nop | ||
103 | nop | ||
104 | nop | ||
105 | nop | ||
106 | mtrtlb | ||
107 | nop | ||
108 | nop | ||
109 | nop | ||
110 | nop | ||
111 | nop | ||
112 | rte /* 6 cycles to make sure tlb entry works */ | ||
113 | |||
114 | ENTRY(score7_KSEG_refill_Handler) | ||
115 | la r31, pgd_current /* get pgd pointer */ | ||
116 | lw r31, [r31, 0] /* get the address of PGD */ | ||
117 | mfcr r30, cr6 | ||
118 | srli r30, r30, 22 /* PGDIR_SHIFT = 22 */ | ||
119 | slli r30, r30, 2 | ||
120 | add r31, r31, r30 | ||
121 | lw r31, [r31, 0] /* get the address of the start address of PTE table */ | ||
122 | |||
123 | mfcr r30, cr6 /* get Bad VPN */ | ||
124 | srli r30, r30, 10 | ||
125 | andi r30, 0xffc /* PTE VPN mask (bit 11~2) */ | ||
126 | |||
127 | add r31, r31, r30 | ||
128 | lw r30, [r31, 0] /* load pte entry */ | ||
129 | mtcr r30, cr12 | ||
130 | nop | ||
131 | nop | ||
132 | nop | ||
133 | nop | ||
134 | nop | ||
135 | mtrtlb | ||
136 | nop | ||
137 | nop | ||
138 | nop | ||
139 | nop | ||
140 | nop | ||
141 | rte /* 6 cycles to make sure tlb entry works */ | ||
142 | |||
143 | nopage_tlbl: | ||
144 | do_fault 0 /* Read */ | ||
145 | |||
146 | ENTRY(handle_tlb_refill) | ||
147 | load_pte r30, r31 | ||
148 | pte_writable r30, r31, handle_tlb_refill_nopage | ||
149 | pte_makewrite r30, r31 /* Access|Modify|Dirty|Valid */ | ||
150 | pte_reload r31 | ||
151 | mtrtlb | ||
152 | nop | ||
153 | nop | ||
154 | nop | ||
155 | nop | ||
156 | nop | ||
157 | rte | ||
158 | handle_tlb_refill_nopage: | ||
159 | do_fault 0 /* Read */ | ||
160 | |||
161 | ENTRY(handle_tlb_invaild) | ||
162 | load_pte r30, r31 | ||
163 | stlb /* find faulting entry */ | ||
164 | pte_writable r30, r31, handle_tlb_invaild_nopage | ||
165 | pte_makewrite r30, r31 /* Access|Modify|Dirty|Valid */ | ||
166 | pte_reload r31 | ||
167 | mtptlb | ||
168 | nop | ||
169 | nop | ||
170 | nop | ||
171 | nop | ||
172 | nop | ||
173 | rte | ||
174 | handle_tlb_invaild_nopage: | ||
175 | do_fault 0 /* Read */ | ||
176 | |||
177 | ENTRY(handle_mod) | ||
178 | load_pte r30, r31 | ||
179 | stlb /* find faulting entry */ | ||
180 | andi r30, _PAGE_WRITE /* Writable? */ | ||
181 | cmpz.c r30 | ||
182 | beq nowrite_mod | ||
183 | lw r30, [r31, 0] /* reload into r30 */ | ||
184 | |||
185 | /* Present and writable bits set, set accessed and dirty bits. */ | ||
186 | pte_makewrite r30, r31 | ||
187 | |||
188 | /* Now reload the entry into the tlb. */ | ||
189 | pte_reload r31 | ||
190 | mtptlb | ||
191 | nop | ||
192 | nop | ||
193 | nop | ||
194 | nop | ||
195 | nop | ||
196 | rte | ||
197 | |||
198 | nowrite_mod: | ||
199 | do_fault 1 /* Write */ | ||
diff --git a/arch/score/mm/tlb-score.c b/arch/score/mm/tlb-score.c new file mode 100644 index 000000000000..4fa5aa5afecc --- /dev/null +++ b/arch/score/mm/tlb-score.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * arch/score/mm/tlb-score.c | ||
3 | * | ||
4 | * Score Processor version. | ||
5 | * | ||
6 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. | ||
7 | * Lennox Wu <lennox.wu@sunplusct.com> | ||
8 | * Chen Liqin <liqin.chen@sunplusct.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, see the file COPYING, or write | ||
22 | * to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/highmem.h> | ||
27 | #include <linux/module.h> | ||
28 | |||
29 | #include <asm/irq.h> | ||
30 | #include <asm/mmu_context.h> | ||
31 | #include <asm/tlb.h> | ||
32 | |||
33 | #define TLBSIZE 32 | ||
34 | |||
35 | unsigned long asid_cache = ASID_FIRST_VERSION; | ||
36 | EXPORT_SYMBOL(asid_cache); | ||
37 | |||
38 | void local_flush_tlb_all(void) | ||
39 | { | ||
40 | unsigned long flags; | ||
41 | unsigned long old_ASID; | ||
42 | int entry; | ||
43 | |||
44 | local_irq_save(flags); | ||
45 | old_ASID = pevn_get() & ASID_MASK; | ||
46 | pectx_set(0); /* invalid */ | ||
47 | entry = tlblock_get(); /* skip locked entries*/ | ||
48 | |||
49 | for (; entry < TLBSIZE; entry++) { | ||
50 | tlbpt_set(entry); | ||
51 | pevn_set(KSEG1); | ||
52 | barrier(); | ||
53 | tlb_write_indexed(); | ||
54 | } | ||
55 | pevn_set(old_ASID); | ||
56 | local_irq_restore(flags); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * If mm is currently active_mm, we can't really drop it. Instead, | ||
61 | * we will get a new one for it. | ||
62 | */ | ||
63 | static inline void | ||
64 | drop_mmu_context(struct mm_struct *mm) | ||
65 | { | ||
66 | unsigned long flags; | ||
67 | |||
68 | local_irq_save(flags); | ||
69 | get_new_mmu_context(mm); | ||
70 | pevn_set(mm->context & ASID_MASK); | ||
71 | local_irq_restore(flags); | ||
72 | } | ||
73 | |||
74 | void local_flush_tlb_mm(struct mm_struct *mm) | ||
75 | { | ||
76 | if (mm->context != 0) | ||
77 | drop_mmu_context(mm); | ||
78 | } | ||
79 | |||
80 | void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | ||
81 | unsigned long end) | ||
82 | { | ||
83 | struct mm_struct *mm = vma->vm_mm; | ||
84 | unsigned long vma_mm_context = mm->context; | ||
85 | if (mm->context != 0) { | ||
86 | unsigned long flags; | ||
87 | int size; | ||
88 | |||
89 | local_irq_save(flags); | ||
90 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | ||
91 | if (size <= TLBSIZE) { | ||
92 | int oldpid = pevn_get() & ASID_MASK; | ||
93 | int newpid = vma_mm_context & ASID_MASK; | ||
94 | |||
95 | start &= PAGE_MASK; | ||
96 | end += (PAGE_SIZE - 1); | ||
97 | end &= PAGE_MASK; | ||
98 | while (start < end) { | ||
99 | int idx; | ||
100 | |||
101 | pevn_set(start | newpid); | ||
102 | start += PAGE_SIZE; | ||
103 | barrier(); | ||
104 | tlb_probe(); | ||
105 | idx = tlbpt_get(); | ||
106 | pectx_set(0); | ||
107 | pevn_set(KSEG1); | ||
108 | if (idx < 0) | ||
109 | continue; | ||
110 | tlb_write_indexed(); | ||
111 | } | ||
112 | pevn_set(oldpid); | ||
113 | } else { | ||
114 | /* Bigger than TLBSIZE, get new ASID directly */ | ||
115 | get_new_mmu_context(mm); | ||
116 | if (mm == current->active_mm) | ||
117 | pevn_set(vma_mm_context & ASID_MASK); | ||
118 | } | ||
119 | local_irq_restore(flags); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) | ||
124 | { | ||
125 | unsigned long flags; | ||
126 | int size; | ||
127 | |||
128 | local_irq_save(flags); | ||
129 | size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | ||
130 | if (size <= TLBSIZE) { | ||
131 | int pid = pevn_get(); | ||
132 | |||
133 | start &= PAGE_MASK; | ||
134 | end += PAGE_SIZE - 1; | ||
135 | end &= PAGE_MASK; | ||
136 | |||
137 | while (start < end) { | ||
138 | long idx; | ||
139 | |||
140 | pevn_set(start); | ||
141 | start += PAGE_SIZE; | ||
142 | tlb_probe(); | ||
143 | idx = tlbpt_get(); | ||
144 | if (idx < 0) | ||
145 | continue; | ||
146 | pectx_set(0); | ||
147 | pevn_set(KSEG1); | ||
148 | barrier(); | ||
149 | tlb_write_indexed(); | ||
150 | } | ||
151 | pevn_set(pid); | ||
152 | } else { | ||
153 | local_flush_tlb_all(); | ||
154 | } | ||
155 | |||
156 | local_irq_restore(flags); | ||
157 | } | ||
158 | |||
159 | void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | ||
160 | { | ||
161 | if (!vma || vma->vm_mm->context != 0) { | ||
162 | unsigned long flags; | ||
163 | int oldpid, newpid, idx; | ||
164 | unsigned long vma_ASID = vma->vm_mm->context; | ||
165 | |||
166 | newpid = vma_ASID & ASID_MASK; | ||
167 | page &= PAGE_MASK; | ||
168 | local_irq_save(flags); | ||
169 | oldpid = pevn_get() & ASID_MASK; | ||
170 | pevn_set(page | newpid); | ||
171 | barrier(); | ||
172 | tlb_probe(); | ||
173 | idx = tlbpt_get(); | ||
174 | pectx_set(0); | ||
175 | pevn_set(KSEG1); | ||
176 | if (idx < 0) /* p_bit(31) - 1: miss, 0: hit*/ | ||
177 | goto finish; | ||
178 | barrier(); | ||
179 | tlb_write_indexed(); | ||
180 | finish: | ||
181 | pevn_set(oldpid); | ||
182 | local_irq_restore(flags); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * This one is only used for pages with the global bit set so we don't care | ||
188 | * much about the ASID. | ||
189 | */ | ||
190 | void local_flush_tlb_one(unsigned long page) | ||
191 | { | ||
192 | unsigned long flags; | ||
193 | int oldpid, idx; | ||
194 | |||
195 | local_irq_save(flags); | ||
196 | oldpid = pevn_get(); | ||
197 | page &= (PAGE_MASK << 1); | ||
198 | pevn_set(page); | ||
199 | barrier(); | ||
200 | tlb_probe(); | ||
201 | idx = tlbpt_get(); | ||
202 | pectx_set(0); | ||
203 | if (idx >= 0) { | ||
204 | /* Make sure all entries differ. */ | ||
205 | pevn_set(KSEG1); | ||
206 | barrier(); | ||
207 | tlb_write_indexed(); | ||
208 | } | ||
209 | pevn_set(oldpid); | ||
210 | local_irq_restore(flags); | ||
211 | } | ||
212 | |||
213 | void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) | ||
214 | { | ||
215 | unsigned long flags; | ||
216 | int idx, pid; | ||
217 | |||
218 | /* | ||
219 | * Handle debugger faulting in for debugee. | ||
220 | */ | ||
221 | if (current->active_mm != vma->vm_mm) | ||
222 | return; | ||
223 | |||
224 | pid = pevn_get() & ASID_MASK; | ||
225 | |||
226 | local_irq_save(flags); | ||
227 | address &= PAGE_MASK; | ||
228 | pevn_set(address | pid); | ||
229 | barrier(); | ||
230 | tlb_probe(); | ||
231 | idx = tlbpt_get(); | ||
232 | pectx_set(pte_val(pte)); | ||
233 | pevn_set(address | pid); | ||
234 | if (idx < 0) | ||
235 | tlb_write_random(); | ||
236 | else | ||
237 | tlb_write_indexed(); | ||
238 | |||
239 | pevn_set(pid); | ||
240 | local_irq_restore(flags); | ||
241 | } | ||
242 | |||
243 | void __cpuinit tlb_init(void) | ||
244 | { | ||
245 | tlblock_set(0); | ||
246 | local_flush_tlb_all(); | ||
247 | memcpy((void *)(EXCEPTION_VECTOR_BASE_ADDR + 0x100), | ||
248 | &score7_FTLB_refill_Handler, 0xFC); | ||
249 | flush_icache_range(EXCEPTION_VECTOR_BASE_ADDR + 0x100, | ||
250 | EXCEPTION_VECTOR_BASE_ADDR + 0x1FC); | ||
251 | } | ||