l.s 11 KB

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