]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/l.s
pc64: fix note handling
[plan9front.git] / sys / src / 9 / pc64 / l.s
1 #include "mem.h"
2
3 MODE $32
4
5 #define DELAY           BYTE $0xEB; BYTE $0x00  /* JMP .+2 */
6
7 #define pFARJMP32(s, o) BYTE $0xea;             /* far jump to ptr32:16 */\
8                         LONG $o; WORD $s
9
10 /*
11  * Enter here in 32-bit protected mode. Welcome to 1982.
12  * Make sure the GDT is set as it should be:
13  *      disable interrupts;
14  *      load the GDT with the table in _gdt32p;
15  *      load all the data segments
16  *      load the code segment via a far jump.
17  */
18 TEXT _protected<>(SB), 1, $-4
19         CLI
20
21         MOVL    $_gdtptr32p<>-KZERO(SB), AX
22         MOVL    (AX), GDTR
23
24         MOVL    $SELECTOR(2, SELGDT, 0), AX
25         MOVW    AX, DS
26         MOVW    AX, ES
27         MOVW    AX, FS
28         MOVW    AX, GS
29         MOVW    AX, SS
30
31         pFARJMP32(SELECTOR(3, SELGDT, 0), _warp64<>-KZERO(SB))
32
33 TEXT _gdt<>(SB), 1, $-4
34         /* null descriptor */
35         LONG    $0
36         LONG    $0
37
38         /* (KESEG) 64 bit long mode exec segment */
39         LONG    $(0xFFFF)
40         LONG    $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
41
42         /* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
43         LONG    $(0xFFFF)
44         LONG    $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
45
46         /* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
47         LONG    $(0xFFFF)
48         LONG    $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
49
50
51 TEXT _gdtptr32p<>(SB), 1, $-4
52         WORD    $(4*8-1)
53         LONG    $_gdt<>-KZERO(SB)
54
55 TEXT _gdtptr64p<>(SB), 1, $-4
56         WORD    $(4*8-1)
57         QUAD    $_gdt<>-KZERO(SB)
58
59 TEXT _gdtptr64v<>(SB), 1, $-4
60         WORD    $(4*8-1)
61         QUAD    $_gdt<>(SB)
62
63 /*
64  * Macros for accessing page table entries; change the
65  * C-style array-index macros into a page table byte offset
66  */
67 #define PML4O(v)        ((PTLX((v), 3))<<3)
68 #define PDPO(v)         ((PTLX((v), 2))<<3)
69 #define PDO(v)          ((PTLX((v), 1))<<3)
70 #define PTO(v)          ((PTLX((v), 0))<<3)
71
72 TEXT _warp64<>(SB), 1, $-4
73
74         /* clear mach and page tables */
75         MOVL    $((CPU0END-CPU0PML4)>>2), CX
76         MOVL    $(CPU0PML4-KZERO), SI
77         MOVL    SI, DI
78         XORL    AX, AX
79         CLD
80         REP;    STOSL
81
82         MOVL    SI, AX                          /* PML4 */
83         MOVL    AX, DX
84         ADDL    $(PTSZ|PTEWRITE|PTEVALID), DX   /* PDP at PML4 + PTSZ */
85         MOVL    DX, PML4O(0)(AX)                /* PML4E for double-map */
86         MOVL    DX, PML4O(KZERO)(AX)            /* PML4E for KZERO */
87
88         ADDL    $PTSZ, AX                       /* PDP at PML4 + PTSZ */
89         ADDL    $PTSZ, DX                       /* PD at PML4 + 2*PTSZ */
90         MOVL    DX, PDPO(0)(AX)                 /* PDPE for double-map */
91         MOVL    DX, PDPO(KZERO)(AX)             /* PDPE for KZERO */
92
93         ADDL    $PTSZ, AX                       /* PD at PML4 + 2*PTSZ */
94         MOVL    $(PTESIZE|PTEGLOBAL|PTEWRITE|PTEVALID), DX
95         MOVL    DX, PDO(0)(AX)                  /* PDE for double-map */
96
97         ADDL    $PDO(KZERO), AX
98 memloop:
99         MOVL    DX, 0(AX)
100         ADDL    $PGLSZ(1), DX
101         ADDL    $8, AX
102         CMPL    DX, $INIMAP
103         JLT     memloop
104
105 /*
106  * Enable and activate Long Mode. From the manual:
107  *      make sure Page Size Extentions are off, and Page Global
108  *      Extensions and Physical Address Extensions are on in CR4;
109  *      set Long Mode Enable in the Extended Feature Enable MSR;
110  *      set Paging Enable in CR0;
111  *      make an inter-segment jump to the Long Mode code.
112  * It's all in 32-bit mode until the jump is made.
113  */
114 TEXT _lme<>(SB), 1, $-4
115         MOVL    SI, CR3                         /* load the mmu */
116         DELAY
117
118         MOVL    CR4, AX
119         ANDL    $~0x00000010, AX                        /* Page Size */
120         ORL     $0x000000A0, AX                 /* Page Global, Phys. Address */
121         MOVL    AX, CR4
122
123         MOVL    $0xc0000080, CX                 /* Extended Feature Enable */
124         RDMSR
125         ORL     $0x00000100, AX                 /* Long Mode Enable */
126         WRMSR
127
128         MOVL    CR0, DX
129         ANDL    $~0x6000000a, DX
130         ORL     $0x80010000, DX                 /* Paging Enable, Write Protect */
131         MOVL    DX, CR0
132
133         pFARJMP32(SELECTOR(KESEG, SELGDT, 0), _identity<>-KZERO(SB))
134
135 /*
136  * Long mode. Welcome to 2003.
137  * Jump out of the identity map space;
138  * load a proper long mode GDT.
139  */
140 MODE $64
141
142 TEXT _identity<>(SB), 1, $-4
143         MOVQ    $_start64v<>(SB), AX
144         JMP*    AX
145
146 TEXT _start64v<>(SB), 1, $-4
147         MOVQ    $_gdtptr64v<>(SB), AX
148         MOVL    (AX), GDTR
149
150         XORQ    AX, AX
151         MOVW    AX, DS                          /* not used in long mode */
152         MOVW    AX, ES                          /* not used in long mode */
153         MOVW    AX, FS
154         MOVW    AX, GS
155         MOVW    AX, SS                          /* not used in long mode */
156
157         MOVW    AX, LDTR
158
159         MOVQ    $(CPU0MACH+MACHSIZE), SP
160         MOVQ    $(CPU0MACH), RMACH
161         MOVQ    AX, RUSER                       /* up = 0; */
162
163 _clearbss:
164         MOVQ    $edata(SB), DI
165         MOVQ    $end(SB), CX
166         SUBQ    DI, CX                          /* end-edata bytes */
167         SHRQ    $2, CX                          /* end-edata doublewords */
168
169         CLD
170         REP;    STOSL                           /* clear BSS */
171
172         PUSHQ   AX                              /* clear flags */
173         POPFQ
174
175         CALL    main(SB)
176
177 /*
178  * The CPUID instruction is always supported on the amd64.
179  */
180 TEXT cpuid(SB), $-4
181         MOVL    RARG, AX                        /* function in AX */
182         CPUID
183
184         MOVQ    info+8(FP), BP
185         MOVL    AX, 0(BP)
186         MOVL    BX, 4(BP)
187         MOVL    CX, 8(BP)
188         MOVL    DX, 12(BP)
189         RET
190
191 /*
192  * Port I/O.
193  */
194 TEXT inb(SB), 1, $-4
195         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
196         XORL    AX, AX
197         INB
198         RET
199
200 TEXT insb(SB), 1, $-4
201         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
202         MOVQ    address+8(FP), DI
203         MOVL    count+16(FP), CX
204         CLD
205         REP;    INSB
206         RET
207
208 TEXT ins(SB), 1, $-4
209         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
210         XORL    AX, AX
211         INW
212         RET
213
214 TEXT inss(SB), 1, $-4
215         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
216         MOVQ    address+8(FP), DI
217         MOVL    count+16(FP), CX
218         CLD
219         REP;    INSW
220         RET
221
222 TEXT inl(SB), 1, $-4
223         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
224         INL
225         RET
226
227 TEXT insl(SB), 1, $-4
228         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
229         MOVQ    address+8(FP), DI
230         MOVL    count+16(FP), CX
231         CLD
232         REP; INSL
233         RET
234
235 TEXT outb(SB), 1, $-1
236         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
237         MOVL    byte+8(FP), AX
238         OUTB
239         RET
240
241 TEXT outsb(SB), 1, $-4
242         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
243         MOVQ    address+8(FP), SI
244         MOVL    count+16(FP), CX
245         CLD
246         REP; OUTSB
247         RET
248
249 TEXT outs(SB), 1, $-4
250         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
251         MOVL    short+8(FP), AX
252         OUTW
253         RET
254
255 TEXT outss(SB), 1, $-4
256         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
257         MOVQ    address+8(FP), SI
258         MOVL    count+16(FP), CX
259         CLD
260         REP; OUTSW
261         RET
262
263 TEXT outl(SB), 1, $-4
264         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
265         MOVL    long+8(FP), AX
266         OUTL
267         RET
268
269 TEXT outsl(SB), 1, $-4
270         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
271         MOVQ    address+8(FP), SI
272         MOVL    count+16(FP), CX
273         CLD
274         REP; OUTSL
275         RET
276
277 TEXT getgdt(SB), 1, $-4
278         MOVQ    RARG, AX
279         MOVL    GDTR, (AX)                      /* Note: 10 bytes returned */
280         RET
281
282 TEXT lgdt(SB), $0                               /* GDTR - global descriptor table */
283         MOVQ    RARG, AX
284         MOVL    (AX), GDTR
285         RET
286
287 TEXT lidt(SB), $0                               /* IDTR - interrupt descriptor table */
288         MOVQ    RARG, AX
289         MOVL    (AX), IDTR
290         RET
291
292 TEXT ltr(SB), 1, $-4
293         MOVW    RARG, AX
294         MOVW    AX, TASK
295         RET
296
297 /*
298  * Read/write various system registers.
299  */
300 TEXT getcr0(SB), 1, $-4                         /* Processor Control */
301         MOVQ    CR0, AX
302         RET
303
304 TEXT putcr0(SB), 1, $-4
305         MOVQ    RARG, CR0
306         RET
307
308 TEXT getcr2(SB), 1, $-4                         /* #PF Linear Address */
309         MOVQ    CR2, AX
310         RET
311
312 TEXT getcr3(SB), 1, $-4                         /* PML4 Base */
313         MOVQ    CR3, AX
314         RET
315
316 TEXT putcr3(SB), 1, $-4
317         MOVQ    RARG, CR3
318         RET
319
320 TEXT getcr4(SB), 1, $-4                         /* Extensions */
321         MOVQ    CR4, AX
322         RET
323
324 TEXT putcr4(SB), 1, $-4
325         MOVQ    RARG, CR4
326         RET
327
328 TEXT mb386(SB), 1, $-4                          /* hack */
329 TEXT mb586(SB), 1, $-4
330         XORL    AX, AX
331         CPUID
332         RET
333
334 /*
335  * Park a processor. Should never fall through a return from main to here,
336  * should only be called by application processors when shutting down.
337  */
338 TEXT idle(SB), 1, $-4
339 _idle:
340         STI
341         HLT
342         JMP     _idle
343
344 /*
345  * BIOS32.
346  */
347 TEXT bios32call(SB), 1, $-4
348         XORL    AX, AX
349         INCL    AX
350         RET
351
352 /*
353  * Basic timing loop to determine CPU frequency.
354  */
355 TEXT aamloop(SB), 1, $-4
356         MOVL    RARG, CX
357 _aamloop:
358         LOOP    _aamloop
359         RET
360
361 TEXT _cycles(SB), 1, $-4                        /* time stamp counter */
362         RDTSC
363         MOVL    AX, 0(RARG)                     /* lo */
364         MOVL    DX, 4(RARG)                     /* hi */
365         RET
366
367 TEXT rdmsr(SB), 1, $-4                          /* Model-Specific Register */
368         MOVL    RARG, CX
369         MOVQ    $0, BP
370 TEXT _rdmsrinst(SB), $0
371         RDMSR
372         MOVQ    vlong+8(FP), CX                 /* &vlong */
373         MOVL    AX, 0(CX)                       /* lo */
374         MOVL    DX, 4(CX)                       /* hi */
375         MOVQ    BP, AX                          /* BP set to -1 if traped */
376         RET
377         
378 TEXT wrmsr(SB), 1, $-4
379         MOVL    RARG, CX
380         MOVL    lo+8(FP), AX
381         MOVL    hi+12(FP), DX
382         MOVQ    $0, BP
383 TEXT _wrmsrinst(SB), $0
384         WRMSR
385         MOVQ    BP, AX                          /* BP set to -1 if traped */
386         RET
387
388 TEXT invlpg(SB), 1, $-4                         /* INVLPG va+0(FP) */
389         MOVQ    RARG, va+0(FP)
390
391         INVLPG  va+0(FP)
392
393         RET
394
395 TEXT wbinvd(SB), 1, $-4
396         WBINVD
397         RET
398
399 /*
400  * Serialisation.
401  */
402 TEXT lfence(SB), 1, $-4
403         LFENCE
404         RET
405
406 TEXT mfence(SB), 1, $-4
407         MFENCE
408         RET
409
410 TEXT sfence(SB), 1, $-4
411         SFENCE
412         RET
413
414 /*
415  * Note: CLI and STI are not serialising instructions.
416  * Is that assumed anywhere?
417  */
418 TEXT splhi(SB), 1, $-4
419 _splhi:
420         PUSHFQ
421         POPQ    AX
422         TESTQ   $0x200, AX                      /* 0x200 - Interrupt Flag */
423         JZ      _alreadyhi                      /* use CMOVLEQ etc. here? */
424
425         MOVQ    (SP), BX
426         MOVQ    BX, 8(RMACH)                    /* save PC in m->splpc */
427
428 _alreadyhi:
429         CLI
430         RET
431
432 TEXT spllo(SB), 1, $-4
433 _spllo:
434         PUSHFQ
435         POPQ    AX
436         TESTQ   $0x200, AX                      /* 0x200 - Interrupt Flag */
437         JNZ     _alreadylo                      /* use CMOVLEQ etc. here? */
438
439         MOVQ    $0, 8(RMACH)                    /* clear m->splpc */
440
441 _alreadylo:
442         STI
443         RET
444
445 TEXT splx(SB), 1, $-4
446         TESTQ   $0x200, RARG                    /* 0x200 - Interrupt Flag */
447         JNZ     _spllo
448         JMP     _splhi
449
450 TEXT spldone(SB), 1, $-4
451         RET
452
453 TEXT islo(SB), 1, $-4
454         PUSHFQ
455         POPQ    AX
456         ANDQ    $0x200, AX                      /* 0x200 - Interrupt Flag */
457         RET
458
459 /*
460  * Synchronisation
461  */
462 TEXT ainc8(SB), 1, $-4
463         XORL    AX, AX
464         INCL    AX
465         LOCK;   XADDB AX, (RARG)
466 /* BOTCH        INCL    AX */
467         RET
468
469 TEXT _xinc(SB), 1, $-4                          /* int _inc(long*); */
470         MOVL    $1, AX
471         LOCK; XADDL AX, (RARG)
472         ADDL    $1, AX                          /* overflow if -ve or 0 */
473         JGT     _return
474 _trap:
475         XORQ    BX, BX
476         MOVQ    (BX), BX                        /* over under sideways down */
477 _return:
478         RET
479
480 TEXT _xdec(SB), 1, $-4                          /* int _dec(long*); */
481         MOVL    $-1, AX
482         LOCK; XADDL AX, (RARG)
483         SUBL    $1, AX                          /* underflow if -ve */
484         JLT     _trap
485         RET
486
487 TEXT tas(SB), 1, $-4
488         MOVL    $0xdeaddead, AX
489         XCHGL   AX, (RARG)                      /*  */
490         RET
491
492 TEXT fas64(SB), 1, $-4
493         MOVQ    p+8(FP), AX
494         LOCK; XCHGQ     AX, (RARG)                      /*  */
495         RET
496
497 TEXT cmpswap486(SB), 1, $-4
498 TEXT cas(SB), 1, $-4
499         MOVL    exp+8(FP), AX
500         MOVL    new+16(FP), BX
501         LOCK; CMPXCHGL BX, (RARG)
502         MOVL    $1, AX                          /* use CMOVLEQ etc. here? */
503         JNZ     _cas32r0
504 _cas32r1:
505         RET
506 _cas32r0:
507         DECL    AX
508         RET
509
510 TEXT cas64(SB), 1, $-4
511         MOVQ    exp+8(FP), AX
512         MOVQ    new+16(FP), BX
513         LOCK; CMPXCHGQ BX, (RARG)
514         MOVL    $1, AX                          /* use CMOVLEQ etc. here? */
515         JNZ     _cas64r0
516 _cas64r1:
517         RET
518 _cas64r0:
519         DECL    AX
520         RET
521
522 /*
523  * Label consists of a stack pointer and a programme counter
524  */
525 TEXT gotolabel(SB), 1, $-4
526         MOVQ    0(RARG), SP                     /* restore SP */
527         MOVQ    8(RARG), AX                     /* put return PC on the stack */
528         MOVQ    AX, 0(SP)
529         MOVL    $1, AX                          /* return 1 */
530         RET
531
532 TEXT setlabel(SB), 1, $-4
533         MOVQ    SP, 0(RARG)                     /* store SP */
534         MOVQ    0(SP), BX                       /* store return PC */
535         MOVQ    BX, 8(RARG)
536         MOVL    $0, AX                          /* return 0 */
537         RET
538
539 TEXT halt(SB), 1, $-4
540         CLI
541         CMPL    nrdy(SB), $0
542         JEQ     _nothingready
543         STI
544         RET
545 _nothingready:
546         STI
547         HLT
548         RET
549
550 TEXT mwait(SB), 1, $-4
551         MOVQ    RARG, AX
552         MOVL    (AX), CX
553         ORL     CX, CX
554         JNZ     _mwaitdone
555         XORL    DX, DX
556         BYTE $0x0f; BYTE $0x01; BYTE $0xc8      /* MONITOR */
557         MOVL    (AX), CX
558         ORL     CX, CX
559         JNZ     _mwaitdone
560         XORL    AX, AX
561         BYTE $0x0f; BYTE $0x01; BYTE $0xc9      /* MWAIT */
562 _mwaitdone:
563         RET
564
565 /*
566  * SIMD Floating Point.
567  * Note: for x87 instructions which have both a 'wait' and 'nowait' version,
568  * 8a only knows the 'wait' mnemonic but does NOT insertthe WAIT prefix byte
569  * (i.e. they act like their FNxxx variations) so WAIT instructions must be
570  * explicitly placed in the code if necessary.
571  */
572 TEXT _clts(SB), 1, $-4
573         CLTS
574         RET
575
576 TEXT _fldcw(SB), 1, $-4                         /* Load x87 FPU Control Word */
577         MOVQ    RARG, cw+0(FP)
578         FLDCW   cw+0(FP)
579         RET
580
581 TEXT _fnclex(SB), 1, $-4
582         FCLEX
583         RET
584
585 TEXT _fninit(SB), 1, $-4
586         FINIT                                   /* no WAIT */
587         RET
588
589 TEXT _fxrstor(SB), 1, $-4
590         FXRSTOR64 (RARG)
591         RET
592
593 TEXT _fxsave(SB), 1, $-4
594         FXSAVE64 (RARG)
595         RET
596
597 TEXT _fwait(SB), 1, $-4
598         WAIT
599         RET
600
601 TEXT _ldmxcsr(SB), 1, $-4                       /* Load MXCSR */
602         MOVQ    RARG, mxcsr+0(FP)
603         LDMXCSR mxcsr+0(FP)
604         RET
605
606 TEXT _stts(SB), 1, $-4
607         MOVQ    CR0, AX
608         ORQ     $8, AX                          /* Ts */
609         MOVQ    AX, CR0
610         RET
611
612 TEXT mul64fract(SB), 1, $-4
613         MOVQ    a+8(FP), AX
614         MULQ    b+16(FP)                        /* a*b */
615         SHRQ    $32, AX:DX
616         MOVQ    AX, (RARG)
617         RET
618
619 #define RDRANDAX        BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
620 #define RDRAND64AX      BYTE $0x48; BYTE $0x0f; BYTE $0xc7;  BYTE $0xf0
621
622 TEXT rdrand32(SB), $-4
623 loop32:
624         RDRANDAX
625         JCC             loop32
626         RET
627
628 TEXT rdrand64(SB), $-4
629 loop64:
630         RDRAND64AX
631         JCC             loop64
632         RET
633
634 TEXT rdrandbuf(SB), $0
635         MOVQ    RARG, DX
636
637         MOVLQZX cnt+8(FP), CX
638         SHRQ    $3, CX
639 eights:
640         CMPL    CX, $0
641         JLE     f1
642         CALL    rdrand64(SB)
643         MOVQ    AX, 0(DX)
644         ADDQ    $8, DX
645         SUBL    $1, CX
646         JMP     eights
647
648 f1:
649         MOVLQZX cnt+8(FP), CX
650         ANDL    $7, CX
651         SHRQ    $2, CX
652 fours:
653         CMPL    CX, $0
654         JLE     f2
655         CALL    rdrand32(SB)
656         MOVL    AX, 0(DX)
657         ADDQ    $4, DX
658         SUBL    $1, CX
659         JMP     fours
660
661 f2:
662         MOVLQZX cnt+8(FP), CX
663         ANDL    $3, CX
664 ones:
665         CMPL    CX, $0
666         JLE     f3
667         CALL    rdrand32(SB)
668         MOVB    AX, 0(DX)
669         ADDQ    $1, DX
670         SUBL    $1, CX
671         JMP     ones
672
673 f3:
674         RET
675
676 /*
677  */
678 TEXT touser(SB), 1, $-4
679         CLI
680         SWAPGS
681         MOVQ    $UDSEL, AX
682         MOVW    AX, DS
683         MOVW    AX, ES
684         MOVW    AX, FS
685         MOVW    AX, GS
686
687         MOVQ    $(UTZERO+0x28), CX              /* ip */
688         MOVQ    $0x200, R11                     /* flags */
689
690         MOVQ    RARG, SP                        /* sp */
691
692         BYTE $0x48; SYSRET                      /* SYSRETQ */
693
694 /*
695  */
696 TEXT syscallentry(SB), 1, $-4
697         SWAPGS
698         BYTE $0x65; MOVQ 0, RMACH               /* m-> (MOVQ GS:0x0, R15) */
699         MOVQ    16(RMACH), RUSER                /* m->proc */
700         MOVQ    SP, R13
701         MOVQ    16(RUSER), SP                   /* m->proc->kstack */
702         ADDQ    $KSTACK, SP
703         PUSHQ   $UDSEL                          /* old stack segment */
704         PUSHQ   R13                             /* old sp */
705         PUSHQ   R11                             /* old flags */
706         PUSHQ   $UESEL                          /* old code segment */
707         PUSHQ   CX                              /* old ip */
708
709         SUBQ    $(17*8), SP                     /* unsaved registers */
710         PUSHQ   RARG                            /* system call number */
711
712         MOVW    $UDSEL, (15*8+0)(SP)
713         MOVW    ES, (15*8+2)(SP)
714         MOVW    FS, (15*8+4)(SP)
715         MOVW    GS, (15*8+6)(SP)
716
717         MOVQ    SP, RARG
718         PUSHQ   SP                              /* Ureg* */
719         CALL    syscall(SB)
720
721 TEXT forkret(SB), 1, $-4
722         MOVQ    8(SP), AX                       /* Ureg.ax */
723         MOVQ    (8+6*8)(SP), BP                 /* Ureg.bp */
724         ADDQ    $(16*8), SP                     /* registers + arguments */
725
726         CLI
727         SWAPGS
728         MOVW    0(SP), DS
729         MOVW    2(SP), ES
730         MOVW    4(SP), FS
731         MOVW    6(SP), GS
732
733         MOVQ    24(SP), CX                      /* ip */
734         MOVQ    40(SP), R11                     /* flags */
735
736         MOVQ    48(SP), SP                      /* sp */
737
738         BYTE $0x48; SYSRET                      /* SYSRETQ */
739
740 TEXT noteret(SB), 1, $-4
741         CLI
742         JMP _intrestore
743
744 /*
745  * Interrupt/exception handling.
746  */
747
748 TEXT _strayintr(SB), 1, $-4                     /* no error code pushed */
749         PUSHQ   AX                              /* save AX */
750         MOVQ    8(SP), AX                       /* vectortable(SB) PC */
751         JMP     _intrcommon
752
753 TEXT _strayintrx(SB), 1, $-4                    /* error code pushed */
754         XCHGQ   AX, (SP)
755 _intrcommon:
756         MOVBQZX (AX), AX
757         XCHGQ   AX, (SP)
758
759         SUBQ    $24, SP                         /* R1[45], [DEFG]S */
760         CMPW    48(SP), $KESEL                  /* old CS */
761         JEQ     _intrnested
762
763         MOVQ    RUSER, 0(SP)
764         MOVQ    RMACH, 8(SP)
765         MOVW    DS, 16(SP)
766         MOVW    ES, 18(SP)
767         MOVW    FS, 20(SP)
768         MOVW    GS, 22(SP)
769
770         SWAPGS
771         BYTE $0x65; MOVQ 0, RMACH               /* m-> (MOVQ GS:0x0, R15) */
772         MOVQ    16(RMACH), RUSER                /* up */
773
774 _intrnested:
775         PUSHQ   R13
776         PUSHQ   R12
777         PUSHQ   R11
778         PUSHQ   R10
779         PUSHQ   R9
780         PUSHQ   R8
781         PUSHQ   BP
782         PUSHQ   DI
783         PUSHQ   SI
784         PUSHQ   DX
785         PUSHQ   CX
786         PUSHQ   BX
787         PUSHQ   AX
788
789         MOVQ    SP, RARG
790         PUSHQ   SP
791         CALL    trap(SB)
792
793 _intrestore:
794         POPQ    AX
795
796         POPQ    AX
797         POPQ    BX
798         POPQ    CX
799         POPQ    DX
800         POPQ    SI
801         POPQ    DI
802         POPQ    BP
803         POPQ    R8
804         POPQ    R9
805         POPQ    R10
806         POPQ    R11
807         POPQ    R12
808         POPQ    R13
809
810         CMPQ    48(SP), $KESEL
811         JEQ     _iretnested
812
813         SWAPGS
814         MOVW    22(SP), GS
815         MOVW    20(SP), FS
816         MOVW    18(SP), ES
817         MOVW    16(SP), DS
818         MOVQ    8(SP), RMACH
819         MOVQ    0(SP), RUSER
820
821 _iretnested:
822         ADDQ    $40, SP
823         IRETQ
824
825 TEXT vectortable(SB), $0
826         CALL _strayintr(SB); BYTE $0x00         /* divide error */
827         CALL _strayintr(SB); BYTE $0x01         /* debug exception */
828         CALL _strayintr(SB); BYTE $0x02         /* NMI interrupt */
829         CALL _strayintr(SB); BYTE $0x03         /* breakpoint */
830         CALL _strayintr(SB); BYTE $0x04         /* overflow */
831         CALL _strayintr(SB); BYTE $0x05         /* bound */
832         CALL _strayintr(SB); BYTE $0x06         /* invalid opcode */
833         CALL _strayintr(SB); BYTE $0x07         /* no coprocessor available */
834         CALL _strayintrx(SB); BYTE $0x08        /* double fault */
835         CALL _strayintr(SB); BYTE $0x09         /* coprocessor segment overflow */
836         CALL _strayintrx(SB); BYTE $0x0A        /* invalid TSS */
837         CALL _strayintrx(SB); BYTE $0x0B        /* segment not available */
838         CALL _strayintrx(SB); BYTE $0x0C        /* stack exception */
839         CALL _strayintrx(SB); BYTE $0x0D        /* general protection error */
840         CALL _strayintrx(SB); BYTE $0x0E        /* page fault */
841         CALL _strayintr(SB); BYTE $0x0F         /*  */
842         CALL _strayintr(SB); BYTE $0x10         /* coprocessor error */
843         CALL _strayintrx(SB); BYTE $0x11        /* alignment check */
844         CALL _strayintr(SB); BYTE $0x12         /* machine check */
845         CALL _strayintr(SB); BYTE $0x13
846         CALL _strayintr(SB); BYTE $0x14
847         CALL _strayintr(SB); BYTE $0x15
848         CALL _strayintr(SB); BYTE $0x16
849         CALL _strayintr(SB); BYTE $0x17
850         CALL _strayintr(SB); BYTE $0x18
851         CALL _strayintr(SB); BYTE $0x19
852         CALL _strayintr(SB); BYTE $0x1A
853         CALL _strayintr(SB); BYTE $0x1B
854         CALL _strayintr(SB); BYTE $0x1C
855         CALL _strayintr(SB); BYTE $0x1D
856         CALL _strayintr(SB); BYTE $0x1E
857         CALL _strayintr(SB); BYTE $0x1F
858         CALL _strayintr(SB); BYTE $0x20         /* VectorLAPIC */
859         CALL _strayintr(SB); BYTE $0x21
860         CALL _strayintr(SB); BYTE $0x22
861         CALL _strayintr(SB); BYTE $0x23
862         CALL _strayintr(SB); BYTE $0x24
863         CALL _strayintr(SB); BYTE $0x25
864         CALL _strayintr(SB); BYTE $0x26
865         CALL _strayintr(SB); BYTE $0x27
866         CALL _strayintr(SB); BYTE $0x28
867         CALL _strayintr(SB); BYTE $0x29
868         CALL _strayintr(SB); BYTE $0x2A
869         CALL _strayintr(SB); BYTE $0x2B
870         CALL _strayintr(SB); BYTE $0x2C
871         CALL _strayintr(SB); BYTE $0x2D
872         CALL _strayintr(SB); BYTE $0x2E
873         CALL _strayintr(SB); BYTE $0x2F
874         CALL _strayintr(SB); BYTE $0x30
875         CALL _strayintr(SB); BYTE $0x31
876         CALL _strayintr(SB); BYTE $0x32
877         CALL _strayintr(SB); BYTE $0x33
878         CALL _strayintr(SB); BYTE $0x34
879         CALL _strayintr(SB); BYTE $0x35
880         CALL _strayintr(SB); BYTE $0x36
881         CALL _strayintr(SB); BYTE $0x37
882         CALL _strayintr(SB); BYTE $0x38
883         CALL _strayintr(SB); BYTE $0x39
884         CALL _strayintr(SB); BYTE $0x3A
885         CALL _strayintr(SB); BYTE $0x3B
886         CALL _strayintr(SB); BYTE $0x3C
887         CALL _strayintr(SB); BYTE $0x3D
888         CALL _strayintr(SB); BYTE $0x3E
889         CALL _strayintr(SB); BYTE $0x3F
890         CALL _strayintr(SB); BYTE $0x40         /* was VectorSYSCALL */
891         CALL _strayintr(SB); BYTE $0x41
892         CALL _strayintr(SB); BYTE $0x42
893         CALL _strayintr(SB); BYTE $0x43
894         CALL _strayintr(SB); BYTE $0x44
895         CALL _strayintr(SB); BYTE $0x45
896         CALL _strayintr(SB); BYTE $0x46
897         CALL _strayintr(SB); BYTE $0x47
898         CALL _strayintr(SB); BYTE $0x48
899         CALL _strayintr(SB); BYTE $0x49
900         CALL _strayintr(SB); BYTE $0x4A
901         CALL _strayintr(SB); BYTE $0x4B
902         CALL _strayintr(SB); BYTE $0x4C
903         CALL _strayintr(SB); BYTE $0x4D
904         CALL _strayintr(SB); BYTE $0x4E
905         CALL _strayintr(SB); BYTE $0x4F
906         CALL _strayintr(SB); BYTE $0x50
907         CALL _strayintr(SB); BYTE $0x51
908         CALL _strayintr(SB); BYTE $0x52
909         CALL _strayintr(SB); BYTE $0x53
910         CALL _strayintr(SB); BYTE $0x54
911         CALL _strayintr(SB); BYTE $0x55
912         CALL _strayintr(SB); BYTE $0x56
913         CALL _strayintr(SB); BYTE $0x57
914         CALL _strayintr(SB); BYTE $0x58
915         CALL _strayintr(SB); BYTE $0x59
916         CALL _strayintr(SB); BYTE $0x5A
917         CALL _strayintr(SB); BYTE $0x5B
918         CALL _strayintr(SB); BYTE $0x5C
919         CALL _strayintr(SB); BYTE $0x5D
920         CALL _strayintr(SB); BYTE $0x5E
921         CALL _strayintr(SB); BYTE $0x5F
922         CALL _strayintr(SB); BYTE $0x60
923         CALL _strayintr(SB); BYTE $0x61
924         CALL _strayintr(SB); BYTE $0x62
925         CALL _strayintr(SB); BYTE $0x63
926         CALL _strayintr(SB); BYTE $0x64
927         CALL _strayintr(SB); BYTE $0x65
928         CALL _strayintr(SB); BYTE $0x66
929         CALL _strayintr(SB); BYTE $0x67
930         CALL _strayintr(SB); BYTE $0x68
931         CALL _strayintr(SB); BYTE $0x69
932         CALL _strayintr(SB); BYTE $0x6A
933         CALL _strayintr(SB); BYTE $0x6B
934         CALL _strayintr(SB); BYTE $0x6C
935         CALL _strayintr(SB); BYTE $0x6D
936         CALL _strayintr(SB); BYTE $0x6E
937         CALL _strayintr(SB); BYTE $0x6F
938         CALL _strayintr(SB); BYTE $0x70
939         CALL _strayintr(SB); BYTE $0x71
940         CALL _strayintr(SB); BYTE $0x72
941         CALL _strayintr(SB); BYTE $0x73
942         CALL _strayintr(SB); BYTE $0x74
943         CALL _strayintr(SB); BYTE $0x75
944         CALL _strayintr(SB); BYTE $0x76
945         CALL _strayintr(SB); BYTE $0x77
946         CALL _strayintr(SB); BYTE $0x78
947         CALL _strayintr(SB); BYTE $0x79
948         CALL _strayintr(SB); BYTE $0x7A
949         CALL _strayintr(SB); BYTE $0x7B
950         CALL _strayintr(SB); BYTE $0x7C
951         CALL _strayintr(SB); BYTE $0x7D
952         CALL _strayintr(SB); BYTE $0x7E
953         CALL _strayintr(SB); BYTE $0x7F
954         CALL _strayintr(SB); BYTE $0x80         /* Vector[A]PIC */
955         CALL _strayintr(SB); BYTE $0x81
956         CALL _strayintr(SB); BYTE $0x82
957         CALL _strayintr(SB); BYTE $0x83
958         CALL _strayintr(SB); BYTE $0x84
959         CALL _strayintr(SB); BYTE $0x85
960         CALL _strayintr(SB); BYTE $0x86
961         CALL _strayintr(SB); BYTE $0x87
962         CALL _strayintr(SB); BYTE $0x88
963         CALL _strayintr(SB); BYTE $0x89
964         CALL _strayintr(SB); BYTE $0x8A
965         CALL _strayintr(SB); BYTE $0x8B
966         CALL _strayintr(SB); BYTE $0x8C
967         CALL _strayintr(SB); BYTE $0x8D
968         CALL _strayintr(SB); BYTE $0x8E
969         CALL _strayintr(SB); BYTE $0x8F
970         CALL _strayintr(SB); BYTE $0x90
971         CALL _strayintr(SB); BYTE $0x91
972         CALL _strayintr(SB); BYTE $0x92
973         CALL _strayintr(SB); BYTE $0x93
974         CALL _strayintr(SB); BYTE $0x94
975         CALL _strayintr(SB); BYTE $0x95
976         CALL _strayintr(SB); BYTE $0x96
977         CALL _strayintr(SB); BYTE $0x97
978         CALL _strayintr(SB); BYTE $0x98
979         CALL _strayintr(SB); BYTE $0x99
980         CALL _strayintr(SB); BYTE $0x9A
981         CALL _strayintr(SB); BYTE $0x9B
982         CALL _strayintr(SB); BYTE $0x9C
983         CALL _strayintr(SB); BYTE $0x9D
984         CALL _strayintr(SB); BYTE $0x9E
985         CALL _strayintr(SB); BYTE $0x9F
986         CALL _strayintr(SB); BYTE $0xA0
987         CALL _strayintr(SB); BYTE $0xA1
988         CALL _strayintr(SB); BYTE $0xA2
989         CALL _strayintr(SB); BYTE $0xA3
990         CALL _strayintr(SB); BYTE $0xA4
991         CALL _strayintr(SB); BYTE $0xA5
992         CALL _strayintr(SB); BYTE $0xA6
993         CALL _strayintr(SB); BYTE $0xA7
994         CALL _strayintr(SB); BYTE $0xA8
995         CALL _strayintr(SB); BYTE $0xA9
996         CALL _strayintr(SB); BYTE $0xAA
997         CALL _strayintr(SB); BYTE $0xAB
998         CALL _strayintr(SB); BYTE $0xAC
999         CALL _strayintr(SB); BYTE $0xAD
1000         CALL _strayintr(SB); BYTE $0xAE
1001         CALL _strayintr(SB); BYTE $0xAF
1002         CALL _strayintr(SB); BYTE $0xB0
1003         CALL _strayintr(SB); BYTE $0xB1
1004         CALL _strayintr(SB); BYTE $0xB2
1005         CALL _strayintr(SB); BYTE $0xB3
1006         CALL _strayintr(SB); BYTE $0xB4
1007         CALL _strayintr(SB); BYTE $0xB5
1008         CALL _strayintr(SB); BYTE $0xB6
1009         CALL _strayintr(SB); BYTE $0xB7
1010         CALL _strayintr(SB); BYTE $0xB8
1011         CALL _strayintr(SB); BYTE $0xB9
1012         CALL _strayintr(SB); BYTE $0xBA
1013         CALL _strayintr(SB); BYTE $0xBB
1014         CALL _strayintr(SB); BYTE $0xBC
1015         CALL _strayintr(SB); BYTE $0xBD
1016         CALL _strayintr(SB); BYTE $0xBE
1017         CALL _strayintr(SB); BYTE $0xBF
1018         CALL _strayintr(SB); BYTE $0xC0
1019         CALL _strayintr(SB); BYTE $0xC1
1020         CALL _strayintr(SB); BYTE $0xC2
1021         CALL _strayintr(SB); BYTE $0xC3
1022         CALL _strayintr(SB); BYTE $0xC4
1023         CALL _strayintr(SB); BYTE $0xC5
1024         CALL _strayintr(SB); BYTE $0xC6
1025         CALL _strayintr(SB); BYTE $0xC7
1026         CALL _strayintr(SB); BYTE $0xC8
1027         CALL _strayintr(SB); BYTE $0xC9
1028         CALL _strayintr(SB); BYTE $0xCA
1029         CALL _strayintr(SB); BYTE $0xCB
1030         CALL _strayintr(SB); BYTE $0xCC
1031         CALL _strayintr(SB); BYTE $0xCD
1032         CALL _strayintr(SB); BYTE $0xCE
1033         CALL _strayintr(SB); BYTE $0xCF
1034         CALL _strayintr(SB); BYTE $0xD0
1035         CALL _strayintr(SB); BYTE $0xD1
1036         CALL _strayintr(SB); BYTE $0xD2
1037         CALL _strayintr(SB); BYTE $0xD3
1038         CALL _strayintr(SB); BYTE $0xD4
1039         CALL _strayintr(SB); BYTE $0xD5
1040         CALL _strayintr(SB); BYTE $0xD6
1041         CALL _strayintr(SB); BYTE $0xD7
1042         CALL _strayintr(SB); BYTE $0xD8
1043         CALL _strayintr(SB); BYTE $0xD9
1044         CALL _strayintr(SB); BYTE $0xDA
1045         CALL _strayintr(SB); BYTE $0xDB
1046         CALL _strayintr(SB); BYTE $0xDC
1047         CALL _strayintr(SB); BYTE $0xDD
1048         CALL _strayintr(SB); BYTE $0xDE
1049         CALL _strayintr(SB); BYTE $0xDF
1050         CALL _strayintr(SB); BYTE $0xE0
1051         CALL _strayintr(SB); BYTE $0xE1
1052         CALL _strayintr(SB); BYTE $0xE2
1053         CALL _strayintr(SB); BYTE $0xE3
1054         CALL _strayintr(SB); BYTE $0xE4
1055         CALL _strayintr(SB); BYTE $0xE5
1056         CALL _strayintr(SB); BYTE $0xE6
1057         CALL _strayintr(SB); BYTE $0xE7
1058         CALL _strayintr(SB); BYTE $0xE8
1059         CALL _strayintr(SB); BYTE $0xE9
1060         CALL _strayintr(SB); BYTE $0xEA
1061         CALL _strayintr(SB); BYTE $0xEB
1062         CALL _strayintr(SB); BYTE $0xEC
1063         CALL _strayintr(SB); BYTE $0xED
1064         CALL _strayintr(SB); BYTE $0xEE
1065         CALL _strayintr(SB); BYTE $0xEF
1066         CALL _strayintr(SB); BYTE $0xF0
1067         CALL _strayintr(SB); BYTE $0xF1
1068         CALL _strayintr(SB); BYTE $0xF2
1069         CALL _strayintr(SB); BYTE $0xF3
1070         CALL _strayintr(SB); BYTE $0xF4
1071         CALL _strayintr(SB); BYTE $0xF5
1072         CALL _strayintr(SB); BYTE $0xF6
1073         CALL _strayintr(SB); BYTE $0xF7
1074         CALL _strayintr(SB); BYTE $0xF8
1075         CALL _strayintr(SB); BYTE $0xF9
1076         CALL _strayintr(SB); BYTE $0xFA
1077         CALL _strayintr(SB); BYTE $0xFB
1078         CALL _strayintr(SB); BYTE $0xFC
1079         CALL _strayintr(SB); BYTE $0xFD
1080         CALL _strayintr(SB); BYTE $0xFE
1081         CALL _strayintr(SB); BYTE $0xFF