l.s 18 KB

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