l.s 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. #include "mem.h"
  2. #define PADDR(a) ((a) & ~KZERO)
  3. #define KADDR(a) (KZERO|(a))
  4. /*
  5. * Some machine instructions not handled by 8[al].
  6. */
  7. #define OP16 BYTE $0x66
  8. #define DELAY BYTE $0xEB; BYTE $0x00 /* JMP .+2 */
  9. #define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
  10. #define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */
  11. #define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */
  12. #define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */
  13. #define HLT BYTE $0xF4
  14. /*
  15. * Macros for calculating offsets within the page directory base
  16. * and page tables. Note that these are assembler-specific hence
  17. * the '<<2'.
  18. */
  19. #define PDO(a) (((((a))>>22) & 0x03FF)<<2)
  20. #define PTO(a) (((((a))>>12) & 0x03FF)<<2)
  21. /*
  22. * For backwards compatiblity with 9load - should go away when 9load is changed
  23. * 9load currently sets up the mmu, however the first 16MB of memory is identity
  24. * mapped, so behave as if the mmu was not setup
  25. */
  26. TEXT _start0x80100020(SB), $0
  27. MOVL $_start0x00100020(SB), AX
  28. ANDL $~KZERO, AX
  29. JMP* AX
  30. /*
  31. * Must be 4-byte aligned.
  32. */
  33. TEXT _multibootheader(SB), $0
  34. LONG $0x1BADB002 /* magic */
  35. LONG $0x00010003 /* flags */
  36. LONG $-(0x1BADB002 + 0x00010003) /* checksum */
  37. LONG $_multibootheader-KZERO(SB) /* header_addr */
  38. LONG $_start0x80100020-KZERO(SB) /* load_addr */
  39. LONG $edata-KZERO(SB) /* load_end_addr */
  40. LONG $end-KZERO(SB) /* bss_end_addr */
  41. LONG $_start0x80100020-KZERO(SB) /* entry_addr */
  42. LONG $0 /* mode_type */
  43. LONG $0 /* width */
  44. LONG $0 /* height */
  45. LONG $0 /* depth */
  46. /*
  47. * In protected mode with paging turned off and segment registers setup to linear map all memory.
  48. * Entered via a jump to 0x00100020, the physical address of the virtual kernel entry point of 0x80100020
  49. * Make the basic page tables for processor 0. Four pages are needed for the basic set:
  50. * a page directory, a page table for mapping the first 4MB of physical memory to KZERO,
  51. * and virtual and physical pages for mapping the Mach structure.
  52. * The remaining PTEs will be allocated later when memory is sized.
  53. * An identity mmu map is also needed for the switch to virtual mode. This
  54. * identity mapping is removed once the MMU is going and the JMP has been made
  55. * to virtual memory.
  56. */
  57. TEXT _start0x00100020(SB), $0
  58. CLI /* make sure interrupts are off */
  59. /* set up the gdt so we have sane plan 9 style gdts. */
  60. MOVL $tgdtptr(SB), AX
  61. ANDL $~KZERO, AX
  62. MOVL (AX), GDTR
  63. MOVW $1, AX
  64. MOVW AX, MSW
  65. /* clear prefetch queue (weird code to avoid optimizations) */
  66. DELAY
  67. /* set segs to something sane (avoid traps later) */
  68. MOVW $(1<<3), AX
  69. MOVW AX, DS
  70. MOVW AX, SS
  71. MOVW AX, ES
  72. MOVW AX, FS
  73. MOVW AX, GS
  74. /* JMP $(2<<3):$mode32bit(SB) /**/
  75. BYTE $0xEA
  76. LONG $mode32bit-KZERO(SB)
  77. WORD $(2<<3)
  78. /*
  79. * gdt to get us to 32-bit/segmented/unpaged mode
  80. */
  81. TEXT tgdt(SB), $0
  82. /* null descriptor */
  83. LONG $0
  84. LONG $0
  85. /* data segment descriptor for 4 gigabytes (PL 0) */
  86. LONG $(0xFFFF)
  87. LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
  88. /* exec segment descriptor for 4 gigabytes (PL 0) */
  89. LONG $(0xFFFF)
  90. LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
  91. /*
  92. * pointer to initial gdt
  93. * Note the -KZERO which puts the physical address in the gdtptr.
  94. * that's needed as we start executing in physical addresses.
  95. */
  96. TEXT tgdtptr(SB), $0
  97. WORD $(3*8)
  98. LONG $tgdt-KZERO(SB)
  99. TEXT mode32bit(SB), $0
  100. /* At this point, the GDT setup is done. */
  101. MOVL $PADDR(CPU0PDB), DI /* clear 4 pages for the tables etc. */
  102. XORL AX, AX
  103. MOVL $(4*BY2PG), CX
  104. SHRL $2, CX
  105. CLD
  106. REP; STOSL
  107. MOVL $PADDR(CPU0PDB), AX
  108. ADDL $PDO(KZERO), AX /* page directory offset for KZERO */
  109. MOVL $PADDR(CPU0PTE), (AX) /* PTE's for 0x80000000 */
  110. MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
  111. ORL BX, (AX)
  112. MOVL $PADDR(CPU0PTE), AX /* first page of page table */
  113. MOVL $1024, CX /* 1024 pages in 4MB */
  114. _setpte:
  115. MOVL BX, (AX)
  116. ADDL $(1<<PGSHIFT), BX
  117. ADDL $4, AX
  118. LOOP _setpte
  119. MOVL $PADDR(CPU0PTE), AX
  120. ADDL $PTO(MACHADDR), AX /* page table entry offset for MACHADDR */
  121. MOVL $PADDR(CPU0MACH), (AX) /* PTE for Mach */
  122. MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
  123. ORL BX, (AX)
  124. /*
  125. * Now ready to use the new map. Make sure the processor options are what is wanted.
  126. * It is necessary on some processors to immediately follow mode switching with a JMP instruction
  127. * to clear the prefetch queues.
  128. */
  129. MOVL $PADDR(CPU0PDB), CX /* load address of page directory */
  130. MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */
  131. MOVL DX, (PDO(0))(CX)
  132. MOVL CX, CR3
  133. DELAY /* JMP .+2 */
  134. MOVL CR0, DX
  135. ORL $0x80010000, DX /* PG|WP */
  136. ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
  137. MOVL $_startpg(SB), AX /* this is a virtual address */
  138. MOVL DX, CR0 /* turn on paging */
  139. JMP* AX /* jump to the virtual nirvana */
  140. /*
  141. * Basic machine environment set, can clear BSS and create a stack.
  142. * The stack starts at the top of the page containing the Mach structure.
  143. * The x86 architecture forces the use of the same virtual address for
  144. * each processor's Mach structure, so the global Mach pointer 'm' can
  145. * be initialised here.
  146. */
  147. TEXT _startpg(SB), $0
  148. MOVL $0, (PDO(0))(CX) /* undo double-map of KZERO at 0 */
  149. MOVL CX, CR3 /* load and flush the mmu */
  150. _clearbss:
  151. MOVL $edata(SB), DI
  152. XORL AX, AX
  153. MOVL $end(SB), CX
  154. SUBL DI, CX /* end-edata bytes */
  155. SHRL $2, CX /* end-edata doublewords */
  156. CLD
  157. REP; STOSL /* clear BSS */
  158. MOVL $MACHADDR, SP
  159. MOVL SP, m(SB) /* initialise global Mach pointer */
  160. MOVL $0, 0(SP) /* initialise m->machno */
  161. ADDL $(MACHSIZE-4), SP /* initialise stack */
  162. /*
  163. * Need to do one final thing to ensure a clean machine environment,
  164. * clear the EFLAGS register, which can only be done once there is a stack.
  165. */
  166. MOVL $0, AX
  167. PUSHL AX
  168. POPFL
  169. CALL main(SB)
  170. /*
  171. * Park a processor. Should never fall through a return from main to here,
  172. * should only be called by application processors when shutting down.
  173. */
  174. TEXT idle(SB), $0
  175. _idle:
  176. STI
  177. HLT
  178. JMP _idle
  179. /*
  180. * Port I/O.
  181. * in[bsl] input a byte|short|long
  182. * ins[bsl] input a string of bytes|shorts|longs
  183. * out[bsl] output a byte|short|long
  184. * outs[bsl] output a string of bytes|shorts|longs
  185. */
  186. TEXT inb(SB), $0
  187. MOVL port+0(FP), DX
  188. XORL AX, AX
  189. INB
  190. RET
  191. TEXT insb(SB), $0
  192. MOVL port+0(FP), DX
  193. MOVL address+4(FP), DI
  194. MOVL count+8(FP), CX
  195. CLD
  196. REP; INSB
  197. RET
  198. TEXT ins(SB), $0
  199. MOVL port+0(FP), DX
  200. XORL AX, AX
  201. OP16; INL
  202. RET
  203. TEXT inss(SB), $0
  204. MOVL port+0(FP), DX
  205. MOVL address+4(FP), DI
  206. MOVL count+8(FP), CX
  207. CLD
  208. REP; OP16; INSL
  209. RET
  210. TEXT inl(SB), $0
  211. MOVL port+0(FP), DX
  212. INL
  213. RET
  214. TEXT insl(SB), $0
  215. MOVL port+0(FP), DX
  216. MOVL address+4(FP), DI
  217. MOVL count+8(FP), CX
  218. CLD
  219. REP; INSL
  220. RET
  221. TEXT outb(SB), $0
  222. MOVL port+0(FP), DX
  223. MOVL byte+4(FP), AX
  224. OUTB
  225. RET
  226. TEXT outsb(SB), $0
  227. MOVL port+0(FP), DX
  228. MOVL address+4(FP), SI
  229. MOVL count+8(FP), CX
  230. CLD
  231. REP; OUTSB
  232. RET
  233. TEXT outs(SB), $0
  234. MOVL port+0(FP), DX
  235. MOVL short+4(FP), AX
  236. OP16; OUTL
  237. RET
  238. TEXT outss(SB), $0
  239. MOVL port+0(FP), DX
  240. MOVL address+4(FP), SI
  241. MOVL count+8(FP), CX
  242. CLD
  243. REP; OP16; OUTSL
  244. RET
  245. TEXT outl(SB), $0
  246. MOVL port+0(FP), DX
  247. MOVL long+4(FP), AX
  248. OUTL
  249. RET
  250. TEXT outsl(SB), $0
  251. MOVL port+0(FP), DX
  252. MOVL address+4(FP), SI
  253. MOVL count+8(FP), CX
  254. CLD
  255. REP; OUTSL
  256. RET
  257. /*
  258. * Read/write various system registers.
  259. * CR4 and the 'model specific registers' should only be read/written
  260. * after it has been determined the processor supports them
  261. */
  262. TEXT lgdt(SB), $0 /* GDTR - global descriptor table */
  263. MOVL gdtptr+0(FP), AX
  264. MOVL (AX), GDTR
  265. RET
  266. TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */
  267. MOVL idtptr+0(FP), AX
  268. MOVL (AX), IDTR
  269. RET
  270. TEXT ltr(SB), $0 /* TR - task register */
  271. MOVL tptr+0(FP), AX
  272. MOVW AX, TASK
  273. RET
  274. TEXT getcr0(SB), $0 /* CR0 - processor control */
  275. MOVL CR0, AX
  276. RET
  277. TEXT getcr2(SB), $0 /* CR2 - page fault linear address */
  278. MOVL CR2, AX
  279. RET
  280. TEXT getcr3(SB), $0 /* CR3 - page directory base */
  281. MOVL CR3, AX
  282. RET
  283. TEXT putcr3(SB), $0
  284. MOVL cr3+0(FP), AX
  285. MOVL AX, CR3
  286. RET
  287. TEXT getcr4(SB), $0 /* CR4 - extensions */
  288. MOVL CR4, AX
  289. RET
  290. TEXT putcr4(SB), $0
  291. MOVL cr4+0(FP), AX
  292. MOVL AX, CR4
  293. RET
  294. TEXT _cycles(SB), $0 /* time stamp counter */
  295. RDTSC
  296. MOVL vlong+0(FP), CX /* &vlong */
  297. MOVL AX, 0(CX) /* lo */
  298. MOVL DX, 4(CX) /* hi */
  299. RET
  300. TEXT rdmsr(SB), $0 /* model-specific register */
  301. MOVL index+0(FP), CX
  302. RDMSR
  303. MOVL vlong+4(FP), CX /* &vlong */
  304. MOVL AX, 0(CX) /* lo */
  305. MOVL DX, 4(CX) /* hi */
  306. RET
  307. TEXT wrmsr(SB), $0
  308. MOVL index+0(FP), CX
  309. MOVL lo+4(FP), AX
  310. MOVL hi+8(FP), DX
  311. WRMSR
  312. RET
  313. /*
  314. * Try to determine the CPU type which requires fiddling with EFLAGS.
  315. * If the Id bit can be toggled then the CPUID instruction can be used
  316. * to determine CPU identity and features. First have to check if it's
  317. * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
  318. * toggled then it's an older 486 of some kind.
  319. *
  320. * cpuid(id[], &ax, &dx);
  321. */
  322. TEXT cpuid(SB), $0
  323. MOVL $0x240000, AX
  324. PUSHL AX
  325. POPFL /* set Id|Ac */
  326. PUSHFL
  327. POPL BX /* retrieve value */
  328. MOVL $0, AX
  329. PUSHL AX
  330. POPFL /* clear Id|Ac, EFLAGS initialised */
  331. PUSHFL
  332. POPL AX /* retrieve value */
  333. XORL BX, AX
  334. TESTL $0x040000, AX /* Ac */
  335. JZ _cpu386 /* can't set this bit on 386 */
  336. TESTL $0x200000, AX /* Id */
  337. JZ _cpu486 /* can't toggle this bit on some 486 */
  338. MOVL $0, AX
  339. CPUID
  340. MOVL id+0(FP), BP
  341. MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */
  342. MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */
  343. MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */
  344. MOVL $1, AX
  345. CPUID
  346. JMP _cpuid
  347. _cpu486:
  348. MOVL $0x400, AX
  349. MOVL $0, DX
  350. JMP _cpuid
  351. _cpu386:
  352. MOVL $0x300, AX
  353. MOVL $0, DX
  354. _cpuid:
  355. MOVL ax+4(FP), BP
  356. MOVL AX, 0(BP)
  357. MOVL dx+8(FP), BP
  358. MOVL DX, 0(BP)
  359. RET
  360. /*
  361. * Basic timing loop to determine CPU frequency.
  362. */
  363. TEXT aamloop(SB), $0
  364. MOVL count+0(FP), CX
  365. _aamloop:
  366. AAM
  367. LOOP _aamloop
  368. RET
  369. /*
  370. * Floating point.
  371. * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW
  372. * instructions do NOT have the WAIT prefix byte (i.e. they act like their
  373. * FNxxx variations) so WAIT instructions must be explicitly placed in the
  374. * code as necessary.
  375. */
  376. #define FPOFF(l) ;\
  377. MOVL CR0, AX ;\
  378. ANDL $0xC, AX /* EM, TS */ ;\
  379. CMPL AX, $0x8 ;\
  380. JEQ l ;\
  381. WAIT ;\
  382. l: ;\
  383. MOVL CR0, AX ;\
  384. ANDL $~0x4, AX /* EM=0 */ ;\
  385. ORL $0x28, AX /* NE=1, TS=1 */ ;\
  386. MOVL AX, CR0
  387. #define FPON ;\
  388. MOVL CR0, AX ;\
  389. ANDL $~0xC, AX /* EM=0, TS=0 */ ;\
  390. MOVL AX, CR0
  391. TEXT fpoff(SB), $0 /* disable */
  392. FPOFF(l1)
  393. RET
  394. TEXT fpinit(SB), $0 /* enable and init */
  395. FPON
  396. FINIT
  397. WAIT
  398. /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
  399. /* note that low 6 bits are masks, not enables, on this chip */
  400. PUSHW $0x0232
  401. FLDCW 0(SP)
  402. POPW AX
  403. WAIT
  404. RET
  405. TEXT fpsave(SB), $0 /* save state and disable */
  406. MOVL p+0(FP), AX
  407. FSAVE 0(AX) /* no WAIT */
  408. FPOFF(l2)
  409. RET
  410. TEXT fprestore(SB), $0 /* enable and restore state */
  411. FPON
  412. MOVL p+0(FP), AX
  413. FRSTOR 0(AX)
  414. WAIT
  415. RET
  416. TEXT fpstatus(SB), $0 /* get floating point status */
  417. FSTSW AX
  418. RET
  419. TEXT fpenv(SB), $0 /* save state without waiting */
  420. MOVL p+0(FP), AX
  421. FSTENV 0(AX)
  422. RET
  423. TEXT fpclear(SB), $0 /* clear pending exceptions */
  424. FPON
  425. FCLEX /* no WAIT */
  426. FPOFF(l3)
  427. RET
  428. /*
  429. */
  430. TEXT splhi(SB), $0
  431. shi:
  432. PUSHFL
  433. POPL AX
  434. TESTL $0x200, AX
  435. JZ alreadyhi
  436. MOVL $(MACHADDR+0x04), CX /* save PC in m->splpc */
  437. MOVL (SP), BX
  438. MOVL BX, (CX)
  439. alreadyhi:
  440. CLI
  441. RET
  442. TEXT spllo(SB), $0
  443. slo:
  444. PUSHFL
  445. POPL AX
  446. TESTL $0x200, AX
  447. JNZ alreadylo
  448. MOVL $(MACHADDR+0x04), CX /* clear m->splpc */
  449. MOVL $0, (CX)
  450. alreadylo:
  451. STI
  452. RET
  453. TEXT splx(SB), $0
  454. MOVL s+0(FP), AX
  455. TESTL $0x200, AX
  456. JNZ slo
  457. JMP shi
  458. TEXT spldone(SB), $0
  459. RET
  460. TEXT islo(SB), $0
  461. PUSHFL
  462. POPL AX
  463. ANDL $0x200, AX /* interrupt enable flag */
  464. RET
  465. /*
  466. * Test-And-Set
  467. */
  468. TEXT tas(SB), $0
  469. MOVL $0xDEADDEAD, AX
  470. MOVL lock+0(FP), BX
  471. XCHGL AX, (BX) /* lock->key */
  472. RET
  473. TEXT _xinc(SB), $0 /* void _xinc(long*); */
  474. MOVL l+0(FP), AX
  475. LOCK; INCL 0(AX)
  476. RET
  477. TEXT _xdec(SB), $0 /* long _xdec(long*); */
  478. MOVL l+0(FP), BX
  479. XORL AX, AX
  480. LOCK; DECL 0(BX)
  481. JLT _xdeclt
  482. JGT _xdecgt
  483. RET
  484. _xdecgt:
  485. INCL AX
  486. RET
  487. _xdeclt:
  488. DECL AX
  489. RET
  490. TEXT mb386(SB), $0
  491. POPL AX /* return PC */
  492. PUSHFL
  493. PUSHL CS
  494. PUSHL AX
  495. IRETL
  496. TEXT mb586(SB), $0
  497. XORL AX, AX
  498. CPUID
  499. RET
  500. TEXT xchgw(SB), $0
  501. MOVL v+4(FP), AX
  502. MOVL p+0(FP), BX
  503. XCHGW AX, (BX)
  504. RET
  505. TEXT mul64fract(SB), $0
  506. /*
  507. * Multiply two 64-bit number s and keep the middle 64 bits from the 128-bit result
  508. * See ../port/tod.c for motivation.
  509. */
  510. MOVL r+0(FP), CX
  511. XORL BX, BX /* BX = 0 */
  512. MOVL a+8(FP), AX
  513. MULL b+16(FP) /* a1*b1 */
  514. MOVL AX, 4(CX) /* r2 = lo(a1*b1) */
  515. MOVL a+8(FP), AX
  516. MULL b+12(FP) /* a1*b0 */
  517. MOVL AX, 0(CX) /* r1 = lo(a1*b0) */
  518. ADDL DX, 4(CX) /* r2 += hi(a1*b0) */
  519. MOVL a+4(FP), AX
  520. MULL b+16(FP) /* a0*b1 */
  521. ADDL AX, 0(CX) /* r1 += lo(a0*b1) */
  522. ADCL DX, 4(CX) /* r2 += hi(a0*b1) + carry */
  523. MOVL a+4(FP), AX
  524. MULL b+12(FP) /* a0*b0 */
  525. ADDL DX, 0(CX) /* r1 += hi(a0*b0) */
  526. ADCL BX, 4(CX) /* r2 += carry */
  527. RET
  528. /*
  529. * label consists of a stack pointer and a PC
  530. */
  531. TEXT gotolabel(SB), $0
  532. MOVL label+0(FP), AX
  533. MOVL 0(AX), SP /* restore sp */
  534. MOVL 4(AX), AX /* put return pc on the stack */
  535. MOVL AX, 0(SP)
  536. MOVL $1, AX /* return 1 */
  537. RET
  538. TEXT setlabel(SB), $0
  539. MOVL label+0(FP), AX
  540. MOVL SP, 0(AX) /* store sp */
  541. MOVL 0(SP), BX /* store return pc */
  542. MOVL BX, 4(AX)
  543. MOVL $0, AX /* return 0 */
  544. RET
  545. /*
  546. * Attempt at power saving. -rsc
  547. */
  548. TEXT halt(SB), $0
  549. CLI
  550. CMPL nrdy(SB), $0
  551. JEQ _nothingready
  552. STI
  553. RET
  554. _nothingready:
  555. STI
  556. HLT
  557. RET
  558. /*
  559. * Interrupt/exception handling.
  560. * Each entry in the vector table calls either _strayintr or _strayintrx depending
  561. * on whether an error code has been automatically pushed onto the stack
  562. * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
  563. * the trap type from the vector table entry and placing it on the stack as part
  564. * of the Ureg structure.
  565. * The size of each entry in the vector table (6 bytes) is known in trapinit().
  566. */
  567. TEXT _strayintr(SB), $0
  568. PUSHL AX /* save AX */
  569. MOVL 4(SP), AX /* return PC from vectortable(SB) */
  570. JMP intrcommon
  571. TEXT _strayintrx(SB), $0
  572. XCHGL AX, (SP) /* swap AX with vectortable CALL PC */
  573. intrcommon:
  574. PUSHL DS /* save DS */
  575. PUSHL $(KDSEL)
  576. POPL DS /* fix up DS */
  577. MOVBLZX (AX), AX /* trap type -> AX */
  578. XCHGL AX, 4(SP) /* exchange trap type with saved AX */
  579. PUSHL ES /* save ES */
  580. PUSHL $(KDSEL)
  581. POPL ES /* fix up ES */
  582. PUSHL FS /* save the rest of the Ureg struct */
  583. PUSHL GS
  584. PUSHAL
  585. PUSHL SP /* Ureg* argument to trap */
  586. CALL trap(SB)
  587. TEXT forkret(SB), $0
  588. POPL AX
  589. POPAL
  590. POPL GS
  591. POPL FS
  592. POPL ES
  593. POPL DS
  594. ADDL $8, SP /* pop error code and trap type */
  595. IRETL
  596. TEXT vectortable(SB), $0
  597. CALL _strayintr(SB); BYTE $0x00 /* divide error */
  598. CALL _strayintr(SB); BYTE $0x01 /* debug exception */
  599. CALL _strayintr(SB); BYTE $0x02 /* NMI interrupt */
  600. CALL _strayintr(SB); BYTE $0x03 /* breakpoint */
  601. CALL _strayintr(SB); BYTE $0x04 /* overflow */
  602. CALL _strayintr(SB); BYTE $0x05 /* bound */
  603. CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */
  604. CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */
  605. CALL _strayintrx(SB); BYTE $0x08 /* double fault */
  606. CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
  607. CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */
  608. CALL _strayintrx(SB); BYTE $0x0B /* segment not available */
  609. CALL _strayintrx(SB); BYTE $0x0C /* stack exception */
  610. CALL _strayintrx(SB); BYTE $0x0D /* general protection error */
  611. CALL _strayintrx(SB); BYTE $0x0E /* page fault */
  612. CALL _strayintr(SB); BYTE $0x0F /* */
  613. CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
  614. CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
  615. CALL _strayintr(SB); BYTE $0x12 /* machine check */
  616. CALL _strayintr(SB); BYTE $0x13
  617. CALL _strayintr(SB); BYTE $0x14
  618. CALL _strayintr(SB); BYTE $0x15
  619. CALL _strayintr(SB); BYTE $0x16
  620. CALL _strayintr(SB); BYTE $0x17
  621. CALL _strayintr(SB); BYTE $0x18
  622. CALL _strayintr(SB); BYTE $0x19
  623. CALL _strayintr(SB); BYTE $0x1A
  624. CALL _strayintr(SB); BYTE $0x1B
  625. CALL _strayintr(SB); BYTE $0x1C
  626. CALL _strayintr(SB); BYTE $0x1D
  627. CALL _strayintr(SB); BYTE $0x1E
  628. CALL _strayintr(SB); BYTE $0x1F
  629. CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */
  630. CALL _strayintr(SB); BYTE $0x21
  631. CALL _strayintr(SB); BYTE $0x22
  632. CALL _strayintr(SB); BYTE $0x23
  633. CALL _strayintr(SB); BYTE $0x24
  634. CALL _strayintr(SB); BYTE $0x25
  635. CALL _strayintr(SB); BYTE $0x26
  636. CALL _strayintr(SB); BYTE $0x27
  637. CALL _strayintr(SB); BYTE $0x28
  638. CALL _strayintr(SB); BYTE $0x29
  639. CALL _strayintr(SB); BYTE $0x2A
  640. CALL _strayintr(SB); BYTE $0x2B
  641. CALL _strayintr(SB); BYTE $0x2C
  642. CALL _strayintr(SB); BYTE $0x2D
  643. CALL _strayintr(SB); BYTE $0x2E
  644. CALL _strayintr(SB); BYTE $0x2F
  645. CALL _strayintr(SB); BYTE $0x30
  646. CALL _strayintr(SB); BYTE $0x31
  647. CALL _strayintr(SB); BYTE $0x32
  648. CALL _strayintr(SB); BYTE $0x33
  649. CALL _strayintr(SB); BYTE $0x34
  650. CALL _strayintr(SB); BYTE $0x35
  651. CALL _strayintr(SB); BYTE $0x36
  652. CALL _strayintr(SB); BYTE $0x37
  653. CALL _strayintr(SB); BYTE $0x38
  654. CALL _strayintr(SB); BYTE $0x39
  655. CALL _strayintr(SB); BYTE $0x3A
  656. CALL _strayintr(SB); BYTE $0x3B
  657. CALL _strayintr(SB); BYTE $0x3C
  658. CALL _strayintr(SB); BYTE $0x3D
  659. CALL _strayintr(SB); BYTE $0x3E
  660. CALL _strayintr(SB); BYTE $0x3F
  661. CALL _syscallintr(SB); BYTE $0x40 /* VectorSYSCALL */
  662. CALL _strayintr(SB); BYTE $0x41
  663. CALL _strayintr(SB); BYTE $0x42
  664. CALL _strayintr(SB); BYTE $0x43
  665. CALL _strayintr(SB); BYTE $0x44
  666. CALL _strayintr(SB); BYTE $0x45
  667. CALL _strayintr(SB); BYTE $0x46
  668. CALL _strayintr(SB); BYTE $0x47
  669. CALL _strayintr(SB); BYTE $0x48
  670. CALL _strayintr(SB); BYTE $0x49
  671. CALL _strayintr(SB); BYTE $0x4A
  672. CALL _strayintr(SB); BYTE $0x4B
  673. CALL _strayintr(SB); BYTE $0x4C
  674. CALL _strayintr(SB); BYTE $0x4D
  675. CALL _strayintr(SB); BYTE $0x4E
  676. CALL _strayintr(SB); BYTE $0x4F
  677. CALL _strayintr(SB); BYTE $0x50
  678. CALL _strayintr(SB); BYTE $0x51
  679. CALL _strayintr(SB); BYTE $0x52
  680. CALL _strayintr(SB); BYTE $0x53
  681. CALL _strayintr(SB); BYTE $0x54
  682. CALL _strayintr(SB); BYTE $0x55
  683. CALL _strayintr(SB); BYTE $0x56
  684. CALL _strayintr(SB); BYTE $0x57
  685. CALL _strayintr(SB); BYTE $0x58
  686. CALL _strayintr(SB); BYTE $0x59
  687. CALL _strayintr(SB); BYTE $0x5A
  688. CALL _strayintr(SB); BYTE $0x5B
  689. CALL _strayintr(SB); BYTE $0x5C
  690. CALL _strayintr(SB); BYTE $0x5D
  691. CALL _strayintr(SB); BYTE $0x5E
  692. CALL _strayintr(SB); BYTE $0x5F
  693. CALL _strayintr(SB); BYTE $0x60
  694. CALL _strayintr(SB); BYTE $0x61
  695. CALL _strayintr(SB); BYTE $0x62
  696. CALL _strayintr(SB); BYTE $0x63
  697. CALL _strayintr(SB); BYTE $0x64
  698. CALL _strayintr(SB); BYTE $0x65
  699. CALL _strayintr(SB); BYTE $0x66
  700. CALL _strayintr(SB); BYTE $0x67
  701. CALL _strayintr(SB); BYTE $0x68
  702. CALL _strayintr(SB); BYTE $0x69
  703. CALL _strayintr(SB); BYTE $0x6A
  704. CALL _strayintr(SB); BYTE $0x6B
  705. CALL _strayintr(SB); BYTE $0x6C
  706. CALL _strayintr(SB); BYTE $0x6D
  707. CALL _strayintr(SB); BYTE $0x6E
  708. CALL _strayintr(SB); BYTE $0x6F
  709. CALL _strayintr(SB); BYTE $0x70
  710. CALL _strayintr(SB); BYTE $0x71
  711. CALL _strayintr(SB); BYTE $0x72
  712. CALL _strayintr(SB); BYTE $0x73
  713. CALL _strayintr(SB); BYTE $0x74
  714. CALL _strayintr(SB); BYTE $0x75
  715. CALL _strayintr(SB); BYTE $0x76
  716. CALL _strayintr(SB); BYTE $0x77
  717. CALL _strayintr(SB); BYTE $0x78
  718. CALL _strayintr(SB); BYTE $0x79
  719. CALL _strayintr(SB); BYTE $0x7A
  720. CALL _strayintr(SB); BYTE $0x7B
  721. CALL _strayintr(SB); BYTE $0x7C
  722. CALL _strayintr(SB); BYTE $0x7D
  723. CALL _strayintr(SB); BYTE $0x7E
  724. CALL _strayintr(SB); BYTE $0x7F
  725. CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
  726. CALL _strayintr(SB); BYTE $0x81
  727. CALL _strayintr(SB); BYTE $0x82
  728. CALL _strayintr(SB); BYTE $0x83
  729. CALL _strayintr(SB); BYTE $0x84
  730. CALL _strayintr(SB); BYTE $0x85
  731. CALL _strayintr(SB); BYTE $0x86
  732. CALL _strayintr(SB); BYTE $0x87
  733. CALL _strayintr(SB); BYTE $0x88
  734. CALL _strayintr(SB); BYTE $0x89
  735. CALL _strayintr(SB); BYTE $0x8A
  736. CALL _strayintr(SB); BYTE $0x8B
  737. CALL _strayintr(SB); BYTE $0x8C
  738. CALL _strayintr(SB); BYTE $0x8D
  739. CALL _strayintr(SB); BYTE $0x8E
  740. CALL _strayintr(SB); BYTE $0x8F
  741. CALL _strayintr(SB); BYTE $0x90
  742. CALL _strayintr(SB); BYTE $0x91
  743. CALL _strayintr(SB); BYTE $0x92
  744. CALL _strayintr(SB); BYTE $0x93
  745. CALL _strayintr(SB); BYTE $0x94
  746. CALL _strayintr(SB); BYTE $0x95
  747. CALL _strayintr(SB); BYTE $0x96
  748. CALL _strayintr(SB); BYTE $0x97
  749. CALL _strayintr(SB); BYTE $0x98
  750. CALL _strayintr(SB); BYTE $0x99
  751. CALL _strayintr(SB); BYTE $0x9A
  752. CALL _strayintr(SB); BYTE $0x9B
  753. CALL _strayintr(SB); BYTE $0x9C
  754. CALL _strayintr(SB); BYTE $0x9D
  755. CALL _strayintr(SB); BYTE $0x9E
  756. CALL _strayintr(SB); BYTE $0x9F
  757. CALL _strayintr(SB); BYTE $0xA0
  758. CALL _strayintr(SB); BYTE $0xA1
  759. CALL _strayintr(SB); BYTE $0xA2
  760. CALL _strayintr(SB); BYTE $0xA3
  761. CALL _strayintr(SB); BYTE $0xA4
  762. CALL _strayintr(SB); BYTE $0xA5
  763. CALL _strayintr(SB); BYTE $0xA6
  764. CALL _strayintr(SB); BYTE $0xA7
  765. CALL _strayintr(SB); BYTE $0xA8
  766. CALL _strayintr(SB); BYTE $0xA9
  767. CALL _strayintr(SB); BYTE $0xAA
  768. CALL _strayintr(SB); BYTE $0xAB
  769. CALL _strayintr(SB); BYTE $0xAC
  770. CALL _strayintr(SB); BYTE $0xAD
  771. CALL _strayintr(SB); BYTE $0xAE
  772. CALL _strayintr(SB); BYTE $0xAF
  773. CALL _strayintr(SB); BYTE $0xB0
  774. CALL _strayintr(SB); BYTE $0xB1
  775. CALL _strayintr(SB); BYTE $0xB2
  776. CALL _strayintr(SB); BYTE $0xB3
  777. CALL _strayintr(SB); BYTE $0xB4
  778. CALL _strayintr(SB); BYTE $0xB5
  779. CALL _strayintr(SB); BYTE $0xB6
  780. CALL _strayintr(SB); BYTE $0xB7
  781. CALL _strayintr(SB); BYTE $0xB8
  782. CALL _strayintr(SB); BYTE $0xB9
  783. CALL _strayintr(SB); BYTE $0xBA
  784. CALL _strayintr(SB); BYTE $0xBB
  785. CALL _strayintr(SB); BYTE $0xBC
  786. CALL _strayintr(SB); BYTE $0xBD
  787. CALL _strayintr(SB); BYTE $0xBE
  788. CALL _strayintr(SB); BYTE $0xBF
  789. CALL _strayintr(SB); BYTE $0xC0
  790. CALL _strayintr(SB); BYTE $0xC1
  791. CALL _strayintr(SB); BYTE $0xC2
  792. CALL _strayintr(SB); BYTE $0xC3
  793. CALL _strayintr(SB); BYTE $0xC4
  794. CALL _strayintr(SB); BYTE $0xC5
  795. CALL _strayintr(SB); BYTE $0xC6
  796. CALL _strayintr(SB); BYTE $0xC7
  797. CALL _strayintr(SB); BYTE $0xC8
  798. CALL _strayintr(SB); BYTE $0xC9
  799. CALL _strayintr(SB); BYTE $0xCA
  800. CALL _strayintr(SB); BYTE $0xCB
  801. CALL _strayintr(SB); BYTE $0xCC
  802. CALL _strayintr(SB); BYTE $0xCD
  803. CALL _strayintr(SB); BYTE $0xCE
  804. CALL _strayintr(SB); BYTE $0xCF
  805. CALL _strayintr(SB); BYTE $0xD0
  806. CALL _strayintr(SB); BYTE $0xD1
  807. CALL _strayintr(SB); BYTE $0xD2
  808. CALL _strayintr(SB); BYTE $0xD3
  809. CALL _strayintr(SB); BYTE $0xD4
  810. CALL _strayintr(SB); BYTE $0xD5
  811. CALL _strayintr(SB); BYTE $0xD6
  812. CALL _strayintr(SB); BYTE $0xD7
  813. CALL _strayintr(SB); BYTE $0xD8
  814. CALL _strayintr(SB); BYTE $0xD9
  815. CALL _strayintr(SB); BYTE $0xDA
  816. CALL _strayintr(SB); BYTE $0xDB
  817. CALL _strayintr(SB); BYTE $0xDC
  818. CALL _strayintr(SB); BYTE $0xDD
  819. CALL _strayintr(SB); BYTE $0xDE
  820. CALL _strayintr(SB); BYTE $0xDF
  821. CALL _strayintr(SB); BYTE $0xE0
  822. CALL _strayintr(SB); BYTE $0xE1
  823. CALL _strayintr(SB); BYTE $0xE2
  824. CALL _strayintr(SB); BYTE $0xE3
  825. CALL _strayintr(SB); BYTE $0xE4
  826. CALL _strayintr(SB); BYTE $0xE5
  827. CALL _strayintr(SB); BYTE $0xE6
  828. CALL _strayintr(SB); BYTE $0xE7
  829. CALL _strayintr(SB); BYTE $0xE8
  830. CALL _strayintr(SB); BYTE $0xE9
  831. CALL _strayintr(SB); BYTE $0xEA
  832. CALL _strayintr(SB); BYTE $0xEB
  833. CALL _strayintr(SB); BYTE $0xEC
  834. CALL _strayintr(SB); BYTE $0xED
  835. CALL _strayintr(SB); BYTE $0xEE
  836. CALL _strayintr(SB); BYTE $0xEF
  837. CALL _strayintr(SB); BYTE $0xF0
  838. CALL _strayintr(SB); BYTE $0xF1
  839. CALL _strayintr(SB); BYTE $0xF2
  840. CALL _strayintr(SB); BYTE $0xF3
  841. CALL _strayintr(SB); BYTE $0xF4
  842. CALL _strayintr(SB); BYTE $0xF5
  843. CALL _strayintr(SB); BYTE $0xF6
  844. CALL _strayintr(SB); BYTE $0xF7
  845. CALL _strayintr(SB); BYTE $0xF8
  846. CALL _strayintr(SB); BYTE $0xF9
  847. CALL _strayintr(SB); BYTE $0xFA
  848. CALL _strayintr(SB); BYTE $0xFB
  849. CALL _strayintr(SB); BYTE $0xFC
  850. CALL _strayintr(SB); BYTE $0xFD
  851. CALL _strayintr(SB); BYTE $0xFE
  852. CALL _strayintr(SB); BYTE $0xFF