l.s 18 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. #include "x16.h"
  2. #include "mem.h"
  3. #define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */
  4. #define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */
  5. #define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */
  6. #ifdef PXE
  7. #define PDB 0x90000 /* temporary page tables (24KB) */
  8. #else
  9. #define PDB 0x08000
  10. #endif PXE
  11. #define NoScreenBlank 1
  12. /*#define ResetDiscs 1*/
  13. TEXT origin(SB), $0
  14. /*
  15. * This part of l.s is used only in the boot kernel.
  16. * It assumes that we are in real address mode, i.e.,
  17. * that we look like an 8086.
  18. *
  19. * Make sure the segments are reasonable.
  20. * If we were started directly from the BIOS
  21. * (i.e. no MS-DOS) then DS may not be
  22. * right.
  23. */
  24. MOVW CS, AX
  25. MOVW AX, DS
  26. #ifdef NoScreenBlank
  27. /*
  28. * Get the current video mode. If it isn't mode 3,
  29. * set text mode 3.
  30. * Well, no. Windows95 won't co-operate here so we have
  31. * to explicitly set mode 3.
  32. */
  33. XORL AX, AX
  34. MOVB $0x0F, AH
  35. INT $0x10 /* get current video mode in AL */
  36. CMPB AL, $03
  37. JEQ sayhello
  38. #endif /* NoScreenBlank */
  39. XORL AX, AX
  40. MOVB $0x03, AL
  41. INT $0x10 /* set video mode in AL */
  42. sayhello:
  43. LWI(hello(SB), rSI)
  44. CALL16(biosputs(SB))
  45. #ifdef ResetDiscs
  46. XORL AX, AX /* reset disc system */
  47. XORL DX, DX
  48. MOVB $0x80, DL
  49. INT $0x13
  50. #endif /* ResetDiscs */
  51. #ifdef DOTCOM
  52. /*
  53. * relocate everything to a half meg and jump there
  54. * - looks weird because it is being assembled by a 32 bit
  55. * assembler for a 16 bit world
  56. *
  57. * only b.com does this - not 9load
  58. */
  59. MOVL $0,BX
  60. INCL BX
  61. SHLL $15,BX
  62. MOVL BX,CX
  63. MOVW BX,ES
  64. MOVL $0,SI
  65. MOVL SI,DI
  66. CLD
  67. REP
  68. MOVSL
  69. /*
  70. * Jump to the copied image;
  71. * fix up the DS for the new location.
  72. */
  73. FARJUMP16(0x8000, _start8000(SB))
  74. TEXT _start8000(SB), $0
  75. MFSR(rCS, rAX) /* fix up DS, ES (0x8000) */
  76. MTSR(rAX, rDS)
  77. MTSR(rAX, rES)
  78. /*
  79. * If we are already in protected mode, have to get back
  80. * to real mode before trying any privileged operations
  81. * (like going into protected mode...).
  82. * Try to reset with a restart vector.
  83. */
  84. MFCR(rCR0, rAX) /* are we in protected mode? */
  85. ANDI(0x0001, rAX)
  86. JEQ _real
  87. CLR(rBX)
  88. MTSR(rBX, rES)
  89. LWI(0x0467, rBX) /* reset entry point */
  90. LWI(_start8000(SB), rAX) /* offset within segment */
  91. BYTE $0x26
  92. BYTE $0x89
  93. BYTE $0x07 /* MOVW AX, ES:[BX] */
  94. LBI(0x69, rBL)
  95. MFSR(rCS, rAX) /* segment */
  96. BYTE $0x26
  97. BYTE $0x89
  98. BYTE $0x07 /* MOVW AX, ES:[BX] */
  99. CLR(rDX)
  100. OUTPORTB(0x70, 0x8F)
  101. OUTPORTB(0x71, 0x0A)
  102. FARJUMP16(0xFFFF, 0x0000) /* reset */
  103. #endif /* DOTCOM */
  104. _real:
  105. /*
  106. * do things that need to be done in real mode.
  107. * the results get written to CONFADDR (0x1200)
  108. * in a series of <4-byte-magic-number><block-of-data>
  109. * the data length is dependent on the magic number.
  110. *
  111. * this gets parsed by conf.c:/^readlsconf
  112. *
  113. * N.B. CALL16 kills rDI, so we can't call anything.
  114. */
  115. LWI(0x0000, rAX)
  116. MTSR(rAX, rES)
  117. LWI(0x1200, rDI)
  118. /*
  119. * turn off interrupts
  120. */
  121. CLI
  122. /*
  123. * detect APM1.2 bios support
  124. */
  125. /* save DI */
  126. SW(rDI, rock(SB))
  127. /* disconnect anyone else */
  128. LWI(0x5304, rAX)
  129. LWI(0x0000, rBX)
  130. INT $0x15
  131. /* connect */
  132. CLC
  133. LWI(0x5303, rAX)
  134. LWI(0x0000, rBX)
  135. INT $0x15
  136. CLI /* apm put interrupts back? */
  137. JC noapm
  138. OPSIZE; PUSHR(rSI)
  139. OPSIZE; PUSHR(rBX)
  140. PUSHR(rDI)
  141. PUSHR(rDX)
  142. PUSHR(rCX)
  143. PUSHR(rAX)
  144. /* put DI, ES back */
  145. LW(rock(SB), rDI)
  146. LWI(0x0000, rAX)
  147. MTSR(rAX, rES)
  148. /*
  149. * write APM data. first four bytes are APM\0.
  150. */
  151. LWI(0x5041, rAX)
  152. STOSW
  153. LWI(0x004d, rAX)
  154. STOSW
  155. LWI(8, rCX)
  156. apmmove:
  157. POPR(rAX)
  158. STOSW
  159. LOOP apmmove
  160. noapm:
  161. /*
  162. * end of real mode hacks: write terminator, put ES back.
  163. */
  164. LWI(0x0000, rAX)
  165. STOSW
  166. STOSW
  167. MFSR(rCS, rAX) /* fix up ES (0x8000) */
  168. MTSR(rAX, rES)
  169. /*
  170. * goto protected mode
  171. */
  172. /* MOVL tgdtptr(SB),GDTR /**/
  173. BYTE $0x0f
  174. BYTE $0x01
  175. BYTE $0x16
  176. WORD $tgdtptr(SB)
  177. LWI(1, rAX)
  178. /* MOV AX,MSW */
  179. BYTE $0x0F; BYTE $0x01; BYTE $0xF0
  180. /*
  181. * clear prefetch queue (weird code to avoid optimizations)
  182. */
  183. /* JMP .+2 */
  184. BYTE $0xEB
  185. BYTE $0x00
  186. /*
  187. * set all segs
  188. */
  189. /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
  190. BYTE $0xc7
  191. BYTE $0xc0
  192. WORD $SELECTOR(1, SELGDT, 0)
  193. MOVW AX,DS
  194. MOVW AX,SS
  195. MOVW AX,ES
  196. MOVW AX,FS
  197. MOVW AX,GS
  198. /* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
  199. BYTE $0x66
  200. BYTE $0xEA
  201. LONG $mode32bit-KZERO(SB)
  202. WORD $SELECTOR(2, SELGDT, 0)
  203. TEXT mode32bit(SB),$0
  204. /*
  205. * make a bottom level page table page that maps the first
  206. * 16 meg of physical memory
  207. */
  208. MOVL $PDB, DI /* clear 6 pages for the tables etc. */
  209. XORL AX, AX
  210. MOVL $(6*BY2PG), CX
  211. SHRL $2, CX
  212. CLD
  213. REP; STOSL
  214. MOVL $PDB, AX /* phys addr of temporary page table */
  215. MOVL $(4*1024),CX /* pte's per page */
  216. MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
  217. setpte:
  218. MOVL BX,-4(AX)(CX*4)
  219. SUBL $(1<<PGSHIFT),BX
  220. LOOP setpte
  221. /*
  222. * make a top level page table page that maps the first
  223. * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
  224. */
  225. MOVL AX,BX
  226. ADDL $(4*BY2PG),AX
  227. ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
  228. MOVL BX,0(AX)
  229. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
  230. ADDL $BY2PG,BX
  231. MOVL BX,4(AX)
  232. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
  233. ADDL $BY2PG,BX
  234. MOVL BX,8(AX)
  235. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
  236. ADDL $BY2PG,BX
  237. MOVL BX,12(AX)
  238. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
  239. /*
  240. * point processor to top level page & turn on paging
  241. *
  242. * this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"
  243. * message in the VMware log.
  244. */
  245. MOVL AX,CR3
  246. MOVL CR0,AX
  247. ORL $0X80000000,AX
  248. MOVL AX,CR0
  249. /*
  250. * use a jump to an absolute location to get the PC into
  251. * KZERO.
  252. */
  253. LEAL tokzero(SB),AX
  254. JMP* AX
  255. /*
  256. * When we load 9load from DOS, the bootstrap jumps
  257. * to the instruction right after `JUMP', which gets
  258. * us into kzero.
  259. *
  260. * The name prevents it from being optimized away.
  261. */
  262. TEXT jumplabel(SB), $0
  263. BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P'
  264. LEAL tokzero(SB),AX
  265. JMP* AX
  266. TEXT tokzero(SB),$0
  267. /*
  268. * Clear BSS
  269. */
  270. LEAL edata(SB),SI
  271. MOVL SI,DI
  272. ADDL $4,DI
  273. MOVL $0,AX
  274. MOVL AX,(SI)
  275. LEAL end(SB),CX
  276. SUBL DI,CX
  277. SHRL $2,CX
  278. CLD
  279. REP
  280. MOVSL
  281. /*
  282. * stack and mach
  283. */
  284. MOVL $mach0(SB),SP
  285. MOVL SP,m(SB)
  286. MOVL $0,0(SP)
  287. ADDL $(MACHSIZE-4),SP /* start stack above machine struct */
  288. CALL main(SB)
  289. loop:
  290. JMP loop
  291. GLOBL mach0+0(SB), $MACHSIZE
  292. GLOBL m(SB), $4
  293. /*
  294. * gdt to get us to 32-bit/segmented/unpaged mode
  295. */
  296. TEXT tgdt(SB),$0
  297. /* null descriptor */
  298. LONG $0
  299. LONG $0
  300. /* data segment descriptor for 4 gigabytes (PL 0) */
  301. LONG $(0xFFFF)
  302. LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
  303. /* exec segment descriptor for 4 gigabytes (PL 0) */
  304. LONG $(0xFFFF)
  305. LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
  306. /* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */
  307. LONG $(0xFFFF)
  308. LONG $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
  309. /*
  310. * pointer to initial gdt
  311. */
  312. TEXT tgdtptr(SB),$0
  313. WORD $(4*8)
  314. LONG $tgdt-KZERO(SB)
  315. /*
  316. * Output a string to the display.
  317. * String argument is in rSI.
  318. */
  319. TEXT biosputs(SB), $0
  320. PUSHA
  321. CLR(rBX)
  322. _BIOSputs:
  323. LODSB
  324. ORB(rAL, rAL)
  325. JEQ _BIOSputsret
  326. LBI(0x0E, rAH)
  327. BIOSCALL(0x10)
  328. JMP _BIOSputs
  329. _BIOSputsret:
  330. POPA
  331. RET
  332. /*
  333. * input a byte
  334. */
  335. TEXT inb(SB),$0
  336. MOVL p+0(FP),DX
  337. XORL AX,AX
  338. INB
  339. RET
  340. /*
  341. * input a short from a port
  342. */
  343. TEXT ins(SB), $0
  344. MOVL p+0(FP), DX
  345. XORL AX, AX
  346. OPSIZE; INL
  347. RET
  348. /*
  349. * input a long from a port
  350. */
  351. TEXT inl(SB), $0
  352. MOVL p+0(FP), DX
  353. XORL AX, AX
  354. INL
  355. RET
  356. /*
  357. * output a byte
  358. */
  359. TEXT outb(SB),$0
  360. MOVL p+0(FP),DX
  361. MOVL b+4(FP),AX
  362. OUTB
  363. RET
  364. /*
  365. * output a short to a port
  366. */
  367. TEXT outs(SB), $0
  368. MOVL p+0(FP), DX
  369. MOVL s+4(FP), AX
  370. OPSIZE; OUTL
  371. RET
  372. /*
  373. * output a long to a port
  374. */
  375. TEXT outl(SB), $0
  376. MOVL p+0(FP), DX
  377. MOVL s+4(FP), AX
  378. OUTL
  379. RET
  380. /*
  381. * input a string of bytes from a port
  382. */
  383. TEXT insb(SB),$0
  384. MOVL p+0(FP),DX
  385. MOVL a+4(FP),DI
  386. MOVL c+8(FP),CX
  387. CLD; REP; INSB
  388. RET
  389. /*
  390. * input a string of shorts from a port
  391. */
  392. TEXT inss(SB),$0
  393. MOVL p+0(FP),DX
  394. MOVL a+4(FP),DI
  395. MOVL c+8(FP),CX
  396. CLD
  397. REP; OPSIZE; INSL
  398. RET
  399. /*
  400. * output a string of bytes to a port
  401. */
  402. TEXT outsb(SB),$0
  403. MOVL p+0(FP),DX
  404. MOVL a+4(FP),SI
  405. MOVL c+8(FP),CX
  406. CLD; REP; OUTSB
  407. RET
  408. /*
  409. * output a string of shorts to a port
  410. */
  411. TEXT outss(SB),$0
  412. MOVL p+0(FP),DX
  413. MOVL a+4(FP),SI
  414. MOVL c+8(FP),CX
  415. CLD
  416. REP; OPSIZE; OUTSL
  417. RET
  418. /*
  419. * input a string of longs from a port
  420. */
  421. TEXT insl(SB),$0
  422. MOVL p+0(FP),DX
  423. MOVL a+4(FP),DI
  424. MOVL c+8(FP),CX
  425. CLD; REP; INSL
  426. RET
  427. /*
  428. * output a string of longs to a port
  429. */
  430. TEXT outsl(SB),$0
  431. MOVL p+0(FP),DX
  432. MOVL a+4(FP),SI
  433. MOVL c+8(FP),CX
  434. CLD; REP; OUTSL
  435. RET
  436. /*
  437. * routines to load/read various system registers
  438. */
  439. GLOBL idtptr(SB),$6
  440. TEXT putidt(SB),$0 /* interrupt descriptor table */
  441. MOVL t+0(FP),AX
  442. MOVL AX,idtptr+2(SB)
  443. MOVL l+4(FP),AX
  444. MOVW AX,idtptr(SB)
  445. MOVL idtptr(SB),IDTR
  446. RET
  447. TEXT putcr3(SB),$0 /* top level page table pointer */
  448. MOVL t+0(FP),AX
  449. MOVL AX,CR3
  450. RET
  451. TEXT getcr0(SB),$0 /* coprocessor bits */
  452. MOVL CR0,AX
  453. RET
  454. TEXT getcr2(SB),$0 /* fault address */
  455. MOVL CR2,AX
  456. RET
  457. TEXT getcr3(SB),$0 /* page directory base */
  458. MOVL CR3,AX
  459. RET
  460. TEXT getcr4(SB), $0 /* CR4 - extensions */
  461. MOVL CR4, AX
  462. RET
  463. TEXT _cycles(SB), $0 /* time stamp counter */
  464. RDTSC
  465. MOVL vlong+0(FP), CX /* &vlong */
  466. MOVL AX, 0(CX) /* lo */
  467. MOVL DX, 4(CX) /* hi */
  468. RET
  469. TEXT rdmsr(SB), $0 /* model-specific register */
  470. MOVL index+0(FP), CX
  471. RDMSR
  472. MOVL vlong+4(FP), CX /* &vlong */
  473. MOVL AX, 0(CX) /* lo */
  474. MOVL DX, 4(CX) /* hi */
  475. RET
  476. TEXT wrmsr(SB), $0
  477. MOVL index+0(FP), CX
  478. MOVL lo+4(FP), AX
  479. MOVL hi+8(FP), DX
  480. WRMSR
  481. RET
  482. TEXT mb386(SB), $0
  483. POPL AX /* return PC */
  484. PUSHFL
  485. PUSHL CS
  486. PUSHL AX
  487. IRETL
  488. /*
  489. * special traps
  490. */
  491. TEXT intr0(SB),$0
  492. PUSHL $0
  493. PUSHL $0
  494. JMP intrcommon
  495. TEXT intr1(SB),$0
  496. PUSHL $0
  497. PUSHL $1
  498. JMP intrcommon
  499. TEXT intr2(SB),$0
  500. PUSHL $0
  501. PUSHL $2
  502. JMP intrcommon
  503. TEXT intr3(SB),$0
  504. PUSHL $0
  505. PUSHL $3
  506. JMP intrcommon
  507. TEXT intr4(SB),$0
  508. PUSHL $0
  509. PUSHL $4
  510. JMP intrcommon
  511. TEXT intr5(SB),$0
  512. PUSHL $0
  513. PUSHL $5
  514. JMP intrcommon
  515. TEXT intr6(SB),$0
  516. PUSHL $0
  517. PUSHL $6
  518. JMP intrcommon
  519. TEXT intr7(SB),$0
  520. PUSHL $0
  521. PUSHL $7
  522. JMP intrcommon
  523. TEXT intr8(SB),$0
  524. PUSHL $8
  525. JMP intrcommon
  526. TEXT intr9(SB),$0
  527. PUSHL $0
  528. PUSHL $9
  529. JMP intrcommon
  530. TEXT intr10(SB),$0
  531. PUSHL $10
  532. JMP intrcommon
  533. TEXT intr11(SB),$0
  534. PUSHL $11
  535. JMP intrcommon
  536. TEXT intr12(SB),$0
  537. PUSHL $12
  538. JMP intrcommon
  539. TEXT intr13(SB),$0
  540. PUSHL $13
  541. JMP intrcommon
  542. TEXT intr14(SB),$0
  543. PUSHL $14
  544. JMP intrcommon
  545. TEXT intr15(SB),$0
  546. PUSHL $0
  547. PUSHL $15
  548. JMP intrcommon
  549. TEXT intr16(SB),$0
  550. PUSHL $0
  551. PUSHL $16
  552. JMP intrcommon
  553. TEXT intr24(SB),$0
  554. PUSHL $0
  555. PUSHL $24
  556. JMP intrcommon
  557. TEXT intr25(SB),$0
  558. PUSHL $0
  559. PUSHL $25
  560. JMP intrcommon
  561. TEXT intr26(SB),$0
  562. PUSHL $0
  563. PUSHL $26
  564. JMP intrcommon
  565. TEXT intr27(SB),$0
  566. PUSHL $0
  567. PUSHL $27
  568. JMP intrcommon
  569. TEXT intr28(SB),$0
  570. PUSHL $0
  571. PUSHL $28
  572. JMP intrcommon
  573. TEXT intr29(SB),$0
  574. PUSHL $0
  575. PUSHL $29
  576. JMP intrcommon
  577. TEXT intr30(SB),$0
  578. PUSHL $0
  579. PUSHL $30
  580. JMP intrcommon
  581. TEXT intr31(SB),$0
  582. PUSHL $0
  583. PUSHL $31
  584. JMP intrcommon
  585. TEXT intr32(SB),$0
  586. PUSHL $0
  587. PUSHL $32
  588. JMP intrcommon
  589. TEXT intr33(SB),$0
  590. PUSHL $0
  591. PUSHL $33
  592. JMP intrcommon
  593. TEXT intr34(SB),$0
  594. PUSHL $0
  595. PUSHL $34
  596. JMP intrcommon
  597. TEXT intr35(SB),$0
  598. PUSHL $0
  599. PUSHL $35
  600. JMP intrcommon
  601. TEXT intr36(SB),$0
  602. PUSHL $0
  603. PUSHL $36
  604. JMP intrcommon
  605. TEXT intr37(SB),$0
  606. PUSHL $0
  607. PUSHL $37
  608. JMP intrcommon
  609. TEXT intr38(SB),$0
  610. PUSHL $0
  611. PUSHL $38
  612. JMP intrcommon
  613. TEXT intr39(SB),$0
  614. PUSHL $0
  615. PUSHL $39
  616. JMP intrcommon
  617. TEXT intr64(SB),$0
  618. PUSHL $0
  619. PUSHL $64
  620. JMP intrcommon
  621. TEXT intrbad(SB),$0
  622. PUSHL $0
  623. PUSHL $0x1ff
  624. JMP intrcommon
  625. intrcommon:
  626. PUSHL DS
  627. PUSHL ES
  628. PUSHL FS
  629. PUSHL GS
  630. PUSHAL
  631. MOVL $(KDSEL),AX
  632. MOVW AX,DS
  633. MOVW AX,ES
  634. LEAL 0(SP),AX
  635. PUSHL AX
  636. CALL trap(SB)
  637. POPL AX
  638. POPAL
  639. POPL GS
  640. POPL FS
  641. POPL ES
  642. POPL DS
  643. ADDL $8,SP /* error code and trap type */
  644. IRETL
  645. /*
  646. * interrupt level is interrupts on or off
  647. */
  648. TEXT spllo(SB),$0
  649. PUSHFL
  650. POPL AX
  651. STI
  652. RET
  653. TEXT splhi(SB),$0
  654. PUSHFL
  655. POPL AX
  656. CLI
  657. RET
  658. TEXT splx(SB),$0
  659. MOVL s+0(FP),AX
  660. PUSHL AX
  661. POPFL
  662. RET
  663. /*
  664. * do nothing whatsoever till interrupt happens
  665. */
  666. TEXT idle(SB),$0
  667. HLT
  668. RET
  669. /*
  670. * Try to determine the CPU type which requires fiddling with EFLAGS.
  671. * If the Id bit can be toggled then the CPUID instruciton can be used
  672. * to determine CPU identity and features. First have to check if it's
  673. * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
  674. * toggled then it's an older 486 of some kind.
  675. *
  676. * cpuid(id[], &ax, &dx);
  677. */
  678. #define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
  679. TEXT cpuid(SB), $0
  680. MOVL $0x240000, AX
  681. PUSHL AX
  682. POPFL /* set Id|Ac */
  683. PUSHFL
  684. POPL BX /* retrieve value */
  685. MOVL $0, AX
  686. PUSHL AX
  687. POPFL /* clear Id|Ac, EFLAGS initialised */
  688. PUSHFL
  689. POPL AX /* retrieve value */
  690. XORL BX, AX
  691. TESTL $0x040000, AX /* Ac */
  692. JZ _cpu386 /* can't set this bit on 386 */
  693. TESTL $0x200000, AX /* Id */
  694. JZ _cpu486 /* can't toggle this bit on some 486 */
  695. MOVL $0, AX
  696. CPUID
  697. MOVL id+0(FP), BP
  698. MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */
  699. MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */
  700. MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */
  701. MOVL $1, AX
  702. CPUID
  703. JMP _cpuid
  704. _cpu486:
  705. MOVL $0x400, AX
  706. MOVL $0, DX
  707. JMP _cpuid
  708. _cpu386:
  709. MOVL $0x300, AX
  710. MOVL $0, DX
  711. _cpuid:
  712. MOVL ax+4(FP), BP
  713. MOVL AX, 0(BP)
  714. MOVL dx+8(FP), BP
  715. MOVL DX, 0(BP)
  716. RET
  717. /*
  718. * basic timing loop to determine CPU frequency
  719. */
  720. TEXT aamloop(SB),$0
  721. MOVL c+0(FP),CX
  722. aaml1:
  723. AAM
  724. LOOP aaml1
  725. RET
  726. TEXT hello(SB), $0
  727. BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
  728. BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
  729. BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
  730. BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
  731. BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
  732. BYTE $'s';
  733. BYTE $'\r';
  734. BYTE $'\n';
  735. BYTE $'\z';
  736. TEXT rock(SB), $0
  737. BYTE $0; BYTE $0; BYTE $0; BYTE $0;
  738. GLOBL pxe(SB), $4
  739. #ifdef PXE
  740. DATA pxe+0(SB)/4, $1
  741. #else
  742. DATA pxe+0(SB)/4, $0
  743. #endif /* PXE */
  744. /*
  745. * Save registers.
  746. */
  747. TEXT saveregs(SB), $0
  748. /* appease 8l */
  749. SUBL $32, SP
  750. POPL AX
  751. POPL AX
  752. POPL AX
  753. POPL AX
  754. POPL AX
  755. POPL AX
  756. POPL AX
  757. POPL AX
  758. PUSHL AX
  759. PUSHL BX
  760. PUSHL CX
  761. PUSHL DX
  762. PUSHL BP
  763. PUSHL DI
  764. PUSHL SI
  765. PUSHFL
  766. XCHGL 32(SP), AX /* swap return PC and saved flags */
  767. XCHGL 0(SP), AX
  768. XCHGL 32(SP), AX
  769. RET
  770. TEXT restoreregs(SB), $0
  771. /* appease 8l */
  772. PUSHL AX
  773. PUSHL AX
  774. PUSHL AX
  775. PUSHL AX
  776. PUSHL AX
  777. PUSHL AX
  778. PUSHL AX
  779. PUSHL AX
  780. ADDL $32, SP
  781. XCHGL 32(SP), AX /* swap return PC and saved flags */
  782. XCHGL 0(SP), AX
  783. XCHGL 32(SP), AX
  784. POPFL
  785. POPL SI
  786. POPL DI
  787. POPL BP
  788. POPL DX
  789. POPL CX
  790. POPL BX
  791. POPL AX
  792. RET
  793. /*
  794. * Assumed to be in protected mode at time of call.
  795. * Switch to real mode, execute an interrupt, and
  796. * then switch back to protected mode.
  797. *
  798. * Assumes:
  799. *
  800. * - no device interrupts are going to come in
  801. * - 0-16MB is identity mapped in page tables
  802. * - can use code segment 0x1000 in real mode
  803. * to get at l.s code
  804. */
  805. TEXT realmodeidtptr(SB), $0
  806. WORD $(4*256-1)
  807. LONG $0
  808. TEXT realmode0(SB), $0
  809. CALL saveregs(SB)
  810. /* switch to low code address */
  811. LEAL physcode-KZERO(SB), AX
  812. JMP *AX
  813. TEXT physcode(SB), $0
  814. /* switch to low stack */
  815. MOVL SP, AX
  816. MOVL $0x7C00, SP
  817. PUSHL AX
  818. /* load IDT with real-mode version; GDT already fine */
  819. MOVL realmodeidtptr(SB), IDTR
  820. /* edit INT $0x00 instruction below */
  821. MOVL realmodeintr(SB), AX
  822. MOVB AX, realmodeintrinst+1(SB)
  823. /* disable paging */
  824. MOVL CR0, AX
  825. ANDL $0x7FFFFFFF, AX
  826. MOVL AX, CR0
  827. /* JMP .+2 to clear prefetch queue*/
  828. BYTE $0xEB; BYTE $0x00
  829. /* jump to 16-bit code segment */
  830. /* JMPFAR SELECTOR(3, SELGDT, 0):$again16bit(SB) /**/
  831. BYTE $0xEA
  832. LONG $again16bit-KZERO(SB)
  833. WORD $SELECTOR(3, SELGDT, 0)
  834. TEXT again16bit(SB), $0
  835. /*
  836. * Now in 16-bit compatibility mode.
  837. * These are 32-bit instructions being interpreted
  838. * as 16-bit instructions. I'm being lazy and
  839. * not using the macros because I know when
  840. * the 16- and 32-bit instructions look the same
  841. * or close enough.
  842. */
  843. /* disable protected mode and jump to real mode cs */
  844. OPSIZE; MOVL CR0, AX
  845. OPSIZE; XORL BX, BX
  846. OPSIZE; INCL BX
  847. OPSIZE; XORL BX, AX
  848. OPSIZE; MOVL AX, CR0
  849. /* JMPFAR 0x1000:now16real */
  850. BYTE $0xEA
  851. WORD $now16real-KZERO(SB)
  852. WORD $0x1000
  853. TEXT now16real(SB), $0
  854. /* copy the registers for the bios call */
  855. LWI(0x1000, rAX)
  856. MOVW AX,SS
  857. LWI(realmoderegs(SB), rBP)
  858. /* offsets are in Ureg */
  859. LXW(44, xBP, rAX)
  860. MOVW AX, DS
  861. LXW(40, xBP, rAX)
  862. MOVW AX, ES
  863. OPSIZE; LXW(0, xBP, rDI)
  864. OPSIZE; LXW(4, xBP, rSI)
  865. OPSIZE; LXW(16, xBP, rBX)
  866. OPSIZE; LXW(20, xBP, rDX)
  867. OPSIZE; LXW(24, xBP, rCX)
  868. OPSIZE; LXW(28, xBP, rAX)
  869. CLC
  870. TEXT realmodeintrinst(SB), $0
  871. INT $0x00
  872. /* save the registers after the call */
  873. LWI(0x7bfc, rSP)
  874. OPSIZE; PUSHFL
  875. OPSIZE; PUSHL AX
  876. LWI(0x1000, rAX)
  877. MOVW AX,SS
  878. LWI(realmoderegs(SB), rBP)
  879. OPSIZE; SXW(rDI, 0, xBP)
  880. OPSIZE; SXW(rSI, 4, xBP)
  881. OPSIZE; SXW(rBX, 16, xBP)
  882. OPSIZE; SXW(rDX, 20, xBP)
  883. OPSIZE; SXW(rCX, 24, xBP)
  884. OPSIZE; POPL AX
  885. OPSIZE; SXW(rAX, 28, xBP)
  886. MOVW DS, AX
  887. OPSIZE; SXW(rAX, 44, xBP)
  888. MOVW ES, AX
  889. OPSIZE; SXW(rAX, 40, xBP)
  890. OPSIZE; POPL AX
  891. OPSIZE; SXW(rAX, 64, xBP) /* flags */
  892. /* re-enter protected mode and jump to 32-bit code */
  893. OPSIZE; MOVL $1, AX
  894. OPSIZE; MOVL AX, CR0
  895. /* JMPFAR SELECTOR(2, SELGDT, 0):$again32bit(SB) /**/
  896. OPSIZE
  897. BYTE $0xEA
  898. LONG $again32bit-KZERO(SB)
  899. WORD $SELECTOR(2, SELGDT, 0)
  900. TEXT again32bit(SB), $0
  901. MOVW $SELECTOR(1, SELGDT, 0),AX
  902. MOVW AX,DS
  903. MOVW AX,SS
  904. MOVW AX,ES
  905. MOVW AX,FS
  906. MOVW AX,GS
  907. /* enable paging and jump to kzero-address code */
  908. MOVL CR0, AX
  909. ORL $0x80000000, AX
  910. MOVL AX, CR0
  911. LEAL again32kzero(SB), AX
  912. JMP* AX
  913. TEXT again32kzero(SB), $0
  914. /* breathe a sigh of relief - back in 32-bit protected mode */
  915. /* switch to old stack */
  916. PUSHL AX /* match popl below for 8l */
  917. MOVL $0x7BFC, SP
  918. POPL SP
  919. /* restore idt */
  920. MOVL idtptr(SB),IDTR
  921. CALL restoreregs(SB)
  922. RET
  923. TEXT realmoderegs(SB), $0
  924. LONG $0; LONG $0; LONG $0; LONG $0
  925. LONG $0; LONG $0; LONG $0; LONG $0
  926. LONG $0; LONG $0; LONG $0; LONG $0
  927. LONG $0; LONG $0; LONG $0; LONG $0
  928. LONG $0; LONG $0; LONG $0; LONG $0
  929. TEXT realmodeintr(SB), $0
  930. LONG $0