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 fpx87save0(SB), $0 /* save state and disable */
168 FSAVE 0(AX) /* no WAIT */
172 TEXT fpx87restore0(SB), $0 /* enable and restore state */
179 TEXT fpclear(SB), $0 /* clear pending exceptions */
185 TEXT fpssesave(SB), $0 /* save state and disable */
187 FXSAVE 0(AX) /* no WAIT */
191 TEXT fpsserestore(SB), $0 /* enable and restore state */
198 TEXT ldmxcsr(SB), $0 /* Load MXCSR */
209 XCHGL AX, (BX) /* lock->key */
212 TEXT getstack(SB), $0
216 POPL AX /* return PC */
264 /* Return the position of the first bit set. Undefined if zero. */
270 TEXT cmpswap486(SB), $0
275 BYTE $0x0F; BYTE $0xB1; BYTE $0x0B /* CMPXCHGL CX, (BX) */
283 TEXT mul64fract(SB), $0
285 XORL BX, BX /* BX = 0 */
288 MULL b+16(FP) /* a1*b1 */
289 MOVL AX, 4(CX) /* r2 = lo(a1*b1) */
292 MULL b+12(FP) /* a1*b0 */
293 MOVL AX, 0(CX) /* r1 = lo(a1*b0) */
294 ADDL DX, 4(CX) /* r2 += hi(a1*b0) */
297 MULL b+16(FP) /* a0*b1 */
298 ADDL AX, 0(CX) /* r1 += lo(a0*b1) */
299 ADCL DX, 4(CX) /* r2 += hi(a0*b1) + carry */
302 MULL b+12(FP) /* a0*b0 */
303 ADDL DX, 0(CX) /* r1 += hi(a0*b0) */
304 ADCL BX, 4(CX) /* r2 += carry */
307 #define RDRANDAX BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
309 TEXT rdrand32(SB), $-4
315 TEXT rdrandbuf(SB), $0
340 * label consists of a stack pointer and a PC
342 TEXT gotolabel(SB), $0
344 MOVL 0(AX), SP /* restore sp */
345 MOVL 4(AX), AX /* put return pc on the stack */
347 MOVL $1, AX /* return 1 */
350 TEXT setlabel(SB), $0
352 MOVL SP, 0(AX) /* store sp */
353 MOVL 0(SP), BX /* store return pc */
355 MOVL $0, AX /* return 0 */
364 BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */
369 BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */
374 * Interrupt/exception handling.
375 * Each entry in the vector table calls either _strayintr or _strayintrx depending
376 * on whether an error code has been automatically pushed onto the stack
377 * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
378 * the trap type from the vector table entry and placing it on the stack as part
379 * of the Ureg structure.
380 * Exceptions to this are the syscall vector and the page fault
381 * vector. Syscalls are dispatched seperately. Page faults
382 * have to take care of the extra cr2 parameter that xen places
383 * at the top of the stack.
384 * The size of each entry in the vector table (6 bytes) is known in trapinit().
386 TEXT _strayintr(SB), $0
387 PUSHL AX /* save AX */
388 MOVL 4(SP), AX /* return PC from vectortable(SB) */
391 TEXT _strayintrx(SB), $0
392 XCHGL AX, (SP) /* swap AX with vectortable CALL PC */
394 PUSHL DS /* save DS */
396 POPL DS /* fix up DS */
397 MOVBLZX (AX), AX /* trap type -> AX */
398 XCHGL AX, 4(SP) /* exchange trap type with saved AX */
400 PUSHL ES /* save ES */
402 POPL ES /* fix up ES */
404 PUSHL FS /* save the rest of the Ureg struct */
408 PUSHL SP /* Ureg* argument to trap */
418 ADDL $8, SP /* pop error code and trap type */
421 TEXT vectortable(SB), $0
422 CALL _strayintr(SB); BYTE $0x00 /* divide error */
423 CALL _strayintr(SB); BYTE $0x01 /* debug exception */
424 CALL _strayintr(SB); BYTE $0x02 /* NMI interrupt */
425 CALL _strayintr(SB); BYTE $0x03 /* breakpoint */
426 CALL _strayintr(SB); BYTE $0x04 /* overflow */
427 CALL _strayintr(SB); BYTE $0x05 /* bound */
428 CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */
429 CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */
430 CALL _strayintrx(SB); BYTE $0x08 /* double fault */
431 CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
432 CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */
433 CALL _strayintrx(SB); BYTE $0x0B /* segment not available */
434 CALL _strayintrx(SB); BYTE $0x0C /* stack exception */
435 CALL _strayintrx(SB); BYTE $0x0D /* general protection error */
436 CALL _strayintrx(SB); BYTE $0x0E /* page fault */
437 CALL _strayintr(SB); BYTE $0x0F /* */
438 CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
439 CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
440 CALL _strayintr(SB); BYTE $0x12 /* machine check */
441 CALL _strayintr(SB); BYTE $0x13
442 CALL _strayintr(SB); BYTE $0x14
443 CALL _strayintr(SB); BYTE $0x15
444 CALL _strayintr(SB); BYTE $0x16
445 CALL _strayintr(SB); BYTE $0x17
446 CALL _strayintr(SB); BYTE $0x18
447 CALL _strayintr(SB); BYTE $0x19
448 CALL _strayintr(SB); BYTE $0x1A
449 CALL _strayintr(SB); BYTE $0x1B
450 CALL _strayintr(SB); BYTE $0x1C
451 CALL _strayintr(SB); BYTE $0x1D
452 CALL _strayintr(SB); BYTE $0x1E
453 CALL _strayintr(SB); BYTE $0x1F
454 CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */
455 CALL _strayintr(SB); BYTE $0x21
456 CALL _strayintr(SB); BYTE $0x22
457 CALL _strayintr(SB); BYTE $0x23
458 CALL _strayintr(SB); BYTE $0x24
459 CALL _strayintr(SB); BYTE $0x25
460 CALL _strayintr(SB); BYTE $0x26
461 CALL _strayintr(SB); BYTE $0x27
462 CALL _strayintr(SB); BYTE $0x28
463 CALL _strayintr(SB); BYTE $0x29
464 CALL _strayintr(SB); BYTE $0x2A
465 CALL _strayintr(SB); BYTE $0x2B
466 CALL _strayintr(SB); BYTE $0x2C
467 CALL _strayintr(SB); BYTE $0x2D
468 CALL _strayintr(SB); BYTE $0x2E
469 CALL _strayintr(SB); BYTE $0x2F
470 CALL _strayintr(SB); BYTE $0x30
471 CALL _strayintr(SB); BYTE $0x31
472 CALL _strayintr(SB); BYTE $0x32
473 CALL _strayintr(SB); BYTE $0x33
474 CALL _strayintr(SB); BYTE $0x34
475 CALL _strayintr(SB); BYTE $0x35
476 CALL _strayintr(SB); BYTE $0x36
477 CALL _strayintr(SB); BYTE $0x37
478 CALL _strayintr(SB); BYTE $0x38
479 CALL _strayintr(SB); BYTE $0x39
480 CALL _strayintr(SB); BYTE $0x3A
481 CALL _strayintr(SB); BYTE $0x3B
482 CALL _strayintr(SB); BYTE $0x3C
483 CALL _strayintr(SB); BYTE $0x3D
484 CALL _strayintr(SB); BYTE $0x3E
485 CALL _strayintr(SB); BYTE $0x3F
486 CALL _syscallintr(SB); BYTE $0x40 /* VectorSYSCALL */
487 CALL _strayintr(SB); BYTE $0x41
488 CALL _strayintr(SB); BYTE $0x42
489 CALL _strayintr(SB); BYTE $0x43
490 CALL _strayintr(SB); BYTE $0x44
491 CALL _strayintr(SB); BYTE $0x45
492 CALL _strayintr(SB); BYTE $0x46
493 CALL _strayintr(SB); BYTE $0x47
494 CALL _strayintr(SB); BYTE $0x48
495 CALL _strayintr(SB); BYTE $0x49
496 CALL _strayintr(SB); BYTE $0x4A
497 CALL _strayintr(SB); BYTE $0x4B
498 CALL _strayintr(SB); BYTE $0x4C
499 CALL _strayintr(SB); BYTE $0x4D
500 CALL _strayintr(SB); BYTE $0x4E
501 CALL _strayintr(SB); BYTE $0x4F
502 CALL _strayintr(SB); BYTE $0x50
503 CALL _strayintr(SB); BYTE $0x51
504 CALL _strayintr(SB); BYTE $0x52
505 CALL _strayintr(SB); BYTE $0x53
506 CALL _strayintr(SB); BYTE $0x54
507 CALL _strayintr(SB); BYTE $0x55
508 CALL _strayintr(SB); BYTE $0x56
509 CALL _strayintr(SB); BYTE $0x57
510 CALL _strayintr(SB); BYTE $0x58
511 CALL _strayintr(SB); BYTE $0x59
512 CALL _strayintr(SB); BYTE $0x5A
513 CALL _strayintr(SB); BYTE $0x5B
514 CALL _strayintr(SB); BYTE $0x5C
515 CALL _strayintr(SB); BYTE $0x5D
516 CALL _strayintr(SB); BYTE $0x5E
517 CALL _strayintr(SB); BYTE $0x5F
518 CALL _strayintr(SB); BYTE $0x60
519 CALL _strayintr(SB); BYTE $0x61
520 CALL _strayintr(SB); BYTE $0x62
521 CALL _strayintr(SB); BYTE $0x63
522 CALL _strayintr(SB); BYTE $0x64
523 CALL _strayintr(SB); BYTE $0x65
524 CALL _strayintr(SB); BYTE $0x66
525 CALL _strayintr(SB); BYTE $0x67
526 CALL _strayintr(SB); BYTE $0x68
527 CALL _strayintr(SB); BYTE $0x69
528 CALL _strayintr(SB); BYTE $0x6A
529 CALL _strayintr(SB); BYTE $0x6B
530 CALL _strayintr(SB); BYTE $0x6C
531 CALL _strayintr(SB); BYTE $0x6D
532 CALL _strayintr(SB); BYTE $0x6E
533 CALL _strayintr(SB); BYTE $0x6F
534 CALL _strayintr(SB); BYTE $0x70
535 CALL _strayintr(SB); BYTE $0x71
536 CALL _strayintr(SB); BYTE $0x72
537 CALL _strayintr(SB); BYTE $0x73
538 CALL _strayintr(SB); BYTE $0x74
539 CALL _strayintr(SB); BYTE $0x75
540 CALL _strayintr(SB); BYTE $0x76
541 CALL _strayintr(SB); BYTE $0x77
542 CALL _strayintr(SB); BYTE $0x78
543 CALL _strayintr(SB); BYTE $0x79
544 CALL _strayintr(SB); BYTE $0x7A
545 CALL _strayintr(SB); BYTE $0x7B
546 CALL _strayintr(SB); BYTE $0x7C
547 CALL _strayintr(SB); BYTE $0x7D
548 CALL _strayintr(SB); BYTE $0x7E
549 CALL _strayintr(SB); BYTE $0x7F
550 CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
551 CALL _strayintr(SB); BYTE $0x81
552 CALL _strayintr(SB); BYTE $0x82
553 CALL _strayintr(SB); BYTE $0x83
554 CALL _strayintr(SB); BYTE $0x84
555 CALL _strayintr(SB); BYTE $0x85
556 CALL _strayintr(SB); BYTE $0x86
557 CALL _strayintr(SB); BYTE $0x87
558 CALL _strayintr(SB); BYTE $0x88
559 CALL _strayintr(SB); BYTE $0x89
560 CALL _strayintr(SB); BYTE $0x8A
561 CALL _strayintr(SB); BYTE $0x8B
562 CALL _strayintr(SB); BYTE $0x8C
563 CALL _strayintr(SB); BYTE $0x8D
564 CALL _strayintr(SB); BYTE $0x8E
565 CALL _strayintr(SB); BYTE $0x8F
566 CALL _strayintr(SB); BYTE $0x90
567 CALL _strayintr(SB); BYTE $0x91
568 CALL _strayintr(SB); BYTE $0x92
569 CALL _strayintr(SB); BYTE $0x93
570 CALL _strayintr(SB); BYTE $0x94
571 CALL _strayintr(SB); BYTE $0x95
572 CALL _strayintr(SB); BYTE $0x96
573 CALL _strayintr(SB); BYTE $0x97
574 CALL _strayintr(SB); BYTE $0x98
575 CALL _strayintr(SB); BYTE $0x99
576 CALL _strayintr(SB); BYTE $0x9A
577 CALL _strayintr(SB); BYTE $0x9B
578 CALL _strayintr(SB); BYTE $0x9C
579 CALL _strayintr(SB); BYTE $0x9D
580 CALL _strayintr(SB); BYTE $0x9E
581 CALL _strayintr(SB); BYTE $0x9F
582 CALL _strayintr(SB); BYTE $0xA0
583 CALL _strayintr(SB); BYTE $0xA1
584 CALL _strayintr(SB); BYTE $0xA2
585 CALL _strayintr(SB); BYTE $0xA3
586 CALL _strayintr(SB); BYTE $0xA4
587 CALL _strayintr(SB); BYTE $0xA5
588 CALL _strayintr(SB); BYTE $0xA6
589 CALL _strayintr(SB); BYTE $0xA7
590 CALL _strayintr(SB); BYTE $0xA8
591 CALL _strayintr(SB); BYTE $0xA9
592 CALL _strayintr(SB); BYTE $0xAA
593 CALL _strayintr(SB); BYTE $0xAB
594 CALL _strayintr(SB); BYTE $0xAC
595 CALL _strayintr(SB); BYTE $0xAD
596 CALL _strayintr(SB); BYTE $0xAE
597 CALL _strayintr(SB); BYTE $0xAF
598 CALL _strayintr(SB); BYTE $0xB0
599 CALL _strayintr(SB); BYTE $0xB1
600 CALL _strayintr(SB); BYTE $0xB2
601 CALL _strayintr(SB); BYTE $0xB3
602 CALL _strayintr(SB); BYTE $0xB4
603 CALL _strayintr(SB); BYTE $0xB5
604 CALL _strayintr(SB); BYTE $0xB6
605 CALL _strayintr(SB); BYTE $0xB7
606 CALL _strayintr(SB); BYTE $0xB8
607 CALL _strayintr(SB); BYTE $0xB9
608 CALL _strayintr(SB); BYTE $0xBA
609 CALL _strayintr(SB); BYTE $0xBB
610 CALL _strayintr(SB); BYTE $0xBC
611 CALL _strayintr(SB); BYTE $0xBD
612 CALL _strayintr(SB); BYTE $0xBE
613 CALL _strayintr(SB); BYTE $0xBF
614 CALL _strayintr(SB); BYTE $0xC0
615 CALL _strayintr(SB); BYTE $0xC1
616 CALL _strayintr(SB); BYTE $0xC2
617 CALL _strayintr(SB); BYTE $0xC3
618 CALL _strayintr(SB); BYTE $0xC4
619 CALL _strayintr(SB); BYTE $0xC5
620 CALL _strayintr(SB); BYTE $0xC6
621 CALL _strayintr(SB); BYTE $0xC7
622 CALL _strayintr(SB); BYTE $0xC8
623 CALL _strayintr(SB); BYTE $0xC9
624 CALL _strayintr(SB); BYTE $0xCA
625 CALL _strayintr(SB); BYTE $0xCB
626 CALL _strayintr(SB); BYTE $0xCC
627 CALL _strayintr(SB); BYTE $0xCD
628 CALL _strayintr(SB); BYTE $0xCE
629 CALL _strayintr(SB); BYTE $0xCF
630 CALL _strayintr(SB); BYTE $0xD0
631 CALL _strayintr(SB); BYTE $0xD1
632 CALL _strayintr(SB); BYTE $0xD2
633 CALL _strayintr(SB); BYTE $0xD3
634 CALL _strayintr(SB); BYTE $0xD4
635 CALL _strayintr(SB); BYTE $0xD5
636 CALL _strayintr(SB); BYTE $0xD6
637 CALL _strayintr(SB); BYTE $0xD7
638 CALL _strayintr(SB); BYTE $0xD8
639 CALL _strayintr(SB); BYTE $0xD9
640 CALL _strayintr(SB); BYTE $0xDA
641 CALL _strayintr(SB); BYTE $0xDB
642 CALL _strayintr(SB); BYTE $0xDC
643 CALL _strayintr(SB); BYTE $0xDD
644 CALL _strayintr(SB); BYTE $0xDE
645 CALL _strayintr(SB); BYTE $0xDF
646 CALL _strayintr(SB); BYTE $0xE0
647 CALL _strayintr(SB); BYTE $0xE1
648 CALL _strayintr(SB); BYTE $0xE2
649 CALL _strayintr(SB); BYTE $0xE3
650 CALL _strayintr(SB); BYTE $0xE4
651 CALL _strayintr(SB); BYTE $0xE5
652 CALL _strayintr(SB); BYTE $0xE6
653 CALL _strayintr(SB); BYTE $0xE7
654 CALL _strayintr(SB); BYTE $0xE8
655 CALL _strayintr(SB); BYTE $0xE9
656 CALL _strayintr(SB); BYTE $0xEA
657 CALL _strayintr(SB); BYTE $0xEB
658 CALL _strayintr(SB); BYTE $0xEC
659 CALL _strayintr(SB); BYTE $0xED
660 CALL _strayintr(SB); BYTE $0xEE
661 CALL _strayintr(SB); BYTE $0xEF
662 CALL _strayintr(SB); BYTE $0xF0
663 CALL _strayintr(SB); BYTE $0xF1
664 CALL _strayintr(SB); BYTE $0xF2
665 CALL _strayintr(SB); BYTE $0xF3
666 CALL _strayintr(SB); BYTE $0xF4
667 CALL _strayintr(SB); BYTE $0xF5
668 CALL _strayintr(SB); BYTE $0xF6
669 CALL _strayintr(SB); BYTE $0xF7
670 CALL _strayintr(SB); BYTE $0xF8
671 CALL _strayintr(SB); BYTE $0xF9
672 CALL _strayintr(SB); BYTE $0xFA
673 CALL _strayintr(SB); BYTE $0xFB
674 CALL _strayintr(SB); BYTE $0xFC
675 CALL _strayintr(SB); BYTE $0xFD
676 CALL _strayintr(SB); BYTE $0xFE
677 CALL _strayintr(SB); BYTE $0xFF