5 * Some machine instructions not handled by 8[al].
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 #define BSFL BYTE $0xf; BYTE $0xbc; BYTE $0xc0 /* bsfl AX,AX */
17 * Macros for calculating offsets within the page directory base
18 * and page tables. Note that these are assembler-specific hence
21 #define PDO(a) (((((a))>>22) & 0x03FF)<<2)
22 #define PTO(a) (((((a))>>12) & 0x03FF)<<2)
25 * Entry point from XEN's "linux" builder.
26 * At this point RAM from 0..4M ("physical") is mapped at KZERO,
27 * the kernel is loaded, we're running on a boot stack and a
28 * boot page table. The start_info structure describes the
29 * situation, and is pointed to by SI.
30 * The stack is the highest used address.
33 MOVL SP, xentop(SB) /* set global for top of mapped region */
34 MOVL SI, xenstart(SB) /* set global to start_info_t */
35 MOVL $0, AX /* clear EFLAGS */
38 CALL mmumapcpu0(SB) /* make mapping before using stack */
39 MOVL $(MACHADDR+MACHSIZE-4), SP /* set stack */
43 * Park a processor. Should never fall through a return from main to here,
44 * should only be called by application processors when shutting down.
53 * Read/write various system registers.
54 * CR4 and the 'model specific registers' should only be read/written
55 * after it has been determined the processor supports them
57 TEXT _cycles(SB), $0 /* time stamp counter; cycles since power up */
59 MOVL vlong+0(FP), CX /* &vlong */
60 MOVL AX, 0(CX) /* lo */
61 MOVL DX, 4(CX) /* hi */
64 TEXT rdmsr(SB), $0 /* model-specific register */
67 MOVL vlong+4(FP), CX /* &vlong */
68 MOVL AX, 0(CX) /* lo */
69 MOVL DX, 4(CX) /* hi */
72 /* Xen doesn't let us do this */
78 * Try to determine the CPU type which requires fiddling with EFLAGS.
79 * If the Id bit can be toggled then the CPUID instruction can be used
80 * to determine CPU identity and features. First have to check if it's
81 * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
82 * toggled then it's an older 486 of some kind.
84 * cpuid(fun, regs[4]);
91 POPL BX /* retrieve value */
94 POPFL /* clear Id|Ac, EFLAGS initialised */
96 POPL AX /* retrieve value */
98 TESTL $0x040000, AX /* Ac */
99 JZ _cpu386 /* can't set this bit on 386 */
100 TESTL $0x200000, AX /* Id */
101 JZ _cpu486 /* can't toggle this bit on some 486 */
128 * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW
129 * instructions do NOT have the WAIT prefix byte (i.e. they act like their
130 * FNxxx variations) so WAIT instructions must be explicitly placed in the
135 ANDL $0xC, AX /* EM, TS */ ;\
141 ANDL $~0x4, AX /* EM=0 */ ;\
142 ORL $0x28, AX /* NE=1, TS=1 */ ;\
147 ANDL $~0xC, AX /* EM=0, TS=0 */ ;\
150 TEXT fpoff(SB), $0 /* disable */
154 TEXT fpinit(SB), $0 /* enable and init */
158 /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
159 /* note that low 6 bits are masks, not enables, on this chip */
166 TEXT fpx87save(SB), $0 /* save state and disable */
168 FSAVE 0(AX) /* no WAIT */
172 TEXT fpx87restore(SB), $0 /* enable and restore state */
179 TEXT fpstatus(SB), $0 /* get floating point status */
183 TEXT fpenv(SB), $0 /* save state without waiting */
188 TEXT fpclear(SB), $0 /* clear pending exceptions */
201 XCHGL AX, (BX) /* lock->key */
204 TEXT getstack(SB), $0
208 POPL AX /* return PC */
256 /* Return the position of the first bit set. Undefined if zero. */
262 TEXT cmpswap486(SB), $0
267 BYTE $0x0F; BYTE $0xB1; BYTE $0x0B /* CMPXCHGL CX, (BX) */
275 TEXT mul64fract(SB), $0
277 XORL BX, BX /* BX = 0 */
280 MULL b+16(FP) /* a1*b1 */
281 MOVL AX, 4(CX) /* r2 = lo(a1*b1) */
284 MULL b+12(FP) /* a1*b0 */
285 MOVL AX, 0(CX) /* r1 = lo(a1*b0) */
286 ADDL DX, 4(CX) /* r2 += hi(a1*b0) */
289 MULL b+16(FP) /* a0*b1 */
290 ADDL AX, 0(CX) /* r1 += lo(a0*b1) */
291 ADCL DX, 4(CX) /* r2 += hi(a0*b1) + carry */
294 MULL b+12(FP) /* a0*b0 */
295 ADDL DX, 0(CX) /* r1 += hi(a0*b0) */
296 ADCL BX, 4(CX) /* r2 += carry */
299 #define RDRANDAX BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
301 TEXT rdrand32(SB), $-4
307 TEXT rdrandbuf(SB), $0
332 * label consists of a stack pointer and a PC
334 TEXT gotolabel(SB), $0
336 MOVL 0(AX), SP /* restore sp */
337 MOVL 4(AX), AX /* put return pc on the stack */
339 MOVL $1, AX /* return 1 */
342 TEXT setlabel(SB), $0
344 MOVL SP, 0(AX) /* store sp */
345 MOVL 0(SP), BX /* store return pc */
347 MOVL $0, AX /* return 0 */
356 BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */
361 BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */
366 * Interrupt/exception handling.
367 * Each entry in the vector table calls either _strayintr or _strayintrx depending
368 * on whether an error code has been automatically pushed onto the stack
369 * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
370 * the trap type from the vector table entry and placing it on the stack as part
371 * of the Ureg structure.
372 * Exceptions to this are the syscall vector and the page fault
373 * vector. Syscalls are dispatched seperately. Page faults
374 * have to take care of the extra cr2 parameter that xen places
375 * at the top of the stack.
376 * The size of each entry in the vector table (6 bytes) is known in trapinit().
378 TEXT _strayintr(SB), $0
379 PUSHL AX /* save AX */
380 MOVL 4(SP), AX /* return PC from vectortable(SB) */
383 TEXT _strayintrx(SB), $0
384 XCHGL AX, (SP) /* swap AX with vectortable CALL PC */
386 PUSHL DS /* save DS */
388 POPL DS /* fix up DS */
389 MOVBLZX (AX), AX /* trap type -> AX */
390 XCHGL AX, 4(SP) /* exchange trap type with saved AX */
392 PUSHL ES /* save ES */
394 POPL ES /* fix up ES */
396 PUSHL FS /* save the rest of the Ureg struct */
400 PUSHL SP /* Ureg* argument to trap */
410 ADDL $8, SP /* pop error code and trap type */
413 TEXT vectortable(SB), $0
414 CALL _strayintr(SB); BYTE $0x00 /* divide error */
415 CALL _strayintr(SB); BYTE $0x01 /* debug exception */
416 CALL _strayintr(SB); BYTE $0x02 /* NMI interrupt */
417 CALL _strayintr(SB); BYTE $0x03 /* breakpoint */
418 CALL _strayintr(SB); BYTE $0x04 /* overflow */
419 CALL _strayintr(SB); BYTE $0x05 /* bound */
420 CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */
421 CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */
422 CALL _strayintrx(SB); BYTE $0x08 /* double fault */
423 CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
424 CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */
425 CALL _strayintrx(SB); BYTE $0x0B /* segment not available */
426 CALL _strayintrx(SB); BYTE $0x0C /* stack exception */
427 CALL _strayintrx(SB); BYTE $0x0D /* general protection error */
428 CALL _strayintrx(SB); BYTE $0x0E /* page fault */
429 CALL _strayintr(SB); BYTE $0x0F /* */
430 CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
431 CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
432 CALL _strayintr(SB); BYTE $0x12 /* machine check */
433 CALL _strayintr(SB); BYTE $0x13
434 CALL _strayintr(SB); BYTE $0x14
435 CALL _strayintr(SB); BYTE $0x15
436 CALL _strayintr(SB); BYTE $0x16
437 CALL _strayintr(SB); BYTE $0x17
438 CALL _strayintr(SB); BYTE $0x18
439 CALL _strayintr(SB); BYTE $0x19
440 CALL _strayintr(SB); BYTE $0x1A
441 CALL _strayintr(SB); BYTE $0x1B
442 CALL _strayintr(SB); BYTE $0x1C
443 CALL _strayintr(SB); BYTE $0x1D
444 CALL _strayintr(SB); BYTE $0x1E
445 CALL _strayintr(SB); BYTE $0x1F
446 CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */
447 CALL _strayintr(SB); BYTE $0x21
448 CALL _strayintr(SB); BYTE $0x22
449 CALL _strayintr(SB); BYTE $0x23
450 CALL _strayintr(SB); BYTE $0x24
451 CALL _strayintr(SB); BYTE $0x25
452 CALL _strayintr(SB); BYTE $0x26
453 CALL _strayintr(SB); BYTE $0x27
454 CALL _strayintr(SB); BYTE $0x28
455 CALL _strayintr(SB); BYTE $0x29
456 CALL _strayintr(SB); BYTE $0x2A
457 CALL _strayintr(SB); BYTE $0x2B
458 CALL _strayintr(SB); BYTE $0x2C
459 CALL _strayintr(SB); BYTE $0x2D
460 CALL _strayintr(SB); BYTE $0x2E
461 CALL _strayintr(SB); BYTE $0x2F
462 CALL _strayintr(SB); BYTE $0x30
463 CALL _strayintr(SB); BYTE $0x31
464 CALL _strayintr(SB); BYTE $0x32
465 CALL _strayintr(SB); BYTE $0x33
466 CALL _strayintr(SB); BYTE $0x34
467 CALL _strayintr(SB); BYTE $0x35
468 CALL _strayintr(SB); BYTE $0x36
469 CALL _strayintr(SB); BYTE $0x37
470 CALL _strayintr(SB); BYTE $0x38
471 CALL _strayintr(SB); BYTE $0x39
472 CALL _strayintr(SB); BYTE $0x3A
473 CALL _strayintr(SB); BYTE $0x3B
474 CALL _strayintr(SB); BYTE $0x3C
475 CALL _strayintr(SB); BYTE $0x3D
476 CALL _strayintr(SB); BYTE $0x3E
477 CALL _strayintr(SB); BYTE $0x3F
478 CALL _syscallintr(SB); BYTE $0x40 /* VectorSYSCALL */
479 CALL _strayintr(SB); BYTE $0x41
480 CALL _strayintr(SB); BYTE $0x42
481 CALL _strayintr(SB); BYTE $0x43
482 CALL _strayintr(SB); BYTE $0x44
483 CALL _strayintr(SB); BYTE $0x45
484 CALL _strayintr(SB); BYTE $0x46
485 CALL _strayintr(SB); BYTE $0x47
486 CALL _strayintr(SB); BYTE $0x48
487 CALL _strayintr(SB); BYTE $0x49
488 CALL _strayintr(SB); BYTE $0x4A
489 CALL _strayintr(SB); BYTE $0x4B
490 CALL _strayintr(SB); BYTE $0x4C
491 CALL _strayintr(SB); BYTE $0x4D
492 CALL _strayintr(SB); BYTE $0x4E
493 CALL _strayintr(SB); BYTE $0x4F
494 CALL _strayintr(SB); BYTE $0x50
495 CALL _strayintr(SB); BYTE $0x51
496 CALL _strayintr(SB); BYTE $0x52
497 CALL _strayintr(SB); BYTE $0x53
498 CALL _strayintr(SB); BYTE $0x54
499 CALL _strayintr(SB); BYTE $0x55
500 CALL _strayintr(SB); BYTE $0x56
501 CALL _strayintr(SB); BYTE $0x57
502 CALL _strayintr(SB); BYTE $0x58
503 CALL _strayintr(SB); BYTE $0x59
504 CALL _strayintr(SB); BYTE $0x5A
505 CALL _strayintr(SB); BYTE $0x5B
506 CALL _strayintr(SB); BYTE $0x5C
507 CALL _strayintr(SB); BYTE $0x5D
508 CALL _strayintr(SB); BYTE $0x5E
509 CALL _strayintr(SB); BYTE $0x5F
510 CALL _strayintr(SB); BYTE $0x60
511 CALL _strayintr(SB); BYTE $0x61
512 CALL _strayintr(SB); BYTE $0x62
513 CALL _strayintr(SB); BYTE $0x63
514 CALL _strayintr(SB); BYTE $0x64
515 CALL _strayintr(SB); BYTE $0x65
516 CALL _strayintr(SB); BYTE $0x66
517 CALL _strayintr(SB); BYTE $0x67
518 CALL _strayintr(SB); BYTE $0x68
519 CALL _strayintr(SB); BYTE $0x69
520 CALL _strayintr(SB); BYTE $0x6A
521 CALL _strayintr(SB); BYTE $0x6B
522 CALL _strayintr(SB); BYTE $0x6C
523 CALL _strayintr(SB); BYTE $0x6D
524 CALL _strayintr(SB); BYTE $0x6E
525 CALL _strayintr(SB); BYTE $0x6F
526 CALL _strayintr(SB); BYTE $0x70
527 CALL _strayintr(SB); BYTE $0x71
528 CALL _strayintr(SB); BYTE $0x72
529 CALL _strayintr(SB); BYTE $0x73
530 CALL _strayintr(SB); BYTE $0x74
531 CALL _strayintr(SB); BYTE $0x75
532 CALL _strayintr(SB); BYTE $0x76
533 CALL _strayintr(SB); BYTE $0x77
534 CALL _strayintr(SB); BYTE $0x78
535 CALL _strayintr(SB); BYTE $0x79
536 CALL _strayintr(SB); BYTE $0x7A
537 CALL _strayintr(SB); BYTE $0x7B
538 CALL _strayintr(SB); BYTE $0x7C
539 CALL _strayintr(SB); BYTE $0x7D
540 CALL _strayintr(SB); BYTE $0x7E
541 CALL _strayintr(SB); BYTE $0x7F
542 CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
543 CALL _strayintr(SB); BYTE $0x81
544 CALL _strayintr(SB); BYTE $0x82
545 CALL _strayintr(SB); BYTE $0x83
546 CALL _strayintr(SB); BYTE $0x84
547 CALL _strayintr(SB); BYTE $0x85
548 CALL _strayintr(SB); BYTE $0x86
549 CALL _strayintr(SB); BYTE $0x87
550 CALL _strayintr(SB); BYTE $0x88
551 CALL _strayintr(SB); BYTE $0x89
552 CALL _strayintr(SB); BYTE $0x8A
553 CALL _strayintr(SB); BYTE $0x8B
554 CALL _strayintr(SB); BYTE $0x8C
555 CALL _strayintr(SB); BYTE $0x8D
556 CALL _strayintr(SB); BYTE $0x8E
557 CALL _strayintr(SB); BYTE $0x8F
558 CALL _strayintr(SB); BYTE $0x90
559 CALL _strayintr(SB); BYTE $0x91
560 CALL _strayintr(SB); BYTE $0x92
561 CALL _strayintr(SB); BYTE $0x93
562 CALL _strayintr(SB); BYTE $0x94
563 CALL _strayintr(SB); BYTE $0x95
564 CALL _strayintr(SB); BYTE $0x96
565 CALL _strayintr(SB); BYTE $0x97
566 CALL _strayintr(SB); BYTE $0x98
567 CALL _strayintr(SB); BYTE $0x99
568 CALL _strayintr(SB); BYTE $0x9A
569 CALL _strayintr(SB); BYTE $0x9B
570 CALL _strayintr(SB); BYTE $0x9C
571 CALL _strayintr(SB); BYTE $0x9D
572 CALL _strayintr(SB); BYTE $0x9E
573 CALL _strayintr(SB); BYTE $0x9F
574 CALL _strayintr(SB); BYTE $0xA0
575 CALL _strayintr(SB); BYTE $0xA1
576 CALL _strayintr(SB); BYTE $0xA2
577 CALL _strayintr(SB); BYTE $0xA3
578 CALL _strayintr(SB); BYTE $0xA4
579 CALL _strayintr(SB); BYTE $0xA5
580 CALL _strayintr(SB); BYTE $0xA6
581 CALL _strayintr(SB); BYTE $0xA7
582 CALL _strayintr(SB); BYTE $0xA8
583 CALL _strayintr(SB); BYTE $0xA9
584 CALL _strayintr(SB); BYTE $0xAA
585 CALL _strayintr(SB); BYTE $0xAB
586 CALL _strayintr(SB); BYTE $0xAC
587 CALL _strayintr(SB); BYTE $0xAD
588 CALL _strayintr(SB); BYTE $0xAE
589 CALL _strayintr(SB); BYTE $0xAF
590 CALL _strayintr(SB); BYTE $0xB0
591 CALL _strayintr(SB); BYTE $0xB1
592 CALL _strayintr(SB); BYTE $0xB2
593 CALL _strayintr(SB); BYTE $0xB3
594 CALL _strayintr(SB); BYTE $0xB4
595 CALL _strayintr(SB); BYTE $0xB5
596 CALL _strayintr(SB); BYTE $0xB6
597 CALL _strayintr(SB); BYTE $0xB7
598 CALL _strayintr(SB); BYTE $0xB8
599 CALL _strayintr(SB); BYTE $0xB9
600 CALL _strayintr(SB); BYTE $0xBA
601 CALL _strayintr(SB); BYTE $0xBB
602 CALL _strayintr(SB); BYTE $0xBC
603 CALL _strayintr(SB); BYTE $0xBD
604 CALL _strayintr(SB); BYTE $0xBE
605 CALL _strayintr(SB); BYTE $0xBF
606 CALL _strayintr(SB); BYTE $0xC0
607 CALL _strayintr(SB); BYTE $0xC1
608 CALL _strayintr(SB); BYTE $0xC2
609 CALL _strayintr(SB); BYTE $0xC3
610 CALL _strayintr(SB); BYTE $0xC4
611 CALL _strayintr(SB); BYTE $0xC5
612 CALL _strayintr(SB); BYTE $0xC6
613 CALL _strayintr(SB); BYTE $0xC7
614 CALL _strayintr(SB); BYTE $0xC8
615 CALL _strayintr(SB); BYTE $0xC9
616 CALL _strayintr(SB); BYTE $0xCA
617 CALL _strayintr(SB); BYTE $0xCB
618 CALL _strayintr(SB); BYTE $0xCC
619 CALL _strayintr(SB); BYTE $0xCD
620 CALL _strayintr(SB); BYTE $0xCE
621 CALL _strayintr(SB); BYTE $0xCF
622 CALL _strayintr(SB); BYTE $0xD0
623 CALL _strayintr(SB); BYTE $0xD1
624 CALL _strayintr(SB); BYTE $0xD2
625 CALL _strayintr(SB); BYTE $0xD3
626 CALL _strayintr(SB); BYTE $0xD4
627 CALL _strayintr(SB); BYTE $0xD5
628 CALL _strayintr(SB); BYTE $0xD6
629 CALL _strayintr(SB); BYTE $0xD7
630 CALL _strayintr(SB); BYTE $0xD8
631 CALL _strayintr(SB); BYTE $0xD9
632 CALL _strayintr(SB); BYTE $0xDA
633 CALL _strayintr(SB); BYTE $0xDB
634 CALL _strayintr(SB); BYTE $0xDC
635 CALL _strayintr(SB); BYTE $0xDD
636 CALL _strayintr(SB); BYTE $0xDE
637 CALL _strayintr(SB); BYTE $0xDF
638 CALL _strayintr(SB); BYTE $0xE0
639 CALL _strayintr(SB); BYTE $0xE1
640 CALL _strayintr(SB); BYTE $0xE2
641 CALL _strayintr(SB); BYTE $0xE3
642 CALL _strayintr(SB); BYTE $0xE4
643 CALL _strayintr(SB); BYTE $0xE5
644 CALL _strayintr(SB); BYTE $0xE6
645 CALL _strayintr(SB); BYTE $0xE7
646 CALL _strayintr(SB); BYTE $0xE8
647 CALL _strayintr(SB); BYTE $0xE9
648 CALL _strayintr(SB); BYTE $0xEA
649 CALL _strayintr(SB); BYTE $0xEB
650 CALL _strayintr(SB); BYTE $0xEC
651 CALL _strayintr(SB); BYTE $0xED
652 CALL _strayintr(SB); BYTE $0xEE
653 CALL _strayintr(SB); BYTE $0xEF
654 CALL _strayintr(SB); BYTE $0xF0
655 CALL _strayintr(SB); BYTE $0xF1
656 CALL _strayintr(SB); BYTE $0xF2
657 CALL _strayintr(SB); BYTE $0xF3
658 CALL _strayintr(SB); BYTE $0xF4
659 CALL _strayintr(SB); BYTE $0xF5
660 CALL _strayintr(SB); BYTE $0xF6
661 CALL _strayintr(SB); BYTE $0xF7
662 CALL _strayintr(SB); BYTE $0xF8
663 CALL _strayintr(SB); BYTE $0xF9
664 CALL _strayintr(SB); BYTE $0xFA
665 CALL _strayintr(SB); BYTE $0xFB
666 CALL _strayintr(SB); BYTE $0xFC
667 CALL _strayintr(SB); BYTE $0xFD
668 CALL _strayintr(SB); BYTE $0xFE
669 CALL _strayintr(SB); BYTE $0xFF