kernel.fuc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*
  2. * Copyright 2013 Red Hat Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * Authors: Ben Skeggs
  23. */
  24. /******************************************************************************
  25. * kernel data segment
  26. *****************************************************************************/
  27. #ifdef INCLUDE_PROC
  28. proc_kern:
  29. process(PROC_KERN, 0, 0)
  30. proc_list_head:
  31. #endif
  32. #ifdef INCLUDE_DATA
  33. proc_list_tail:
  34. time_prev: .b32 0
  35. time_next: .b32 0
  36. #endif
  37. /******************************************************************************
  38. * kernel code segment
  39. *****************************************************************************/
  40. #ifdef INCLUDE_CODE
  41. bra #init
  42. // read nv register
  43. //
  44. // $r15 - current
  45. // $r14 - addr
  46. // $r13 - data (return)
  47. // $r0 - zero
  48. rd32:
  49. nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
  50. mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
  51. sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
  52. nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
  53. rd32_wait:
  54. nv_iord($r13, NV_PPWR_MMIO_CTRL)
  55. and $r13 NV_PPWR_MMIO_CTRL_STATUS
  56. bra nz #rd32_wait
  57. nv_iord($r13, NV_PPWR_MMIO_DATA)
  58. ret
  59. // write nv register
  60. //
  61. // $r15 - current
  62. // $r14 - addr
  63. // $r13 - data
  64. // $r0 - zero
  65. wr32:
  66. nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
  67. nv_iowr(NV_PPWR_MMIO_DATA, $r13)
  68. mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
  69. or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
  70. sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
  71. #ifdef NVKM_FALCON_MMIO_TRAP
  72. push $r13
  73. mov $r13 NV_PPWR_INTR_TRIGGER_USER1
  74. nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
  75. wr32_host:
  76. nv_iord($r13, NV_PPWR_INTR)
  77. and $r13 NV_PPWR_INTR_USER1
  78. bra nz #wr32_host
  79. pop $r13
  80. #endif
  81. nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
  82. wr32_wait:
  83. nv_iord($r13, NV_PPWR_MMIO_CTRL)
  84. and $r13 NV_PPWR_MMIO_CTRL_STATUS
  85. bra nz #wr32_wait
  86. ret
  87. // busy-wait for a period of time
  88. //
  89. // $r15 - current
  90. // $r14 - ns
  91. // $r0 - zero
  92. nsec:
  93. push $r9
  94. push $r8
  95. nv_iord($r8, NV_PPWR_TIMER_LOW)
  96. nsec_loop:
  97. nv_iord($r9, NV_PPWR_TIMER_LOW)
  98. sub b32 $r9 $r8
  99. cmp b32 $r9 $r14
  100. bra l #nsec_loop
  101. pop $r8
  102. pop $r9
  103. ret
  104. // busy-wait for a period of time
  105. //
  106. // $r15 - current
  107. // $r14 - addr
  108. // $r13 - mask
  109. // $r12 - data
  110. // $r11 - timeout (ns)
  111. // $r0 - zero
  112. wait:
  113. push $r9
  114. push $r8
  115. nv_iord($r8, NV_PPWR_TIMER_LOW)
  116. wait_loop:
  117. nv_rd32($r10, $r14)
  118. and $r10 $r13
  119. cmp b32 $r10 $r12
  120. bra e #wait_done
  121. nv_iord($r9, NV_PPWR_TIMER_LOW)
  122. sub b32 $r9 $r8
  123. cmp b32 $r9 $r11
  124. bra l #wait_loop
  125. wait_done:
  126. pop $r8
  127. pop $r9
  128. ret
  129. // $r15 - current (kern)
  130. // $r14 - process
  131. // $r8 - NV_PPWR_INTR
  132. intr_watchdog:
  133. // read process' timer status, skip if not enabled
  134. ld b32 $r9 D[$r14 + #proc_time]
  135. cmp b32 $r9 0
  136. bra z #intr_watchdog_next_proc
  137. // subtract last timer's value from process' timer,
  138. // if it's <= 0 then the timer has expired
  139. ld b32 $r10 D[$r0 + #time_prev]
  140. sub b32 $r9 $r10
  141. bra g #intr_watchdog_next_time
  142. mov $r13 KMSG_ALARM
  143. call(send_proc)
  144. clear b32 $r9
  145. bra #intr_watchdog_next_proc
  146. // otherwise, update the next timer's value if this
  147. // process' timer is the soonest
  148. intr_watchdog_next_time:
  149. // ... or if there's no next timer yet
  150. ld b32 $r10 D[$r0 + #time_next]
  151. cmp b32 $r10 0
  152. bra z #intr_watchdog_next_time_set
  153. cmp b32 $r9 $r10
  154. bra g #intr_watchdog_next_proc
  155. intr_watchdog_next_time_set:
  156. st b32 D[$r0 + #time_next] $r9
  157. // update process' timer status, and advance
  158. intr_watchdog_next_proc:
  159. st b32 D[$r14 + #proc_time] $r9
  160. add b32 $r14 #proc_size
  161. cmp b32 $r14 #proc_list_tail
  162. bra ne #intr_watchdog
  163. ret
  164. intr:
  165. push $r0
  166. clear b32 $r0
  167. push $r8
  168. push $r9
  169. push $r10
  170. push $r11
  171. push $r12
  172. push $r13
  173. push $r14
  174. push $r15
  175. mov $r15 #proc_kern
  176. mov $r8 $flags
  177. push $r8
  178. nv_iord($r8, NV_PPWR_DSCRATCH(0))
  179. add b32 $r8 1
  180. nv_iowr(NV_PPWR_DSCRATCH(0), $r8)
  181. nv_iord($r8, NV_PPWR_INTR)
  182. and $r9 $r8 NV_PPWR_INTR_WATCHDOG
  183. bra z #intr_skip_watchdog
  184. st b32 D[$r0 + #time_next] $r0
  185. mov $r14 #proc_list_head
  186. call(intr_watchdog)
  187. ld b32 $r9 D[$r0 + #time_next]
  188. cmp b32 $r9 0
  189. bra z #intr_skip_watchdog
  190. nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9)
  191. st b32 D[$r0 + #time_prev] $r9
  192. intr_skip_watchdog:
  193. and $r9 $r8 NV_PPWR_INTR_SUBINTR
  194. bra z #intr_skip_subintr
  195. nv_iord($r9, NV_PPWR_SUBINTR)
  196. and $r10 $r9 NV_PPWR_SUBINTR_FIFO
  197. bra z #intr_subintr_skip_fifo
  198. nv_iord($r12, NV_PPWR_FIFO_INTR)
  199. push $r12
  200. mov $r14 (PROC_HOST & 0x0000ffff)
  201. sethi $r14 (PROC_HOST & 0xffff0000)
  202. mov $r13 KMSG_FIFO
  203. call(send)
  204. pop $r12
  205. nv_iowr(NV_PPWR_FIFO_INTR, $r12)
  206. intr_subintr_skip_fifo:
  207. nv_iowr(NV_PPWR_SUBINTR, $r9)
  208. intr_skip_subintr:
  209. and $r9 $r8 NV_PPWR_INTR_PAUSE
  210. bra z #intr_skip_pause
  211. and $r10 0xffbf
  212. intr_skip_pause:
  213. and $r9 $r8 NV_PPWR_INTR_USER0
  214. bra z #intr_skip_user0
  215. and $r10 0xffbf
  216. intr_skip_user0:
  217. nv_iowr(NV_PPWR_INTR_ACK, $r8)
  218. pop $r8
  219. mov $flags $r8
  220. pop $r15
  221. pop $r14
  222. pop $r13
  223. pop $r12
  224. pop $r11
  225. pop $r10
  226. pop $r9
  227. pop $r8
  228. pop $r0
  229. bclr $flags $p0
  230. iret
  231. // calculate the number of ticks in the specified nanoseconds delay
  232. //
  233. // $r15 - current
  234. // $r14 - ns
  235. // $r14 - ticks (return)
  236. // $r0 - zero
  237. ticks_from_ns:
  238. push $r12
  239. push $r11
  240. /* try not losing precision (multiply then divide) */
  241. imm32($r13, HW_TICKS_PER_US)
  242. call #mulu32_32_64
  243. /* use an immeditate, it's ok because HW_TICKS_PER_US < 16 bits */
  244. div $r12 $r12 1000
  245. /* check if there wasn't any overflow */
  246. cmpu b32 $r11 0
  247. bra e #ticks_from_ns_quit
  248. /* let's divide then multiply, too bad for the precision! */
  249. div $r14 $r14 1000
  250. imm32($r13, HW_TICKS_PER_US)
  251. call #mulu32_32_64
  252. /* this cannot overflow as long as HW_TICKS_PER_US < 1000 */
  253. ticks_from_ns_quit:
  254. mov b32 $r14 $r12
  255. pop $r11
  256. pop $r12
  257. ret
  258. // calculate the number of ticks in the specified microsecond delay
  259. //
  260. // $r15 - current
  261. // $r14 - us
  262. // $r14 - ticks (return)
  263. // $r0 - zero
  264. ticks_from_us:
  265. push $r12
  266. push $r11
  267. /* simply multiply $us by HW_TICKS_PER_US */
  268. imm32($r13, HW_TICKS_PER_US)
  269. call #mulu32_32_64
  270. mov b32 $r14 $r12
  271. /* check if there wasn't any overflow */
  272. cmpu b32 $r11 0
  273. bra e #ticks_from_us_quit
  274. /* Overflow! */
  275. clear b32 $r14
  276. ticks_from_us_quit:
  277. pop $r11
  278. pop $r12
  279. ret
  280. // calculate the number of ticks in the specified microsecond delay
  281. //
  282. // $r15 - current
  283. // $r14 - ticks
  284. // $r14 - us (return)
  285. // $r0 - zero
  286. ticks_to_us:
  287. /* simply divide $ticks by HW_TICKS_PER_US */
  288. imm32($r13, HW_TICKS_PER_US)
  289. div $r14 $r14 $r13
  290. ret
  291. // request the current process be sent a message after a timeout expires
  292. //
  293. // $r15 - current
  294. // $r14 - ticks (make sure it is < 2^31 to avoid any possible overflow)
  295. // $r0 - zero
  296. timer:
  297. push $r9
  298. push $r8
  299. // interrupts off to prevent racing with timer isr
  300. bclr $flags ie0
  301. // if current process already has a timer set, bail
  302. ld b32 $r8 D[$r15 + #proc_time]
  303. cmp b32 $r8 0
  304. bra g #timer_done
  305. // halt watchdog timer temporarily
  306. clear b32 $r8
  307. nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)
  308. // find out how much time elapsed since the last update
  309. // of the watchdog and add this time to the wanted ticks
  310. nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
  311. ld b32 $r9 D[$r0 + #time_prev]
  312. sub b32 $r9 $r8
  313. add b32 $r14 $r9
  314. st b32 D[$r15 + #proc_time] $r14
  315. // check for a pending interrupt. if there's one already
  316. // pending, we can just bail since the timer isr will
  317. // queue the next soonest right after it's done
  318. nv_iord($r8, NV_PPWR_INTR)
  319. and $r8 NV_PPWR_INTR_WATCHDOG
  320. bra nz #timer_enable
  321. // update the watchdog if this timer should expire first,
  322. // or if there's no timeout already set
  323. nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
  324. cmp b32 $r14 $r0
  325. bra e #timer_reset
  326. cmp b32 $r14 $r8
  327. bra g #timer_enable
  328. timer_reset:
  329. nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14)
  330. st b32 D[$r0 + #time_prev] $r14
  331. // re-enable the watchdog timer
  332. timer_enable:
  333. mov $r8 1
  334. nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)
  335. // interrupts back on
  336. timer_done:
  337. bset $flags ie0
  338. pop $r8
  339. pop $r9
  340. ret
  341. // send message to another process
  342. //
  343. // $r15 - current
  344. // $r14 - process
  345. // $r13 - message
  346. // $r12 - message data 0
  347. // $r11 - message data 1
  348. // $r0 - zero
  349. send_proc:
  350. push $r8
  351. push $r9
  352. // check for space in queue
  353. ld b32 $r8 D[$r14 + #proc_qget]
  354. ld b32 $r9 D[$r14 + #proc_qput]
  355. xor $r8 #proc_qmaskb
  356. cmp b32 $r8 $r9
  357. bra e #send_done
  358. // enqueue message
  359. and $r8 $r9 #proc_qmaskp
  360. shl b32 $r8 $r8 #proc_qlen
  361. add b32 $r8 #proc_queue
  362. add b32 $r8 $r14
  363. ld b32 $r10 D[$r15 + #proc_id]
  364. st b32 D[$r8 + #msg_process] $r10
  365. st b32 D[$r8 + #msg_message] $r13
  366. st b32 D[$r8 + #msg_data0] $r12
  367. st b32 D[$r8 + #msg_data1] $r11
  368. // increment PUT
  369. add b32 $r9 1
  370. and $r9 #proc_qmaskf
  371. st b32 D[$r14 + #proc_qput] $r9
  372. bset $flags $p2
  373. send_done:
  374. pop $r9
  375. pop $r8
  376. ret
  377. // lookup process structure by its name
  378. //
  379. // $r15 - current
  380. // $r14 - process name
  381. // $r0 - zero
  382. //
  383. // $r14 - process
  384. // $p1 - success
  385. find:
  386. push $r8
  387. mov $r8 #proc_list_head
  388. bset $flags $p1
  389. find_loop:
  390. ld b32 $r10 D[$r8 + #proc_id]
  391. cmp b32 $r10 $r14
  392. bra e #find_done
  393. add b32 $r8 #proc_size
  394. cmp b32 $r8 #proc_list_tail
  395. bra ne #find_loop
  396. bclr $flags $p1
  397. find_done:
  398. mov b32 $r14 $r8
  399. pop $r8
  400. ret
  401. // send message to another process
  402. //
  403. // $r15 - current
  404. // $r14 - process id
  405. // $r13 - message
  406. // $r12 - message data 0
  407. // $r11 - message data 1
  408. // $r0 - zero
  409. send:
  410. call(find)
  411. bra $p1 #send_proc
  412. ret
  413. // process single message for a given process
  414. //
  415. // $r15 - current
  416. // $r14 - process
  417. // $r0 - zero
  418. recv:
  419. push $r9
  420. push $r8
  421. ld b32 $r8 D[$r14 + #proc_qget]
  422. ld b32 $r9 D[$r14 + #proc_qput]
  423. bclr $flags $p1
  424. cmp b32 $r8 $r9
  425. bra e #recv_done
  426. // dequeue message
  427. and $r9 $r8 #proc_qmaskp
  428. add b32 $r8 1
  429. and $r8 #proc_qmaskf
  430. st b32 D[$r14 + #proc_qget] $r8
  431. ld b32 $r10 D[$r14 + #proc_recv]
  432. push $r15
  433. mov $r15 $flags
  434. push $r15
  435. mov b32 $r15 $r14
  436. shl b32 $r9 $r9 #proc_qlen
  437. add b32 $r14 $r9
  438. add b32 $r14 #proc_queue
  439. ld b32 $r11 D[$r14 + #msg_data1]
  440. ld b32 $r12 D[$r14 + #msg_data0]
  441. ld b32 $r13 D[$r14 + #msg_message]
  442. ld b32 $r14 D[$r14 + #msg_process]
  443. // process it
  444. call $r10
  445. pop $r15
  446. mov $flags $r15
  447. bset $flags $p1
  448. pop $r15
  449. recv_done:
  450. pop $r8
  451. pop $r9
  452. ret
  453. init:
  454. // setup stack
  455. nv_iord($r1, NV_PPWR_CAPS)
  456. extr $r1 $r1 9:17
  457. shl b32 $r1 8
  458. mov $sp $r1
  459. #ifdef NVKM_FALCON_MMIO_UAS
  460. // somehow allows the magic "access mmio via D[]" stuff that's
  461. // used by the nv_rd32/nv_wr32 macros to work
  462. mov $r1 0x0010
  463. sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE
  464. nv_iowrs(NV_PPWR_UAS_CONFIG, $r1)
  465. #endif
  466. // route all interrupts except user0/1 and pause to fuc
  467. mov $r1 0x00e0
  468. sethi $r1 0x00000000
  469. nv_iowr(NV_PPWR_INTR_ROUTE, $r1)
  470. // enable watchdog and subintr intrs
  471. mov $r1 NV_PPWR_INTR_EN_CLR_MASK
  472. nv_iowr(NV_PPWR_INTR_EN_CLR, $r1)
  473. mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG
  474. or $r1 NV_PPWR_INTR_EN_SET_SUBINTR
  475. nv_iowr(NV_PPWR_INTR_EN_SET, $r1)
  476. // enable interrupts globally
  477. mov $r1 #intr
  478. sethi $r1 0x00000000
  479. mov $iv0 $r1
  480. bset $flags ie0
  481. // enable watchdog timer
  482. mov $r1 1
  483. nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1)
  484. // bootstrap processes, idle process will be last, and not return
  485. mov $r15 #proc_list_head
  486. init_proc:
  487. ld b32 $r1 D[$r15 + #proc_init]
  488. cmp b32 $r1 0
  489. bra z #init_proc
  490. call $r1
  491. add b32 $r15 #proc_size
  492. bra #init_proc
  493. #endif