1#include "/sys/src/boot/pc/x16.h" 2#include "mem.h" 3 4#define KB 1024 5#define MB (1024*1024) 6 7#define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */ 8#define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */ 9#define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */ 10#define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */ 11 12TEXT _start32v(SB),$0 13 CLI 14 15 MOVL $edata(SB), DI 16 XORL AX, AX 17 MOVL $end(SB), CX 18 SUBL DI, CX /* end-edata bytes */ 19 SHRL $2, CX /* end-edata doublewords */ 20 21 CLD 22 REP; STOSL /* clear BSS */ 23 24 MOVL CR3, AX 25 /* 1+LOWPTEPAGES zeroed pages at (AX): pdb, pte */ 26 ADDL $KZERO, AX /* VA of PDB */ 27 MOVL AX, mach0pdb(SB) 28 ADDL $((1+LOWPTEPAGES)*BY2PG), AX /* skip pdb & n pte */ 29 MOVL AX, memstart(SB) /* start of available memory */ 30 31 /* 2 zeroed pages at CPU0MACH: mach, gdt */ 32 MOVL $CPU0MACH, AX 33 MOVL AX, mach0m(SB) /* ... VA of Mach */ 34 MOVL AX, m(SB) /* initialise global Mach pointer */ 35 MOVL $0, 0(AX) /* initialise m->machno */ 36 ADDL $MACHSIZE, AX 37 MOVL AX, SP /* switch to new stack in Mach */ 38 MOVL $CPU0GDT, mach0gdt(SB) 39 40 MOVL $0x240000, AX /* try to set Id|Ac in EFLAGS */ 41 PUSHL AX 42 POPFL 43 44 PUSHFL /* retrieve EFLAGS -> BX */ 45 POPL BX 46 47 MOVL $0, AX /* clear Id|Ac, EFLAGS initialised */ 48 PUSHL AX 49 POPFL 50 51 PUSHFL /* retrieve EFLAGS -> AX */ 52 53 XORL BX, (SP) /* togglable bits */ 54 CALL main(SB) 55 56/* 57 * Park a processor. Should never fall through a return from main to here, 58 * should only be called by application processors when shutting down. 59 */ 60TEXT idle(SB), $0 61_idle: 62 STI 63 HLT 64 JMP _idle 65 66TEXT hlt(SB), $0 67 STI 68 HLT 69 RET 70 71#ifdef UNUSED 72/* 73 */ 74TEXT _warp9o(SB), $0 75 MOVL entry+0(FP), CX 76 MOVL multibootheader-KZERO(SB), BX /* multiboot data pointer */ 77 MOVL $0x2badb002, AX /* multiboot magic */ 78 79 CLI 80 JMP* CX 81 82 JMP _idle 83 84/* 85 * Macro for calculating offset within the page directory base. 86 * Note that this is assembler-specific hence the '<<2'. 87 */ 88#define PDO(a) (((((a))>>22) & 0x03FF)<<2) 89 90/* 91 */ 92TEXT _warp9(SB), $0 93 CLI 94 MOVL entry+0(FP), BP 95 96 MOVL CR3, CX /* load address of PDB */ 97 ADDL $KZERO, CX 98 MOVL PDO(KZERO)(CX), DX /* double-map KZERO at 0 */ 99 MOVL DX, PDO(0)(CX) 100 101 MOVL CR3, CX 102 MOVL CX, CR3 /* load and flush the mmu */ 103 104 MOVL $_start32id<>-KZERO(SB), AX 105 JMP* AX /* jump to identity-map */ 106 107TEXT _start32id<>(SB), $0 108 MOVL CR0, DX /* turn off paging */ 109 ANDL $~PG, DX 110 111 MOVL $_stop32pg<>-KZERO(SB), AX 112 MOVL DX, CR0 113 JMP* AX /* forward into the past */ 114 115TEXT _stop32pg<>(SB), $0 116 MOVL multibootheader-KZERO(SB), BX /* multiboot data pointer */ 117 MOVL $0x2badb002, AX /* multiboot magic */ 118 119 JMP* BP 120 121 JMP _idle 122#endif 123 124/* 125 * input a byte 126 */ 127TEXT inb(SB),$0 128 129 MOVL p+0(FP),DX 130 XORL AX,AX 131 INB 132 RET 133 134/* 135 * input a short from a port 136 */ 137TEXT ins(SB), $0 138 139 MOVL p+0(FP), DX 140 XORL AX, AX 141 OPSIZE; INL 142 RET 143 144/* 145 * input a long from a port 146 */ 147TEXT inl(SB), $0 148 149 MOVL p+0(FP), DX 150 XORL AX, AX 151 INL 152 RET 153 154/* 155 * output a byte 156 */ 157TEXT outb(SB),$0 158 159 MOVL p+0(FP),DX 160 MOVL b+4(FP),AX 161 OUTB 162 RET 163 164/* 165 * output a short to a port 166 */ 167TEXT outs(SB), $0 168 MOVL p+0(FP), DX 169 MOVL s+4(FP), AX 170 OPSIZE; OUTL 171 RET 172 173/* 174 * output a long to a port 175 */ 176TEXT outl(SB), $0 177 MOVL p+0(FP), DX 178 MOVL s+4(FP), AX 179 OUTL 180 RET 181 182/* 183 * input a string of bytes from a port 184 */ 185TEXT insb(SB),$0 186 187 MOVL p+0(FP),DX 188 MOVL a+4(FP),DI 189 MOVL c+8(FP),CX 190 CLD; REP; INSB 191 RET 192 193/* 194 * input a string of shorts from a port 195 */ 196TEXT inss(SB),$0 197 MOVL p+0(FP),DX 198 MOVL a+4(FP),DI 199 MOVL c+8(FP),CX 200 CLD 201 REP; OPSIZE; INSL 202 RET 203 204/* 205 * output a string of bytes to a port 206 */ 207TEXT outsb(SB),$0 208 209 MOVL p+0(FP),DX 210 MOVL a+4(FP),SI 211 MOVL c+8(FP),CX 212 CLD; REP; OUTSB 213 RET 214 215/* 216 * output a string of shorts to a port 217 */ 218TEXT outss(SB),$0 219 MOVL p+0(FP),DX 220 MOVL a+4(FP),SI 221 MOVL c+8(FP),CX 222 CLD 223 REP; OPSIZE; OUTSL 224 RET 225 226/* 227 * input a string of longs from a port 228 */ 229TEXT insl(SB),$0 230 231 MOVL p+0(FP),DX 232 MOVL a+4(FP),DI 233 MOVL c+8(FP),CX 234 CLD; REP; INSL 235 RET 236 237/* 238 * output a string of longs to a port 239 */ 240TEXT outsl(SB),$0 241 242 MOVL p+0(FP),DX 243 MOVL a+4(FP),SI 244 MOVL c+8(FP),CX 245 CLD; REP; OUTSL 246 RET 247 248/* 249 * routines to load/read various system registers 250 */ 251GLOBL idtptr(SB),$6 252TEXT putidt(SB),$0 /* interrupt descriptor table */ 253 MOVL t+0(FP),AX 254 MOVL AX,idtptr+2(SB) 255 MOVL l+4(FP),AX 256 MOVW AX,idtptr(SB) 257 MOVL idtptr(SB),IDTR 258 RET 259 260TEXT lgdt(SB), $0 /* GDTR - global descriptor table */ 261 MOVL gdtptr+0(FP), AX 262 MOVL (AX), GDTR 263 RET 264 265TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */ 266 MOVL idtptr+0(FP), AX 267 MOVL (AX), IDTR 268 RET 269 270TEXT putcr3(SB),$0 /* top level page table pointer */ 271 MOVL t+0(FP),AX 272 MOVL AX,CR3 273 RET 274 275TEXT getcr0(SB),$0 /* coprocessor bits */ 276 MOVL CR0,AX 277 RET 278 279TEXT getcr2(SB),$0 /* fault address */ 280 MOVL CR2,AX 281 RET 282 283TEXT getcr3(SB),$0 /* page directory base */ 284 MOVL CR3,AX 285 RET 286 287TEXT getcr4(SB), $0 /* CR4 - extensions */ 288 MOVL CR4, AX 289 RET 290 291TEXT putcr4(SB), $0 292 MOVL cr4+0(FP), AX 293 MOVL AX, CR4 294 RET 295 296TEXT _cycles(SB), $0 /* time stamp counter */ 297 RDTSC 298 MOVL vlong+0(FP), CX /* &vlong */ 299 MOVL AX, 0(CX) /* lo */ 300 MOVL DX, 4(CX) /* hi */ 301 RET 302 303TEXT rdmsr(SB), $0 /* model-specific register */ 304 MOVL index+0(FP), CX 305 RDMSR 306 MOVL vlong+4(FP), CX /* &vlong */ 307 MOVL AX, 0(CX) /* lo */ 308 MOVL DX, 4(CX) /* hi */ 309 RET 310 311TEXT wrmsr(SB), $0 312 MOVL index+0(FP), CX 313 MOVL lo+4(FP), AX 314 MOVL hi+8(FP), DX 315 WRMSR 316 RET 317 318/* 319 * memory barriers 320 */ 321TEXT mb386(SB), $0 322 POPL AX /* return PC */ 323 PUSHFL 324 PUSHL CS 325 PUSHL AX 326 IRETL 327 328TEXT mb586(SB), $0 329 XORL AX, AX 330 CPUID 331 RET 332 333TEXT sfence(SB), $0 334 BYTE $0x0f 335 BYTE $0xae 336 BYTE $0xf8 337 RET 338 339TEXT lfence(SB), $0 340 BYTE $0x0f 341 BYTE $0xae 342 BYTE $0xe8 343 RET 344 345TEXT mfence(SB), $0 346 BYTE $0x0f 347 BYTE $0xae 348 BYTE $0xf0 349 RET 350 351/* 352 * special traps 353 */ 354TEXT intr0(SB),$0 355 PUSHL $0 356 PUSHL $0 357 JMP intrcommon 358TEXT intr1(SB),$0 359 PUSHL $0 360 PUSHL $1 361 JMP intrcommon 362TEXT intr2(SB),$0 363 PUSHL $0 364 PUSHL $2 365 JMP intrcommon 366TEXT intr3(SB),$0 367 PUSHL $0 368 PUSHL $3 369 JMP intrcommon 370TEXT intr4(SB),$0 371 PUSHL $0 372 PUSHL $4 373 JMP intrcommon 374TEXT intr5(SB),$0 375 PUSHL $0 376 PUSHL $5 377 JMP intrcommon 378TEXT intr6(SB),$0 379 PUSHL $0 380 PUSHL $6 381 JMP intrcommon 382TEXT intr7(SB),$0 383 PUSHL $0 384 PUSHL $7 385 JMP intrcommon 386TEXT intr8(SB),$0 387 PUSHL $8 388 JMP intrcommon 389TEXT intr9(SB),$0 390 PUSHL $0 391 PUSHL $9 392 JMP intrcommon 393TEXT intr10(SB),$0 394 PUSHL $10 395 JMP intrcommon 396TEXT intr11(SB),$0 397 PUSHL $11 398 JMP intrcommon 399TEXT intr12(SB),$0 400 PUSHL $12 401 JMP intrcommon 402TEXT intr13(SB),$0 403 PUSHL $13 404 JMP intrcommon 405TEXT intr14(SB),$0 406 PUSHL $14 407 JMP intrcommon 408TEXT intr15(SB),$0 409 PUSHL $0 410 PUSHL $15 411 JMP intrcommon 412TEXT intr16(SB),$0 413 PUSHL $0 414 PUSHL $16 415 JMP intrcommon 416TEXT intr24(SB),$0 417 PUSHL $0 418 PUSHL $24 419 JMP intrcommon 420TEXT intr25(SB),$0 421 PUSHL $0 422 PUSHL $25 423 JMP intrcommon 424TEXT intr26(SB),$0 425 PUSHL $0 426 PUSHL $26 427 JMP intrcommon 428TEXT intr27(SB),$0 429 PUSHL $0 430 PUSHL $27 431 JMP intrcommon 432TEXT intr28(SB),$0 433 PUSHL $0 434 PUSHL $28 435 JMP intrcommon 436TEXT intr29(SB),$0 437 PUSHL $0 438 PUSHL $29 439 JMP intrcommon 440TEXT intr30(SB),$0 441 PUSHL $0 442 PUSHL $30 443 JMP intrcommon 444TEXT intr31(SB),$0 445 PUSHL $0 446 PUSHL $31 447 JMP intrcommon 448TEXT intr32(SB),$0 449 PUSHL $0 450 PUSHL $32 451 JMP intrcommon 452TEXT intr33(SB),$0 453 PUSHL $0 454 PUSHL $33 455 JMP intrcommon 456TEXT intr34(SB),$0 457 PUSHL $0 458 PUSHL $34 459 JMP intrcommon 460TEXT intr35(SB),$0 461 PUSHL $0 462 PUSHL $35 463 JMP intrcommon 464TEXT intr36(SB),$0 465 PUSHL $0 466 PUSHL $36 467 JMP intrcommon 468TEXT intr37(SB),$0 469 PUSHL $0 470 PUSHL $37 471 JMP intrcommon 472TEXT intr38(SB),$0 473 PUSHL $0 474 PUSHL $38 475 JMP intrcommon 476TEXT intr39(SB),$0 477 PUSHL $0 478 PUSHL $39 479 JMP intrcommon 480TEXT intr64(SB),$0 481 PUSHL $0 482 PUSHL $64 483 JMP intrcommon 484TEXT intrbad(SB),$0 485 PUSHL $0 486 PUSHL $0x1ff 487 JMP intrcommon 488 489intrcommon: 490 PUSHL DS 491 PUSHL ES 492 PUSHL FS 493 PUSHL GS 494 PUSHAL 495 MOVL $(KDSEL),AX 496 MOVW AX,DS 497 MOVW AX,ES 498 LEAL 0(SP),AX 499 PUSHL AX 500 CALL trap(SB) 501 POPL AX 502 POPAL 503 POPL GS 504 POPL FS 505 POPL ES 506 POPL DS 507 ADDL $8,SP /* error code and trap type */ 508 IRETL 509 510 511/* 512 * interrupt level is interrupts on or off. 513 * kprof knows that spllo to spldone is splx routines. 514 */ 515TEXT spllo(SB),$0 516 PUSHFL 517 POPL AX 518 STI 519 RET 520 521TEXT splhi(SB),$0 522 PUSHFL 523 POPL AX 524 CLI 525 RET 526 527TEXT splx(SB),$0 528 MOVL s+0(FP),AX 529 PUSHL AX 530 POPFL 531 RET 532 533TEXT spldone(SB), $0 534 RET 535 536TEXT islo(SB), $0 537 PUSHFL 538 POPL AX 539 ANDL $0x200, AX /* interrupt enable flag */ 540 RET 541 542/* 543 * Miscellany 544 */ 545TEXT bsr(SB), $0 546 BSRL word+0(FP), AX /* count leading zeros */ 547 RET 548 549/* 550 * basic timing loop to determine CPU frequency 551 */ 552TEXT aamloop(SB),$0 553 554 MOVL c+0(FP),CX 555aaml1: 556 AAM 557 LOOP aaml1 558 RET 559