l.s 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  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. /*
  307. * pointer to initial gdt
  308. */
  309. TEXT tgdtptr(SB),$0
  310. WORD $(3*8)
  311. LONG $tgdt-KZERO(SB)
  312. /*
  313. * Output a string to the display.
  314. * String argument is in rSI.
  315. */
  316. TEXT biosputs(SB), $0
  317. PUSHA
  318. CLR(rBX)
  319. _BIOSputs:
  320. LODSB
  321. ORB(rAL, rAL)
  322. JEQ _BIOSputsret
  323. LBI(0x0E, rAH)
  324. BIOSCALL(0x10)
  325. JMP _BIOSputs
  326. _BIOSputsret:
  327. POPA
  328. RET
  329. /*
  330. * input a byte
  331. */
  332. TEXT inb(SB),$0
  333. MOVL p+0(FP),DX
  334. XORL AX,AX
  335. INB
  336. RET
  337. /*
  338. * input a short from a port
  339. */
  340. TEXT ins(SB), $0
  341. MOVL p+0(FP), DX
  342. XORL AX, AX
  343. OPSIZE; INL
  344. RET
  345. /*
  346. * input a long from a port
  347. */
  348. TEXT inl(SB), $0
  349. MOVL p+0(FP), DX
  350. XORL AX, AX
  351. INL
  352. RET
  353. /*
  354. * output a byte
  355. */
  356. TEXT outb(SB),$0
  357. MOVL p+0(FP),DX
  358. MOVL b+4(FP),AX
  359. OUTB
  360. RET
  361. /*
  362. * output a short to a port
  363. */
  364. TEXT outs(SB), $0
  365. MOVL p+0(FP), DX
  366. MOVL s+4(FP), AX
  367. OPSIZE; OUTL
  368. RET
  369. /*
  370. * output a long to a port
  371. */
  372. TEXT outl(SB), $0
  373. MOVL p+0(FP), DX
  374. MOVL s+4(FP), AX
  375. OUTL
  376. RET
  377. /*
  378. * input a string of bytes from a port
  379. */
  380. TEXT insb(SB),$0
  381. MOVL p+0(FP),DX
  382. MOVL a+4(FP),DI
  383. MOVL c+8(FP),CX
  384. CLD; REP; INSB
  385. RET
  386. /*
  387. * input a string of shorts from a port
  388. */
  389. TEXT inss(SB),$0
  390. MOVL p+0(FP),DX
  391. MOVL a+4(FP),DI
  392. MOVL c+8(FP),CX
  393. CLD
  394. REP; OPSIZE; INSL
  395. RET
  396. /*
  397. * output a string of bytes to a port
  398. */
  399. TEXT outsb(SB),$0
  400. MOVL p+0(FP),DX
  401. MOVL a+4(FP),SI
  402. MOVL c+8(FP),CX
  403. CLD; REP; OUTSB
  404. RET
  405. /*
  406. * output a string of shorts to a port
  407. */
  408. TEXT outss(SB),$0
  409. MOVL p+0(FP),DX
  410. MOVL a+4(FP),SI
  411. MOVL c+8(FP),CX
  412. CLD
  413. REP; OPSIZE; OUTSL
  414. RET
  415. /*
  416. * input a string of longs from a port
  417. */
  418. TEXT insl(SB),$0
  419. MOVL p+0(FP),DX
  420. MOVL a+4(FP),DI
  421. MOVL c+8(FP),CX
  422. CLD; REP; INSL
  423. RET
  424. /*
  425. * output a string of longs to a port
  426. */
  427. TEXT outsl(SB),$0
  428. MOVL p+0(FP),DX
  429. MOVL a+4(FP),SI
  430. MOVL c+8(FP),CX
  431. CLD; REP; OUTSL
  432. RET
  433. /*
  434. * routines to load/read various system registers
  435. */
  436. GLOBL idtptr(SB),$6
  437. TEXT putidt(SB),$0 /* interrupt descriptor table */
  438. MOVL t+0(FP),AX
  439. MOVL AX,idtptr+2(SB)
  440. MOVL l+4(FP),AX
  441. MOVW AX,idtptr(SB)
  442. MOVL idtptr(SB),IDTR
  443. RET
  444. TEXT putcr3(SB),$0 /* top level page table pointer */
  445. MOVL t+0(FP),AX
  446. MOVL AX,CR3
  447. RET
  448. TEXT getcr0(SB),$0 /* coprocessor bits */
  449. MOVL CR0,AX
  450. RET
  451. TEXT getcr2(SB),$0 /* fault address */
  452. MOVL CR2,AX
  453. RET
  454. TEXT getcr3(SB),$0 /* page directory base */
  455. MOVL CR3,AX
  456. RET
  457. TEXT getcr4(SB), $0 /* CR4 - extensions */
  458. MOVL CR4, AX
  459. RET
  460. TEXT _cycles(SB), $0 /* time stamp counter */
  461. RDTSC
  462. MOVL vlong+0(FP), CX /* &vlong */
  463. MOVL AX, 0(CX) /* lo */
  464. MOVL DX, 4(CX) /* hi */
  465. RET
  466. TEXT rdmsr(SB), $0 /* model-specific register */
  467. MOVL index+0(FP), CX
  468. RDMSR
  469. MOVL vlong+4(FP), CX /* &vlong */
  470. MOVL AX, 0(CX) /* lo */
  471. MOVL DX, 4(CX) /* hi */
  472. RET
  473. TEXT wrmsr(SB), $0
  474. MOVL index+0(FP), CX
  475. MOVL lo+4(FP), AX
  476. MOVL hi+8(FP), DX
  477. WRMSR
  478. RET
  479. TEXT mb386(SB), $0
  480. POPL AX /* return PC */
  481. PUSHFL
  482. PUSHL CS
  483. PUSHL AX
  484. IRETL
  485. /*
  486. * special traps
  487. */
  488. TEXT intr0(SB),$0
  489. PUSHL $0
  490. PUSHL $0
  491. JMP intrcommon
  492. TEXT intr1(SB),$0
  493. PUSHL $0
  494. PUSHL $1
  495. JMP intrcommon
  496. TEXT intr2(SB),$0
  497. PUSHL $0
  498. PUSHL $2
  499. JMP intrcommon
  500. TEXT intr3(SB),$0
  501. PUSHL $0
  502. PUSHL $3
  503. JMP intrcommon
  504. TEXT intr4(SB),$0
  505. PUSHL $0
  506. PUSHL $4
  507. JMP intrcommon
  508. TEXT intr5(SB),$0
  509. PUSHL $0
  510. PUSHL $5
  511. JMP intrcommon
  512. TEXT intr6(SB),$0
  513. PUSHL $0
  514. PUSHL $6
  515. JMP intrcommon
  516. TEXT intr7(SB),$0
  517. PUSHL $0
  518. PUSHL $7
  519. JMP intrcommon
  520. TEXT intr8(SB),$0
  521. PUSHL $8
  522. JMP intrcommon
  523. TEXT intr9(SB),$0
  524. PUSHL $0
  525. PUSHL $9
  526. JMP intrcommon
  527. TEXT intr10(SB),$0
  528. PUSHL $10
  529. JMP intrcommon
  530. TEXT intr11(SB),$0
  531. PUSHL $11
  532. JMP intrcommon
  533. TEXT intr12(SB),$0
  534. PUSHL $12
  535. JMP intrcommon
  536. TEXT intr13(SB),$0
  537. PUSHL $13
  538. JMP intrcommon
  539. TEXT intr14(SB),$0
  540. PUSHL $14
  541. JMP intrcommon
  542. TEXT intr15(SB),$0
  543. PUSHL $0
  544. PUSHL $15
  545. JMP intrcommon
  546. TEXT intr16(SB),$0
  547. PUSHL $0
  548. PUSHL $16
  549. JMP intrcommon
  550. TEXT intr24(SB),$0
  551. PUSHL $0
  552. PUSHL $24
  553. JMP intrcommon
  554. TEXT intr25(SB),$0
  555. PUSHL $0
  556. PUSHL $25
  557. JMP intrcommon
  558. TEXT intr26(SB),$0
  559. PUSHL $0
  560. PUSHL $26
  561. JMP intrcommon
  562. TEXT intr27(SB),$0
  563. PUSHL $0
  564. PUSHL $27
  565. JMP intrcommon
  566. TEXT intr28(SB),$0
  567. PUSHL $0
  568. PUSHL $28
  569. JMP intrcommon
  570. TEXT intr29(SB),$0
  571. PUSHL $0
  572. PUSHL $29
  573. JMP intrcommon
  574. TEXT intr30(SB),$0
  575. PUSHL $0
  576. PUSHL $30
  577. JMP intrcommon
  578. TEXT intr31(SB),$0
  579. PUSHL $0
  580. PUSHL $31
  581. JMP intrcommon
  582. TEXT intr32(SB),$0
  583. PUSHL $0
  584. PUSHL $32
  585. JMP intrcommon
  586. TEXT intr33(SB),$0
  587. PUSHL $0
  588. PUSHL $33
  589. JMP intrcommon
  590. TEXT intr34(SB),$0
  591. PUSHL $0
  592. PUSHL $34
  593. JMP intrcommon
  594. TEXT intr35(SB),$0
  595. PUSHL $0
  596. PUSHL $35
  597. JMP intrcommon
  598. TEXT intr36(SB),$0
  599. PUSHL $0
  600. PUSHL $36
  601. JMP intrcommon
  602. TEXT intr37(SB),$0
  603. PUSHL $0
  604. PUSHL $37
  605. JMP intrcommon
  606. TEXT intr38(SB),$0
  607. PUSHL $0
  608. PUSHL $38
  609. JMP intrcommon
  610. TEXT intr39(SB),$0
  611. PUSHL $0
  612. PUSHL $39
  613. JMP intrcommon
  614. TEXT intr64(SB),$0
  615. PUSHL $0
  616. PUSHL $64
  617. JMP intrcommon
  618. TEXT intrbad(SB),$0
  619. PUSHL $0
  620. PUSHL $0x1ff
  621. JMP intrcommon
  622. intrcommon:
  623. PUSHL DS
  624. PUSHL ES
  625. PUSHL FS
  626. PUSHL GS
  627. PUSHAL
  628. MOVL $(KDSEL),AX
  629. MOVW AX,DS
  630. MOVW AX,ES
  631. LEAL 0(SP),AX
  632. PUSHL AX
  633. CALL trap(SB)
  634. POPL AX
  635. POPAL
  636. POPL GS
  637. POPL FS
  638. POPL ES
  639. POPL DS
  640. ADDL $8,SP /* error code and trap type */
  641. IRETL
  642. /*
  643. * interrupt level is interrupts on or off
  644. */
  645. TEXT spllo(SB),$0
  646. PUSHFL
  647. POPL AX
  648. STI
  649. RET
  650. TEXT splhi(SB),$0
  651. PUSHFL
  652. POPL AX
  653. CLI
  654. RET
  655. TEXT splx(SB),$0
  656. MOVL s+0(FP),AX
  657. PUSHL AX
  658. POPFL
  659. RET
  660. /*
  661. * do nothing whatsoever till interrupt happens
  662. */
  663. TEXT idle(SB),$0
  664. HLT
  665. RET
  666. /*
  667. * Try to determine the CPU type which requires fiddling with EFLAGS.
  668. * If the Id bit can be toggled then the CPUID instruciton can be used
  669. * to determine CPU identity and features. First have to check if it's
  670. * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
  671. * toggled then it's an older 486 of some kind.
  672. *
  673. * cpuid(id[], &ax, &dx);
  674. */
  675. #define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
  676. TEXT cpuid(SB), $0
  677. MOVL $0x240000, AX
  678. PUSHL AX
  679. POPFL /* set Id|Ac */
  680. PUSHFL
  681. POPL BX /* retrieve value */
  682. MOVL $0, AX
  683. PUSHL AX
  684. POPFL /* clear Id|Ac, EFLAGS initialised */
  685. PUSHFL
  686. POPL AX /* retrieve value */
  687. XORL BX, AX
  688. TESTL $0x040000, AX /* Ac */
  689. JZ _cpu386 /* can't set this bit on 386 */
  690. TESTL $0x200000, AX /* Id */
  691. JZ _cpu486 /* can't toggle this bit on some 486 */
  692. MOVL $0, AX
  693. CPUID
  694. MOVL id+0(FP), BP
  695. MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */
  696. MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */
  697. MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */
  698. MOVL $1, AX
  699. CPUID
  700. JMP _cpuid
  701. _cpu486:
  702. MOVL $0x400, AX
  703. MOVL $0, DX
  704. JMP _cpuid
  705. _cpu386:
  706. MOVL $0x300, AX
  707. MOVL $0, DX
  708. _cpuid:
  709. MOVL ax+4(FP), BP
  710. MOVL AX, 0(BP)
  711. MOVL dx+8(FP), BP
  712. MOVL DX, 0(BP)
  713. RET
  714. /*
  715. * basic timing loop to determine CPU frequency
  716. */
  717. TEXT aamloop(SB),$0
  718. MOVL c+0(FP),CX
  719. aaml1:
  720. AAM
  721. LOOP aaml1
  722. RET
  723. TEXT hello(SB), $0
  724. BYTE $'P'; BYTE $'l'; BYTE $'a'; BYTE $'n';
  725. BYTE $' '; BYTE $'9'; BYTE $' '; BYTE $'f';
  726. BYTE $'r'; BYTE $'o'; BYTE $'m'; BYTE $' ';
  727. BYTE $'B'; BYTE $'e'; BYTE $'l'; BYTE $'l';
  728. BYTE $' '; BYTE $'L'; BYTE $'a'; BYTE $'b';
  729. BYTE $'s';
  730. BYTE $'\r';
  731. BYTE $'\n';
  732. BYTE $'\z';
  733. TEXT rock(SB), $0
  734. BYTE $0; BYTE $0; BYTE $0; BYTE $0;
  735. GLOBL pxe(SB), $4
  736. #ifdef PXE
  737. DATA pxe+0(SB)/4, $1
  738. #else
  739. DATA pxe+0(SB)/4, $0
  740. #endif /* PXE */