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