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 64ENTRY(debug_exception_vector) 65 nop! 66 nop! 67 nop! 68 nop! 69 nop! 70 nop! 71 nop! 72 nop! 73 74ENTRY(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 83ENTRY(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; 94general_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 104interrupt_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 115ENTRY(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 122ENTRY(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 135ENTRY(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 144ENTRY(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 153ENTRY(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 162ENTRY(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 171ENTRY(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 180ENTRY(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 193ENTRY(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 202ENTRY(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 211ENTRY(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 220ENTRY(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 237ENTRY(ret_from_exception) 238 disable_irq # preempt stop 239 nop 240 j __ret_from_irq 241 nop 242#endif 243 244ENTRY(ret_from_irq) 245 sw r16, [r28, TI_REGS] 246 247ENTRY(__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 252resume_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 263resume_kernel: 264 disable_irq 265 lw r8, [r28, TI_PRE_COUNT] 266 cmpz.c r8 267 bne r8, restore_all 268need_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 281ENTRY(ret_from_fork) 282 bl schedule_tail # r4=struct task_struct *prev 283 284ENTRY(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 292ENTRY(restore_all) # restore full frame 293 RESTORE_ALL_AND_RET 294 295work_pending: 296 andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS 297 beq work_notifysig 298work_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 310work_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 318ENTRY(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 */ 368ENTRY(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 396ENTRY(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 bgeu 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 4331: 434 cmpi.c r4, -MAX_ERRNO - 1 435 ble 2f 436 ldi r8, 0x1; 437 sw r8, [r0, PT_R7] 438 neg r4, r4 4392: 440 sw r4, [r0, PT_R4] # save result 441 442syscall_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 450syscall_return_work: 451 j syscall_exit_work 452 453syscall_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 4721: sw r4, [r0, PT_R2] # result 473 j syscall_exit 474 475illegal_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 483ENTRY(sys_execve) 484 mv r4, r0 485 la r8, score_execve 486 br r8 487 488ENTRY(sys_clone) 489 mv r4, r0 490 la r8, score_clone 491 br r8 492 493ENTRY(sys_rt_sigreturn) 494 mv r4, r0 495 la r8, score_rt_sigreturn 496 br r8 497 498ENTRY(sys_sigaltstack) 499 mv r4, r0 500 la r8, score_sigaltstack 501 br r8 502 503#ifdef __ARCH_WANT_SYSCALL_DEPRECATED 504ENTRY(sys_fork) 505 mv r4, r0 506 la r8, score_fork 507 br r8 508 509ENTRY(sys_vfork) 510 mv r4, r0 511 la r8, score_vfork 512 br r8 513#endif /* __ARCH_WANT_SYSCALL_DEPRECATED */ 514 515