l.s 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. #include "mem.h"
  2. #define OP16 BYTE $0x66
  3. #define NOP XCHGL AX,AX
  4. #define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
  5. #define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */
  6. #define RDTSC BYTE $0x0F; BYTE $0x31
  7. TEXT origin(SB),$0
  8. CLI
  9. /*
  10. * Clear BSS
  11. */
  12. LEAL edata-KZERO(SB),SI
  13. MOVL SI,DI
  14. ADDL $4,DI
  15. MOVL $0,AX
  16. MOVL AX,(SI)
  17. LEAL end-KZERO(SB),CX
  18. SUBL DI,CX
  19. SHRL $2,CX
  20. CLD; REP; MOVSL
  21. /*
  22. * make a bottom level page table page that maps the first
  23. * 16 meg of physical memory
  24. */
  25. LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */
  26. ADDL $(BY2PG-1),AX /* must be page alligned */
  27. ANDL $(~(BY2PG-1)),AX /* ... */
  28. MOVL $(1024),CX /* pte's per page */
  29. MOVL $((((1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
  30. setpte:
  31. MOVL BX,-4(AX)(CX*4)
  32. SUBL $(1<<PGSHIFT),BX
  33. LOOP setpte
  34. /*
  35. * make a top level page table page that maps the first
  36. * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
  37. */
  38. MOVL AX,BX
  39. ADDL $(BY2PG),AX
  40. ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
  41. MOVL BX,0(AX)
  42. MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
  43. /*
  44. * point processor to top level page & turn on paging & make
  45. * supervisor obey the R/W bit in the page map
  46. */
  47. MOVL AX,CR3
  48. MOVL CR0,AX
  49. ORL $0X80010000,AX
  50. ANDL $~(0x40000000|0x20000000|0x8|0x2),AX /* CD=0, NW=0, TS=0, MP=0 */
  51. MOVL AX,CR0
  52. /*
  53. * use a jump to an absolute location to get the PC into
  54. * KZERO.
  55. */
  56. LEAL tokzero(SB),AX
  57. JMP* AX
  58. TEXT tokzero(SB),$0
  59. /*
  60. * stack and mach
  61. */
  62. MOVL $mach0(SB),SP
  63. MOVL SP,m(SB)
  64. MOVL $0,0(SP)
  65. ADDL $(MACHSIZE-4),SP /* start stack under machine struct */
  66. MOVL $0, u(SB)
  67. /*
  68. * clear flags
  69. */
  70. MOVL $0,AX
  71. PUSHL AX
  72. POPFL
  73. CALL main(SB)
  74. loop:
  75. JMP loop
  76. GLOBL mach0+0(SB), $MACHSIZE
  77. GLOBL u(SB), $4
  78. GLOBL m(SB), $4
  79. GLOBL tpt(SB), $(BY2PG*3)
  80. /*
  81. * gdt to get us to 32-bit/segmented/unpaged mode
  82. */
  83. TEXT tgdt(SB),$0
  84. /* null descriptor */
  85. LONG $0
  86. LONG $0
  87. /* data segment descriptor for 4 gigabytes (PL 0) */
  88. LONG $(0xFFFF)
  89. LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
  90. /* exec segment descriptor for 4 gigabytes (PL 0) */
  91. LONG $(0xFFFF)
  92. LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
  93. /*
  94. * pointer to initial gdt
  95. */
  96. TEXT tgdtptr(SB),$0
  97. WORD $(3*8)
  98. LONG $tgdt-KZERO(SB)
  99. /*
  100. * input a byte
  101. */
  102. TEXT inb(SB),$0
  103. MOVL p+0(FP),DX
  104. XORL AX,AX
  105. INB
  106. RET
  107. /*
  108. * input a string of bytes from a port
  109. */
  110. TEXT insb(SB),$0
  111. MOVL p+0(FP),DX
  112. MOVL a+4(FP),DI
  113. MOVL c+8(FP),CX
  114. CLD; REP; INSB
  115. RET
  116. /*
  117. * output a byte
  118. */
  119. TEXT outb(SB),$0
  120. MOVL p+0(FP),DX
  121. MOVL b+4(FP),AX
  122. OUTB
  123. RET
  124. /*
  125. * output a string of bytes to a port
  126. */
  127. TEXT outsb(SB),$0
  128. MOVL p+0(FP),DX
  129. MOVL a+4(FP),SI
  130. MOVL c+8(FP),CX
  131. CLD; REP; OUTSB
  132. RET
  133. /*
  134. * input a short from a port
  135. */
  136. TEXT ins(SB), $0
  137. MOVL p+0(FP), DX
  138. XORL AX, AX
  139. OP16; INL
  140. RET
  141. /*
  142. * input a string of shorts from a port
  143. */
  144. TEXT inss(SB),$0
  145. MOVL p+0(FP),DX
  146. MOVL a+4(FP),DI
  147. MOVL c+8(FP),CX
  148. CLD; REP; OP16; INSL
  149. RET
  150. /*
  151. * input a long from a port
  152. */
  153. TEXT inl(SB), $0
  154. MOVL p+0(FP), DX
  155. XORL AX, AX
  156. INL
  157. RET
  158. /*
  159. * input a string of longs from a port
  160. */
  161. TEXT insl(SB),$0
  162. MOVL p+0(FP),DX
  163. MOVL a+4(FP),DI
  164. MOVL c+8(FP),CX
  165. CLD; REP; INSL
  166. RET
  167. /*
  168. * output a short to a port
  169. */
  170. TEXT outs(SB), $0
  171. MOVL p+0(FP), DX
  172. MOVL s+4(FP), AX
  173. OP16; OUTL
  174. RET
  175. /*
  176. * output a string of shorts to a port
  177. */
  178. TEXT outss(SB),$0
  179. MOVL p+0(FP),DX
  180. MOVL a+4(FP),SI
  181. MOVL c+8(FP),CX
  182. CLD; REP; OP16; OUTSL
  183. RET
  184. /*
  185. * output a long to a port
  186. */
  187. TEXT outl(SB), $0
  188. MOVL p+0(FP), DX
  189. MOVL s+4(FP), AX
  190. OUTL
  191. RET
  192. /*
  193. * output a string of longs to a port
  194. */
  195. TEXT outsl(SB),$0
  196. MOVL p+0(FP),DX
  197. MOVL a+4(FP),SI
  198. MOVL c+8(FP),CX
  199. CLD; REP; OUTSL
  200. RET
  201. /*
  202. * test and set
  203. */
  204. TEXT tas(SB),$0
  205. MOVL $0xdeadead,AX
  206. MOVL l+0(FP),BX
  207. XCHGL AX,(BX)
  208. RET
  209. TEXT wbflush(SB), $0
  210. CPUID
  211. RET
  212. /*
  213. * routines to load/read various system registers
  214. */
  215. GLOBL idtptr(SB),$6
  216. TEXT putidt(SB),$0 /* interrupt descriptor table */
  217. MOVL t+0(FP),AX
  218. MOVL AX,idtptr+2(SB)
  219. MOVL l+4(FP),AX
  220. MOVW AX,idtptr(SB)
  221. MOVL idtptr(SB),IDTR
  222. RET
  223. GLOBL gdtptr(SB),$6
  224. TEXT putgdt(SB),$0 /* global descriptor table */
  225. MOVL t+0(FP),AX
  226. MOVL AX,gdtptr+2(SB)
  227. MOVL l+4(FP),AX
  228. MOVW AX,gdtptr(SB)
  229. MOVL gdtptr(SB),GDTR
  230. RET
  231. TEXT putcr3(SB),$0 /* top level page table pointer */
  232. MOVL t+0(FP),AX
  233. MOVL AX,CR3
  234. RET
  235. TEXT getcr4(SB), $0 /* CR4 - extensions */
  236. MOVL CR4, AX
  237. RET
  238. TEXT putcr4(SB), $0
  239. MOVL cr4+0(FP), AX
  240. MOVL AX, CR4
  241. RET
  242. TEXT puttr(SB),$0 /* task register */
  243. MOVL t+0(FP),AX
  244. MOVW AX,TASK
  245. RET
  246. TEXT getcr0(SB),$0 /* coprocessor bits */
  247. MOVL CR0,AX
  248. RET
  249. TEXT getcr2(SB),$0 /* fault address */
  250. MOVL CR2,AX
  251. RET
  252. #define FPOFF\
  253. WAIT;\
  254. MOVL CR0,AX;\
  255. ORL $0x24,AX /* EM=1, NE=1 */;\
  256. MOVL AX,CR0
  257. #define FPON\
  258. MOVL CR0,AX;\
  259. ANDL $~0x4,AX /* EM=0 */;\
  260. MOVL AX,CR0
  261. TEXT fpoff(SB),$0 /* turn off floating point */
  262. FPOFF
  263. RET
  264. TEXT fpinit(SB),$0 /* turn on & init the floating point */
  265. FPON
  266. FINIT
  267. WAIT
  268. PUSHW $0x033E
  269. FLDCW 0(SP) /* ignore underflow/precision, signal others */
  270. POPW AX
  271. WAIT
  272. RET
  273. TEXT fpsave(SB),$0 /* save floating point state and turn off */
  274. MOVL p+0(FP),AX
  275. WAIT
  276. FSAVE 0(AX)
  277. FPOFF
  278. RET
  279. TEXT fprestore(SB),$0 /* turn on floating point and restore regs */
  280. FPON
  281. MOVL p+0(FP),AX
  282. FRSTOR 0(AX)
  283. WAIT
  284. RET
  285. TEXT fpstatus(SB),$0 /* get floating point status */
  286. FSTSW AX
  287. RET
  288. TEXT fpenv(SB),$0 /* save floating point environment without waiting */
  289. MOVL p+0(FP),AX
  290. FSTENV 0(AX)
  291. RET
  292. /*
  293. * special traps
  294. */
  295. TEXT intr0(SB),$0
  296. PUSHL $0
  297. PUSHL $0
  298. JMP intrcommon
  299. TEXT intr1(SB),$0
  300. PUSHL $0
  301. PUSHL $1
  302. JMP intrcommon
  303. TEXT intr2(SB),$0
  304. PUSHL $0
  305. PUSHL $2
  306. JMP intrcommon
  307. TEXT intr3(SB),$0
  308. PUSHL $0
  309. PUSHL $3
  310. JMP intrcommon
  311. TEXT intr4(SB),$0
  312. PUSHL $0
  313. PUSHL $4
  314. JMP intrcommon
  315. TEXT intr5(SB),$0
  316. PUSHL $0
  317. PUSHL $5
  318. JMP intrcommon
  319. TEXT intr6(SB),$0
  320. PUSHL $0
  321. PUSHL $6
  322. JMP intrcommon
  323. TEXT intr7(SB),$0
  324. PUSHL $0
  325. PUSHL $7
  326. JMP intrcommon
  327. TEXT intr8(SB),$0
  328. PUSHL $8
  329. JMP intrscommon
  330. TEXT intr9(SB),$0
  331. PUSHL $0
  332. PUSHL $9
  333. JMP intrcommon
  334. TEXT intr10(SB),$0
  335. PUSHL $10
  336. JMP intrscommon
  337. TEXT intr11(SB),$0
  338. PUSHL $11
  339. JMP intrscommon
  340. TEXT intr12(SB),$0
  341. PUSHL $12
  342. JMP intrscommon
  343. TEXT intr13(SB),$0
  344. PUSHL $13
  345. JMP intrscommon
  346. TEXT intr14(SB),$0
  347. PUSHL $14
  348. JMP intrscommon
  349. TEXT intr15(SB),$0
  350. PUSHL $0
  351. PUSHL $15
  352. JMP intrcommon
  353. TEXT intr16(SB),$0
  354. PUSHL $0
  355. PUSHL $16
  356. JMP intrcommon
  357. TEXT intr24(SB),$0
  358. PUSHL $0
  359. PUSHL $24
  360. JMP intrcommon
  361. TEXT intr25(SB),$0
  362. PUSHL $0
  363. PUSHL $25
  364. JMP intrcommon
  365. TEXT intr26(SB),$0
  366. PUSHL $0
  367. PUSHL $26
  368. JMP intrcommon
  369. TEXT intr27(SB),$0
  370. PUSHL $0
  371. PUSHL $27
  372. JMP intrcommon
  373. TEXT intr28(SB),$0
  374. PUSHL $0
  375. PUSHL $28
  376. JMP intrcommon
  377. TEXT intr29(SB),$0
  378. PUSHL $0
  379. PUSHL $29
  380. JMP intrcommon
  381. TEXT intr30(SB),$0
  382. PUSHL $0
  383. PUSHL $30
  384. JMP intrcommon
  385. TEXT intr31(SB),$0
  386. PUSHL $0
  387. PUSHL $31
  388. JMP intrcommon
  389. TEXT intr32(SB),$0
  390. PUSHL $0
  391. PUSHL $32
  392. JMP intrcommon
  393. TEXT intr33(SB),$0
  394. PUSHL $0
  395. PUSHL $33
  396. JMP intrcommon
  397. TEXT intr34(SB),$0
  398. PUSHL $0
  399. PUSHL $34
  400. JMP intrcommon
  401. TEXT intr35(SB),$0
  402. PUSHL $0
  403. PUSHL $35
  404. JMP intrcommon
  405. TEXT intr36(SB),$0
  406. PUSHL $0
  407. PUSHL $36
  408. JMP intrcommon
  409. TEXT intr37(SB),$0
  410. PUSHL $0
  411. PUSHL $37
  412. JMP intrcommon
  413. TEXT intr38(SB),$0
  414. PUSHL $0
  415. PUSHL $38
  416. JMP intrcommon
  417. TEXT intr39(SB),$0
  418. PUSHL $0
  419. PUSHL $39
  420. JMP intrcommon
  421. TEXT intr64(SB),$0
  422. PUSHL $0
  423. PUSHL $64
  424. JMP intrcommon
  425. TEXT intrbad(SB),$0
  426. PUSHL $0
  427. PUSHL $0x1ff
  428. JMP intrcommon
  429. intrcommon:
  430. PUSHL DS
  431. PUSHL ES
  432. PUSHL FS
  433. PUSHL GS
  434. PUSHAL
  435. MOVL $(KDSEL),AX
  436. MOVW AX,DS
  437. MOVW AX,ES
  438. LEAL 0(SP),AX
  439. PUSHL AX
  440. CALL trap(SB)
  441. POPL AX
  442. POPAL
  443. NOP
  444. POPL GS
  445. POPL FS
  446. POPL ES
  447. POPL DS
  448. NOP
  449. ADDL $8,SP /* error code and trap type */
  450. IRETL
  451. intrscommon:
  452. PUSHL DS
  453. PUSHL ES
  454. PUSHL FS
  455. PUSHL GS
  456. PUSHAL
  457. MOVL $(KDSEL),AX
  458. MOVW AX,DS
  459. MOVW AX,ES
  460. LEAL 0(SP),AX
  461. PUSHL AX
  462. CALL trap(SB)
  463. POPL AX
  464. POPAL
  465. NOP
  466. POPL GS
  467. POPL FS
  468. POPL ES
  469. POPL DS
  470. NOP
  471. ADDL $8,SP /* error code and trap type */
  472. IRETL
  473. /*
  474. * interrupt level is interrupts on or off
  475. */
  476. TEXT spllo(SB),$0
  477. PUSHFL
  478. POPL AX
  479. STI
  480. RET
  481. TEXT splhi(SB),$0
  482. PUSHFL
  483. POPL AX
  484. CLI
  485. RET
  486. TEXT splx(SB),$0
  487. MOVL s+0(FP),AX
  488. PUSHL AX
  489. POPFL
  490. RET
  491. TEXT getstatus(SB),$0
  492. PUSHFL
  493. POPL AX
  494. RET
  495. TEXT rdtsc(SB), $0 /* time stamp counter; cycles since power up */
  496. RDTSC
  497. MOVL vlong+0(FP), CX /* &vlong */
  498. MOVL AX, 0(CX) /* lo */
  499. MOVL DX, 4(CX) /* hi */
  500. RET
  501. TEXT rdmsr(SB), $0 /* model-specific register */
  502. MOVL index+0(FP), CX
  503. RDMSR
  504. MOVL vlong+4(FP), CX /* &vlong */
  505. MOVL AX, (CX) /* lo */
  506. MOVL DX, 4(CX) /* hi */
  507. RET
  508. /*
  509. * Try to determine the CPU type which requires fiddling with EFLAGS.
  510. * If the Id bit can be toggled then the CPUID instruciton can be used
  511. * to determine CPU identity and features. First have to check if it's
  512. * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
  513. * toggled then it's an older 486 of some kind.
  514. *
  515. * cpuid(id[], &ax, &dx);
  516. */
  517. TEXT cpuid(SB), $0
  518. MOVL $0x240000, AX
  519. PUSHL AX
  520. POPFL /* set Id|Ac */
  521. PUSHFL
  522. POPL BX /* retrieve value */
  523. MOVL $0, AX
  524. PUSHL AX
  525. POPFL /* clear Id|Ac, EFLAGS initialised */
  526. PUSHFL
  527. POPL AX /* retrieve value */
  528. XORL BX, AX
  529. TESTL $0x040000, AX /* Ac */
  530. JZ _cpu386 /* can't set this bit on 386 */
  531. TESTL $0x200000, AX /* Id */
  532. JZ _cpu486 /* can't toggle this bit on some 486 */
  533. MOVL $0, AX
  534. CPUID
  535. MOVL id+0(FP), BP
  536. MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */
  537. MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */
  538. MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */
  539. MOVL $1, AX
  540. CPUID
  541. JMP _cpuid
  542. _cpu486:
  543. MOVL $0x400, AX
  544. MOVL $0, DX
  545. JMP _cpuid
  546. _cpu386:
  547. MOVL $0x300, AX
  548. MOVL $0, DX
  549. _cpuid:
  550. MOVL ax+4(FP), BP
  551. MOVL AX, 0(BP)
  552. MOVL dx+8(FP), BP
  553. MOVL DX, 0(BP)
  554. RET
  555. /*
  556. * basic timing loop to determine CPU frequency
  557. */
  558. TEXT aamloop(SB),$0
  559. MOVL c+0(FP),CX
  560. aaml1:
  561. AAM
  562. LOOP aaml1
  563. RET
  564. /*
  565. * do nothing whatsoever till interrupt happens
  566. */
  567. TEXT idle(SB),$0
  568. HLT
  569. RET
  570. /*
  571. * label consists of a stack pointer and a PC
  572. */
  573. TEXT gotolabel(SB),$0
  574. MOVL l+0(FP),AX
  575. MOVL 4(AX),SP /* restore sp */
  576. MOVL 0(AX),AX /* put return pc on the stack */
  577. MOVL AX,0(SP)
  578. MOVL $1,AX /* return 1 */
  579. RET
  580. TEXT setlabel(SB),$0
  581. MOVL l+0(FP),AX
  582. MOVL SP,4(AX) /* store sp */
  583. MOVL 0(SP),BX /* store return pc */
  584. MOVL BX,0(AX)
  585. MOVL $0,AX /* return 0 */
  586. RET
  587. TEXT famd+0(SB), $4
  588. PUSHFL
  589. CLI /* spl hi */
  590. FMOVL b+4(FP), F0
  591. FADDF a+0(FP), F0
  592. FMOVL c+8(FP), F0
  593. FMULDP F0, F1
  594. FMOVL d+12(FP), F0
  595. FDIVDP F0, F1
  596. FMOVFP F0, .safe-4(SP)
  597. MOVL .safe-4(SP), AX
  598. POPFL /* splx */
  599. RET
  600. TEXT fdf+0(SB), $4
  601. PUSHFL
  602. CLI /* spl hi */
  603. FMOVL b+4(FP), F0
  604. FDIVRF a+0(FP), F0
  605. FMOVLP F0, .safe-4(SP)
  606. MOVL .safe-4(SP), AX
  607. POPFL /* splx */
  608. RET