entry.h (9b8c7d1e7107c30a50aae27c1f33fe706c8c6c67) | entry.h (6d1a20b1d237db29878ae54142e39c87a36d0e95) |
---|---|
1/* | 1/* |
2 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) |
|
2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 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 version 2 as 6 * published by the Free Software Foundation. | 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. |
7 * 8 * Vineetg: March 2009 (Supporting 2 levels of Interrupts) 9 * Stack switching code can no longer reliably rely on the fact that 10 * if we are NOT in user mode, stack is switched to kernel mode. 11 * e.g. L2 IRQ interrupted a L1 ISR which had not yet completed 12 * it's prologue including stack switching from user mode 13 * 14 * Vineetg: Aug 28th 2008: Bug #94984 15 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap 16 * Normally CPU does this automatically, however when doing FAKE rtie, 17 * we also need to explicitly do this. The problem in macros 18 * FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit 19 * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context 20 * 21 * Vineetg: May 5th 2008 22 * -Modified CALLEE_REG save/restore macros to handle the fact that 23 * r25 contains the kernel current task ptr 24 * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs 25 * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the 26 * address Write back load ld.ab instead of seperate ld/add instn 27 * 28 * Amit Bhor, Sameer Dhavale: Codito Technologies 2004 | |
29 */ 30 31#ifndef __ASM_ARC_ENTRY_H 32#define __ASM_ARC_ENTRY_H 33 | 8 */ 9 10#ifndef __ASM_ARC_ENTRY_H 11#define __ASM_ARC_ENTRY_H 12 |
34#ifdef __ASSEMBLY__ | |
35#include <asm/unistd.h> /* For NR_syscalls defination */ | 13#include <asm/unistd.h> /* For NR_syscalls defination */ |
36#include <asm/asm-offsets.h> | |
37#include <asm/arcregs.h> 38#include <asm/ptrace.h> 39#include <asm/processor.h> /* For VMALLOC_START */ | 14#include <asm/arcregs.h> 15#include <asm/ptrace.h> 16#include <asm/processor.h> /* For VMALLOC_START */ |
40#include <asm/thread_info.h> /* For THREAD_SIZE */ | |
41#include <asm/mmu.h> 42 | 17#include <asm/mmu.h> 18 |
19#include <asm/entry-compact.h> /* ISA specific bits */ 20 |
|
43/* Note on the LD/ST addr modes with addr reg wback 44 * 45 * LD.a same as LD.aw 46 * 47 * LD.a reg1, [reg2, x] => Pre Incr 48 * Eff Addr for load = [reg2 + x] 49 * 50 * LD.ab reg1, [reg2, x] => Post Incr --- 184 unchanged lines hidden (view full) --- 235 /* Get task->thread_info (this is essentially start of a PAGE) */ 236 ld \out, [\tsk, TASK_THREAD_INFO] 237 238 /* Go to end of page where stack begins (grows upwards) */ 239 add2 \out, \out, (THREAD_SIZE)/4 240 241.endm 242 | 21/* Note on the LD/ST addr modes with addr reg wback 22 * 23 * LD.a same as LD.aw 24 * 25 * LD.a reg1, [reg2, x] => Pre Incr 26 * Eff Addr for load = [reg2 + x] 27 * 28 * LD.ab reg1, [reg2, x] => Post Incr --- 184 unchanged lines hidden (view full) --- 213 /* Get task->thread_info (this is essentially start of a PAGE) */ 214 ld \out, [\tsk, TASK_THREAD_INFO] 215 216 /* Go to end of page where stack begins (grows upwards) */ 217 add2 \out, \out, (THREAD_SIZE)/4 218 219.endm 220 |
243/*-------------------------------------------------------------- 244 * Switch to Kernel Mode stack if SP points to User Mode stack 245 * 246 * Entry : r9 contains pre-IRQ/exception/trap status32 247 * Exit : SP is set to kernel mode stack pointer 248 * If CURR_IN_REG, r25 set to "current" task pointer 249 * Clobbers: r9 250 *-------------------------------------------------------------*/ 251 252.macro SWITCH_TO_KERNEL_STK 253 254 /* User Mode when this happened ? Yes: Proceed to switch stack */ 255 bbit1 r9, STATUS_U_BIT, 88f 256 257 /* OK we were already in kernel mode when this event happened, thus can 258 * assume SP is kernel mode SP. _NO_ need to do any stack switching 259 */ 260 261#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS 262 /* However.... 263 * If Level 2 Interrupts enabled, we may end up with a corner case: 264 * 1. User Task executing 265 * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode) 266 * 3. But before it could switch SP from USER to KERNEL stack 267 * a L2 IRQ "Interrupts" L1 268 * Thay way although L2 IRQ happened in Kernel mode, stack is still 269 * not switched. 270 * To handle this, we may need to switch stack even if in kernel mode 271 * provided SP has values in range of USER mode stack ( < 0x7000_0000 ) 272 */ 273 brlo sp, VMALLOC_START, 88f 274 275 /* TODO: vineetg: 276 * We need to be a bit more cautious here. What if a kernel bug in 277 * L1 ISR, caused SP to go whaco (some small value which looks like 278 * USER stk) and then we take L2 ISR. 279 * Above brlo alone would treat it as a valid L1-L2 sceanrio 280 * instead of shouting alound 281 * The only feasible way is to make sure this L2 happened in 282 * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in 283 * L1 ISR before it switches stack 284 */ 285 286#endif 287 288 /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack 289 * safe-keeping not really needed, but it keeps the epilogue code 290 * (SP restore) simpler/uniform. 291 */ 292 b.d 66f 293 mov r9, sp 294 29588: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */ 296 297 GET_CURR_TASK_ON_CPU r9 298 299 /* With current tsk in r9, get it's kernel mode stack base */ 300 GET_TSK_STACK_BASE r9, r9 301 30266: 303#ifdef CONFIG_ARC_CURR_IN_REG 304 /* 305 * Treat r25 as scratch reg, save it on stack first 306 * Load it with current task pointer 307 */ 308 st r25, [r9, -4] 309 GET_CURR_TASK_ON_CPU r25 310#endif 311 312 /* Save Pre Intr/Exception User SP on kernel stack */ 313 st.a sp, [r9, -16] ; Make room for orig_r0, ECR, user_r25 314 315 /* CAUTION: 316 * SP should be set at the very end when we are done with everything 317 * In case of 2 levels of interrupt we depend on value of SP to assume 318 * that everything else is done (loading r25 etc) 319 */ 320 321 /* set SP to point to kernel mode stack */ 322 mov sp, r9 323 324 /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */ 325 326.endm 327 328/*------------------------------------------------------------ 329 * "FAKE" a rtie to return from CPU Exception context 330 * This is to re-enable Exceptions within exception 331 * Look at EV_ProtV to see how this is actually used 332 *-------------------------------------------------------------*/ 333 334.macro FAKE_RET_FROM_EXCPN 335 336 ld r9, [sp, PT_status32] 337 bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK) 338 bset r9, r9, STATUS_L_BIT 339 sr r9, [erstatus] 340 mov r9, 55f 341 sr r9, [eret] 342 343 rtie 34455: 345.endm 346 | |
347/* | 221/* |
348 * @reg [OUT] &thread_info of "current" 349 */ 350.macro GET_CURR_THR_INFO_FROM_SP reg 351 bic \reg, sp, (THREAD_SIZE - 1) 352.endm 353 354/* | |
355 * @reg [OUT] thread_info->flags of "current" 356 */ 357.macro GET_CURR_THR_INFO_FLAGS reg 358 GET_CURR_THR_INFO_FROM_SP \reg 359 ld \reg, [\reg, THREAD_INFO_FLAGS] 360.endm 361 | 222 * @reg [OUT] thread_info->flags of "current" 223 */ 224.macro GET_CURR_THR_INFO_FLAGS reg 225 GET_CURR_THR_INFO_FROM_SP \reg 226 ld \reg, [\reg, THREAD_INFO_FLAGS] 227.endm 228 |
362/*-------------------------------------------------------------- 363 * For early Exception/ISR Prologue, a core reg is temporarily needed to 364 * code the rest of prolog (stack switching). This is done by stashing 365 * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP). 366 * 367 * Before saving the full regfile - this reg is restored back, only 368 * to be saved again on kernel mode stack, as part of pt_regs. 369 *-------------------------------------------------------------*/ 370.macro PROLOG_FREEUP_REG reg, mem | |
371#ifdef CONFIG_SMP | 229#ifdef CONFIG_SMP |
372 sr \reg, [ARC_REG_SCRATCH_DATA0] 373#else 374 st \reg, [\mem] 375#endif 376.endm | |
377 | 230 |
378.macro PROLOG_RESTORE_REG reg, mem 379#ifdef CONFIG_SMP 380 lr \reg, [ARC_REG_SCRATCH_DATA0] 381#else 382 ld \reg, [\mem] 383#endif 384.endm 385 386/*-------------------------------------------------------------- 387 * Exception Entry prologue 388 * -Switches stack to K mode (if not already) 389 * -Saves the register file 390 * 391 * After this it is safe to call the "C" handlers 392 *-------------------------------------------------------------*/ 393.macro EXCEPTION_PROLOGUE 394 395 /* Need at least 1 reg to code the early exception prologue */ 396 PROLOG_FREEUP_REG r9, @ex_saved_reg1 397 398 /* U/K mode at time of exception (stack not switched if already K) */ 399 lr r9, [erstatus] 400 401 /* ARC700 doesn't provide auto-stack switching */ 402 SWITCH_TO_KERNEL_STK 403 404 lr r9, [ecr] 405 st r9, [sp, 8] /* ECR */ 406 st r0, [sp, 4] /* orig_r0, needed only for sys calls */ 407 408 /* Restore r9 used to code the early prologue */ 409 PROLOG_RESTORE_REG r9, @ex_saved_reg1 410 411 SAVE_R0_TO_R12 412 PUSH gp 413 PUSH fp 414 PUSH blink 415 PUSHAX eret 416 PUSHAX erstatus 417 PUSH lp_count 418 PUSHAX lp_end 419 PUSHAX lp_start 420 PUSHAX erbta 421.endm 422 423/*-------------------------------------------------------------- 424 * Restore all registers used by system call or Exceptions 425 * SP should always be pointing to the next free stack element 426 * when entering this macro. 427 * 428 * NOTE: 429 * 430 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg 431 * for memory load operations. If used in that way interrupts are deffered 432 * by hardware and that is not good. 433 *-------------------------------------------------------------*/ 434.macro EXCEPTION_EPILOGUE 435 POPAX erbta 436 POPAX lp_start 437 POPAX lp_end 438 439 POP r9 440 mov lp_count, r9 ;LD to lp_count is not allowed 441 442 POPAX erstatus 443 POPAX eret 444 POP blink 445 POP fp 446 POP gp 447 RESTORE_R12_TO_R0 448 449 ld sp, [sp] /* restore original sp */ 450 /* orig_r0, ECR, user_r25 skipped automatically */ 451.endm 452 453/* Dummy ECR values for Interrupts */ 454#define event_IRQ1 0x0031abcd 455#define event_IRQ2 0x0032abcd 456 457.macro INTERRUPT_PROLOGUE LVL 458 459 /* free up r9 as scratchpad */ 460 PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg 461 462 /* Which mode (user/kernel) was the system in when intr occurred */ 463 lr r9, [status32_l\LVL\()] 464 465 SWITCH_TO_KERNEL_STK 466 467 /* restore original r9 */ 468 PROLOG_RESTORE_REG r9, @int\LVL\()_saved_reg 469 470 /* now we are ready to save the remaining context */ 471 st 0x003\LVL\()abcd, [sp, 8] /* Dummy ECR */ 472 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */ 473 474 SAVE_R0_TO_R12 475 PUSH gp 476 PUSH fp 477 PUSH blink 478 PUSH ilink\LVL\() 479 PUSHAX status32_l\LVL\() 480 PUSH lp_count 481 PUSHAX lp_end 482 PUSHAX lp_start 483 PUSHAX bta_l\LVL\() 484.endm 485 486/*-------------------------------------------------------------- 487 * Restore all registers used by interrupt handlers. 488 * 489 * NOTE: 490 * 491 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg 492 * for memory load operations. If used in that way interrupts are deffered 493 * by hardware and that is not good. 494 *-------------------------------------------------------------*/ 495.macro INTERRUPT_EPILOGUE LVL 496 POPAX bta_l\LVL\() 497 POPAX lp_start 498 POPAX lp_end 499 500 POP r9 501 mov lp_count, r9 ;LD to lp_count is not allowed 502 503 POPAX status32_l\LVL\() 504 POP ilink\LVL\() 505 POP blink 506 POP fp 507 POP gp 508 RESTORE_R12_TO_R0 509 510 ld sp, [sp] /* restore original sp */ 511 /* orig_r0, ECR, user_r25 skipped automatically */ 512.endm 513 514/* Get CPU-ID of this core */ 515.macro GET_CPU_ID reg 516 lr \reg, [identity] 517 lsr \reg, \reg, 8 518 bmsk \reg, \reg, 7 519.endm 520 521#ifdef CONFIG_SMP 522 | |
523/*------------------------------------------------- 524 * Retrieve the current running task on this CPU 525 * 1. Determine curr CPU id. 526 * 2. Use it to index into _current_task[ ] 527 */ 528.macro GET_CURR_TASK_ON_CPU reg 529 GET_CPU_ID \reg 530 ld.as \reg, [@_current_task, \reg] --- 50 unchanged lines hidden (view full) --- 581 582.macro GET_CURR_TASK_FIELD_PTR off, reg 583 GET_CURR_TASK_ON_CPU \reg 584 add \reg, \reg, \off 585.endm 586 587#endif /* CONFIG_ARC_CURR_IN_REG */ 588 | 231/*------------------------------------------------- 232 * Retrieve the current running task on this CPU 233 * 1. Determine curr CPU id. 234 * 2. Use it to index into _current_task[ ] 235 */ 236.macro GET_CURR_TASK_ON_CPU reg 237 GET_CPU_ID \reg 238 ld.as \reg, [@_current_task, \reg] --- 50 unchanged lines hidden (view full) --- 289 290.macro GET_CURR_TASK_FIELD_PTR off, reg 291 GET_CURR_TASK_ON_CPU \reg 292 add \reg, \reg, \off 293.endm 294 295#endif /* CONFIG_ARC_CURR_IN_REG */ 296 |
589#endif /* __ASSEMBLY__ */ 590 | |
591#endif /* __ASM_ARC_ENTRY_H */ | 297#endif /* __ASM_ARC_ENTRY_H */ |