1 /* !! 1 /* -*- mode: asm -*- 2 * Low-level system-call handling, trap handle << 3 * 2 * 4 * Copyright (C) 2008-2009 Michal Simek <monstr !! 3 * linux/arch/m68k/kernel/entry.S 5 * Copyright (C) 2008-2009 PetaLogix << 6 * Copyright (C) 2003 John Williams < << 7 * Copyright (C) 2001,2002 NEC Corporatio << 8 * Copyright (C) 2001,2002 Miles Bader <mi << 9 * 4 * 10 * This file is subject to the terms and condi !! 5 * Copyright (C) 1991, 1992 Linus Torvalds 11 * Public License. See the file COPYING in the << 12 * archive for more details. << 13 * 6 * 14 * Written by Miles Bader <miles@gnu.org> !! 7 * This file is subject to the terms and conditions of the GNU General Public 15 * Heavily modified by John Williams for Micro !! 8 * License. See the file README.legal in the main directory of this archive 16 */ !! 9 * for more details. 17 << 18 #include <linux/sys.h> << 19 #include <linux/linkage.h> << 20 << 21 #include <asm/entry.h> << 22 #include <asm/current.h> << 23 #include <asm/processor.h> << 24 #include <asm/exceptions.h> << 25 #include <asm/asm-offsets.h> << 26 #include <asm/thread_info.h> << 27 << 28 #include <asm/page.h> << 29 #include <asm/unistd.h> << 30 #include <asm/xilinx_mb_manager.h> << 31 << 32 #include <linux/errno.h> << 33 #include <asm/signal.h> << 34 #include <asm/mmu.h> << 35 << 36 #undef DEBUG << 37 << 38 #ifdef DEBUG << 39 /* Create space for syscalls counting. */ << 40 .section .data << 41 .global syscall_debug_table << 42 .align 4 << 43 syscall_debug_table: << 44 .space (__NR_syscalls * 4) << 45 #endif /* DEBUG */ << 46 << 47 #define C_ENTRY(name) .globl name; .align 4; << 48 << 49 /* << 50 * Various ways of setting and clearing BIP in << 51 * This is mucky, but necessary using microbla << 52 * allows msr ops to write to BIP << 53 */ << 54 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR << 55 .macro clear_bip << 56 msrclr r0, MSR_BIP << 57 .endm << 58 << 59 .macro set_bip << 60 msrset r0, MSR_BIP << 61 .endm << 62 << 63 .macro clear_eip << 64 msrclr r0, MSR_EIP << 65 .endm << 66 << 67 .macro set_ee << 68 msrset r0, MSR_EE << 69 .endm << 70 << 71 .macro disable_irq << 72 msrclr r0, MSR_IE << 73 .endm << 74 << 75 .macro enable_irq << 76 msrset r0, MSR_IE << 77 .endm << 78 << 79 .macro set_ums << 80 msrset r0, MSR_UMS << 81 msrclr r0, MSR_VMS << 82 .endm << 83 << 84 .macro set_vms << 85 msrclr r0, MSR_UMS << 86 msrset r0, MSR_VMS << 87 .endm << 88 << 89 .macro clear_ums << 90 msrclr r0, MSR_UMS << 91 .endm << 92 << 93 .macro clear_vms_ums << 94 msrclr r0, MSR_VMS | MSR_UMS << 95 .endm << 96 #else << 97 .macro clear_bip << 98 mfs r11, rmsr << 99 andi r11, r11, ~MSR_BIP << 100 mts rmsr, r11 << 101 .endm << 102 << 103 .macro set_bip << 104 mfs r11, rmsr << 105 ori r11, r11, MSR_BIP << 106 mts rmsr, r11 << 107 .endm << 108 << 109 .macro clear_eip << 110 mfs r11, rmsr << 111 andi r11, r11, ~MSR_EIP << 112 mts rmsr, r11 << 113 .endm << 114 << 115 .macro set_ee << 116 mfs r11, rmsr << 117 ori r11, r11, MSR_EE << 118 mts rmsr, r11 << 119 .endm << 120 << 121 .macro disable_irq << 122 mfs r11, rmsr << 123 andi r11, r11, ~MSR_IE << 124 mts rmsr, r11 << 125 .endm << 126 << 127 .macro enable_irq << 128 mfs r11, rmsr << 129 ori r11, r11, MSR_IE << 130 mts rmsr, r11 << 131 .endm << 132 << 133 .macro set_ums << 134 mfs r11, rmsr << 135 ori r11, r11, MSR_VMS << 136 andni r11, r11, MSR_UMS << 137 mts rmsr, r11 << 138 .endm << 139 << 140 .macro set_vms << 141 mfs r11, rmsr << 142 ori r11, r11, MSR_VMS << 143 andni r11, r11, MSR_UMS << 144 mts rmsr, r11 << 145 .endm << 146 << 147 .macro clear_ums << 148 mfs r11, rmsr << 149 andni r11, r11, MSR_UMS << 150 mts rmsr,r11 << 151 .endm << 152 << 153 .macro clear_vms_ums << 154 mfs r11, rmsr << 155 andni r11, r11, (MSR_VMS|MSR_UMS) << 156 mts rmsr,r11 << 157 .endm << 158 #endif << 159 << 160 /* Define how to call high-level functions. Wi << 161 * enabled when calling the high-level functio << 162 * VM_ON, VM_OFF, DO_JUMP_BIPCLR, DO_CALL << 163 */ << 164 << 165 /* turn on virtual protected mode save */ << 166 #define VM_ON \ << 167 set_ums; \ << 168 rted r0, 2f; \ << 169 nop; \ << 170 2: << 171 << 172 /* turn off virtual protected mode save and us << 173 #define VM_OFF \ << 174 clear_vms_ums; \ << 175 rted r0, TOPHYS(1f); \ << 176 nop; \ << 177 1: << 178 << 179 #define SAVE_REGS \ << 180 swi r2, r1, PT_R2; /* Save SDA */ << 181 swi r3, r1, PT_R3; << 182 swi r4, r1, PT_R4; << 183 swi r5, r1, PT_R5; << 184 swi r6, r1, PT_R6; << 185 swi r7, r1, PT_R7; << 186 swi r8, r1, PT_R8; << 187 swi r9, r1, PT_R9; << 188 swi r10, r1, PT_R10; << 189 swi r11, r1, PT_R11; /* sav << 190 swi r12, r1, PT_R12; << 191 swi r13, r1, PT_R13; /* Sav << 192 swi r14, r1, PT_PC; /* PC, before << 193 swi r15, r1, PT_R15; /* Sav << 194 swi r16, r1, PT_R16; << 195 swi r17, r1, PT_R17; << 196 swi r18, r1, PT_R18; /* Sav << 197 swi r19, r1, PT_R19; << 198 swi r20, r1, PT_R20; << 199 swi r21, r1, PT_R21; << 200 swi r22, r1, PT_R22; << 201 swi r23, r1, PT_R23; << 202 swi r24, r1, PT_R24; << 203 swi r25, r1, PT_R25; << 204 swi r26, r1, PT_R26; << 205 swi r27, r1, PT_R27; << 206 swi r28, r1, PT_R28; << 207 swi r29, r1, PT_R29; << 208 swi r30, r1, PT_R30; << 209 swi r31, r1, PT_R31; /* Sav << 210 mfs r11, rmsr; /* sav << 211 swi r11, r1, PT_MSR; << 212 << 213 #define RESTORE_REGS_GP \ << 214 lwi r2, r1, PT_R2; /* restore SDA << 215 lwi r3, r1, PT_R3; << 216 lwi r4, r1, PT_R4; << 217 lwi r5, r1, PT_R5; << 218 lwi r6, r1, PT_R6; << 219 lwi r7, r1, PT_R7; << 220 lwi r8, r1, PT_R8; << 221 lwi r9, r1, PT_R9; << 222 lwi r10, r1, PT_R10; << 223 lwi r11, r1, PT_R11; /* res << 224 lwi r12, r1, PT_R12; << 225 lwi r13, r1, PT_R13; /* res << 226 lwi r14, r1, PT_PC; /* RESTORE_LIN << 227 lwi r15, r1, PT_R15; /* res << 228 lwi r16, r1, PT_R16; << 229 lwi r17, r1, PT_R17; << 230 lwi r18, r1, PT_R18; /* res << 231 lwi r19, r1, PT_R19; << 232 lwi r20, r1, PT_R20; << 233 lwi r21, r1, PT_R21; << 234 lwi r22, r1, PT_R22; << 235 lwi r23, r1, PT_R23; << 236 lwi r24, r1, PT_R24; << 237 lwi r25, r1, PT_R25; << 238 lwi r26, r1, PT_R26; << 239 lwi r27, r1, PT_R27; << 240 lwi r28, r1, PT_R28; << 241 lwi r29, r1, PT_R29; << 242 lwi r30, r1, PT_R30; << 243 lwi r31, r1, PT_R31; /* Res << 244 << 245 #define RESTORE_REGS \ << 246 lwi r11, r1, PT_MSR; << 247 mts rmsr , r11; << 248 RESTORE_REGS_GP << 249 << 250 #define RESTORE_REGS_RTBD \ << 251 lwi r11, r1, PT_MSR; << 252 andni r11, r11, MSR_EIP; /* << 253 ori r11, r11, MSR_EE | MSR_BIP; /* << 254 mts rmsr , r11; << 255 RESTORE_REGS_GP << 256 << 257 #define SAVE_STATE \ << 258 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 259 /* See if already in kernel mode.*/ << 260 mfs r1, rmsr; << 261 andi r1, r1, MSR_UMS; << 262 bnei r1, 1f; << 263 /* Kernel-mode state save. */ << 264 /* Reload kernel stack-ptr. */ << 265 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 266 /* FIXME: I can add these two lines to << 267 /* tophys(r1,r1); */ << 268 /* addik r1, r1, -PT_SIZE; */ << 269 addik r1, r1, CONFIG_KERNEL_BASE_ADD << 270 SAVE_REGS << 271 brid 2f; << 272 swi r1, r1, PT_MODE; << 273 1: /* User-mode state save. */ << 274 lwi r1, r0, TOPHYS(PER_CPU(CURRENT << 275 tophys(r1,r1); << 276 lwi r1, r1, TS_THREAD_INFO; /* get << 277 /* MS these three instructions can be << 278 /* addik r1, r1, THREAD_SIZE; * << 279 /* tophys(r1,r1); */ << 280 /* addik r1, r1, -PT_SIZE; */ << 281 addik r1, r1, THREAD_SIZE + CONFIG_KER << 282 SAVE_REGS << 283 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 284 swi r11, r1, PT_R1; /* Store user << 285 swi r0, r1, PT_MODE; /* Was in use << 286 /* MS: I am clearing UMS even in case << 287 clear_ums; << 288 2: lwi CURRENT_TASK, r0, TOPHYS(PER_C << 289 << 290 .text << 291 << 292 .extern cpuinfo << 293 << 294 C_ENTRY(mb_flush_dcache): << 295 addik r1, r1, -PT_SIZE << 296 SAVE_REGS << 297 << 298 addik r3, r0, cpuinfo << 299 lwi r7, r3, CI_DCS << 300 lwi r8, r3, CI_DCL << 301 sub r9, r7, r8 << 302 1: << 303 wdc.flush r9, r0 << 304 bgtid r9, 1b << 305 addk r9, r9, r8 << 306 << 307 RESTORE_REGS << 308 addik r1, r1, PT_SIZE << 309 rtsd r15, 8 << 310 nop << 311 << 312 C_ENTRY(mb_invalidate_icache): << 313 addik r1, r1, -PT_SIZE << 314 SAVE_REGS << 315 << 316 addik r3, r0, cpuinfo << 317 lwi r7, r3, CI_ICS << 318 lwi r8, r3, CI_ICL << 319 sub r9, r7, r8 << 320 1: << 321 wic r9, r0 << 322 bgtid r9, 1b << 323 addk r9, r9, r8 << 324 << 325 RESTORE_REGS << 326 addik r1, r1, PT_SIZE << 327 rtsd r15, 8 << 328 nop << 329 << 330 /* << 331 * User trap. << 332 * 10 * 333 * System calls are handled here. !! 11 * Linux/m68k support by Hamish Macdonald 334 * 12 * 335 * Syscall protocol: !! 13 * 68060 fixes by Jesper Skov 336 * Syscall number in r12, args in r5-r10 << 337 * Return value in r3 << 338 * 14 * 339 * Trap entered via brki instruction, so BIP b << 340 * are masked. This is nice, means we don't ha << 341 */ 15 */ 342 C_ENTRY(_user_exception): << 343 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 344 addi r14, r14, 4 /* return addr << 345 << 346 lwi r1, r0, TOPHYS(PER_CPU(CURRENT << 347 tophys(r1,r1); << 348 lwi r1, r1, TS_THREAD_INFO; /* get << 349 /* calculate kernel stack pointer from task st << 350 addik r1, r1, THREAD_SIZE; << 351 tophys(r1,r1); << 352 << 353 addik r1, r1, -PT_SIZE; /* Make room << 354 SAVE_REGS << 355 swi r0, r1, PT_R3 << 356 swi r0, r1, PT_R4 << 357 << 358 swi r0, r1, PT_MODE; << 359 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 360 swi r11, r1, PT_R1; /* Sto << 361 clear_ums; << 362 2: lwi CURRENT_TASK, r0, TOPHYS(PER_C << 363 /* Save away the syscall number. */ << 364 swi r12, r1, PT_R0; << 365 tovirt(r1,r1) << 366 << 367 /* where the trap should return need -8 to adj << 368 /* Jump to the appropriate function for the sy << 369 * (r12 is not preserved), or return an error << 370 * register should point to the location where << 371 * the called function should return. [note t << 372 << 373 /* Step into virtual mode */ << 374 rtbd r0, 3f << 375 nop << 376 3: << 377 lwi r11, CURRENT_TASK, TS_THREAD_I << 378 lwi r11, r11, TI_FLAGS /* ge << 379 andi r11, r11, _TIF_WORK_SYSCALL_MA << 380 beqi r11, 4f << 381 << 382 addik r3, r0, -ENOSYS << 383 swi r3, r1, PT_R3 << 384 brlid r15, do_syscall_trace_enter << 385 addik r5, r1, PT_R0 << 386 << 387 # do_syscall_trace_enter returns the n << 388 addk r12, r0, r3 << 389 lwi r5, r1, PT_R5; << 390 lwi r6, r1, PT_R6; << 391 lwi r7, r1, PT_R7; << 392 lwi r8, r1, PT_R8; << 393 lwi r9, r1, PT_R9; << 394 lwi r10, r1, PT_R10; << 395 4: << 396 /* Jump to the appropriate function for the sy << 397 * (r12 is not preserved), or return an error << 398 * The LP register should point to the locatio << 399 * should return. [note that MAKE_SYS_CALL us << 400 /* See if the system call number is va << 401 blti r12, 5f << 402 addi r11, r12, -__NR_syscalls; << 403 bgei r11, 5f; << 404 /* Figure out which function to use fo << 405 /* Note Microblaze barrel shift is opt << 406 add r12, r12, r12; << 407 add r12, r12, r12; << 408 addi r30, r0, 1 << 409 << 410 #ifdef DEBUG << 411 /* Trac syscalls and stored them to sy << 412 /* The first syscall location stores t << 413 lwi r3, r0, syscall_debug_table << 414 addi r3, r3, 1 << 415 swi r3, r0, syscall_debug_table << 416 lwi r3, r12, syscall_debug_table << 417 addi r3, r3, 1 << 418 swi r3, r12, syscall_debug_table << 419 #endif << 420 << 421 # Find and jump into the syscall handl << 422 lwi r12, r12, sys_call_table << 423 /* where the trap should return need - << 424 addi r15, r0, ret_from_trap-8 << 425 bra r12 << 426 << 427 /* The syscall number is invalid, retu << 428 5: << 429 braid ret_from_trap << 430 addi r3, r0, -ENOSYS; << 431 << 432 /* Entry point used to return from a syscall/t << 433 /* We re-enable BIP bit before state restore * << 434 C_ENTRY(ret_from_trap): << 435 swi r3, r1, PT_R3 << 436 swi r4, r1, PT_R4 << 437 << 438 lwi r11, r1, PT_MODE; << 439 /* See if returning to kernel mode, if so, ski << 440 bnei r11, 2f; << 441 /* We're returning to user mode, so ch << 442 * trigger rescheduling. */ << 443 /* FIXME: Restructure all these flag c << 444 lwi r11, CURRENT_TASK, TS_THREAD_I << 445 lwi r11, r11, TI_FLAGS; << 446 andi r11, r11, _TIF_WORK_SYSCALL_MA << 447 beqi r11, 1f << 448 << 449 brlid r15, do_syscall_trace_leave << 450 addik r5, r1, PT_R0 << 451 1: << 452 /* We're returning to user mode, so ch << 453 * trigger rescheduling. */ << 454 /* get thread info from current task * << 455 lwi r11, CURRENT_TASK, TS_THREAD_I << 456 lwi r19, r11, TI_FLAGS; << 457 andi r11, r19, _TIF_NEED_RESCHED; << 458 beqi r11, 5f; << 459 << 460 bralid r15, schedule; /* Call schedu << 461 nop; /* del << 462 bri 1b << 463 << 464 /* Maybe handle a signal */ << 465 5: << 466 andi r11, r19, _TIF_SIGPENDING | _T << 467 beqi r11, 4f; /* Sig << 468 << 469 addik r5, r1, 0; /* Arg << 470 bralid r15, do_notify_resume; /* Han << 471 add r6, r30, r0; /* Arg << 472 add r30, r0, r0 /* no << 473 bri 1b << 474 << 475 /* Finally, return to user state. */ << 476 4: set_bip; /* In << 477 swi CURRENT_TASK, r0, PER_CPU(CURR << 478 VM_OFF; << 479 tophys(r1,r1); << 480 RESTORE_REGS_RTBD; << 481 addik r1, r1, PT_SIZE /* Cle << 482 lwi r1, r1, PT_R1 - PT_SIZE;/* Res << 483 bri 6f; << 484 << 485 /* Return to kernel state. */ << 486 2: set_bip; /* In << 487 VM_OFF; << 488 tophys(r1,r1); << 489 RESTORE_REGS_RTBD; << 490 addik r1, r1, PT_SIZE /* Cle << 491 tovirt(r1,r1); << 492 6: << 493 TRAP_return: /* Make global symbol << 494 rtbd r14, 0; /* Instructions to ret << 495 nop; << 496 << 497 << 498 /* This the initial entry point for a new chil << 499 stack in place that makes it look like the << 500 syscall. This function is actually `return << 501 (copy_thread makes ret_from_fork the return << 502 saved context). */ << 503 C_ENTRY(ret_from_fork): << 504 bralid r15, schedule_tail; /* ...whic << 505 add r5, r3, r0; /* switch_thre << 506 /* ( in the de << 507 brid ret_from_trap; /* Do normal t << 508 add r3, r0, r0; /* Child's for << 509 << 510 C_ENTRY(ret_from_kernel_thread): << 511 bralid r15, schedule_tail; /* ...whic << 512 add r5, r3, r0; /* switch_thre << 513 /* ( in the de << 514 brald r15, r20 /* fn was left << 515 addk r5, r0, r19 /* ... and arg << 516 brid ret_from_trap << 517 add r3, r0, r0 << 518 << 519 C_ENTRY(sys_rt_sigreturn_wrapper): << 520 addik r30, r0, 0 /* no << 521 brid sys_rt_sigreturn /* Do << 522 addik r5, r1, 0; /* add << 523 16 524 /* 17 /* 525 * HW EXCEPTION rutine start !! 18 * entry.S contains the system-call and fault low-level handling routines. 526 */ !! 19 * This also contains the timer-interrupt handler, as well as all interrupts 527 C_ENTRY(full_exception_trap): !! 20 * and faults that can result in a task-switch. 528 /* adjust exception address for privil << 529 * for finding where is it */ << 530 addik r17, r17, -4 << 531 SAVE_STATE /* Save registers */ << 532 /* PC, before IRQ/trap - this is one i << 533 swi r17, r1, PT_PC; << 534 tovirt(r1,r1) << 535 /* FIXME this can be store directly in << 536 * I tested it but there is a fault */ << 537 /* where the trap should return need - << 538 addik r15, r0, ret_from_exc - 8 << 539 mfs r6, resr << 540 mfs r7, rfsr; /* sav << 541 mts rfsr, r0; /* Clear stick << 542 rted r0, full_exception << 543 addik r5, r1, 0 /* pa << 544 << 545 /* << 546 * Unaligned data trap. << 547 * << 548 * Unaligned data trap last on 4k page is hand << 549 * 21 * 550 * Trap entered via exception, so EE bit is se !! 22 * NOTE: This code handles signal-recognition, which happens every time 551 * are masked. This is nice, means we don't h !! 23 * after a timer-interrupt and after each system call. 552 * 24 * 553 * The assembler routine is in "arch/microblaz << 554 */ 25 */ 555 C_ENTRY(unaligned_data_trap): << 556 /* MS: I have to save r11 value and th << 557 * set_bit, clear_eip, set_ee use r11 << 558 * instructions are not used. We don't << 559 * are used and they use r0 instead of << 560 * I am using ENTRY_SP which should be << 561 * pointer saving. */ << 562 swi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 563 set_bip; /* equalize initial st << 564 clear_eip; << 565 set_ee; << 566 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 567 SAVE_STATE /* Save regist << 568 /* PC, before IRQ/trap - this is one i << 569 swi r17, r1, PT_PC; << 570 tovirt(r1,r1) << 571 /* where the trap should return need - << 572 addik r15, r0, ret_from_exc-8 << 573 mfs r3, resr /* ESR << 574 mfs r4, rear /* EAR << 575 rtbd r0, _unaligned_data_exception << 576 addik r7, r1, 0 /* par << 577 26 578 /* 27 /* 579 * Page fault traps. !! 28 * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so 580 * !! 29 * all pointers that used to be 'current' are now entry 581 * If the real exception handler (from hw_exce !! 30 * number 0 in the 'current_set' list. 582 * the mapping for the process, then we're thr << 583 * << 584 * Trap entered via exceptions, so EE bit is s << 585 * are masked. This is nice, means we don't h << 586 * << 587 * Build a standard exception frame for TLB Ac << 588 * will bail out to this point if they can't r << 589 * 31 * 590 * The C function called is in "arch/microblaz !! 32 * 6/05/00 RZ: addedd writeback completion after return from sighandler 591 * void do_page_fault(struct pt_regs *regs, !! 33 * for 68040 592 * unsigned long << 593 * unsigned long << 594 */ 34 */ 595 /* data and intruction trap - which is choose << 596 C_ENTRY(page_fault_data_trap): << 597 SAVE_STATE /* Save regist << 598 /* PC, before IRQ/trap - this is one i << 599 swi r17, r1, PT_PC; << 600 tovirt(r1,r1) << 601 /* where the trap should return need - << 602 addik r15, r0, ret_from_exc-8 << 603 mfs r6, rear /* par << 604 mfs r7, resr /* par << 605 rted r0, do_page_fault << 606 addik r5, r1, 0 /* par << 607 << 608 C_ENTRY(page_fault_instr_trap): << 609 SAVE_STATE /* Save regist << 610 /* PC, before IRQ/trap - this is one i << 611 swi r17, r1, PT_PC; << 612 tovirt(r1,r1) << 613 /* where the trap should return need - << 614 addik r15, r0, ret_from_exc-8 << 615 mfs r6, rear /* par << 616 ori r7, r0, 0 /* par << 617 rted r0, do_page_fault << 618 addik r5, r1, 0 /* par << 619 << 620 /* Entry point used to return from an exceptio << 621 C_ENTRY(ret_from_exc): << 622 lwi r11, r1, PT_MODE; << 623 bnei r11, 2f; /* See << 624 /* ... << 625 35 626 /* We're returning to user mode, so ch !! 36 #include <linux/linkage.h> 627 trigger rescheduling. */ !! 37 #include <asm/errno.h> 628 1: !! 38 #include <asm/setup.h> 629 lwi r11, CURRENT_TASK, TS_THREAD_I !! 39 #include <asm/traps.h> 630 lwi r19, r11, TI_FLAGS; /* get !! 40 #include <asm/unistd.h> 631 andi r11, r19, _TIF_NEED_RESCHED; !! 41 #include <asm/asm-offsets.h> 632 beqi r11, 5f; !! 42 #include <asm/entry.h> 633 << 634 /* Call the scheduler before returning from a << 635 bralid r15, schedule; /* Call schedu << 636 nop; /* del << 637 bri 1b << 638 << 639 /* Maybe handle a signal */ << 640 5: andi r11, r19, _TIF_SIGPENDING | _T << 641 beqi r11, 4f; /* Sig << 642 << 643 /* << 644 * Handle a signal return; Pending sig << 645 * << 646 * Not all registers are saved by the << 647 * points (for instance, call-saved re << 648 * C-compiler calling sequence in the << 649 * preserved), and call-clobbered regi << 650 * traps), but signal handlers may wan << 651 * complete register state. Here we s << 652 * the normal entry sequence, so that << 653 * (in a possibly modified form) after << 654 addik r5, r1, 0; /* Arg << 655 bralid r15, do_notify_resume; /* Han << 656 addi r6, r0, 0; /* Arg << 657 bri 1b << 658 << 659 /* Finally, return to user state. */ << 660 4: set_bip; /* Int << 661 swi CURRENT_TASK, r0, PER_CPU(CURR << 662 VM_OFF; << 663 tophys(r1,r1); << 664 << 665 RESTORE_REGS_RTBD; << 666 addik r1, r1, PT_SIZE /* Cle << 667 << 668 lwi r1, r1, PT_R1 - PT_SIZE; /* Re << 669 bri 6f; << 670 /* Return to kernel state. */ << 671 2: set_bip; /* Int << 672 VM_OFF; << 673 tophys(r1,r1); << 674 RESTORE_REGS_RTBD; << 675 addik r1, r1, PT_SIZE /* Cle << 676 << 677 tovirt(r1,r1); << 678 6: << 679 EXC_return: /* Make global symbol << 680 rtbd r14, 0; /* Instructions to ret << 681 nop; << 682 43 683 /* !! 44 .globl system_call, buserr, trap, resume 684 * HW EXCEPTION rutine end !! 45 .globl sys_call_table 685 */ !! 46 .globl __sys_fork, __sys_clone, __sys_vfork >> 47 .globl bad_interrupt >> 48 .globl auto_irqhandler_fixup >> 49 .globl user_irqvec_fixup 686 50 687 /* !! 51 .text 688 * Hardware maskable interrupts. !! 52 ENTRY(__sys_fork) 689 * !! 53 SAVE_SWITCH_STACK 690 * The stack-pointer (r1) should have already !! 54 jbsr sys_fork 691 * location PER_CPU(ENTRY_SP). !! 55 lea %sp@(24),%sp 692 */ !! 56 rts 693 C_ENTRY(_interrupt): !! 57 694 /* MS: we are in physical address */ !! 58 ENTRY(__sys_clone) 695 /* Save registers, switch to proper stack, con !! 59 SAVE_SWITCH_STACK 696 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S !! 60 pea %sp@(SWITCH_STACK_SIZE) 697 /* MS: See if already in kernel mode. !! 61 jbsr m68k_clone 698 mfs r1, rmsr !! 62 lea %sp@(28),%sp 699 nop !! 63 rts 700 andi r1, r1, MSR_UMS !! 64 701 bnei r1, 1f !! 65 ENTRY(__sys_vfork) 702 !! 66 SAVE_SWITCH_STACK 703 /* Kernel-mode state save. */ !! 67 jbsr sys_vfork 704 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_S !! 68 lea %sp@(24),%sp 705 tophys(r1,r1); /* MS: I have in r1 phy !! 69 rts 706 /* save registers */ !! 70 707 /* MS: Make room on the stack -> activation re !! 71 ENTRY(__sys_clone3) 708 addik r1, r1, -PT_SIZE; !! 72 SAVE_SWITCH_STACK 709 SAVE_REGS !! 73 pea %sp@(SWITCH_STACK_SIZE) 710 brid 2f; !! 74 jbsr m68k_clone3 711 swi r1, r1, PT_MODE; /* 0 - user m !! 75 lea %sp@(28),%sp 712 1: !! 76 rts 713 /* User-mode state save. */ !! 77 714 /* MS: get the saved current */ !! 78 ENTRY(sys_sigreturn) 715 lwi r1, r0, TOPHYS(PER_CPU(CURRENT !! 79 SAVE_SWITCH_STACK 716 tophys(r1,r1); !! 80 movel %sp,%a1 | switch_stack pointer 717 lwi r1, r1, TS_THREAD_INFO; !! 81 lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer 718 addik r1, r1, THREAD_SIZE; !! 82 lea %sp@(-84),%sp | leave a gap 719 tophys(r1,r1); !! 83 movel %a1,%sp@- 720 /* save registers */ !! 84 movel %a0,%sp@- 721 addik r1, r1, -PT_SIZE; !! 85 jbsr do_sigreturn 722 SAVE_REGS !! 86 jra 1f | shared with rt_sigreturn() 723 /* calculate mode */ !! 87 724 swi r0, r1, PT_MODE; !! 88 ENTRY(sys_rt_sigreturn) 725 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ !! 89 SAVE_SWITCH_STACK 726 swi r11, r1, PT_R1; !! 90 movel %sp,%a1 | switch_stack pointer 727 clear_ums; !! 91 lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer 728 2: !! 92 lea %sp@(-84),%sp | leave a gap 729 lwi CURRENT_TASK, r0, TOPHYS(PER_C !! 93 movel %a1,%sp@- 730 tovirt(r1,r1) !! 94 movel %a0,%sp@- 731 addik r15, r0, irq_call; !! 95 | stack contents: 732 irq_call:rtbd r0, do_IRQ; !! 96 | [original pt_regs address] [original switch_stack address] 733 addik r5, r1, 0; !! 97 | [gap] [switch_stack] [pt_regs] [exception frame] 734 !! 98 jbsr do_rt_sigreturn 735 /* MS: we are in virtual mode */ << 736 ret_from_irq: << 737 lwi r11, r1, PT_MODE; << 738 bnei r11, 2f; << 739 99 740 1: 100 1: 741 lwi r11, CURRENT_TASK, TS_THREAD_I !! 101 | stack contents now: 742 lwi r19, r11, TI_FLAGS; /* MS: get !! 102 | [original pt_regs address] [original switch_stack address] 743 andi r11, r19, _TIF_NEED_RESCHED; !! 103 | [unused part of the gap] [moved switch_stack] [moved pt_regs] 744 beqi r11, 5f !! 104 | [replacement exception frame] 745 bralid r15, schedule; !! 105 | return value of do_{rt_,}sigreturn() points to moved switch_stack. 746 nop; /* delay slot */ !! 106 747 bri 1b !! 107 movel %d0,%sp | discard the leftover junk 748 !! 108 RESTORE_SWITCH_STACK 749 /* Maybe handle a signal */ !! 109 | stack contents now is just [syscall return address] [pt_regs] [frame] 750 5: andi r11, r19, _TIF_SIGPENDING | _T !! 110 | return pt_regs.d0 751 beqid r11, no_intr_resched !! 111 movel %sp@(PT_OFF_D0+4),%d0 752 /* Handle a signal return; Pending signals sho !! 112 rts 753 addik r5, r1, 0; /* Arg 1: struct pt !! 113 754 bralid r15, do_notify_resume; /* Han !! 114 ENTRY(buserr) 755 addi r6, r0, 0; /* Arg 2: int in_sy !! 115 SAVE_ALL_INT 756 bri 1b !! 116 GET_CURRENT(%d0) 757 !! 117 movel %sp,%sp@- | stack frame pointer argument 758 /* Finally, return to user state. */ !! 118 jbsr buserr_c 759 no_intr_resched: !! 119 addql #4,%sp 760 /* Disable interrupts, we are now committe !! 120 jra ret_from_exception 761 disable_irq !! 121 762 swi CURRENT_TASK, r0, PER_CPU(CURR !! 122 ENTRY(trap) 763 VM_OFF; !! 123 SAVE_ALL_INT 764 tophys(r1,r1); !! 124 GET_CURRENT(%d0) 765 RESTORE_REGS !! 125 movel %sp,%sp@- | stack frame pointer argument 766 addik r1, r1, PT_SIZE /* MS: Clean u !! 126 jbsr trap_c 767 lwi r1, r1, PT_R1 - PT_SIZE; !! 127 addql #4,%sp 768 bri 6f; !! 128 jra ret_from_exception 769 /* MS: Return to kernel state. */ !! 129 770 2: !! 130 | After a fork we jump here directly from resume, 771 #ifdef CONFIG_PREEMPTION !! 131 | so that %d1 contains the previous task 772 lwi r11, CURRENT_TASK, TS_THREAD_I !! 132 | schedule_tail now used regardless of CONFIG_SMP 773 /* MS: get preempt_count from thread i !! 133 ENTRY(ret_from_fork) 774 lwi r5, r11, TI_PREEMPT_COUNT; !! 134 movel %d1,%sp@- 775 bgti r5, restore; !! 135 jsr schedule_tail 776 !! 136 addql #4,%sp 777 lwi r5, r11, TI_FLAGS; !! 137 jra ret_from_exception 778 andi r5, r5, _TIF_NEED_RESCHED; !! 138 779 beqi r5, restore /* if zero jump ov !! 139 ENTRY(ret_from_kernel_thread) 780 !! 140 | a3 contains the kernel thread payload, d7 - its argument 781 /* interrupts are off that's why I am !! 141 movel %d1,%sp@- 782 bralid r15, preempt_schedule_irq !! 142 jsr schedule_tail 783 nop !! 143 movel %d7,(%sp) 784 restore: !! 144 jsr %a3@ 785 #endif !! 145 addql #4,%sp 786 VM_OFF /* MS: turn off MMU */ !! 146 jra ret_from_exception 787 tophys(r1,r1) !! 147 788 RESTORE_REGS !! 148 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) 789 addik r1, r1, PT_SIZE /* MS: Clean u !! 149 790 tovirt(r1,r1); !! 150 #ifdef TRAP_DBG_INTERRUPT 791 6: !! 151 792 IRQ_return: /* MS: Make global symbol for debu !! 152 .globl dbginterrupt 793 rtid r14, 0 !! 153 ENTRY(dbginterrupt) 794 nop !! 154 SAVE_ALL_INT 795 !! 155 GET_CURRENT(%d0) 796 #ifdef CONFIG_MB_MANAGER !! 156 movel %sp,%sp@- /* stack frame pointer argument */ 797 !! 157 jsr dbginterrupt_c 798 #define PT_PID PT_SIZE !! 158 addql #4,%sp 799 #define PT_TLBI PT_SIZE + 4 !! 159 jra ret_from_exception 800 #define PT_ZPR PT_SIZE + 8 !! 160 #endif 801 #define PT_TLBL0 PT_SIZE + 12 !! 161 802 #define PT_TLBH0 PT_SIZE + 16 !! 162 ENTRY(reschedule) 803 !! 163 /* save top of frame */ 804 C_ENTRY(_xtmr_manager_reset): !! 164 pea %sp@ 805 lwi r1, r0, xmb_manager_stackpoint !! 165 jbsr set_esp0 806 !! 166 addql #4,%sp 807 /* Restore MSR */ !! 167 pea ret_from_exception 808 lwi r2, r1, PT_MSR !! 168 jmp schedule 809 mts rmsr, r2 !! 169 810 bri 4 !! 170 ENTRY(ret_from_user_signal) 811 !! 171 moveq #__NR_sigreturn,%d0 812 /* restore Special purpose registers * !! 172 trap #0 813 lwi r2, r1, PT_PID !! 173 814 mts rpid, r2 !! 174 ENTRY(ret_from_user_rt_signal) 815 !! 175 movel #__NR_rt_sigreturn,%d0 816 lwi r2, r1, PT_TLBI !! 176 trap #0 817 mts rtlbx, r2 << 818 << 819 lwi r2, r1, PT_ZPR << 820 mts rzpr, r2 << 821 << 822 #if CONFIG_XILINX_MICROBLAZE0_USE_FPU << 823 lwi r2, r1, PT_FSR << 824 mts rfsr, r2 << 825 #endif << 826 << 827 /* restore all the tlb's */ << 828 addik r3, r0, TOPHYS(tlb_skip) << 829 addik r6, r0, PT_TLBL0 << 830 addik r7, r0, PT_TLBH0 << 831 restore_tlb: << 832 add r6, r6, r1 << 833 add r7, r7, r1 << 834 lwi r2, r6, 0 << 835 mts rtlblo, r2 << 836 lwi r2, r7, 0 << 837 mts rtlbhi, r2 << 838 addik r6, r6, 4 << 839 addik r7, r7, 4 << 840 bgtid r3, restore_tlb << 841 addik r3, r3, -1 << 842 << 843 lwi r5, r0, TOPHYS(xmb_manager_dev << 844 lwi r8, r0, TOPHYS(xmb_manager_res << 845 set_vms << 846 /* return from reset need -8 to adjust << 847 addik r15, r0, ret_from_reset - 8 << 848 rtbd r8, 0 << 849 nop << 850 << 851 ret_from_reset: << 852 set_bip /* Ints masked for state resto << 853 VM_OFF << 854 /* MS: Restore all regs */ << 855 RESTORE_REGS << 856 lwi r14, r1, PT_R14 << 857 lwi r16, r1, PT_PC << 858 addik r1, r1, PT_SIZE + 36 << 859 rtbd r16, 0 << 860 nop << 861 << 862 /* << 863 * Break handler for MB Manager. Enter to _xmb << 864 * injecting fault in one of the TMR Microblaz << 865 * FIXME: This break handler supports getting << 866 * called from kernel space only. << 867 */ << 868 C_ENTRY(_xmb_manager_break): << 869 /* << 870 * Reserve memory in the stack for con << 871 * (which includes memory for storing << 872 */ << 873 addik r1, r1, -PT_SIZE - 36 << 874 swi r1, r0, xmb_manager_stackpoint << 875 SAVE_REGS << 876 swi r14, r1, PT_R14 /* rewrite sav << 877 swi r16, r1, PT_PC; /* PC and r16 << 878 << 879 lwi r6, r0, TOPHYS(xmb_manager_bas << 880 lwi r7, r0, TOPHYS(xmb_manager_crv << 881 /* << 882 * When the break vector gets asserted << 883 * the break signal must be blocked be << 884 * break handler, below code configure << 885 * control register to block break sig << 886 */ << 887 swi r7, r6, 0 << 888 << 889 /* Save the special purpose registers << 890 mfs r2, rpid << 891 swi r2, r1, PT_PID << 892 << 893 mfs r2, rtlbx << 894 swi r2, r1, PT_TLBI << 895 << 896 mfs r2, rzpr << 897 swi r2, r1, PT_ZPR << 898 177 899 #if CONFIG_XILINX_MICROBLAZE0_USE_FPU !! 178 #else 900 mfs r2, rfsr << 901 swi r2, r1, PT_FSR << 902 #endif << 903 mfs r2, rmsr << 904 swi r2, r1, PT_MSR << 905 179 906 /* Save all the tlb's */ !! 180 do_trace_entry: 907 addik r3, r0, TOPHYS(tlb_skip) !! 181 movel #-ENOSYS,%sp@(PT_OFF_D0)| needed for strace 908 addik r6, r0, PT_TLBL0 !! 182 subql #4,%sp 909 addik r7, r0, PT_TLBH0 !! 183 SAVE_SWITCH_STACK 910 save_tlb: !! 184 jbsr syscall_trace_enter 911 add r6, r6, r1 !! 185 RESTORE_SWITCH_STACK 912 add r7, r7, r1 !! 186 addql #4,%sp 913 mfs r2, rtlblo !! 187 addql #1,%d0 | optimization for cmpil #-1,%d0 914 swi r2, r6, 0 !! 188 jeq ret_from_syscall 915 mfs r2, rtlbhi !! 189 movel %sp@(PT_OFF_ORIG_D0),%d0 916 swi r2, r7, 0 !! 190 cmpl #NR_syscalls,%d0 917 addik r6, r6, 4 !! 191 jcs syscall 918 addik r7, r7, 4 !! 192 jra ret_from_syscall 919 bgtid r3, save_tlb !! 193 badsys: 920 addik r3, r3, -1 !! 194 movel #-ENOSYS,%sp@(PT_OFF_D0) 921 !! 195 jra ret_from_syscall 922 lwi r5, r0, TOPHYS(xmb_manager_dev !! 196 923 lwi r8, r0, TOPHYS(xmb_manager_cal !! 197 do_trace_exit: 924 /* return from break need -8 to adjust !! 198 subql #4,%sp 925 addik r15, r0, ret_from_break - 8 !! 199 SAVE_SWITCH_STACK 926 rtbd r8, 0 !! 200 jbsr syscall_trace_leave 927 nop !! 201 RESTORE_SWITCH_STACK 928 !! 202 addql #4,%sp 929 ret_from_break: !! 203 jra .Lret_from_exception 930 /* flush the d-cache */ !! 204 931 bralid r15, mb_flush_dcache !! 205 ENTRY(system_call) 932 nop !! 206 SAVE_ALL_SYS >> 207 >> 208 GET_CURRENT(%d1) >> 209 movel %d1,%a1 >> 210 >> 211 | save top of frame >> 212 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) >> 213 >> 214 | syscall trace? >> 215 tstb %a1@(TINFO_FLAGS+2) >> 216 jmi do_trace_entry >> 217 cmpl #NR_syscalls,%d0 >> 218 jcc badsys >> 219 syscall: >> 220 jbsr @(sys_call_table,%d0:l:4)@(0) >> 221 movel %d0,%sp@(PT_OFF_D0) | save the return value >> 222 ret_from_syscall: >> 223 |oriw #0x0700,%sr >> 224 movel %curptr@(TASK_STACK),%a1 >> 225 movew %a1@(TINFO_FLAGS+2),%d0 >> 226 jne syscall_exit_work >> 227 1: RESTORE_ALL >> 228 >> 229 syscall_exit_work: >> 230 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel >> 231 bnes 1b | if so, skip resched, signals >> 232 lslw #1,%d0 >> 233 jcs do_trace_exit >> 234 jmi do_delayed_trace >> 235 lslw #8,%d0 >> 236 jne do_signal_return >> 237 pea resume_userspace >> 238 jra schedule >> 239 >> 240 >> 241 ENTRY(ret_from_exception) >> 242 .Lret_from_exception: >> 243 btst #5,%sp@(PT_OFF_SR) | check if returning to kernel >> 244 bnes 1f | if so, skip resched, signals >> 245 | only allow interrupts when we are really the last one on the >> 246 | kernel stack, otherwise stack overflow can occur during >> 247 | heavy interrupt load >> 248 andw #ALLOWINT,%sr >> 249 >> 250 resume_userspace: >> 251 movel %curptr@(TASK_STACK),%a1 >> 252 moveb %a1@(TINFO_FLAGS+3),%d0 >> 253 jne exit_work >> 254 1: RESTORE_ALL >> 255 >> 256 exit_work: >> 257 | save top of frame >> 258 movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) >> 259 lslb #1,%d0 >> 260 jne do_signal_return >> 261 pea resume_userspace >> 262 jra schedule >> 263 >> 264 >> 265 do_signal_return: >> 266 |andw #ALLOWINT,%sr >> 267 subql #4,%sp | dummy return address >> 268 SAVE_SWITCH_STACK >> 269 pea %sp@(SWITCH_STACK_SIZE) >> 270 bsrl do_notify_resume >> 271 addql #4,%sp >> 272 RESTORE_SWITCH_STACK >> 273 addql #4,%sp >> 274 jbra resume_userspace >> 275 >> 276 do_delayed_trace: >> 277 bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR >> 278 pea 1 | send SIGTRAP >> 279 movel %curptr,%sp@- >> 280 pea LSIGTRAP >> 281 jbsr send_sig >> 282 addql #8,%sp >> 283 addql #4,%sp >> 284 jbra resume_userspace >> 285 >> 286 >> 287 /* This is the main interrupt handler for autovector interrupts */ >> 288 >> 289 ENTRY(auto_inthandler) >> 290 SAVE_ALL_INT >> 291 GET_CURRENT(%d0) >> 292 | put exception # in d0 >> 293 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 >> 294 subw #VEC_SPUR,%d0 >> 295 >> 296 movel %sp,%sp@- >> 297 movel %d0,%sp@- | put vector # on stack >> 298 auto_irqhandler_fixup = . + 2 >> 299 jsr do_IRQ | process the IRQ >> 300 addql #8,%sp | pop parameters off stack >> 301 jra ret_from_exception >> 302 >> 303 /* Handler for user defined interrupt vectors */ >> 304 >> 305 ENTRY(user_inthandler) >> 306 SAVE_ALL_INT >> 307 GET_CURRENT(%d0) >> 308 | put exception # in d0 >> 309 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 >> 310 user_irqvec_fixup = . + 2 >> 311 subw #VEC_USER,%d0 >> 312 >> 313 movel %sp,%sp@- >> 314 movel %d0,%sp@- | put vector # on stack >> 315 jsr do_IRQ | process the IRQ >> 316 addql #8,%sp | pop parameters off stack >> 317 jra ret_from_exception >> 318 >> 319 /* Handler for uninitialized and spurious interrupts */ >> 320 >> 321 ENTRY(bad_inthandler) >> 322 SAVE_ALL_INT >> 323 GET_CURRENT(%d0) >> 324 >> 325 movel %sp,%sp@- >> 326 jsr handle_badint >> 327 addql #4,%sp >> 328 jra ret_from_exception 933 329 >> 330 resume: 934 /* 331 /* 935 * To make sure microblaze i-cache is !! 332 * Beware - when entering resume, prev (the current task) is 936 * invalidate the i-cache. !! 333 * in a0, next (the new task) is in a1,so don't change these >> 334 * registers until their contents are no longer needed. 937 */ 335 */ 938 bralid r15, mb_invalidate_icache << 939 nop << 940 336 941 set_bip; /* Ints masked for state rest !! 337 /* save sr */ 942 VM_OFF; !! 338 movew %sr,%a0@(TASK_THREAD+THREAD_SR) 943 mbar 1 << 944 mbar 2 << 945 bri 4 << 946 suspend << 947 nop << 948 #endif << 949 339 950 /* !! 340 /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ 951 * Debug trap for KGDB. Enter to _debug_except !! 341 movec %sfc,%d0 952 * and call handling function with saved pt_re !! 342 movew %d0,%a0@(TASK_THREAD+THREAD_FC) 953 */ !! 343 954 C_ENTRY(_debug_exception): !! 344 /* save usp */ 955 /* BIP bit is set on entry, no interru !! 345 /* it is better to use a movel here instead of a movew 8*) */ 956 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S !! 346 movec %usp,%d0 957 !! 347 movel %d0,%a0@(TASK_THREAD+THREAD_USP) 958 mfs r1, rmsr !! 348 959 nop !! 349 /* save non-scratch registers on stack */ 960 andi r1, r1, MSR_UMS !! 350 SAVE_SWITCH_STACK 961 bnei r1, 1f !! 351 962 /* MS: Kernel-mode state save - kgdb */ !! 352 /* save current kernel stack pointer */ 963 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_S !! 353 movel %sp,%a0@(TASK_THREAD+THREAD_KSP) 964 !! 354 965 /* BIP bit is set on entry, no interru !! 355 /* save floating point context */ 966 addik r1, r1, CONFIG_KERNEL_BASE_ADD !! 356 #ifndef CONFIG_M68KFPU_EMU_ONLY 967 SAVE_REGS; !! 357 #ifdef CONFIG_M68KFPU_EMU 968 /* save all regs to pt_reg structure * !! 358 tstl m68k_fputype 969 swi r0, r1, PT_R0; /* R0 must be !! 359 jeq 3f 970 swi r14, r1, PT_R14 /* rewrite sav !! 360 #endif 971 swi r16, r1, PT_PC; /* PC and r16 !! 361 fsave %a0@(TASK_THREAD+THREAD_FPSTATE) 972 /* save special purpose registers to p !! 362 973 mfs r11, rear; !! 363 #if defined(CONFIG_M68060) 974 swi r11, r1, PT_EAR; !! 364 #if !defined(CPU_M68060_ONLY) 975 mfs r11, resr; !! 365 btst #3,m68k_cputype+3 976 swi r11, r1, PT_ESR; !! 366 beqs 1f 977 mfs r11, rfsr; !! 367 #endif 978 swi r11, r1, PT_FSR; !! 368 /* The 060 FPU keeps status in bits 15-8 of the first longword */ 979 !! 369 tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2) 980 /* stack pointer is in physical addres !! 370 jeq 3f 981 * by PT_SIZE but we need to get corre !! 371 #if !defined(CPU_M68060_ONLY) 982 addik r11, r1, CONFIG_KERNEL_START - !! 372 jra 2f 983 swi r11, r1, PT_R1 !! 373 #endif 984 /* MS: r31 - current pointer isn't cha !! 374 #endif /* CONFIG_M68060 */ 985 tovirt(r1,r1) !! 375 #if !defined(CPU_M68060_ONLY) 986 #ifdef CONFIG_KGDB !! 376 1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE) 987 addi r5, r1, 0 /* pass pt_reg addre !! 377 jeq 3f 988 addik r15, r0, dbtrap_call; /* retur << 989 rtbd r0, microblaze_kgdb_break << 990 nop; << 991 #endif << 992 /* MS: Place handler for brki from ker << 993 * It is very unlikely that another br << 994 bri 0 << 995 << 996 /* MS: User-mode state save - gdb */ << 997 1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT << 998 tophys(r1,r1); << 999 lwi r1, r1, TS_THREAD_INFO; /* get << 1000 addik r1, r1, THREAD_SIZE; /* ca << 1001 tophys(r1,r1); << 1002 << 1003 addik r1, r1, -PT_SIZE; /* Make roo << 1004 SAVE_REGS; << 1005 swi r16, r1, PT_PC; /* Save LP */ << 1006 swi r0, r1, PT_MODE; /* Was in us << 1007 lwi r11, r0, TOPHYS(PER_CPU(ENTRY << 1008 swi r11, r1, PT_R1; /* Store user << 1009 lwi CURRENT_TASK, r0, TOPHYS(PER_ << 1010 tovirt(r1,r1) << 1011 set_vms; << 1012 addik r5, r1, 0; << 1013 addik r15, r0, dbtrap_call; << 1014 dbtrap_call: /* Return point for kernel/user << 1015 rtbd r0, sw_exception << 1016 nop << 1017 << 1018 /* MS: The first instruction for the << 1019 set_bip; /* Ints masked for state res << 1020 lwi r11, r1, PT_MODE; << 1021 bnei r11, 2f; << 1022 /* MS: Return to user space - gdb */ << 1023 1: << 1024 /* Get current task ptr into r11 */ << 1025 lwi r11, CURRENT_TASK, TS_THREAD_ << 1026 lwi r19, r11, TI_FLAGS; /* ge << 1027 andi r11, r19, _TIF_NEED_RESCHED; << 1028 beqi r11, 5f; << 1029 << 1030 /* Call the scheduler before returnin << 1031 bralid r15, schedule; /* Call sched << 1032 nop; /* de << 1033 bri 1b << 1034 << 1035 /* Maybe handle a signal */ << 1036 5: andi r11, r19, _TIF_SIGPENDING | _ << 1037 beqi r11, 4f; /* Si << 1038 << 1039 addik r5, r1, 0; /* Ar << 1040 bralid r15, do_notify_resume; /* Ha << 1041 addi r6, r0, 0; /* Arg 2: int << 1042 bri 1b << 1043 << 1044 /* Finally, return to user state. */ << 1045 4: swi CURRENT_TASK, r0, PER_CPU(CUR << 1046 VM_OFF; << 1047 tophys(r1,r1); << 1048 /* MS: Restore all regs */ << 1049 RESTORE_REGS_RTBD << 1050 addik r1, r1, PT_SIZE /* Clean up << 1051 lwi r1, r1, PT_R1 - PT_SIZE; /* R << 1052 DBTRAP_return_user: /* MS: Make global symbol << 1053 rtbd r16, 0; /* MS: Instructions t << 1054 nop; << 1055 << 1056 /* MS: Return to kernel state - kgdb */ << 1057 2: VM_OFF; << 1058 tophys(r1,r1); << 1059 /* MS: Restore all regs */ << 1060 RESTORE_REGS_RTBD << 1061 lwi r14, r1, PT_R14; << 1062 lwi r16, r1, PT_PC; << 1063 addik r1, r1, PT_SIZE; /* MS: Clean << 1064 tovirt(r1,r1); << 1065 DBTRAP_return_kernel: /* MS: Make global symb << 1066 rtbd r16, 0; /* MS: Instructions t << 1067 nop; << 1068 << 1069 << 1070 ENTRY(_switch_to) << 1071 /* prepare return value */ << 1072 addk r3, r0, CURRENT_TASK << 1073 << 1074 /* save registers in cpu_context */ << 1075 /* use r11 and r12, volatile register << 1076 /* give start of cpu_context for prev << 1077 addik r11, r5, TI_CPU_CONTEXT << 1078 swi r1, r11, CC_R1 << 1079 swi r2, r11, CC_R2 << 1080 /* skip volatile registers. << 1081 * they are saved on stack when we ju << 1082 /* dedicated registers */ << 1083 swi r13, r11, CC_R13 << 1084 swi r14, r11, CC_R14 << 1085 swi r15, r11, CC_R15 << 1086 swi r16, r11, CC_R16 << 1087 swi r17, r11, CC_R17 << 1088 swi r18, r11, CC_R18 << 1089 /* save non-volatile registers */ << 1090 swi r19, r11, CC_R19 << 1091 swi r20, r11, CC_R20 << 1092 swi r21, r11, CC_R21 << 1093 swi r22, r11, CC_R22 << 1094 swi r23, r11, CC_R23 << 1095 swi r24, r11, CC_R24 << 1096 swi r25, r11, CC_R25 << 1097 swi r26, r11, CC_R26 << 1098 swi r27, r11, CC_R27 << 1099 swi r28, r11, CC_R28 << 1100 swi r29, r11, CC_R29 << 1101 swi r30, r11, CC_R30 << 1102 /* special purpose registers */ << 1103 mfs r12, rmsr << 1104 swi r12, r11, CC_MSR << 1105 mfs r12, rear << 1106 swi r12, r11, CC_EAR << 1107 mfs r12, resr << 1108 swi r12, r11, CC_ESR << 1109 mfs r12, rfsr << 1110 swi r12, r11, CC_FSR << 1111 << 1112 /* update r31, the current-give me po << 1113 lwi CURRENT_TASK, r6, TI_TASK << 1114 /* stored it to current_save too */ << 1115 swi CURRENT_TASK, r0, PER_CPU(CUR << 1116 << 1117 /* get new process' cpu context and r << 1118 /* give me start where start context << 1119 addik r11, r6, TI_CPU_CONTEXT << 1120 << 1121 /* non-volatile registers */ << 1122 lwi r30, r11, CC_R30 << 1123 lwi r29, r11, CC_R29 << 1124 lwi r28, r11, CC_R28 << 1125 lwi r27, r11, CC_R27 << 1126 lwi r26, r11, CC_R26 << 1127 lwi r25, r11, CC_R25 << 1128 lwi r24, r11, CC_R24 << 1129 lwi r23, r11, CC_R23 << 1130 lwi r22, r11, CC_R22 << 1131 lwi r21, r11, CC_R21 << 1132 lwi r20, r11, CC_R20 << 1133 lwi r19, r11, CC_R19 << 1134 /* dedicated registers */ << 1135 lwi r18, r11, CC_R18 << 1136 lwi r17, r11, CC_R17 << 1137 lwi r16, r11, CC_R16 << 1138 lwi r15, r11, CC_R15 << 1139 lwi r14, r11, CC_R14 << 1140 lwi r13, r11, CC_R13 << 1141 /* skip volatile registers */ << 1142 lwi r2, r11, CC_R2 << 1143 lwi r1, r11, CC_R1 << 1144 << 1145 /* special purpose registers */ << 1146 lwi r12, r11, CC_FSR << 1147 mts rfsr, r12 << 1148 lwi r12, r11, CC_MSR << 1149 mts rmsr, r12 << 1150 << 1151 rtsd r15, 8 << 1152 nop << 1153 << 1154 #ifdef CONFIG_MB_MANAGER << 1155 .global xmb_inject_err << 1156 .section .text << 1157 .align 2 << 1158 .ent xmb_inject_err << 1159 .type xmb_inject_err, @function << 1160 xmb_inject_err: << 1161 addik r1, r1, -PT_SIZE << 1162 SAVE_REGS << 1163 << 1164 /* Switch to real mode */ << 1165 VM_OFF; << 1166 set_bip; << 1167 mbar 1 << 1168 mbar 2 << 1169 bralid r15, XMB_INJECT_ERR_OFFSET << 1170 nop; << 1171 << 1172 /* enable virtual mode */ << 1173 set_vms; << 1174 /* barrier for instructions and data << 1175 mbar 1 << 1176 mbar 2 << 1177 /* << 1178 * Enable Interrupts, Virtual Protect << 1179 * initial state for all possible ent << 1180 */ << 1181 rtbd r0, 1f << 1182 nop; << 1183 1: << 1184 RESTORE_REGS << 1185 addik r1, r1, PT_SIZE << 1186 rtsd r15, 8; << 1187 nop; << 1188 .end xmb_inject_err << 1189 << 1190 .section .data << 1191 .global xmb_manager_dev << 1192 .global xmb_manager_baseaddr << 1193 .global xmb_manager_crval << 1194 .global xmb_manager_callback << 1195 .global xmb_manager_reset_callback << 1196 .global xmb_manager_stackpointer << 1197 .align 4 << 1198 xmb_manager_dev: << 1199 .long 0 << 1200 xmb_manager_baseaddr: << 1201 .long 0 << 1202 xmb_manager_crval: << 1203 .long 0 << 1204 xmb_manager_callback: << 1205 .long 0 << 1206 xmb_manager_reset_callback: << 1207 .long 0 << 1208 xmb_manager_stackpointer: << 1209 .long 0 << 1210 << 1211 /* << 1212 * When the break vector gets asserted becaus << 1213 * the break signal must be blocked before ex << 1214 * break handler, Below api updates the manag << 1215 * control register and error count callback << 1216 * which will be used by the break handler to << 1217 * break and call the callback function. << 1218 */ << 1219 .global xmb_manager_register << 1220 .section .text << 1221 .align 2 << 1222 .ent xmb_manager_register << 1223 .type xmb_manager_register, @function << 1224 xmb_manager_register: << 1225 swi r5, r0, xmb_manager_baseaddr << 1226 swi r6, r0, xmb_manager_crval << 1227 swi r7, r0, xmb_manager_callback << 1228 swi r8, r0, xmb_manager_dev << 1229 swi r9, r0, xmb_manager_reset_cal << 1230 << 1231 rtsd r15, 8; << 1232 nop; << 1233 .end xmb_manager_register << 1234 #endif 378 #endif >> 379 2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG) >> 380 fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL) >> 381 3: >> 382 #endif /* CONFIG_M68KFPU_EMU_ONLY */ >> 383 /* Return previous task in %d1 */ >> 384 movel %curptr,%d1 >> 385 >> 386 /* switch to new task (a1 contains new task) */ >> 387 movel %a1,%curptr >> 388 >> 389 /* restore floating point context */ >> 390 #ifndef CONFIG_M68KFPU_EMU_ONLY >> 391 #ifdef CONFIG_M68KFPU_EMU >> 392 tstl m68k_fputype >> 393 jeq 4f >> 394 #endif >> 395 #if defined(CONFIG_M68060) >> 396 #if !defined(CPU_M68060_ONLY) >> 397 btst #3,m68k_cputype+3 >> 398 beqs 1f >> 399 #endif >> 400 /* The 060 FPU keeps status in bits 15-8 of the first longword */ >> 401 tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2) >> 402 jeq 3f >> 403 #if !defined(CPU_M68060_ONLY) >> 404 jra 2f >> 405 #endif >> 406 #endif /* CONFIG_M68060 */ >> 407 #if !defined(CPU_M68060_ONLY) >> 408 1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE) >> 409 jeq 3f >> 410 #endif >> 411 2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7 >> 412 fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar >> 413 3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE) >> 414 4: >> 415 #endif /* CONFIG_M68KFPU_EMU_ONLY */ 1235 416 1236 ENTRY(_reset) !! 417 /* restore the kernel stack pointer */ 1237 VM_OFF !! 418 movel %a1@(TASK_THREAD+THREAD_KSP),%sp 1238 brai 0; /* Jump to reset vector */ << 1239 << 1240 /* These are compiled and loaded into << 1241 * copied into place in mach_early_se << 1242 .section .init.ivt, "ax" << 1243 #if CONFIG_MANUAL_RESET_VECTOR && !defined(CO << 1244 .org 0x0 << 1245 brai CONFIG_MANUAL_RESET_VECTOR << 1246 #elif defined(CONFIG_MB_MANAGER) << 1247 .org 0x0 << 1248 brai TOPHYS(_xtmr_manager_reset); << 1249 #endif << 1250 .org 0x8 << 1251 brai TOPHYS(_user_exception); /* s << 1252 .org 0x10 << 1253 brai TOPHYS(_interrupt); /* In << 1254 #ifdef CONFIG_MB_MANAGER << 1255 .org 0x18 << 1256 brai TOPHYS(_xmb_manager_break); << 1257 #else << 1258 .org 0x18 << 1259 brai TOPHYS(_debug_exception); << 1260 #endif << 1261 .org 0x20 << 1262 brai TOPHYS(_hw_exception_handler) << 1263 419 1264 #ifdef CONFIG_MB_MANAGER !! 420 /* restore non-scratch registers */ 1265 /* !! 421 RESTORE_SWITCH_STACK 1266 * For TMR Inject API which injects t << 1267 * be executed from LMB. << 1268 * TMR Inject is programmed with addr << 1269 * when program counter matches with << 1270 * be injected. 0x200 is expected to << 1271 * offset, hence used for this api. << 1272 */ << 1273 .org XMB_INJECT_ERR_OFFSET << 1274 xmb_inject_error: << 1275 nop << 1276 rtsd r15, 8 << 1277 nop << 1278 #endif << 1279 422 1280 .section .rodata,"a" !! 423 /* restore user stack pointer */ 1281 #include "syscall_table.S" !! 424 movel %a1@(TASK_THREAD+THREAD_USP),%a0 >> 425 movel %a0,%usp 1282 426 1283 syscall_table_size=(.-sys_call_table) !! 427 /* restore fs (sfc,%dfc) */ >> 428 movew %a1@(TASK_THREAD+THREAD_FC),%a0 >> 429 movec %a0,%sfc >> 430 movec %a0,%dfc 1284 431 1285 type_SYSCALL: !! 432 /* restore status register */ 1286 .ascii "SYSCALL\0" !! 433 movew %a1@(TASK_THREAD+THREAD_SR),%d0 1287 type_IRQ: !! 434 oriw #0x0700,%d0 1288 .ascii "IRQ\0" !! 435 movew %d0,%sr 1289 type_IRQ_PREEMPT: << 1290 .ascii "IRQ (PREEMPTED)\0" << 1291 type_SYSCALL_PREEMPT: << 1292 .ascii " SYSCALL (PREEMPTED)\0" << 1293 436 1294 /* !! 437 rts 1295 * Trap decoding for stack unwinder << 1296 * Tuples are (start addr, end addr, << 1297 * If return address lies on [start a << 1298 * unwinder displays 'string' << 1299 */ << 1300 438 1301 .align 4 !! 439 #endif /* CONFIG_MMU && !CONFIG_COLDFIRE */ 1302 .global microblaze_trap_handlers << 1303 microblaze_trap_handlers: << 1304 /* Exact matches come first */ << 1305 .word ret_from_trap; .word ret_from_t << 1306 .word ret_from_irq ; .word ret_from_i << 1307 /* Fuzzy matches go here */ << 1308 .word ret_from_irq ; .word no_intr_re << 1309 .word ret_from_trap; .word TRAP_retur << 1310 /* End of table */ << 1311 .word 0 ; .word 0 <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.