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