entry.S 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. /*
  2. * Low-level system-call handling, trap handlers and context-switching
  3. *
  4. * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  5. * Copyright (C) 2008-2009 PetaLogix
  6. * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au>
  7. * Copyright (C) 2001,2002 NEC Corporation
  8. * Copyright (C) 2001,2002 Miles Bader <miles@gnu.org>
  9. *
  10. * This file is subject to the terms and conditions of the GNU General
  11. * Public License. See the file COPYING in the main directory of this
  12. * archive for more details.
  13. *
  14. * Written by Miles Bader <miles@gnu.org>
  15. * Heavily modified by John Williams for Microblaze
  16. */
  17. #include <linux/sys.h>
  18. #include <linux/linkage.h>
  19. #include <asm/entry.h>
  20. #include <asm/current.h>
  21. #include <asm/processor.h>
  22. #include <asm/exceptions.h>
  23. #include <asm/asm-offsets.h>
  24. #include <asm/thread_info.h>
  25. #include <asm/page.h>
  26. #include <asm/unistd.h>
  27. #include <linux/errno.h>
  28. #include <asm/signal.h>
  29. #undef DEBUG
  30. #ifdef DEBUG
  31. /* Create space for syscalls counting. */
  32. .section .data
  33. .global syscall_debug_table
  34. .align 4
  35. syscall_debug_table:
  36. .space (__NR_syscalls * 4)
  37. #endif /* DEBUG */
  38. #define C_ENTRY(name) .globl name; .align 4; name
  39. /*
  40. * Various ways of setting and clearing BIP in flags reg.
  41. * This is mucky, but necessary using microblaze version that
  42. * allows msr ops to write to BIP
  43. */
  44. #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
  45. .macro clear_bip
  46. msrclr r0, MSR_BIP
  47. .endm
  48. .macro set_bip
  49. msrset r0, MSR_BIP
  50. .endm
  51. .macro clear_eip
  52. msrclr r0, MSR_EIP
  53. .endm
  54. .macro set_ee
  55. msrset r0, MSR_EE
  56. .endm
  57. .macro disable_irq
  58. msrclr r0, MSR_IE
  59. .endm
  60. .macro enable_irq
  61. msrset r0, MSR_IE
  62. .endm
  63. .macro set_ums
  64. msrset r0, MSR_UMS
  65. msrclr r0, MSR_VMS
  66. .endm
  67. .macro set_vms
  68. msrclr r0, MSR_UMS
  69. msrset r0, MSR_VMS
  70. .endm
  71. .macro clear_ums
  72. msrclr r0, MSR_UMS
  73. .endm
  74. .macro clear_vms_ums
  75. msrclr r0, MSR_VMS | MSR_UMS
  76. .endm
  77. #else
  78. .macro clear_bip
  79. mfs r11, rmsr
  80. andi r11, r11, ~MSR_BIP
  81. mts rmsr, r11
  82. .endm
  83. .macro set_bip
  84. mfs r11, rmsr
  85. ori r11, r11, MSR_BIP
  86. mts rmsr, r11
  87. .endm
  88. .macro clear_eip
  89. mfs r11, rmsr
  90. andi r11, r11, ~MSR_EIP
  91. mts rmsr, r11
  92. .endm
  93. .macro set_ee
  94. mfs r11, rmsr
  95. ori r11, r11, MSR_EE
  96. mts rmsr, r11
  97. .endm
  98. .macro disable_irq
  99. mfs r11, rmsr
  100. andi r11, r11, ~MSR_IE
  101. mts rmsr, r11
  102. .endm
  103. .macro enable_irq
  104. mfs r11, rmsr
  105. ori r11, r11, MSR_IE
  106. mts rmsr, r11
  107. .endm
  108. .macro set_ums
  109. mfs r11, rmsr
  110. ori r11, r11, MSR_VMS
  111. andni r11, r11, MSR_UMS
  112. mts rmsr, r11
  113. .endm
  114. .macro set_vms
  115. mfs r11, rmsr
  116. ori r11, r11, MSR_VMS
  117. andni r11, r11, MSR_UMS
  118. mts rmsr, r11
  119. .endm
  120. .macro clear_ums
  121. mfs r11, rmsr
  122. andni r11, r11, MSR_UMS
  123. mts rmsr,r11
  124. .endm
  125. .macro clear_vms_ums
  126. mfs r11, rmsr
  127. andni r11, r11, (MSR_VMS|MSR_UMS)
  128. mts rmsr,r11
  129. .endm
  130. #endif
  131. /* Define how to call high-level functions. With MMU, virtual mode must be
  132. * enabled when calling the high-level function. Clobbers R11.
  133. * VM_ON, VM_OFF, DO_JUMP_BIPCLR, DO_CALL
  134. */
  135. /* turn on virtual protected mode save */
  136. #define VM_ON \
  137. set_ums; \
  138. rted r0, 2f; \
  139. nop; \
  140. 2:
  141. /* turn off virtual protected mode save and user mode save*/
  142. #define VM_OFF \
  143. clear_vms_ums; \
  144. rted r0, TOPHYS(1f); \
  145. nop; \
  146. 1:
  147. #define SAVE_REGS \
  148. swi r2, r1, PT_R2; /* Save SDA */ \
  149. swi r3, r1, PT_R3; \
  150. swi r4, r1, PT_R4; \
  151. swi r5, r1, PT_R5; \
  152. swi r6, r1, PT_R6; \
  153. swi r7, r1, PT_R7; \
  154. swi r8, r1, PT_R8; \
  155. swi r9, r1, PT_R9; \
  156. swi r10, r1, PT_R10; \
  157. swi r11, r1, PT_R11; /* save clobbered regs after rval */\
  158. swi r12, r1, PT_R12; \
  159. swi r13, r1, PT_R13; /* Save SDA2 */ \
  160. swi r14, r1, PT_PC; /* PC, before IRQ/trap */ \
  161. swi r15, r1, PT_R15; /* Save LP */ \
  162. swi r16, r1, PT_R16; \
  163. swi r17, r1, PT_R17; \
  164. swi r18, r1, PT_R18; /* Save asm scratch reg */ \
  165. swi r19, r1, PT_R19; \
  166. swi r20, r1, PT_R20; \
  167. swi r21, r1, PT_R21; \
  168. swi r22, r1, PT_R22; \
  169. swi r23, r1, PT_R23; \
  170. swi r24, r1, PT_R24; \
  171. swi r25, r1, PT_R25; \
  172. swi r26, r1, PT_R26; \
  173. swi r27, r1, PT_R27; \
  174. swi r28, r1, PT_R28; \
  175. swi r29, r1, PT_R29; \
  176. swi r30, r1, PT_R30; \
  177. swi r31, r1, PT_R31; /* Save current task reg */ \
  178. mfs r11, rmsr; /* save MSR */ \
  179. swi r11, r1, PT_MSR;
  180. #define RESTORE_REGS \
  181. lwi r11, r1, PT_MSR; \
  182. mts rmsr , r11; \
  183. lwi r2, r1, PT_R2; /* restore SDA */ \
  184. lwi r3, r1, PT_R3; \
  185. lwi r4, r1, PT_R4; \
  186. lwi r5, r1, PT_R5; \
  187. lwi r6, r1, PT_R6; \
  188. lwi r7, r1, PT_R7; \
  189. lwi r8, r1, PT_R8; \
  190. lwi r9, r1, PT_R9; \
  191. lwi r10, r1, PT_R10; \
  192. lwi r11, r1, PT_R11; /* restore clobbered regs after rval */\
  193. lwi r12, r1, PT_R12; \
  194. lwi r13, r1, PT_R13; /* restore SDA2 */ \
  195. lwi r14, r1, PT_PC; /* RESTORE_LINK PC, before IRQ/trap */\
  196. lwi r15, r1, PT_R15; /* restore LP */ \
  197. lwi r16, r1, PT_R16; \
  198. lwi r17, r1, PT_R17; \
  199. lwi r18, r1, PT_R18; /* restore asm scratch reg */ \
  200. lwi r19, r1, PT_R19; \
  201. lwi r20, r1, PT_R20; \
  202. lwi r21, r1, PT_R21; \
  203. lwi r22, r1, PT_R22; \
  204. lwi r23, r1, PT_R23; \
  205. lwi r24, r1, PT_R24; \
  206. lwi r25, r1, PT_R25; \
  207. lwi r26, r1, PT_R26; \
  208. lwi r27, r1, PT_R27; \
  209. lwi r28, r1, PT_R28; \
  210. lwi r29, r1, PT_R29; \
  211. lwi r30, r1, PT_R30; \
  212. lwi r31, r1, PT_R31; /* Restore cur task reg */
  213. #define SAVE_STATE \
  214. swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */ \
  215. /* See if already in kernel mode.*/ \
  216. mfs r1, rmsr; \
  217. andi r1, r1, MSR_UMS; \
  218. bnei r1, 1f; \
  219. /* Kernel-mode state save. */ \
  220. /* Reload kernel stack-ptr. */ \
  221. lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); \
  222. /* FIXME: I can add these two lines to one */ \
  223. /* tophys(r1,r1); */ \
  224. /* addik r1, r1, -PT_SIZE; */ \
  225. addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \
  226. SAVE_REGS \
  227. brid 2f; \
  228. swi r1, r1, PT_MODE; \
  229. 1: /* User-mode state save. */ \
  230. lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
  231. tophys(r1,r1); \
  232. lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ \
  233. /* MS these three instructions can be added to one */ \
  234. /* addik r1, r1, THREAD_SIZE; */ \
  235. /* tophys(r1,r1); */ \
  236. /* addik r1, r1, -PT_SIZE; */ \
  237. addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \
  238. SAVE_REGS \
  239. lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \
  240. swi r11, r1, PT_R1; /* Store user SP. */ \
  241. swi r0, r1, PT_MODE; /* Was in user-mode. */ \
  242. /* MS: I am clearing UMS even in case when I come from kernel space */ \
  243. clear_ums; \
  244. 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
  245. .text
  246. /*
  247. * User trap.
  248. *
  249. * System calls are handled here.
  250. *
  251. * Syscall protocol:
  252. * Syscall number in r12, args in r5-r10
  253. * Return value in r3
  254. *
  255. * Trap entered via brki instruction, so BIP bit is set, and interrupts
  256. * are masked. This is nice, means we don't have to CLI before state save
  257. */
  258. C_ENTRY(_user_exception):
  259. swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
  260. addi r14, r14, 4 /* return address is 4 byte after call */
  261. lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
  262. tophys(r1,r1);
  263. lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */
  264. /* calculate kernel stack pointer from task struct 8k */
  265. addik r1, r1, THREAD_SIZE;
  266. tophys(r1,r1);
  267. addik r1, r1, -PT_SIZE; /* Make room on the stack. */
  268. SAVE_REGS
  269. swi r0, r1, PT_R3
  270. swi r0, r1, PT_R4
  271. swi r0, r1, PT_MODE; /* Was in user-mode. */
  272. lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
  273. swi r11, r1, PT_R1; /* Store user SP. */
  274. clear_ums;
  275. 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
  276. /* Save away the syscall number. */
  277. swi r12, r1, PT_R0;
  278. tovirt(r1,r1)
  279. /* where the trap should return need -8 to adjust for rtsd r15, 8*/
  280. /* Jump to the appropriate function for the system call number in r12
  281. * (r12 is not preserved), or return an error if r12 is not valid. The LP
  282. * register should point to the location where
  283. * the called function should return. [note that MAKE_SYS_CALL uses label 1] */
  284. /* Step into virtual mode */
  285. rtbd r0, 3f
  286. nop
  287. 3:
  288. lwi r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */
  289. lwi r11, r11, TI_FLAGS /* get flags in thread info */
  290. andi r11, r11, _TIF_WORK_SYSCALL_MASK
  291. beqi r11, 4f
  292. addik r3, r0, -ENOSYS
  293. swi r3, r1, PT_R3
  294. brlid r15, do_syscall_trace_enter
  295. addik r5, r1, PT_R0
  296. # do_syscall_trace_enter returns the new syscall nr.
  297. addk r12, r0, r3
  298. lwi r5, r1, PT_R5;
  299. lwi r6, r1, PT_R6;
  300. lwi r7, r1, PT_R7;
  301. lwi r8, r1, PT_R8;
  302. lwi r9, r1, PT_R9;
  303. lwi r10, r1, PT_R10;
  304. 4:
  305. /* Jump to the appropriate function for the system call number in r12
  306. * (r12 is not preserved), or return an error if r12 is not valid.
  307. * The LP register should point to the location where the called function
  308. * should return. [note that MAKE_SYS_CALL uses label 1] */
  309. /* See if the system call number is valid */
  310. blti r12, 5f
  311. addi r11, r12, -__NR_syscalls;
  312. bgei r11, 5f;
  313. /* Figure out which function to use for this system call. */
  314. /* Note Microblaze barrel shift is optional, so don't rely on it */
  315. add r12, r12, r12; /* convert num -> ptr */
  316. add r12, r12, r12;
  317. addi r30, r0, 1 /* restarts allowed */
  318. #ifdef DEBUG
  319. /* Trac syscalls and stored them to syscall_debug_table */
  320. /* The first syscall location stores total syscall number */
  321. lwi r3, r0, syscall_debug_table
  322. addi r3, r3, 1
  323. swi r3, r0, syscall_debug_table
  324. lwi r3, r12, syscall_debug_table
  325. addi r3, r3, 1
  326. swi r3, r12, syscall_debug_table
  327. #endif
  328. # Find and jump into the syscall handler.
  329. lwi r12, r12, sys_call_table
  330. /* where the trap should return need -8 to adjust for rtsd r15, 8 */
  331. addi r15, r0, ret_from_trap-8
  332. bra r12
  333. /* The syscall number is invalid, return an error. */
  334. 5:
  335. braid ret_from_trap
  336. addi r3, r0, -ENOSYS;
  337. /* Entry point used to return from a syscall/trap */
  338. /* We re-enable BIP bit before state restore */
  339. C_ENTRY(ret_from_trap):
  340. swi r3, r1, PT_R3
  341. swi r4, r1, PT_R4
  342. lwi r11, r1, PT_MODE;
  343. /* See if returning to kernel mode, if so, skip resched &c. */
  344. bnei r11, 2f;
  345. /* We're returning to user mode, so check for various conditions that
  346. * trigger rescheduling. */
  347. /* FIXME: Restructure all these flag checks. */
  348. lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
  349. lwi r11, r11, TI_FLAGS; /* get flags in thread info */
  350. andi r11, r11, _TIF_WORK_SYSCALL_MASK
  351. beqi r11, 1f
  352. brlid r15, do_syscall_trace_leave
  353. addik r5, r1, PT_R0
  354. 1:
  355. /* We're returning to user mode, so check for various conditions that
  356. * trigger rescheduling. */
  357. /* get thread info from current task */
  358. lwi r11, CURRENT_TASK, TS_THREAD_INFO;
  359. lwi r19, r11, TI_FLAGS; /* get flags in thread info */
  360. andi r11, r19, _TIF_NEED_RESCHED;
  361. beqi r11, 5f;
  362. bralid r15, schedule; /* Call scheduler */
  363. nop; /* delay slot */
  364. bri 1b
  365. /* Maybe handle a signal */
  366. 5:
  367. andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
  368. beqi r11, 4f; /* Signals to handle, handle them */
  369. addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
  370. bralid r15, do_notify_resume; /* Handle any signals */
  371. add r6, r30, r0; /* Arg 2: int in_syscall */
  372. add r30, r0, r0 /* no more restarts */
  373. bri 1b
  374. /* Finally, return to user state. */
  375. 4: set_bip; /* Ints masked for state restore */
  376. swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
  377. VM_OFF;
  378. tophys(r1,r1);
  379. RESTORE_REGS;
  380. addik r1, r1, PT_SIZE /* Clean up stack space. */
  381. lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
  382. bri 6f;
  383. /* Return to kernel state. */
  384. 2: set_bip; /* Ints masked for state restore */
  385. VM_OFF;
  386. tophys(r1,r1);
  387. RESTORE_REGS;
  388. addik r1, r1, PT_SIZE /* Clean up stack space. */
  389. tovirt(r1,r1);
  390. 6:
  391. TRAP_return: /* Make global symbol for debugging */
  392. rtbd r14, 0; /* Instructions to return from an IRQ */
  393. nop;
  394. /* This the initial entry point for a new child thread, with an appropriate
  395. stack in place that makes it look the the child is in the middle of an
  396. syscall. This function is actually `returned to' from switch_thread
  397. (copy_thread makes ret_from_fork the return address in each new thread's
  398. saved context). */
  399. C_ENTRY(ret_from_fork):
  400. bralid r15, schedule_tail; /* ...which is schedule_tail's arg */
  401. add r5, r3, r0; /* switch_thread returns the prev task */
  402. /* ( in the delay slot ) */
  403. brid ret_from_trap; /* Do normal trap return */
  404. add r3, r0, r0; /* Child's fork call should return 0. */
  405. C_ENTRY(ret_from_kernel_thread):
  406. bralid r15, schedule_tail; /* ...which is schedule_tail's arg */
  407. add r5, r3, r0; /* switch_thread returns the prev task */
  408. /* ( in the delay slot ) */
  409. brald r15, r20 /* fn was left in r20 */
  410. addk r5, r0, r19 /* ... and argument - in r19 */
  411. brid ret_from_trap
  412. add r3, r0, r0
  413. C_ENTRY(sys_rt_sigreturn_wrapper):
  414. addik r30, r0, 0 /* no restarts */
  415. brid sys_rt_sigreturn /* Do real work */
  416. addik r5, r1, 0; /* add user context as 1st arg */
  417. /*
  418. * HW EXCEPTION rutine start
  419. */
  420. C_ENTRY(full_exception_trap):
  421. /* adjust exception address for privileged instruction
  422. * for finding where is it */
  423. addik r17, r17, -4
  424. SAVE_STATE /* Save registers */
  425. /* PC, before IRQ/trap - this is one instruction above */
  426. swi r17, r1, PT_PC;
  427. tovirt(r1,r1)
  428. /* FIXME this can be store directly in PT_ESR reg.
  429. * I tested it but there is a fault */
  430. /* where the trap should return need -8 to adjust for rtsd r15, 8 */
  431. addik r15, r0, ret_from_exc - 8
  432. mfs r6, resr
  433. mfs r7, rfsr; /* save FSR */
  434. mts rfsr, r0; /* Clear sticky fsr */
  435. rted r0, full_exception
  436. addik r5, r1, 0 /* parameter struct pt_regs * regs */
  437. /*
  438. * Unaligned data trap.
  439. *
  440. * Unaligned data trap last on 4k page is handled here.
  441. *
  442. * Trap entered via exception, so EE bit is set, and interrupts
  443. * are masked. This is nice, means we don't have to CLI before state save
  444. *
  445. * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S"
  446. */
  447. C_ENTRY(unaligned_data_trap):
  448. /* MS: I have to save r11 value and then restore it because
  449. * set_bit, clear_eip, set_ee use r11 as temp register if MSR
  450. * instructions are not used. We don't need to do if MSR instructions
  451. * are used and they use r0 instead of r11.
  452. * I am using ENTRY_SP which should be primary used only for stack
  453. * pointer saving. */
  454. swi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
  455. set_bip; /* equalize initial state for all possible entries */
  456. clear_eip;
  457. set_ee;
  458. lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
  459. SAVE_STATE /* Save registers.*/
  460. /* PC, before IRQ/trap - this is one instruction above */
  461. swi r17, r1, PT_PC;
  462. tovirt(r1,r1)
  463. /* where the trap should return need -8 to adjust for rtsd r15, 8 */
  464. addik r15, r0, ret_from_exc-8
  465. mfs r3, resr /* ESR */
  466. mfs r4, rear /* EAR */
  467. rtbd r0, _unaligned_data_exception
  468. addik r7, r1, 0 /* parameter struct pt_regs * regs */
  469. /*
  470. * Page fault traps.
  471. *
  472. * If the real exception handler (from hw_exception_handler.S) didn't find
  473. * the mapping for the process, then we're thrown here to handle such situation.
  474. *
  475. * Trap entered via exceptions, so EE bit is set, and interrupts
  476. * are masked. This is nice, means we don't have to CLI before state save
  477. *
  478. * Build a standard exception frame for TLB Access errors. All TLB exceptions
  479. * will bail out to this point if they can't resolve the lightweight TLB fault.
  480. *
  481. * The C function called is in "arch/microblaze/mm/fault.c", declared as:
  482. * void do_page_fault(struct pt_regs *regs,
  483. * unsigned long address,
  484. * unsigned long error_code)
  485. */
  486. /* data and intruction trap - which is choose is resolved int fault.c */
  487. C_ENTRY(page_fault_data_trap):
  488. SAVE_STATE /* Save registers.*/
  489. /* PC, before IRQ/trap - this is one instruction above */
  490. swi r17, r1, PT_PC;
  491. tovirt(r1,r1)
  492. /* where the trap should return need -8 to adjust for rtsd r15, 8 */
  493. addik r15, r0, ret_from_exc-8
  494. mfs r6, rear /* parameter unsigned long address */
  495. mfs r7, resr /* parameter unsigned long error_code */
  496. rted r0, do_page_fault
  497. addik r5, r1, 0 /* parameter struct pt_regs * regs */
  498. C_ENTRY(page_fault_instr_trap):
  499. SAVE_STATE /* Save registers.*/
  500. /* PC, before IRQ/trap - this is one instruction above */
  501. swi r17, r1, PT_PC;
  502. tovirt(r1,r1)
  503. /* where the trap should return need -8 to adjust for rtsd r15, 8 */
  504. addik r15, r0, ret_from_exc-8
  505. mfs r6, rear /* parameter unsigned long address */
  506. ori r7, r0, 0 /* parameter unsigned long error_code */
  507. rted r0, do_page_fault
  508. addik r5, r1, 0 /* parameter struct pt_regs * regs */
  509. /* Entry point used to return from an exception. */
  510. C_ENTRY(ret_from_exc):
  511. lwi r11, r1, PT_MODE;
  512. bnei r11, 2f; /* See if returning to kernel mode, */
  513. /* ... if so, skip resched &c. */
  514. /* We're returning to user mode, so check for various conditions that
  515. trigger rescheduling. */
  516. 1:
  517. lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
  518. lwi r19, r11, TI_FLAGS; /* get flags in thread info */
  519. andi r11, r19, _TIF_NEED_RESCHED;
  520. beqi r11, 5f;
  521. /* Call the scheduler before returning from a syscall/trap. */
  522. bralid r15, schedule; /* Call scheduler */
  523. nop; /* delay slot */
  524. bri 1b
  525. /* Maybe handle a signal */
  526. 5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
  527. beqi r11, 4f; /* Signals to handle, handle them */
  528. /*
  529. * Handle a signal return; Pending signals should be in r18.
  530. *
  531. * Not all registers are saved by the normal trap/interrupt entry
  532. * points (for instance, call-saved registers (because the normal
  533. * C-compiler calling sequence in the kernel makes sure they're
  534. * preserved), and call-clobbered registers in the case of
  535. * traps), but signal handlers may want to examine or change the
  536. * complete register state. Here we save anything not saved by
  537. * the normal entry sequence, so that it may be safely restored
  538. * (in a possibly modified form) after do_notify_resume returns. */
  539. addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
  540. bralid r15, do_notify_resume; /* Handle any signals */
  541. addi r6, r0, 0; /* Arg 2: int in_syscall */
  542. bri 1b
  543. /* Finally, return to user state. */
  544. 4: set_bip; /* Ints masked for state restore */
  545. swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
  546. VM_OFF;
  547. tophys(r1,r1);
  548. RESTORE_REGS;
  549. addik r1, r1, PT_SIZE /* Clean up stack space. */
  550. lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
  551. bri 6f;
  552. /* Return to kernel state. */
  553. 2: set_bip; /* Ints masked for state restore */
  554. VM_OFF;
  555. tophys(r1,r1);
  556. RESTORE_REGS;
  557. addik r1, r1, PT_SIZE /* Clean up stack space. */
  558. tovirt(r1,r1);
  559. 6:
  560. EXC_return: /* Make global symbol for debugging */
  561. rtbd r14, 0; /* Instructions to return from an IRQ */
  562. nop;
  563. /*
  564. * HW EXCEPTION rutine end
  565. */
  566. /*
  567. * Hardware maskable interrupts.
  568. *
  569. * The stack-pointer (r1) should have already been saved to the memory
  570. * location PER_CPU(ENTRY_SP).
  571. */
  572. C_ENTRY(_interrupt):
  573. /* MS: we are in physical address */
  574. /* Save registers, switch to proper stack, convert SP to virtual.*/
  575. swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
  576. /* MS: See if already in kernel mode. */
  577. mfs r1, rmsr
  578. nop
  579. andi r1, r1, MSR_UMS
  580. bnei r1, 1f
  581. /* Kernel-mode state save. */
  582. lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
  583. tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
  584. /* save registers */
  585. /* MS: Make room on the stack -> activation record */
  586. addik r1, r1, -PT_SIZE;
  587. SAVE_REGS
  588. brid 2f;
  589. swi r1, r1, PT_MODE; /* 0 - user mode, 1 - kernel mode */
  590. 1:
  591. /* User-mode state save. */
  592. /* MS: get the saved current */
  593. lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
  594. tophys(r1,r1);
  595. lwi r1, r1, TS_THREAD_INFO;
  596. addik r1, r1, THREAD_SIZE;
  597. tophys(r1,r1);
  598. /* save registers */
  599. addik r1, r1, -PT_SIZE;
  600. SAVE_REGS
  601. /* calculate mode */
  602. swi r0, r1, PT_MODE;
  603. lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
  604. swi r11, r1, PT_R1;
  605. clear_ums;
  606. 2:
  607. lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
  608. tovirt(r1,r1)
  609. addik r15, r0, irq_call;
  610. irq_call:rtbd r0, do_IRQ;
  611. addik r5, r1, 0;
  612. /* MS: we are in virtual mode */
  613. ret_from_irq:
  614. lwi r11, r1, PT_MODE;
  615. bnei r11, 2f;
  616. 1:
  617. lwi r11, CURRENT_TASK, TS_THREAD_INFO;
  618. lwi r19, r11, TI_FLAGS; /* MS: get flags from thread info */
  619. andi r11, r19, _TIF_NEED_RESCHED;
  620. beqi r11, 5f
  621. bralid r15, schedule;
  622. nop; /* delay slot */
  623. bri 1b
  624. /* Maybe handle a signal */
  625. 5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
  626. beqid r11, no_intr_resched
  627. /* Handle a signal return; Pending signals should be in r18. */
  628. addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
  629. bralid r15, do_notify_resume; /* Handle any signals */
  630. addi r6, r0, 0; /* Arg 2: int in_syscall */
  631. bri 1b
  632. /* Finally, return to user state. */
  633. no_intr_resched:
  634. /* Disable interrupts, we are now committed to the state restore */
  635. disable_irq
  636. swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
  637. VM_OFF;
  638. tophys(r1,r1);
  639. RESTORE_REGS
  640. addik r1, r1, PT_SIZE /* MS: Clean up stack space. */
  641. lwi r1, r1, PT_R1 - PT_SIZE;
  642. bri 6f;
  643. /* MS: Return to kernel state. */
  644. 2:
  645. #ifdef CONFIG_PREEMPT
  646. lwi r11, CURRENT_TASK, TS_THREAD_INFO;
  647. /* MS: get preempt_count from thread info */
  648. lwi r5, r11, TI_PREEMPT_COUNT;
  649. bgti r5, restore;
  650. lwi r5, r11, TI_FLAGS; /* get flags in thread info */
  651. andi r5, r5, _TIF_NEED_RESCHED;
  652. beqi r5, restore /* if zero jump over */
  653. preempt:
  654. /* interrupts are off that's why I am calling preempt_chedule_irq */
  655. bralid r15, preempt_schedule_irq
  656. nop
  657. lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
  658. lwi r5, r11, TI_FLAGS; /* get flags in thread info */
  659. andi r5, r5, _TIF_NEED_RESCHED;
  660. bnei r5, preempt /* if non zero jump to resched */
  661. restore:
  662. #endif
  663. VM_OFF /* MS: turn off MMU */
  664. tophys(r1,r1)
  665. RESTORE_REGS
  666. addik r1, r1, PT_SIZE /* MS: Clean up stack space. */
  667. tovirt(r1,r1);
  668. 6:
  669. IRQ_return: /* MS: Make global symbol for debugging */
  670. rtid r14, 0
  671. nop
  672. /*
  673. * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18
  674. * and call handling function with saved pt_regs
  675. */
  676. C_ENTRY(_debug_exception):
  677. /* BIP bit is set on entry, no interrupts can occur */
  678. swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
  679. mfs r1, rmsr
  680. nop
  681. andi r1, r1, MSR_UMS
  682. bnei r1, 1f
  683. /* MS: Kernel-mode state save - kgdb */
  684. lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
  685. /* BIP bit is set on entry, no interrupts can occur */
  686. addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE;
  687. SAVE_REGS;
  688. /* save all regs to pt_reg structure */
  689. swi r0, r1, PT_R0; /* R0 must be saved too */
  690. swi r14, r1, PT_R14 /* rewrite saved R14 value */
  691. swi r16, r1, PT_PC; /* PC and r16 are the same */
  692. /* save special purpose registers to pt_regs */
  693. mfs r11, rear;
  694. swi r11, r1, PT_EAR;
  695. mfs r11, resr;
  696. swi r11, r1, PT_ESR;
  697. mfs r11, rfsr;
  698. swi r11, r1, PT_FSR;
  699. /* stack pointer is in physical address at it is decrease
  700. * by PT_SIZE but we need to get correct R1 value */
  701. addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + PT_SIZE;
  702. swi r11, r1, PT_R1
  703. /* MS: r31 - current pointer isn't changed */
  704. tovirt(r1,r1)
  705. #ifdef CONFIG_KGDB
  706. addi r5, r1, 0 /* pass pt_reg address as the first arg */
  707. addik r15, r0, dbtrap_call; /* return address */
  708. rtbd r0, microblaze_kgdb_break
  709. nop;
  710. #endif
  711. /* MS: Place handler for brki from kernel space if KGDB is OFF.
  712. * It is very unlikely that another brki instruction is called. */
  713. bri 0
  714. /* MS: User-mode state save - gdb */
  715. 1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
  716. tophys(r1,r1);
  717. lwi r1, r1, TS_THREAD_INFO; /* get the thread info */
  718. addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */
  719. tophys(r1,r1);
  720. addik r1, r1, -PT_SIZE; /* Make room on the stack. */
  721. SAVE_REGS;
  722. swi r16, r1, PT_PC; /* Save LP */
  723. swi r0, r1, PT_MODE; /* Was in user-mode. */
  724. lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
  725. swi r11, r1, PT_R1; /* Store user SP. */
  726. lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
  727. tovirt(r1,r1)
  728. set_vms;
  729. addik r5, r1, 0;
  730. addik r15, r0, dbtrap_call;
  731. dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
  732. rtbd r0, sw_exception
  733. nop
  734. /* MS: The first instruction for the second part of the gdb/kgdb */
  735. set_bip; /* Ints masked for state restore */
  736. lwi r11, r1, PT_MODE;
  737. bnei r11, 2f;
  738. /* MS: Return to user space - gdb */
  739. 1:
  740. /* Get current task ptr into r11 */
  741. lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
  742. lwi r19, r11, TI_FLAGS; /* get flags in thread info */
  743. andi r11, r19, _TIF_NEED_RESCHED;
  744. beqi r11, 5f;
  745. /* Call the scheduler before returning from a syscall/trap. */
  746. bralid r15, schedule; /* Call scheduler */
  747. nop; /* delay slot */
  748. bri 1b
  749. /* Maybe handle a signal */
  750. 5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
  751. beqi r11, 4f; /* Signals to handle, handle them */
  752. addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
  753. bralid r15, do_notify_resume; /* Handle any signals */
  754. addi r6, r0, 0; /* Arg 2: int in_syscall */
  755. bri 1b
  756. /* Finally, return to user state. */
  757. 4: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
  758. VM_OFF;
  759. tophys(r1,r1);
  760. /* MS: Restore all regs */
  761. RESTORE_REGS
  762. addik r1, r1, PT_SIZE /* Clean up stack space */
  763. lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
  764. DBTRAP_return_user: /* MS: Make global symbol for debugging */
  765. rtbd r16, 0; /* MS: Instructions to return from a debug trap */
  766. nop;
  767. /* MS: Return to kernel state - kgdb */
  768. 2: VM_OFF;
  769. tophys(r1,r1);
  770. /* MS: Restore all regs */
  771. RESTORE_REGS
  772. lwi r14, r1, PT_R14;
  773. lwi r16, r1, PT_PC;
  774. addik r1, r1, PT_SIZE; /* MS: Clean up stack space */
  775. tovirt(r1,r1);
  776. DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
  777. rtbd r16, 0; /* MS: Instructions to return from a debug trap */
  778. nop;
  779. ENTRY(_switch_to)
  780. /* prepare return value */
  781. addk r3, r0, CURRENT_TASK
  782. /* save registers in cpu_context */
  783. /* use r11 and r12, volatile registers, as temp register */
  784. /* give start of cpu_context for previous process */
  785. addik r11, r5, TI_CPU_CONTEXT
  786. swi r1, r11, CC_R1
  787. swi r2, r11, CC_R2
  788. /* skip volatile registers.
  789. * they are saved on stack when we jumped to _switch_to() */
  790. /* dedicated registers */
  791. swi r13, r11, CC_R13
  792. swi r14, r11, CC_R14
  793. swi r15, r11, CC_R15
  794. swi r16, r11, CC_R16
  795. swi r17, r11, CC_R17
  796. swi r18, r11, CC_R18
  797. /* save non-volatile registers */
  798. swi r19, r11, CC_R19
  799. swi r20, r11, CC_R20
  800. swi r21, r11, CC_R21
  801. swi r22, r11, CC_R22
  802. swi r23, r11, CC_R23
  803. swi r24, r11, CC_R24
  804. swi r25, r11, CC_R25
  805. swi r26, r11, CC_R26
  806. swi r27, r11, CC_R27
  807. swi r28, r11, CC_R28
  808. swi r29, r11, CC_R29
  809. swi r30, r11, CC_R30
  810. /* special purpose registers */
  811. mfs r12, rmsr
  812. swi r12, r11, CC_MSR
  813. mfs r12, rear
  814. swi r12, r11, CC_EAR
  815. mfs r12, resr
  816. swi r12, r11, CC_ESR
  817. mfs r12, rfsr
  818. swi r12, r11, CC_FSR
  819. /* update r31, the current-give me pointer to task which will be next */
  820. lwi CURRENT_TASK, r6, TI_TASK
  821. /* stored it to current_save too */
  822. swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE)
  823. /* get new process' cpu context and restore */
  824. /* give me start where start context of next task */
  825. addik r11, r6, TI_CPU_CONTEXT
  826. /* non-volatile registers */
  827. lwi r30, r11, CC_R30
  828. lwi r29, r11, CC_R29
  829. lwi r28, r11, CC_R28
  830. lwi r27, r11, CC_R27
  831. lwi r26, r11, CC_R26
  832. lwi r25, r11, CC_R25
  833. lwi r24, r11, CC_R24
  834. lwi r23, r11, CC_R23
  835. lwi r22, r11, CC_R22
  836. lwi r21, r11, CC_R21
  837. lwi r20, r11, CC_R20
  838. lwi r19, r11, CC_R19
  839. /* dedicated registers */
  840. lwi r18, r11, CC_R18
  841. lwi r17, r11, CC_R17
  842. lwi r16, r11, CC_R16
  843. lwi r15, r11, CC_R15
  844. lwi r14, r11, CC_R14
  845. lwi r13, r11, CC_R13
  846. /* skip volatile registers */
  847. lwi r2, r11, CC_R2
  848. lwi r1, r11, CC_R1
  849. /* special purpose registers */
  850. lwi r12, r11, CC_FSR
  851. mts rfsr, r12
  852. lwi r12, r11, CC_MSR
  853. mts rmsr, r12
  854. rtsd r15, 8
  855. nop
  856. ENTRY(_reset)
  857. brai 0; /* Jump to reset vector */
  858. /* These are compiled and loaded into high memory, then
  859. * copied into place in mach_early_setup */
  860. .section .init.ivt, "ax"
  861. #if CONFIG_MANUAL_RESET_VECTOR
  862. .org 0x0
  863. brai CONFIG_MANUAL_RESET_VECTOR
  864. #endif
  865. .org 0x8
  866. brai TOPHYS(_user_exception); /* syscall handler */
  867. .org 0x10
  868. brai TOPHYS(_interrupt); /* Interrupt handler */
  869. .org 0x18
  870. brai TOPHYS(_debug_exception); /* debug trap handler */
  871. .org 0x20
  872. brai TOPHYS(_hw_exception_handler); /* HW exception handler */
  873. .section .rodata,"a"
  874. #include "syscall_table.S"
  875. syscall_table_size=(.-sys_call_table)
  876. type_SYSCALL:
  877. .ascii "SYSCALL\0"
  878. type_IRQ:
  879. .ascii "IRQ\0"
  880. type_IRQ_PREEMPT:
  881. .ascii "IRQ (PREEMPTED)\0"
  882. type_SYSCALL_PREEMPT:
  883. .ascii " SYSCALL (PREEMPTED)\0"
  884. /*
  885. * Trap decoding for stack unwinder
  886. * Tuples are (start addr, end addr, string)
  887. * If return address lies on [start addr, end addr],
  888. * unwinder displays 'string'
  889. */
  890. .align 4
  891. .global microblaze_trap_handlers
  892. microblaze_trap_handlers:
  893. /* Exact matches come first */
  894. .word ret_from_trap; .word ret_from_trap ; .word type_SYSCALL
  895. .word ret_from_irq ; .word ret_from_irq ; .word type_IRQ
  896. /* Fuzzy matches go here */
  897. .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT
  898. .word ret_from_trap; .word TRAP_return ; .word type_SYSCALL_PREEMPT
  899. /* End of table */
  900. .word 0 ; .word 0 ; .word 0