misc.S 19 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. /*
  2. * This file contains miscellaneous low-level functions.
  3. * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  4. *
  5. * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
  6. * and Paul Mackerras.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version
  11. * 2 of the License, or (at your option) any later version.
  12. *
  13. */
  14. #include <linux/sys.h>
  15. #include <asm/unistd.h>
  16. #include <asm/errno.h>
  17. #include <asm/processor.h>
  18. #include <asm/page.h>
  19. #include <asm/cache.h>
  20. #include <asm/cputable.h>
  21. #include <asm/mmu.h>
  22. #include <asm/ppc_asm.h>
  23. #include <asm/thread_info.h>
  24. #include <asm/asm-offsets.h>
  25. #ifdef CONFIG_8xx
  26. #define ISYNC_8xx isync
  27. #else
  28. #define ISYNC_8xx
  29. #endif
  30. .text
  31. .align 5
  32. _GLOBAL(__delay)
  33. cmpwi 0,r3,0
  34. mtctr r3
  35. beqlr
  36. 1: bdnz 1b
  37. blr
  38. /*
  39. * Returns (address we're running at) - (address we were linked at)
  40. * for use before the text and data are mapped to KERNELBASE.
  41. */
  42. _GLOBAL(reloc_offset)
  43. mflr r0
  44. bl 1f
  45. 1: mflr r3
  46. lis r4,1b@ha
  47. addi r4,r4,1b@l
  48. subf r3,r4,r3
  49. mtlr r0
  50. blr
  51. /*
  52. * add_reloc_offset(x) returns x + reloc_offset().
  53. */
  54. _GLOBAL(add_reloc_offset)
  55. mflr r0
  56. bl 1f
  57. 1: mflr r5
  58. lis r4,1b@ha
  59. addi r4,r4,1b@l
  60. subf r5,r4,r5
  61. add r3,r3,r5
  62. mtlr r0
  63. blr
  64. /*
  65. * sub_reloc_offset(x) returns x - reloc_offset().
  66. */
  67. _GLOBAL(sub_reloc_offset)
  68. mflr r0
  69. bl 1f
  70. 1: mflr r5
  71. lis r4,1b@ha
  72. addi r4,r4,1b@l
  73. subf r5,r4,r5
  74. subf r3,r5,r3
  75. mtlr r0
  76. blr
  77. /*
  78. * reloc_got2 runs through the .got2 section adding an offset
  79. * to each entry.
  80. */
  81. _GLOBAL(reloc_got2)
  82. mflr r11
  83. lis r7,__got2_start@ha
  84. addi r7,r7,__got2_start@l
  85. lis r8,__got2_end@ha
  86. addi r8,r8,__got2_end@l
  87. subf r8,r7,r8
  88. srwi. r8,r8,2
  89. beqlr
  90. mtctr r8
  91. bl 1f
  92. 1: mflr r0
  93. lis r4,1b@ha
  94. addi r4,r4,1b@l
  95. subf r0,r4,r0
  96. add r7,r0,r7
  97. 2: lwz r0,0(r7)
  98. add r0,r0,r3
  99. stw r0,0(r7)
  100. addi r7,r7,4
  101. bdnz 2b
  102. mtlr r11
  103. blr
  104. /*
  105. * identify_cpu,
  106. * called with r3 = data offset and r4 = CPU number
  107. * doesn't change r3
  108. */
  109. _GLOBAL(identify_cpu)
  110. addis r8,r3,cpu_specs@ha
  111. addi r8,r8,cpu_specs@l
  112. mfpvr r7
  113. 1:
  114. lwz r5,CPU_SPEC_PVR_MASK(r8)
  115. and r5,r5,r7
  116. lwz r6,CPU_SPEC_PVR_VALUE(r8)
  117. cmplw 0,r6,r5
  118. beq 1f
  119. addi r8,r8,CPU_SPEC_ENTRY_SIZE
  120. b 1b
  121. 1:
  122. addis r6,r3,cur_cpu_spec@ha
  123. addi r6,r6,cur_cpu_spec@l
  124. sub r8,r8,r3
  125. stw r8,0(r6)
  126. blr
  127. /*
  128. * do_cpu_ftr_fixups - goes through the list of CPU feature fixups
  129. * and writes nop's over sections of code that don't apply for this cpu.
  130. * r3 = data offset (not changed)
  131. */
  132. _GLOBAL(do_cpu_ftr_fixups)
  133. /* Get CPU 0 features */
  134. addis r6,r3,cur_cpu_spec@ha
  135. addi r6,r6,cur_cpu_spec@l
  136. lwz r4,0(r6)
  137. add r4,r4,r3
  138. lwz r4,CPU_SPEC_FEATURES(r4)
  139. /* Get the fixup table */
  140. addis r6,r3,__start___ftr_fixup@ha
  141. addi r6,r6,__start___ftr_fixup@l
  142. addis r7,r3,__stop___ftr_fixup@ha
  143. addi r7,r7,__stop___ftr_fixup@l
  144. /* Do the fixup */
  145. 1: cmplw 0,r6,r7
  146. bgelr
  147. addi r6,r6,16
  148. lwz r8,-16(r6) /* mask */
  149. and r8,r8,r4
  150. lwz r9,-12(r6) /* value */
  151. cmplw 0,r8,r9
  152. beq 1b
  153. lwz r8,-8(r6) /* section begin */
  154. lwz r9,-4(r6) /* section end */
  155. subf. r9,r8,r9
  156. beq 1b
  157. /* write nops over the section of code */
  158. /* todo: if large section, add a branch at the start of it */
  159. srwi r9,r9,2
  160. mtctr r9
  161. add r8,r8,r3
  162. lis r0,0x60000000@h /* nop */
  163. 3: stw r0,0(r8)
  164. andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l
  165. beq 2f
  166. dcbst 0,r8 /* suboptimal, but simpler */
  167. sync
  168. icbi 0,r8
  169. 2: addi r8,r8,4
  170. bdnz 3b
  171. sync /* additional sync needed on g4 */
  172. isync
  173. b 1b
  174. /*
  175. * call_setup_cpu - call the setup_cpu function for this cpu
  176. * r3 = data offset, r24 = cpu number
  177. *
  178. * Setup function is called with:
  179. * r3 = data offset
  180. * r4 = ptr to CPU spec (relocated)
  181. */
  182. _GLOBAL(call_setup_cpu)
  183. addis r4,r3,cur_cpu_spec@ha
  184. addi r4,r4,cur_cpu_spec@l
  185. lwz r4,0(r4)
  186. add r4,r4,r3
  187. lwz r5,CPU_SPEC_SETUP(r4)
  188. cmpi 0,r5,0
  189. add r5,r5,r3
  190. beqlr
  191. mtctr r5
  192. bctr
  193. /*
  194. * complement mask on the msr then "or" some values on.
  195. * _nmask_and_or_msr(nmask, value_to_or)
  196. */
  197. _GLOBAL(_nmask_and_or_msr)
  198. mfmsr r0 /* Get current msr */
  199. andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
  200. or r0,r0,r4 /* Or on the bits in r4 (second parm) */
  201. SYNC /* Some chip revs have problems here... */
  202. mtmsr r0 /* Update machine state */
  203. isync
  204. blr /* Done */
  205. /*
  206. * Flush MMU TLB
  207. */
  208. _GLOBAL(_tlbia)
  209. #if defined(CONFIG_40x)
  210. sync /* Flush to memory before changing mapping */
  211. tlbia
  212. isync /* Flush shadow TLB */
  213. #elif defined(CONFIG_44x)
  214. li r3,0
  215. sync
  216. /* Load high watermark */
  217. lis r4,tlb_44x_hwater@ha
  218. lwz r5,tlb_44x_hwater@l(r4)
  219. 1: tlbwe r3,r3,PPC44x_TLB_PAGEID
  220. addi r3,r3,1
  221. cmpw 0,r3,r5
  222. ble 1b
  223. isync
  224. #elif defined(CONFIG_FSL_BOOKE)
  225. /* Invalidate all entries in TLB0 */
  226. li r3, 0x04
  227. tlbivax 0,3
  228. /* Invalidate all entries in TLB1 */
  229. li r3, 0x0c
  230. tlbivax 0,3
  231. /* Invalidate all entries in TLB2 */
  232. li r3, 0x14
  233. tlbivax 0,3
  234. /* Invalidate all entries in TLB3 */
  235. li r3, 0x1c
  236. tlbivax 0,3
  237. msync
  238. #ifdef CONFIG_SMP
  239. tlbsync
  240. #endif /* CONFIG_SMP */
  241. #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
  242. #if defined(CONFIG_SMP)
  243. rlwinm r8,r1,0,0,18
  244. lwz r8,TI_CPU(r8)
  245. oris r8,r8,10
  246. mfmsr r10
  247. SYNC
  248. rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
  249. rlwinm r0,r0,0,28,26 /* clear DR */
  250. mtmsr r0
  251. SYNC_601
  252. isync
  253. lis r9,mmu_hash_lock@h
  254. ori r9,r9,mmu_hash_lock@l
  255. tophys(r9,r9)
  256. 10: lwarx r7,0,r9
  257. cmpwi 0,r7,0
  258. bne- 10b
  259. stwcx. r8,0,r9
  260. bne- 10b
  261. sync
  262. tlbia
  263. sync
  264. TLBSYNC
  265. li r0,0
  266. stw r0,0(r9) /* clear mmu_hash_lock */
  267. mtmsr r10
  268. SYNC_601
  269. isync
  270. #else /* CONFIG_SMP */
  271. sync
  272. tlbia
  273. sync
  274. #endif /* CONFIG_SMP */
  275. #endif /* ! defined(CONFIG_40x) */
  276. blr
  277. /*
  278. * Flush MMU TLB for a particular address
  279. */
  280. _GLOBAL(_tlbie)
  281. #if defined(CONFIG_40x)
  282. tlbsx. r3, 0, r3
  283. bne 10f
  284. sync
  285. /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.
  286. * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate
  287. * the TLB entry. */
  288. tlbwe r3, r3, TLB_TAG
  289. isync
  290. 10:
  291. #elif defined(CONFIG_44x)
  292. mfspr r4,SPRN_MMUCR
  293. mfspr r5,SPRN_PID /* Get PID */
  294. rlwimi r4,r5,0,24,31 /* Set TID */
  295. mtspr SPRN_MMUCR,r4
  296. tlbsx. r3, 0, r3
  297. bne 10f
  298. sync
  299. /* There are only 64 TLB entries, so r3 < 64,
  300. * which means bit 22, is clear. Since 22 is
  301. * the V bit in the TLB_PAGEID, loading this
  302. * value will invalidate the TLB entry.
  303. */
  304. tlbwe r3, r3, PPC44x_TLB_PAGEID
  305. isync
  306. 10:
  307. #elif defined(CONFIG_FSL_BOOKE)
  308. rlwinm r4, r3, 0, 0, 19
  309. ori r5, r4, 0x08 /* TLBSEL = 1 */
  310. ori r6, r4, 0x10 /* TLBSEL = 2 */
  311. ori r7, r4, 0x18 /* TLBSEL = 3 */
  312. tlbivax 0, r4
  313. tlbivax 0, r5
  314. tlbivax 0, r6
  315. tlbivax 0, r7
  316. msync
  317. #if defined(CONFIG_SMP)
  318. tlbsync
  319. #endif /* CONFIG_SMP */
  320. #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
  321. #if defined(CONFIG_SMP)
  322. rlwinm r8,r1,0,0,18
  323. lwz r8,TI_CPU(r8)
  324. oris r8,r8,11
  325. mfmsr r10
  326. SYNC
  327. rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
  328. rlwinm r0,r0,0,28,26 /* clear DR */
  329. mtmsr r0
  330. SYNC_601
  331. isync
  332. lis r9,mmu_hash_lock@h
  333. ori r9,r9,mmu_hash_lock@l
  334. tophys(r9,r9)
  335. 10: lwarx r7,0,r9
  336. cmpwi 0,r7,0
  337. bne- 10b
  338. stwcx. r8,0,r9
  339. bne- 10b
  340. eieio
  341. tlbie r3
  342. sync
  343. TLBSYNC
  344. li r0,0
  345. stw r0,0(r9) /* clear mmu_hash_lock */
  346. mtmsr r10
  347. SYNC_601
  348. isync
  349. #else /* CONFIG_SMP */
  350. tlbie r3
  351. sync
  352. #endif /* CONFIG_SMP */
  353. #endif /* ! CONFIG_40x */
  354. blr
  355. /*
  356. * Flush instruction cache.
  357. * This is a no-op on the 601.
  358. */
  359. _GLOBAL(flush_instruction_cache)
  360. #if defined(CONFIG_8xx)
  361. isync
  362. lis r5, IDC_INVALL@h
  363. mtspr SPRN_IC_CST, r5
  364. #elif defined(CONFIG_4xx)
  365. #ifdef CONFIG_403GCX
  366. li r3, 512
  367. mtctr r3
  368. lis r4, KERNELBASE@h
  369. 1: iccci 0, r4
  370. addi r4, r4, 16
  371. bdnz 1b
  372. #else
  373. lis r3, KERNELBASE@h
  374. iccci 0,r3
  375. #endif
  376. #elif CONFIG_FSL_BOOKE
  377. BEGIN_FTR_SECTION
  378. mfspr r3,SPRN_L1CSR0
  379. ori r3,r3,L1CSR0_CFI|L1CSR0_CLFC
  380. /* msync; isync recommended here */
  381. mtspr SPRN_L1CSR0,r3
  382. isync
  383. blr
  384. END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
  385. mfspr r3,SPRN_L1CSR1
  386. ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
  387. mtspr SPRN_L1CSR1,r3
  388. #else
  389. mfspr r3,SPRN_PVR
  390. rlwinm r3,r3,16,16,31
  391. cmpwi 0,r3,1
  392. beqlr /* for 601, do nothing */
  393. /* 603/604 processor - use invalidate-all bit in HID0 */
  394. mfspr r3,SPRN_HID0
  395. ori r3,r3,HID0_ICFI
  396. mtspr SPRN_HID0,r3
  397. #endif /* CONFIG_8xx/4xx */
  398. isync
  399. blr
  400. /*
  401. * Write any modified data cache blocks out to memory
  402. * and invalidate the corresponding instruction cache blocks.
  403. * This is a no-op on the 601.
  404. *
  405. * __flush_icache_range(unsigned long start, unsigned long stop)
  406. */
  407. _GLOBAL(__flush_icache_range)
  408. BEGIN_FTR_SECTION
  409. blr /* for 601, do nothing */
  410. END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
  411. li r5,L1_CACHE_BYTES-1
  412. andc r3,r3,r5
  413. subf r4,r3,r4
  414. add r4,r4,r5
  415. srwi. r4,r4,L1_CACHE_SHIFT
  416. beqlr
  417. mtctr r4
  418. mr r6,r3
  419. 1: dcbst 0,r3
  420. addi r3,r3,L1_CACHE_BYTES
  421. bdnz 1b
  422. sync /* wait for dcbst's to get to ram */
  423. mtctr r4
  424. 2: icbi 0,r6
  425. addi r6,r6,L1_CACHE_BYTES
  426. bdnz 2b
  427. sync /* additional sync needed on g4 */
  428. isync
  429. blr
  430. /*
  431. * Write any modified data cache blocks out to memory.
  432. * Does not invalidate the corresponding cache lines (especially for
  433. * any corresponding instruction cache).
  434. *
  435. * clean_dcache_range(unsigned long start, unsigned long stop)
  436. */
  437. _GLOBAL(clean_dcache_range)
  438. li r5,L1_CACHE_BYTES-1
  439. andc r3,r3,r5
  440. subf r4,r3,r4
  441. add r4,r4,r5
  442. srwi. r4,r4,L1_CACHE_SHIFT
  443. beqlr
  444. mtctr r4
  445. 1: dcbst 0,r3
  446. addi r3,r3,L1_CACHE_BYTES
  447. bdnz 1b
  448. sync /* wait for dcbst's to get to ram */
  449. blr
  450. /*
  451. * Write any modified data cache blocks out to memory and invalidate them.
  452. * Does not invalidate the corresponding instruction cache blocks.
  453. *
  454. * flush_dcache_range(unsigned long start, unsigned long stop)
  455. */
  456. _GLOBAL(flush_dcache_range)
  457. li r5,L1_CACHE_BYTES-1
  458. andc r3,r3,r5
  459. subf r4,r3,r4
  460. add r4,r4,r5
  461. srwi. r4,r4,L1_CACHE_SHIFT
  462. beqlr
  463. mtctr r4
  464. 1: dcbf 0,r3
  465. addi r3,r3,L1_CACHE_BYTES
  466. bdnz 1b
  467. sync /* wait for dcbst's to get to ram */
  468. blr
  469. /*
  470. * Like above, but invalidate the D-cache. This is used by the 8xx
  471. * to invalidate the cache so the PPC core doesn't get stale data
  472. * from the CPM (no cache snooping here :-).
  473. *
  474. * invalidate_dcache_range(unsigned long start, unsigned long stop)
  475. */
  476. _GLOBAL(invalidate_dcache_range)
  477. li r5,L1_CACHE_BYTES-1
  478. andc r3,r3,r5
  479. subf r4,r3,r4
  480. add r4,r4,r5
  481. srwi. r4,r4,L1_CACHE_SHIFT
  482. beqlr
  483. mtctr r4
  484. 1: dcbi 0,r3
  485. addi r3,r3,L1_CACHE_BYTES
  486. bdnz 1b
  487. sync /* wait for dcbi's to get to ram */
  488. blr
  489. #ifdef CONFIG_NOT_COHERENT_CACHE
  490. /*
  491. * 40x cores have 8K or 16K dcache and 32 byte line size.
  492. * 44x has a 32K dcache and 32 byte line size.
  493. * 8xx has 1, 2, 4, 8K variants.
  494. * For now, cover the worst case of the 44x.
  495. * Must be called with external interrupts disabled.
  496. */
  497. #define CACHE_NWAYS 64
  498. #define CACHE_NLINES 16
  499. _GLOBAL(flush_dcache_all)
  500. li r4, (2 * CACHE_NWAYS * CACHE_NLINES)
  501. mtctr r4
  502. lis r5, KERNELBASE@h
  503. 1: lwz r3, 0(r5) /* Load one word from every line */
  504. addi r5, r5, L1_CACHE_BYTES
  505. bdnz 1b
  506. blr
  507. #endif /* CONFIG_NOT_COHERENT_CACHE */
  508. /*
  509. * Flush a particular page from the data cache to RAM.
  510. * Note: this is necessary because the instruction cache does *not*
  511. * snoop from the data cache.
  512. * This is a no-op on the 601 which has a unified cache.
  513. *
  514. * void __flush_dcache_icache(void *page)
  515. */
  516. _GLOBAL(__flush_dcache_icache)
  517. BEGIN_FTR_SECTION
  518. blr /* for 601, do nothing */
  519. END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
  520. rlwinm r3,r3,0,0,19 /* Get page base address */
  521. li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
  522. mtctr r4
  523. mr r6,r3
  524. 0: dcbst 0,r3 /* Write line to ram */
  525. addi r3,r3,L1_CACHE_BYTES
  526. bdnz 0b
  527. sync
  528. mtctr r4
  529. 1: icbi 0,r6
  530. addi r6,r6,L1_CACHE_BYTES
  531. bdnz 1b
  532. sync
  533. isync
  534. blr
  535. /*
  536. * Flush a particular page from the data cache to RAM, identified
  537. * by its physical address. We turn off the MMU so we can just use
  538. * the physical address (this may be a highmem page without a kernel
  539. * mapping).
  540. *
  541. * void __flush_dcache_icache_phys(unsigned long physaddr)
  542. */
  543. _GLOBAL(__flush_dcache_icache_phys)
  544. BEGIN_FTR_SECTION
  545. blr /* for 601, do nothing */
  546. END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
  547. mfmsr r10
  548. rlwinm r0,r10,0,28,26 /* clear DR */
  549. mtmsr r0
  550. isync
  551. rlwinm r3,r3,0,0,19 /* Get page base address */
  552. li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
  553. mtctr r4
  554. mr r6,r3
  555. 0: dcbst 0,r3 /* Write line to ram */
  556. addi r3,r3,L1_CACHE_BYTES
  557. bdnz 0b
  558. sync
  559. mtctr r4
  560. 1: icbi 0,r6
  561. addi r6,r6,L1_CACHE_BYTES
  562. bdnz 1b
  563. sync
  564. mtmsr r10 /* restore DR */
  565. isync
  566. blr
  567. /*
  568. * Clear pages using the dcbz instruction, which doesn't cause any
  569. * memory traffic (except to write out any cache lines which get
  570. * displaced). This only works on cacheable memory.
  571. *
  572. * void clear_pages(void *page, int order) ;
  573. */
  574. _GLOBAL(clear_pages)
  575. li r0,4096/L1_CACHE_BYTES
  576. slw r0,r0,r4
  577. mtctr r0
  578. #ifdef CONFIG_8xx
  579. li r4, 0
  580. 1: stw r4, 0(r3)
  581. stw r4, 4(r3)
  582. stw r4, 8(r3)
  583. stw r4, 12(r3)
  584. #else
  585. 1: dcbz 0,r3
  586. #endif
  587. addi r3,r3,L1_CACHE_BYTES
  588. bdnz 1b
  589. blr
  590. /*
  591. * Copy a whole page. We use the dcbz instruction on the destination
  592. * to reduce memory traffic (it eliminates the unnecessary reads of
  593. * the destination into cache). This requires that the destination
  594. * is cacheable.
  595. */
  596. #define COPY_16_BYTES \
  597. lwz r6,4(r4); \
  598. lwz r7,8(r4); \
  599. lwz r8,12(r4); \
  600. lwzu r9,16(r4); \
  601. stw r6,4(r3); \
  602. stw r7,8(r3); \
  603. stw r8,12(r3); \
  604. stwu r9,16(r3)
  605. _GLOBAL(copy_page)
  606. addi r3,r3,-4
  607. addi r4,r4,-4
  608. #ifdef CONFIG_8xx
  609. /* don't use prefetch on 8xx */
  610. li r0,4096/L1_CACHE_BYTES
  611. mtctr r0
  612. 1: COPY_16_BYTES
  613. bdnz 1b
  614. blr
  615. #else /* not 8xx, we can prefetch */
  616. li r5,4
  617. #if MAX_COPY_PREFETCH > 1
  618. li r0,MAX_COPY_PREFETCH
  619. li r11,4
  620. mtctr r0
  621. 11: dcbt r11,r4
  622. addi r11,r11,L1_CACHE_BYTES
  623. bdnz 11b
  624. #else /* MAX_COPY_PREFETCH == 1 */
  625. dcbt r5,r4
  626. li r11,L1_CACHE_BYTES+4
  627. #endif /* MAX_COPY_PREFETCH */
  628. li r0,4096/L1_CACHE_BYTES - MAX_COPY_PREFETCH
  629. crclr 4*cr0+eq
  630. 2:
  631. mtctr r0
  632. 1:
  633. dcbt r11,r4
  634. dcbz r5,r3
  635. COPY_16_BYTES
  636. #if L1_CACHE_BYTES >= 32
  637. COPY_16_BYTES
  638. #if L1_CACHE_BYTES >= 64
  639. COPY_16_BYTES
  640. COPY_16_BYTES
  641. #if L1_CACHE_BYTES >= 128
  642. COPY_16_BYTES
  643. COPY_16_BYTES
  644. COPY_16_BYTES
  645. COPY_16_BYTES
  646. #endif
  647. #endif
  648. #endif
  649. bdnz 1b
  650. beqlr
  651. crnot 4*cr0+eq,4*cr0+eq
  652. li r0,MAX_COPY_PREFETCH
  653. li r11,4
  654. b 2b
  655. #endif /* CONFIG_8xx */
  656. /*
  657. * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
  658. * void atomic_set_mask(atomic_t mask, atomic_t *addr);
  659. */
  660. _GLOBAL(atomic_clear_mask)
  661. 10: lwarx r5,0,r4
  662. andc r5,r5,r3
  663. PPC405_ERR77(0,r4)
  664. stwcx. r5,0,r4
  665. bne- 10b
  666. blr
  667. _GLOBAL(atomic_set_mask)
  668. 10: lwarx r5,0,r4
  669. or r5,r5,r3
  670. PPC405_ERR77(0,r4)
  671. stwcx. r5,0,r4
  672. bne- 10b
  673. blr
  674. /*
  675. * I/O string operations
  676. *
  677. * insb(port, buf, len)
  678. * outsb(port, buf, len)
  679. * insw(port, buf, len)
  680. * outsw(port, buf, len)
  681. * insl(port, buf, len)
  682. * outsl(port, buf, len)
  683. * insw_ns(port, buf, len)
  684. * outsw_ns(port, buf, len)
  685. * insl_ns(port, buf, len)
  686. * outsl_ns(port, buf, len)
  687. *
  688. * The *_ns versions don't do byte-swapping.
  689. */
  690. _GLOBAL(_insb)
  691. cmpwi 0,r5,0
  692. mtctr r5
  693. subi r4,r4,1
  694. blelr-
  695. 00: lbz r5,0(r3)
  696. 01: eieio
  697. 02: stbu r5,1(r4)
  698. ISYNC_8xx
  699. .section .fixup,"ax"
  700. 03: blr
  701. .text
  702. .section __ex_table, "a"
  703. .align 2
  704. .long 00b, 03b
  705. .long 01b, 03b
  706. .long 02b, 03b
  707. .text
  708. bdnz 00b
  709. blr
  710. _GLOBAL(_outsb)
  711. cmpwi 0,r5,0
  712. mtctr r5
  713. subi r4,r4,1
  714. blelr-
  715. 00: lbzu r5,1(r4)
  716. 01: stb r5,0(r3)
  717. 02: eieio
  718. ISYNC_8xx
  719. .section .fixup,"ax"
  720. 03: blr
  721. .text
  722. .section __ex_table, "a"
  723. .align 2
  724. .long 00b, 03b
  725. .long 01b, 03b
  726. .long 02b, 03b
  727. .text
  728. bdnz 00b
  729. blr
  730. _GLOBAL(_insw)
  731. cmpwi 0,r5,0
  732. mtctr r5
  733. subi r4,r4,2
  734. blelr-
  735. 00: lhbrx r5,0,r3
  736. 01: eieio
  737. 02: sthu r5,2(r4)
  738. ISYNC_8xx
  739. .section .fixup,"ax"
  740. 03: blr
  741. .text
  742. .section __ex_table, "a"
  743. .align 2
  744. .long 00b, 03b
  745. .long 01b, 03b
  746. .long 02b, 03b
  747. .text
  748. bdnz 00b
  749. blr
  750. _GLOBAL(_outsw)
  751. cmpwi 0,r5,0
  752. mtctr r5
  753. subi r4,r4,2
  754. blelr-
  755. 00: lhzu r5,2(r4)
  756. 01: eieio
  757. 02: sthbrx r5,0,r3
  758. ISYNC_8xx
  759. .section .fixup,"ax"
  760. 03: blr
  761. .text
  762. .section __ex_table, "a"
  763. .align 2
  764. .long 00b, 03b
  765. .long 01b, 03b
  766. .long 02b, 03b
  767. .text
  768. bdnz 00b
  769. blr
  770. _GLOBAL(_insl)
  771. cmpwi 0,r5,0
  772. mtctr r5
  773. subi r4,r4,4
  774. blelr-
  775. 00: lwbrx r5,0,r3
  776. 01: eieio
  777. 02: stwu r5,4(r4)
  778. ISYNC_8xx
  779. .section .fixup,"ax"
  780. 03: blr
  781. .text
  782. .section __ex_table, "a"
  783. .align 2
  784. .long 00b, 03b
  785. .long 01b, 03b
  786. .long 02b, 03b
  787. .text
  788. bdnz 00b
  789. blr
  790. _GLOBAL(_outsl)
  791. cmpwi 0,r5,0
  792. mtctr r5
  793. subi r4,r4,4
  794. blelr-
  795. 00: lwzu r5,4(r4)
  796. 01: stwbrx r5,0,r3
  797. 02: eieio
  798. ISYNC_8xx
  799. .section .fixup,"ax"
  800. 03: blr
  801. .text
  802. .section __ex_table, "a"
  803. .align 2
  804. .long 00b, 03b
  805. .long 01b, 03b
  806. .long 02b, 03b
  807. .text
  808. bdnz 00b
  809. blr
  810. _GLOBAL(__ide_mm_insw)
  811. _GLOBAL(_insw_ns)
  812. cmpwi 0,r5,0
  813. mtctr r5
  814. subi r4,r4,2
  815. blelr-
  816. 00: lhz r5,0(r3)
  817. 01: eieio
  818. 02: sthu r5,2(r4)
  819. ISYNC_8xx
  820. .section .fixup,"ax"
  821. 03: blr
  822. .text
  823. .section __ex_table, "a"
  824. .align 2
  825. .long 00b, 03b
  826. .long 01b, 03b
  827. .long 02b, 03b
  828. .text
  829. bdnz 00b
  830. blr
  831. _GLOBAL(__ide_mm_outsw)
  832. _GLOBAL(_outsw_ns)
  833. cmpwi 0,r5,0
  834. mtctr r5
  835. subi r4,r4,2
  836. blelr-
  837. 00: lhzu r5,2(r4)
  838. 01: sth r5,0(r3)
  839. 02: eieio
  840. ISYNC_8xx
  841. .section .fixup,"ax"
  842. 03: blr
  843. .text
  844. .section __ex_table, "a"
  845. .align 2
  846. .long 00b, 03b
  847. .long 01b, 03b
  848. .long 02b, 03b
  849. .text
  850. bdnz 00b
  851. blr
  852. _GLOBAL(__ide_mm_insl)
  853. _GLOBAL(_insl_ns)
  854. cmpwi 0,r5,0
  855. mtctr r5
  856. subi r4,r4,4
  857. blelr-
  858. 00: lwz r5,0(r3)
  859. 01: eieio
  860. 02: stwu r5,4(r4)
  861. ISYNC_8xx
  862. .section .fixup,"ax"
  863. 03: blr
  864. .text
  865. .section __ex_table, "a"
  866. .align 2
  867. .long 00b, 03b
  868. .long 01b, 03b
  869. .long 02b, 03b
  870. .text
  871. bdnz 00b
  872. blr
  873. _GLOBAL(__ide_mm_outsl)
  874. _GLOBAL(_outsl_ns)
  875. cmpwi 0,r5,0
  876. mtctr r5
  877. subi r4,r4,4
  878. blelr-
  879. 00: lwzu r5,4(r4)
  880. 01: stw r5,0(r3)
  881. 02: eieio
  882. ISYNC_8xx
  883. .section .fixup,"ax"
  884. 03: blr
  885. .text
  886. .section __ex_table, "a"
  887. .align 2
  888. .long 00b, 03b
  889. .long 01b, 03b
  890. .long 02b, 03b
  891. .text
  892. bdnz 00b
  893. blr
  894. /*
  895. * Extended precision shifts.
  896. *
  897. * Updated to be valid for shift counts from 0 to 63 inclusive.
  898. * -- Gabriel
  899. *
  900. * R3/R4 has 64 bit value
  901. * R5 has shift count
  902. * result in R3/R4
  903. *
  904. * ashrdi3: arithmetic right shift (sign propagation)
  905. * lshrdi3: logical right shift
  906. * ashldi3: left shift
  907. */
  908. _GLOBAL(__ashrdi3)
  909. subfic r6,r5,32
  910. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  911. addi r7,r5,32 # could be xori, or addi with -32
  912. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  913. rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
  914. sraw r7,r3,r7 # t2 = MSW >> (count-32)
  915. or r4,r4,r6 # LSW |= t1
  916. slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
  917. sraw r3,r3,r5 # MSW = MSW >> count
  918. or r4,r4,r7 # LSW |= t2
  919. blr
  920. _GLOBAL(__ashldi3)
  921. subfic r6,r5,32
  922. slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
  923. addi r7,r5,32 # could be xori, or addi with -32
  924. srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
  925. slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
  926. or r3,r3,r6 # MSW |= t1
  927. slw r4,r4,r5 # LSW = LSW << count
  928. or r3,r3,r7 # MSW |= t2
  929. blr
  930. _GLOBAL(__lshrdi3)
  931. subfic r6,r5,32
  932. srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
  933. addi r7,r5,32 # could be xori, or addi with -32
  934. slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
  935. srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
  936. or r4,r4,r6 # LSW |= t1
  937. srw r3,r3,r5 # MSW = MSW >> count
  938. or r4,r4,r7 # LSW |= t2
  939. blr
  940. _GLOBAL(abs)
  941. srawi r4,r3,31
  942. xor r3,r3,r4
  943. sub r3,r3,r4
  944. blr
  945. _GLOBAL(_get_SP)
  946. mr r3,r1 /* Close enough */
  947. blr
  948. /*
  949. * Create a kernel thread
  950. * kernel_thread(fn, arg, flags)
  951. */
  952. _GLOBAL(kernel_thread)
  953. stwu r1,-16(r1)
  954. stw r30,8(r1)
  955. stw r31,12(r1)
  956. mr r30,r3 /* function */
  957. mr r31,r4 /* argument */
  958. ori r3,r5,CLONE_VM /* flags */
  959. oris r3,r3,CLONE_UNTRACED>>16
  960. li r4,0 /* new sp (unused) */
  961. li r0,__NR_clone
  962. sc
  963. cmpwi 0,r3,0 /* parent or child? */
  964. bne 1f /* return if parent */
  965. li r0,0 /* make top-level stack frame */
  966. stwu r0,-16(r1)
  967. mtlr r30 /* fn addr in lr */
  968. mr r3,r31 /* load arg and call fn */
  969. PPC440EP_ERR42
  970. blrl
  971. li r0,__NR_exit /* exit if function returns */
  972. li r3,0
  973. sc
  974. 1: lwz r30,8(r1)
  975. lwz r31,12(r1)
  976. addi r1,r1,16
  977. blr
  978. /*
  979. * This routine is just here to keep GCC happy - sigh...
  980. */
  981. _GLOBAL(__main)
  982. blr
  983. #define SYSCALL(name) \
  984. _GLOBAL(name) \
  985. li r0,__NR_##name; \
  986. sc; \
  987. bnslr; \
  988. lis r4,errno@ha; \
  989. stw r3,errno@l(r4); \
  990. li r3,-1; \
  991. blr
  992. SYSCALL(execve)