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 lgdt(SB), $0 /* GDTR - global descriptor table */
62 TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */
67 TEXT ltr(SB), $0 /* TR - task register */
76 TEXT _cycles(SB), $0 /* time stamp counter; cycles since power up */
78 MOVL vlong+0(FP), CX /* &vlong */
79 MOVL AX, 0(CX) /* lo */
80 MOVL DX, 4(CX) /* hi */
83 TEXT rdmsr(SB), $0 /* model-specific register */
86 MOVL vlong+4(FP), CX /* &vlong */
87 MOVL AX, 0(CX) /* lo */
88 MOVL DX, 4(CX) /* hi */
95 /* Xen doesn't let us do this
101 * Try to determine the CPU type which requires fiddling with EFLAGS.
102 * If the Id bit can be toggled then the CPUID instruction can be used
103 * to determine CPU identity and features. First have to check if it's
104 * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
105 * toggled then it's an older 486 of some kind.
107 * cpuid(fun, regs[4]);
112 POPFL /* set Id|Ac */
114 POPL BX /* retrieve value */
117 POPFL /* clear Id|Ac, EFLAGS initialised */
119 POPL AX /* retrieve value */
121 TESTL $0x040000, AX /* Ac */
122 JZ _cpu386 /* can't set this bit on 386 */
123 TESTL $0x200000, AX /* Id */
124 JZ _cpu486 /* can't toggle this bit on some 486 */
151 * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW
152 * instructions do NOT have the WAIT prefix byte (i.e. they act like their
153 * FNxxx variations) so WAIT instructions must be explicitly placed in the
158 ANDL $0xC, AX /* EM, TS */ ;\
164 ANDL $~0x4, AX /* EM=0 */ ;\
165 ORL $0x28, AX /* NE=1, TS=1 */ ;\
170 ANDL $~0xC, AX /* EM=0, TS=0 */ ;\
173 TEXT fpoff(SB), $0 /* disable */
177 TEXT fpinit(SB), $0 /* enable and init */
181 /* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
182 /* note that low 6 bits are masks, not enables, on this chip */
189 TEXT fpx87save(SB), $0 /* save state and disable */
191 FSAVE 0(AX) /* no WAIT */
195 TEXT fpx87restore(SB), $0 /* enable and restore state */
202 TEXT fpstatus(SB), $0 /* get floating point status */
206 TEXT fpenv(SB), $0 /* save state without waiting */
211 TEXT fpclear(SB), $0 /* clear pending exceptions */
223 XCHGL AX, (BX) /* lock->key */
226 TEXT _xinc(SB), $0 /* void _xinc(long*); */
231 TEXT _xdec(SB), $0 /* long _xdec(long*); */
245 TEXT getstack(SB), $0
249 POPL AX /* return PC */
297 /* Return the position of the first bit set. Undefined if zero. */
303 TEXT cmpswap486(SB), $0
308 BYTE $0x0F; BYTE $0xB1; BYTE $0x0B /* CMPXCHGL CX, (BX) */
316 TEXT mul64fract(SB), $0
318 XORL BX, BX /* BX = 0 */
321 MULL b+16(FP) /* a1*b1 */
322 MOVL AX, 4(CX) /* r2 = lo(a1*b1) */
325 MULL b+12(FP) /* a1*b0 */
326 MOVL AX, 0(CX) /* r1 = lo(a1*b0) */
327 ADDL DX, 4(CX) /* r2 += hi(a1*b0) */
330 MULL b+16(FP) /* a0*b1 */
331 ADDL AX, 0(CX) /* r1 += lo(a0*b1) */
332 ADCL DX, 4(CX) /* r2 += hi(a0*b1) + carry */
335 MULL b+12(FP) /* a0*b0 */
336 ADDL DX, 0(CX) /* r1 += hi(a0*b0) */
337 ADCL BX, 4(CX) /* r2 += carry */
341 * label consists of a stack pointer and a PC
343 TEXT gotolabel(SB), $0
345 MOVL 0(AX), SP /* restore sp */
346 MOVL 4(AX), AX /* put return pc on the stack */
348 MOVL $1, AX /* return 1 */
351 TEXT setlabel(SB), $0
353 MOVL SP, 0(AX) /* store sp */
354 MOVL 0(SP), BX /* store return pc */
356 MOVL $0, AX /* return 0 */
365 BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */
370 BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */
375 * Interrupt/exception handling.
376 * Each entry in the vector table calls either _strayintr or _strayintrx depending
377 * on whether an error code has been automatically pushed onto the stack
378 * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
379 * the trap type from the vector table entry and placing it on the stack as part
380 * of the Ureg structure.
381 * Exceptions to this are the syscall vector and the page fault
382 * vector. Syscalls are dispatched seperately. Page faults
383 * have to take care of the extra cr2 parameter that xen places
384 * at the top of the stack.
385 * The size of each entry in the vector table (6 bytes) is known in trapinit().
387 TEXT _strayintr(SB), $0
388 PUSHL AX /* save AX */
389 MOVL 4(SP), AX /* return PC from vectortable(SB) */
392 TEXT _strayintrx(SB), $0
393 XCHGL AX, (SP) /* swap AX with vectortable CALL PC */
395 PUSHL DS /* save DS */
397 POPL DS /* fix up DS */
398 MOVBLZX (AX), AX /* trap type -> AX */
399 XCHGL AX, 4(SP) /* exchange trap type with saved AX */
401 PUSHL ES /* save ES */
403 POPL ES /* fix up ES */
405 PUSHL FS /* save the rest of the Ureg struct */
409 PUSHL SP /* Ureg* argument to trap */
419 ADDL $8, SP /* pop error code and trap type */
422 TEXT vectortable(SB), $0
423 CALL _strayintr(SB); BYTE $0x00 /* divide error */
424 CALL _strayintr(SB); BYTE $0x01 /* debug exception */
425 CALL _strayintr(SB); BYTE $0x02 /* NMI interrupt */
426 CALL _strayintr(SB); BYTE $0x03 /* breakpoint */
427 CALL _strayintr(SB); BYTE $0x04 /* overflow */
428 CALL _strayintr(SB); BYTE $0x05 /* bound */
429 CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */
430 CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */
431 CALL _strayintrx(SB); BYTE $0x08 /* double fault */
432 CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
433 CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */
434 CALL _strayintrx(SB); BYTE $0x0B /* segment not available */
435 CALL _strayintrx(SB); BYTE $0x0C /* stack exception */
436 CALL _strayintrx(SB); BYTE $0x0D /* general protection error */
437 CALL _strayintrx(SB); BYTE $0x0E /* page fault */
438 CALL _strayintr(SB); BYTE $0x0F /* */
439 CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
440 CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
441 CALL _strayintr(SB); BYTE $0x12 /* machine check */
442 CALL _strayintr(SB); BYTE $0x13
443 CALL _strayintr(SB); BYTE $0x14
444 CALL _strayintr(SB); BYTE $0x15
445 CALL _strayintr(SB); BYTE $0x16
446 CALL _strayintr(SB); BYTE $0x17
447 CALL _strayintr(SB); BYTE $0x18
448 CALL _strayintr(SB); BYTE $0x19
449 CALL _strayintr(SB); BYTE $0x1A
450 CALL _strayintr(SB); BYTE $0x1B
451 CALL _strayintr(SB); BYTE $0x1C
452 CALL _strayintr(SB); BYTE $0x1D
453 CALL _strayintr(SB); BYTE $0x1E
454 CALL _strayintr(SB); BYTE $0x1F
455 CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */
456 CALL _strayintr(SB); BYTE $0x21
457 CALL _strayintr(SB); BYTE $0x22
458 CALL _strayintr(SB); BYTE $0x23
459 CALL _strayintr(SB); BYTE $0x24
460 CALL _strayintr(SB); BYTE $0x25
461 CALL _strayintr(SB); BYTE $0x26
462 CALL _strayintr(SB); BYTE $0x27
463 CALL _strayintr(SB); BYTE $0x28
464 CALL _strayintr(SB); BYTE $0x29
465 CALL _strayintr(SB); BYTE $0x2A
466 CALL _strayintr(SB); BYTE $0x2B
467 CALL _strayintr(SB); BYTE $0x2C
468 CALL _strayintr(SB); BYTE $0x2D
469 CALL _strayintr(SB); BYTE $0x2E
470 CALL _strayintr(SB); BYTE $0x2F
471 CALL _strayintr(SB); BYTE $0x30
472 CALL _strayintr(SB); BYTE $0x31
473 CALL _strayintr(SB); BYTE $0x32
474 CALL _strayintr(SB); BYTE $0x33
475 CALL _strayintr(SB); BYTE $0x34
476 CALL _strayintr(SB); BYTE $0x35
477 CALL _strayintr(SB); BYTE $0x36
478 CALL _strayintr(SB); BYTE $0x37
479 CALL _strayintr(SB); BYTE $0x38
480 CALL _strayintr(SB); BYTE $0x39
481 CALL _strayintr(SB); BYTE $0x3A
482 CALL _strayintr(SB); BYTE $0x3B
483 CALL _strayintr(SB); BYTE $0x3C
484 CALL _strayintr(SB); BYTE $0x3D
485 CALL _strayintr(SB); BYTE $0x3E
486 CALL _strayintr(SB); BYTE $0x3F
487 CALL _syscallintr(SB); BYTE $0x40 /* VectorSYSCALL */
488 CALL _strayintr(SB); BYTE $0x41
489 CALL _strayintr(SB); BYTE $0x42
490 CALL _strayintr(SB); BYTE $0x43
491 CALL _strayintr(SB); BYTE $0x44
492 CALL _strayintr(SB); BYTE $0x45
493 CALL _strayintr(SB); BYTE $0x46
494 CALL _strayintr(SB); BYTE $0x47
495 CALL _strayintr(SB); BYTE $0x48
496 CALL _strayintr(SB); BYTE $0x49
497 CALL _strayintr(SB); BYTE $0x4A
498 CALL _strayintr(SB); BYTE $0x4B
499 CALL _strayintr(SB); BYTE $0x4C
500 CALL _strayintr(SB); BYTE $0x4D
501 CALL _strayintr(SB); BYTE $0x4E
502 CALL _strayintr(SB); BYTE $0x4F
503 CALL _strayintr(SB); BYTE $0x50
504 CALL _strayintr(SB); BYTE $0x51
505 CALL _strayintr(SB); BYTE $0x52
506 CALL _strayintr(SB); BYTE $0x53
507 CALL _strayintr(SB); BYTE $0x54
508 CALL _strayintr(SB); BYTE $0x55
509 CALL _strayintr(SB); BYTE $0x56
510 CALL _strayintr(SB); BYTE $0x57
511 CALL _strayintr(SB); BYTE $0x58
512 CALL _strayintr(SB); BYTE $0x59
513 CALL _strayintr(SB); BYTE $0x5A
514 CALL _strayintr(SB); BYTE $0x5B
515 CALL _strayintr(SB); BYTE $0x5C
516 CALL _strayintr(SB); BYTE $0x5D
517 CALL _strayintr(SB); BYTE $0x5E
518 CALL _strayintr(SB); BYTE $0x5F
519 CALL _strayintr(SB); BYTE $0x60
520 CALL _strayintr(SB); BYTE $0x61
521 CALL _strayintr(SB); BYTE $0x62
522 CALL _strayintr(SB); BYTE $0x63
523 CALL _strayintr(SB); BYTE $0x64
524 CALL _strayintr(SB); BYTE $0x65
525 CALL _strayintr(SB); BYTE $0x66
526 CALL _strayintr(SB); BYTE $0x67
527 CALL _strayintr(SB); BYTE $0x68
528 CALL _strayintr(SB); BYTE $0x69
529 CALL _strayintr(SB); BYTE $0x6A
530 CALL _strayintr(SB); BYTE $0x6B
531 CALL _strayintr(SB); BYTE $0x6C
532 CALL _strayintr(SB); BYTE $0x6D
533 CALL _strayintr(SB); BYTE $0x6E
534 CALL _strayintr(SB); BYTE $0x6F
535 CALL _strayintr(SB); BYTE $0x70
536 CALL _strayintr(SB); BYTE $0x71
537 CALL _strayintr(SB); BYTE $0x72
538 CALL _strayintr(SB); BYTE $0x73
539 CALL _strayintr(SB); BYTE $0x74
540 CALL _strayintr(SB); BYTE $0x75
541 CALL _strayintr(SB); BYTE $0x76
542 CALL _strayintr(SB); BYTE $0x77
543 CALL _strayintr(SB); BYTE $0x78
544 CALL _strayintr(SB); BYTE $0x79
545 CALL _strayintr(SB); BYTE $0x7A
546 CALL _strayintr(SB); BYTE $0x7B
547 CALL _strayintr(SB); BYTE $0x7C
548 CALL _strayintr(SB); BYTE $0x7D
549 CALL _strayintr(SB); BYTE $0x7E
550 CALL _strayintr(SB); BYTE $0x7F
551 CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
552 CALL _strayintr(SB); BYTE $0x81
553 CALL _strayintr(SB); BYTE $0x82
554 CALL _strayintr(SB); BYTE $0x83
555 CALL _strayintr(SB); BYTE $0x84
556 CALL _strayintr(SB); BYTE $0x85
557 CALL _strayintr(SB); BYTE $0x86
558 CALL _strayintr(SB); BYTE $0x87
559 CALL _strayintr(SB); BYTE $0x88
560 CALL _strayintr(SB); BYTE $0x89
561 CALL _strayintr(SB); BYTE $0x8A
562 CALL _strayintr(SB); BYTE $0x8B
563 CALL _strayintr(SB); BYTE $0x8C
564 CALL _strayintr(SB); BYTE $0x8D
565 CALL _strayintr(SB); BYTE $0x8E
566 CALL _strayintr(SB); BYTE $0x8F
567 CALL _strayintr(SB); BYTE $0x90
568 CALL _strayintr(SB); BYTE $0x91
569 CALL _strayintr(SB); BYTE $0x92
570 CALL _strayintr(SB); BYTE $0x93
571 CALL _strayintr(SB); BYTE $0x94
572 CALL _strayintr(SB); BYTE $0x95
573 CALL _strayintr(SB); BYTE $0x96
574 CALL _strayintr(SB); BYTE $0x97
575 CALL _strayintr(SB); BYTE $0x98
576 CALL _strayintr(SB); BYTE $0x99
577 CALL _strayintr(SB); BYTE $0x9A
578 CALL _strayintr(SB); BYTE $0x9B
579 CALL _strayintr(SB); BYTE $0x9C
580 CALL _strayintr(SB); BYTE $0x9D
581 CALL _strayintr(SB); BYTE $0x9E
582 CALL _strayintr(SB); BYTE $0x9F
583 CALL _strayintr(SB); BYTE $0xA0
584 CALL _strayintr(SB); BYTE $0xA1
585 CALL _strayintr(SB); BYTE $0xA2
586 CALL _strayintr(SB); BYTE $0xA3
587 CALL _strayintr(SB); BYTE $0xA4
588 CALL _strayintr(SB); BYTE $0xA5
589 CALL _strayintr(SB); BYTE $0xA6
590 CALL _strayintr(SB); BYTE $0xA7
591 CALL _strayintr(SB); BYTE $0xA8
592 CALL _strayintr(SB); BYTE $0xA9
593 CALL _strayintr(SB); BYTE $0xAA
594 CALL _strayintr(SB); BYTE $0xAB
595 CALL _strayintr(SB); BYTE $0xAC
596 CALL _strayintr(SB); BYTE $0xAD
597 CALL _strayintr(SB); BYTE $0xAE
598 CALL _strayintr(SB); BYTE $0xAF
599 CALL _strayintr(SB); BYTE $0xB0
600 CALL _strayintr(SB); BYTE $0xB1
601 CALL _strayintr(SB); BYTE $0xB2
602 CALL _strayintr(SB); BYTE $0xB3
603 CALL _strayintr(SB); BYTE $0xB4
604 CALL _strayintr(SB); BYTE $0xB5
605 CALL _strayintr(SB); BYTE $0xB6
606 CALL _strayintr(SB); BYTE $0xB7
607 CALL _strayintr(SB); BYTE $0xB8
608 CALL _strayintr(SB); BYTE $0xB9
609 CALL _strayintr(SB); BYTE $0xBA
610 CALL _strayintr(SB); BYTE $0xBB
611 CALL _strayintr(SB); BYTE $0xBC
612 CALL _strayintr(SB); BYTE $0xBD
613 CALL _strayintr(SB); BYTE $0xBE
614 CALL _strayintr(SB); BYTE $0xBF
615 CALL _strayintr(SB); BYTE $0xC0
616 CALL _strayintr(SB); BYTE $0xC1
617 CALL _strayintr(SB); BYTE $0xC2
618 CALL _strayintr(SB); BYTE $0xC3
619 CALL _strayintr(SB); BYTE $0xC4
620 CALL _strayintr(SB); BYTE $0xC5
621 CALL _strayintr(SB); BYTE $0xC6
622 CALL _strayintr(SB); BYTE $0xC7
623 CALL _strayintr(SB); BYTE $0xC8
624 CALL _strayintr(SB); BYTE $0xC9
625 CALL _strayintr(SB); BYTE $0xCA
626 CALL _strayintr(SB); BYTE $0xCB
627 CALL _strayintr(SB); BYTE $0xCC
628 CALL _strayintr(SB); BYTE $0xCD
629 CALL _strayintr(SB); BYTE $0xCE
630 CALL _strayintr(SB); BYTE $0xCF
631 CALL _strayintr(SB); BYTE $0xD0
632 CALL _strayintr(SB); BYTE $0xD1
633 CALL _strayintr(SB); BYTE $0xD2
634 CALL _strayintr(SB); BYTE $0xD3
635 CALL _strayintr(SB); BYTE $0xD4
636 CALL _strayintr(SB); BYTE $0xD5
637 CALL _strayintr(SB); BYTE $0xD6
638 CALL _strayintr(SB); BYTE $0xD7
639 CALL _strayintr(SB); BYTE $0xD8
640 CALL _strayintr(SB); BYTE $0xD9
641 CALL _strayintr(SB); BYTE $0xDA
642 CALL _strayintr(SB); BYTE $0xDB
643 CALL _strayintr(SB); BYTE $0xDC
644 CALL _strayintr(SB); BYTE $0xDD
645 CALL _strayintr(SB); BYTE $0xDE
646 CALL _strayintr(SB); BYTE $0xDF
647 CALL _strayintr(SB); BYTE $0xE0
648 CALL _strayintr(SB); BYTE $0xE1
649 CALL _strayintr(SB); BYTE $0xE2
650 CALL _strayintr(SB); BYTE $0xE3
651 CALL _strayintr(SB); BYTE $0xE4
652 CALL _strayintr(SB); BYTE $0xE5
653 CALL _strayintr(SB); BYTE $0xE6
654 CALL _strayintr(SB); BYTE $0xE7
655 CALL _strayintr(SB); BYTE $0xE8
656 CALL _strayintr(SB); BYTE $0xE9
657 CALL _strayintr(SB); BYTE $0xEA
658 CALL _strayintr(SB); BYTE $0xEB
659 CALL _strayintr(SB); BYTE $0xEC
660 CALL _strayintr(SB); BYTE $0xED
661 CALL _strayintr(SB); BYTE $0xEE
662 CALL _strayintr(SB); BYTE $0xEF
663 CALL _strayintr(SB); BYTE $0xF0
664 CALL _strayintr(SB); BYTE $0xF1
665 CALL _strayintr(SB); BYTE $0xF2
666 CALL _strayintr(SB); BYTE $0xF3
667 CALL _strayintr(SB); BYTE $0xF4
668 CALL _strayintr(SB); BYTE $0xF5
669 CALL _strayintr(SB); BYTE $0xF6
670 CALL _strayintr(SB); BYTE $0xF7
671 CALL _strayintr(SB); BYTE $0xF8
672 CALL _strayintr(SB); BYTE $0xF9
673 CALL _strayintr(SB); BYTE $0xFA
674 CALL _strayintr(SB); BYTE $0xFB
675 CALL _strayintr(SB); BYTE $0xFC
676 CALL _strayintr(SB); BYTE $0xFD
677 CALL _strayintr(SB); BYTE $0xFE
678 CALL _strayintr(SB); BYTE $0xFF