]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc64/l.s
pc64: check if vmap() range fits in VMAPLEN window, remove unneeded vmapsync(), renam...
[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  * Park a processor. Should never fall through a return from main to here,
239  * should only be called by application processors when shutting down.
240  */
241 TEXT idle(SB), 1, $-4
242 _idle:
243         STI
244         HLT
245         JMP     _idle
246
247 /*
248  * The CPUID instruction is always supported on the amd64.
249  */
250 TEXT cpuid(SB), $-4
251         MOVL    RARG, AX                        /* function in AX */
252         CPUID
253
254         MOVQ    info+8(FP), BP
255         MOVL    AX, 0(BP)
256         MOVL    BX, 4(BP)
257         MOVL    CX, 8(BP)
258         MOVL    DX, 12(BP)
259         RET
260
261 /*
262  * Port I/O.
263  */
264 TEXT inb(SB), 1, $-4
265         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
266         XORL    AX, AX
267         INB
268         RET
269
270 TEXT insb(SB), 1, $-4
271         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
272         MOVQ    address+8(FP), DI
273         MOVL    count+16(FP), CX
274         CLD
275         REP;    INSB
276         RET
277
278 TEXT ins(SB), 1, $-4
279         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
280         XORL    AX, AX
281         INW
282         RET
283
284 TEXT inss(SB), 1, $-4
285         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
286         MOVQ    address+8(FP), DI
287         MOVL    count+16(FP), CX
288         CLD
289         REP;    INSW
290         RET
291
292 TEXT inl(SB), 1, $-4
293         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
294         INL
295         RET
296
297 TEXT insl(SB), 1, $-4
298         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
299         MOVQ    address+8(FP), DI
300         MOVL    count+16(FP), CX
301         CLD
302         REP; INSL
303         RET
304
305 TEXT outb(SB), 1, $-1
306         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
307         MOVL    byte+8(FP), AX
308         OUTB
309         RET
310
311 TEXT outsb(SB), 1, $-4
312         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
313         MOVQ    address+8(FP), SI
314         MOVL    count+16(FP), CX
315         CLD
316         REP; OUTSB
317         RET
318
319 TEXT outs(SB), 1, $-4
320         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
321         MOVL    short+8(FP), AX
322         OUTW
323         RET
324
325 TEXT outss(SB), 1, $-4
326         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
327         MOVQ    address+8(FP), SI
328         MOVL    count+16(FP), CX
329         CLD
330         REP; OUTSW
331         RET
332
333 TEXT outl(SB), 1, $-4
334         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
335         MOVL    long+8(FP), AX
336         OUTL
337         RET
338
339 TEXT outsl(SB), 1, $-4
340         MOVL    RARG, DX                        /* MOVL port+0(FP), DX */
341         MOVQ    address+8(FP), SI
342         MOVL    count+16(FP), CX
343         CLD
344         REP; OUTSL
345         RET
346
347 TEXT getgdt(SB), 1, $-4
348         MOVQ    RARG, AX
349         MOVL    GDTR, (AX)                      /* Note: 10 bytes returned */
350         RET
351
352 TEXT lgdt(SB), $0                               /* GDTR - global descriptor table */
353         MOVQ    RARG, AX
354         MOVL    (AX), GDTR
355         RET
356
357 TEXT lidt(SB), $0                               /* IDTR - interrupt descriptor table */
358         MOVQ    RARG, AX
359         MOVL    (AX), IDTR
360         RET
361
362 TEXT ltr(SB), 1, $-4
363         MOVW    RARG, AX
364         MOVW    AX, TASK
365         RET
366
367 /*
368  * Read/write various system registers.
369  */
370 TEXT getcr0(SB), 1, $-4                         /* Processor Control */
371         MOVQ    CR0, AX
372         RET
373
374 TEXT putcr0(SB), 1, $-4
375         MOVQ    RARG, CR0
376         RET
377
378 TEXT getcr2(SB), 1, $-4                         /* #PF Linear Address */
379         MOVQ    CR2, AX
380         RET
381
382 TEXT getcr3(SB), 1, $-4                         /* PML4 Base */
383         MOVQ    CR3, AX
384         RET
385
386 TEXT putcr3(SB), 1, $-4
387         MOVQ    RARG, CR3
388         RET
389
390 TEXT getcr4(SB), 1, $-4                         /* Extensions */
391         MOVQ    CR4, AX
392         RET
393
394 TEXT putcr4(SB), 1, $-4
395         MOVQ    RARG, CR4
396         RET
397
398 TEXT mb386(SB), 1, $-4                          /* hack */
399 TEXT mb586(SB), 1, $-4
400         XORL    AX, AX
401         CPUID
402         RET
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 TEXT _tas(SB), 1, $-4
524         MOVL    $0xdeaddead, AX
525         XCHGL   AX, (RARG)                      /*  */
526         RET
527
528 TEXT cmpswap486(SB), 1, $-4
529 TEXT cas(SB), 1, $-4
530         MOVL    exp+8(FP), AX
531         MOVL    new+16(FP), BX
532         LOCK; CMPXCHGL BX, (RARG)
533         MOVL    $1, AX                          /* use CMOVLEQ etc. here? */
534         JNZ     _cas32r0
535 _cas32r1:
536         RET
537 _cas32r0:
538         DECL    AX
539         RET
540
541 /*
542  * Label consists of a stack pointer and a programme counter
543  */
544 TEXT gotolabel(SB), 1, $-4
545         MOVQ    0(RARG), SP                     /* restore SP */
546         MOVQ    8(RARG), AX                     /* put return PC on the stack */
547         MOVQ    AX, 0(SP)
548         MOVL    $1, AX                          /* return 1 */
549         RET
550
551 TEXT setlabel(SB), 1, $-4
552         MOVQ    SP, 0(RARG)                     /* store SP */
553         MOVQ    0(SP), BX                       /* store return PC */
554         MOVQ    BX, 8(RARG)
555         MOVL    $0, AX                          /* return 0 */
556         RET
557
558 TEXT halt(SB), 1, $-4
559         CLI
560         CMPL    nrdy(SB), $0
561         JEQ     _nothingready
562         STI
563         RET
564 _nothingready:
565         STI
566         HLT
567         RET
568
569 TEXT mwait(SB), 1, $-4
570         MOVQ    RARG, AX
571         MOVL    (AX), CX
572         ORL     CX, CX
573         JNZ     _mwaitdone
574         XORL    DX, DX
575         BYTE $0x0f; BYTE $0x01; BYTE $0xc8      /* MONITOR */
576         MOVL    (AX), CX
577         ORL     CX, CX
578         JNZ     _mwaitdone
579         XORL    AX, AX
580         BYTE $0x0f; BYTE $0x01; BYTE $0xc9      /* MWAIT */
581 _mwaitdone:
582         RET
583
584 /*
585  * SIMD Floating Point.
586  * Note: for x87 instructions which have both a 'wait' and 'nowait' version,
587  * 8a only knows the 'wait' mnemonic but does NOT insertthe WAIT prefix byte
588  * (i.e. they act like their FNxxx variations) so WAIT instructions must be
589  * explicitly placed in the code if necessary.
590  */
591 TEXT _clts(SB), 1, $-4
592         CLTS
593         RET
594
595 TEXT _fldcw(SB), 1, $-4                         /* Load x87 FPU Control Word */
596         MOVQ    RARG, cw+0(FP)
597         FLDCW   cw+0(FP)
598         RET
599
600 TEXT _fnclex(SB), 1, $-4
601         FCLEX
602         RET
603
604 TEXT _fninit(SB), 1, $-4
605         FINIT                                   /* no WAIT */
606         RET
607
608 TEXT _fxrstor(SB), 1, $-4
609         FXRSTOR64 (RARG)
610         RET
611
612 TEXT _fxsave(SB), 1, $-4
613         FXSAVE64 (RARG)
614         RET
615
616 TEXT _fwait(SB), 1, $-4
617         WAIT
618         RET
619
620 TEXT _ldmxcsr(SB), 1, $-4                       /* Load MXCSR */
621         MOVQ    RARG, mxcsr+0(FP)
622         LDMXCSR mxcsr+0(FP)
623         RET
624
625 TEXT _stts(SB), 1, $-4
626         MOVQ    CR0, AX
627         ORQ     $8, AX                          /* Ts */
628         MOVQ    AX, CR0
629         RET
630
631 TEXT mul64fract(SB), 1, $-4
632         MOVQ    a+8(FP), AX
633         MULQ    b+16(FP)                        /* a*b */
634         SHRQ    $32, AX:DX
635         MOVQ    AX, (RARG)
636         RET
637
638 #define RDRANDAX        BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
639 #define RDRAND64AX      BYTE $0x48; BYTE $0x0f; BYTE $0xc7;  BYTE $0xf0
640
641 TEXT rdrand32(SB), $-4
642 loop32:
643         RDRANDAX
644         JCC             loop32
645         RET
646
647 TEXT rdrand64(SB), $-4
648 loop64:
649         RDRAND64AX
650         JCC             loop64
651         RET
652
653 TEXT rdrandbuf(SB), $0
654         MOVQ    RARG, DX
655
656         MOVLQZX cnt+8(FP), CX
657         SHRQ    $3, CX
658 eights:
659         CMPL    CX, $0
660         JLE     f1
661         CALL    rdrand64(SB)
662         MOVQ    AX, 0(DX)
663         ADDQ    $8, DX
664         SUBL    $1, CX
665         JMP     eights
666
667 f1:
668         MOVLQZX cnt+8(FP), CX
669         ANDL    $7, CX
670         SHRQ    $2, CX
671 fours:
672         CMPL    CX, $0
673         JLE     f2
674         CALL    rdrand32(SB)
675         MOVL    AX, 0(DX)
676         ADDQ    $4, DX
677         SUBL    $1, CX
678         JMP     fours
679
680 f2:
681         MOVLQZX cnt+8(FP), CX
682         ANDL    $3, CX
683 ones:
684         CMPL    CX, $0
685         JLE     f3
686         CALL    rdrand32(SB)
687         MOVB    AX, 0(DX)
688         ADDQ    $1, DX
689         SUBL    $1, CX
690         JMP     ones
691
692 f3:
693         RET
694
695 /*
696  */
697 TEXT touser(SB), 1, $-4
698         CLI
699         SWAPGS
700
701         MOVL    $0, RMACH
702         MOVL    $0, RUSER
703
704         MOVQ    $(UTZERO+0x28), CX              /* ip */
705         MOVL    $0x200, R11                     /* flags */
706         MOVQ    RARG, SP                        /* sp */
707
708         BYTE $0x48; SYSRET                      /* SYSRETQ */
709
710 /*
711  */
712 TEXT syscallentry(SB), 1, $-4
713         SWAPGS
714         BYTE $0x65; MOVQ 0, AX                  /* m-> (MOVQ GS:0x0, AX) */
715         MOVQ    16(AX), BX                      /* m->proc */
716         MOVQ    SP, R13
717         MOVQ    16(BX), SP                      /* m->proc->kstack */
718         ADDQ    $KSTACK, SP
719
720         PUSHQ   $UDSEL                          /* old stack segment */
721         PUSHQ   R13                             /* old sp */
722         PUSHQ   R11                             /* old flags */
723         PUSHQ   $UESEL                          /* old code segment */
724         PUSHQ   CX                              /* old ip */
725
726         SUBQ    $(8 + 23*8-5*8), SP             /* arg + sizeof(Ureg)-pushed */
727
728         MOVQ    RMACH, (15*8)(SP)               /* old r15 */
729         MOVQ    RUSER, (14*8)(SP)               /* old r14 */
730
731         MOVQ    RARG, (7*8)(SP)                 /* system call number */
732
733         MOVQ    AX, RMACH                       /* m */
734         MOVQ    BX, RUSER                       /* up */
735
736         LEAQ    8(SP), RARG                     /* Ureg* arg */
737
738         CALL    syscall(SB)
739
740 TEXT forkret(SB), 1, $-4
741         CLI
742         SWAPGS
743
744         MOVQ    8(SP), AX                       /* return value */
745
746         MOVQ    (15*8)(SP), RMACH               /* r15 */
747         MOVQ    (14*8)(SP), RUSER               /* r14 */
748
749         MOVQ    (19*8)(SP), CX                  /* ip */
750         MOVQ    (21*8)(SP), R11                 /* flags */
751         MOVQ    (22*8)(SP), SP                  /* sp */
752
753         BYTE $0x48; SYSRET                      /* SYSRETQ */
754
755 TEXT noteret(SB), 1, $-4
756         CLI
757         JMP _intrestore
758
759 /*
760  * Interrupt/exception handling.
761  */
762
763 TEXT _strayintr(SB), 1, $-4                     /* no error code pushed */
764         PUSHQ   AX                              /* save AX */
765         MOVQ    8(SP), AX                       /* vectortable(SB) PC */
766         JMP     _intrcommon
767
768 TEXT _strayintrx(SB), 1, $-4                    /* error code pushed */
769         XCHGQ   AX, (SP)
770 _intrcommon:
771         MOVBQZX (AX), AX
772         XCHGQ   AX, (SP)
773
774         SUBQ    $24, SP                         /* R1[45], [DEFG]S */
775         CMPW    48(SP), $KESEL                  /* old CS */
776         JEQ     _intrnested
777
778         MOVQ    RUSER, 0(SP)
779         MOVQ    RMACH, 8(SP)
780
781         SWAPGS
782         BYTE $0x65; MOVQ 0, RMACH               /* m-> (MOVQ GS:0x0, R15) */
783         MOVQ    16(RMACH), RUSER                /* up */
784
785 _intrnested:
786         PUSHQ   R13
787         PUSHQ   R12
788         PUSHQ   R11
789         PUSHQ   R10
790         PUSHQ   R9
791         PUSHQ   R8
792         PUSHQ   BP
793         PUSHQ   DI
794         PUSHQ   SI
795         PUSHQ   DX
796         PUSHQ   CX
797         PUSHQ   BX
798         PUSHQ   AX
799
800         MOVQ    SP, RARG
801         PUSHQ   SP
802         CALL    trap(SB)
803
804 _intrestore:
805         POPQ    AX
806
807         POPQ    AX
808         POPQ    BX
809         POPQ    CX
810         POPQ    DX
811         POPQ    SI
812         POPQ    DI
813         POPQ    BP
814         POPQ    R8
815         POPQ    R9
816         POPQ    R10
817         POPQ    R11
818         POPQ    R12
819         POPQ    R13
820
821         CMPQ    48(SP), $KESEL
822         JEQ     _iretnested
823
824         SWAPGS
825
826         MOVQ    8(SP), RMACH
827         MOVQ    0(SP), RUSER
828
829 _iretnested:
830         ADDQ    $40, SP
831         IRETQ
832
833 TEXT vectortable(SB), $0
834         CALL _strayintr(SB); BYTE $0x00         /* divide error */
835         CALL _strayintr(SB); BYTE $0x01         /* debug exception */
836         CALL _strayintr(SB); BYTE $0x02         /* NMI interrupt */
837         CALL _strayintr(SB); BYTE $0x03         /* breakpoint */
838         CALL _strayintr(SB); BYTE $0x04         /* overflow */
839         CALL _strayintr(SB); BYTE $0x05         /* bound */
840         CALL _strayintr(SB); BYTE $0x06         /* invalid opcode */
841         CALL _strayintr(SB); BYTE $0x07         /* no coprocessor available */
842         CALL _strayintrx(SB); BYTE $0x08        /* double fault */
843         CALL _strayintr(SB); BYTE $0x09         /* coprocessor segment overflow */
844         CALL _strayintrx(SB); BYTE $0x0A        /* invalid TSS */
845         CALL _strayintrx(SB); BYTE $0x0B        /* segment not available */
846         CALL _strayintrx(SB); BYTE $0x0C        /* stack exception */
847         CALL _strayintrx(SB); BYTE $0x0D        /* general protection error */
848         CALL _strayintrx(SB); BYTE $0x0E        /* page fault */
849         CALL _strayintr(SB); BYTE $0x0F         /*  */
850         CALL _strayintr(SB); BYTE $0x10         /* coprocessor error */
851         CALL _strayintrx(SB); BYTE $0x11        /* alignment check */
852         CALL _strayintr(SB); BYTE $0x12         /* machine check */
853         CALL _strayintr(SB); BYTE $0x13         /* simd error */
854         CALL _strayintr(SB); BYTE $0x14
855         CALL _strayintr(SB); BYTE $0x15
856         CALL _strayintr(SB); BYTE $0x16
857         CALL _strayintr(SB); BYTE $0x17
858         CALL _strayintr(SB); BYTE $0x18
859         CALL _strayintr(SB); BYTE $0x19
860         CALL _strayintr(SB); BYTE $0x1A
861         CALL _strayintr(SB); BYTE $0x1B
862         CALL _strayintr(SB); BYTE $0x1C
863         CALL _strayintr(SB); BYTE $0x1D
864         CALL _strayintr(SB); BYTE $0x1E
865         CALL _strayintr(SB); BYTE $0x1F
866         CALL _strayintr(SB); BYTE $0x20         /* VectorLAPIC */
867         CALL _strayintr(SB); BYTE $0x21
868         CALL _strayintr(SB); BYTE $0x22
869         CALL _strayintr(SB); BYTE $0x23
870         CALL _strayintr(SB); BYTE $0x24
871         CALL _strayintr(SB); BYTE $0x25
872         CALL _strayintr(SB); BYTE $0x26
873         CALL _strayintr(SB); BYTE $0x27
874         CALL _strayintr(SB); BYTE $0x28
875         CALL _strayintr(SB); BYTE $0x29
876         CALL _strayintr(SB); BYTE $0x2A
877         CALL _strayintr(SB); BYTE $0x2B
878         CALL _strayintr(SB); BYTE $0x2C
879         CALL _strayintr(SB); BYTE $0x2D
880         CALL _strayintr(SB); BYTE $0x2E
881         CALL _strayintr(SB); BYTE $0x2F
882         CALL _strayintr(SB); BYTE $0x30
883         CALL _strayintr(SB); BYTE $0x31
884         CALL _strayintr(SB); BYTE $0x32
885         CALL _strayintr(SB); BYTE $0x33
886         CALL _strayintr(SB); BYTE $0x34
887         CALL _strayintr(SB); BYTE $0x35
888         CALL _strayintr(SB); BYTE $0x36
889         CALL _strayintr(SB); BYTE $0x37
890         CALL _strayintr(SB); BYTE $0x38
891         CALL _strayintr(SB); BYTE $0x39
892         CALL _strayintr(SB); BYTE $0x3A
893         CALL _strayintr(SB); BYTE $0x3B
894         CALL _strayintr(SB); BYTE $0x3C
895         CALL _strayintr(SB); BYTE $0x3D
896         CALL _strayintr(SB); BYTE $0x3E
897         CALL _strayintr(SB); BYTE $0x3F
898         CALL _strayintr(SB); BYTE $0x40         /* was VectorSYSCALL */
899         CALL _strayintr(SB); BYTE $0x41
900         CALL _strayintr(SB); BYTE $0x42
901         CALL _strayintr(SB); BYTE $0x43
902         CALL _strayintr(SB); BYTE $0x44
903         CALL _strayintr(SB); BYTE $0x45
904         CALL _strayintr(SB); BYTE $0x46
905         CALL _strayintr(SB); BYTE $0x47
906         CALL _strayintr(SB); BYTE $0x48
907         CALL _strayintr(SB); BYTE $0x49
908         CALL _strayintr(SB); BYTE $0x4A
909         CALL _strayintr(SB); BYTE $0x4B
910         CALL _strayintr(SB); BYTE $0x4C
911         CALL _strayintr(SB); BYTE $0x4D
912         CALL _strayintr(SB); BYTE $0x4E
913         CALL _strayintr(SB); BYTE $0x4F
914         CALL _strayintr(SB); BYTE $0x50
915         CALL _strayintr(SB); BYTE $0x51
916         CALL _strayintr(SB); BYTE $0x52
917         CALL _strayintr(SB); BYTE $0x53
918         CALL _strayintr(SB); BYTE $0x54
919         CALL _strayintr(SB); BYTE $0x55
920         CALL _strayintr(SB); BYTE $0x56
921         CALL _strayintr(SB); BYTE $0x57
922         CALL _strayintr(SB); BYTE $0x58
923         CALL _strayintr(SB); BYTE $0x59
924         CALL _strayintr(SB); BYTE $0x5A
925         CALL _strayintr(SB); BYTE $0x5B
926         CALL _strayintr(SB); BYTE $0x5C
927         CALL _strayintr(SB); BYTE $0x5D
928         CALL _strayintr(SB); BYTE $0x5E
929         CALL _strayintr(SB); BYTE $0x5F
930         CALL _strayintr(SB); BYTE $0x60
931         CALL _strayintr(SB); BYTE $0x61
932         CALL _strayintr(SB); BYTE $0x62
933         CALL _strayintr(SB); BYTE $0x63
934         CALL _strayintr(SB); BYTE $0x64
935         CALL _strayintr(SB); BYTE $0x65
936         CALL _strayintr(SB); BYTE $0x66
937         CALL _strayintr(SB); BYTE $0x67
938         CALL _strayintr(SB); BYTE $0x68
939         CALL _strayintr(SB); BYTE $0x69
940         CALL _strayintr(SB); BYTE $0x6A
941         CALL _strayintr(SB); BYTE $0x6B
942         CALL _strayintr(SB); BYTE $0x6C
943         CALL _strayintr(SB); BYTE $0x6D
944         CALL _strayintr(SB); BYTE $0x6E
945         CALL _strayintr(SB); BYTE $0x6F
946         CALL _strayintr(SB); BYTE $0x70
947         CALL _strayintr(SB); BYTE $0x71
948         CALL _strayintr(SB); BYTE $0x72
949         CALL _strayintr(SB); BYTE $0x73
950         CALL _strayintr(SB); BYTE $0x74
951         CALL _strayintr(SB); BYTE $0x75
952         CALL _strayintr(SB); BYTE $0x76
953         CALL _strayintr(SB); BYTE $0x77
954         CALL _strayintr(SB); BYTE $0x78
955         CALL _strayintr(SB); BYTE $0x79
956         CALL _strayintr(SB); BYTE $0x7A
957         CALL _strayintr(SB); BYTE $0x7B
958         CALL _strayintr(SB); BYTE $0x7C
959         CALL _strayintr(SB); BYTE $0x7D
960         CALL _strayintr(SB); BYTE $0x7E
961         CALL _strayintr(SB); BYTE $0x7F
962         CALL _strayintr(SB); BYTE $0x80         /* Vector[A]PIC */
963         CALL _strayintr(SB); BYTE $0x81
964         CALL _strayintr(SB); BYTE $0x82
965         CALL _strayintr(SB); BYTE $0x83
966         CALL _strayintr(SB); BYTE $0x84
967         CALL _strayintr(SB); BYTE $0x85
968         CALL _strayintr(SB); BYTE $0x86
969         CALL _strayintr(SB); BYTE $0x87
970         CALL _strayintr(SB); BYTE $0x88
971         CALL _strayintr(SB); BYTE $0x89
972         CALL _strayintr(SB); BYTE $0x8A
973         CALL _strayintr(SB); BYTE $0x8B
974         CALL _strayintr(SB); BYTE $0x8C
975         CALL _strayintr(SB); BYTE $0x8D
976         CALL _strayintr(SB); BYTE $0x8E
977         CALL _strayintr(SB); BYTE $0x8F
978         CALL _strayintr(SB); BYTE $0x90
979         CALL _strayintr(SB); BYTE $0x91
980         CALL _strayintr(SB); BYTE $0x92
981         CALL _strayintr(SB); BYTE $0x93
982         CALL _strayintr(SB); BYTE $0x94
983         CALL _strayintr(SB); BYTE $0x95
984         CALL _strayintr(SB); BYTE $0x96
985         CALL _strayintr(SB); BYTE $0x97
986         CALL _strayintr(SB); BYTE $0x98
987         CALL _strayintr(SB); BYTE $0x99
988         CALL _strayintr(SB); BYTE $0x9A
989         CALL _strayintr(SB); BYTE $0x9B
990         CALL _strayintr(SB); BYTE $0x9C
991         CALL _strayintr(SB); BYTE $0x9D
992         CALL _strayintr(SB); BYTE $0x9E
993         CALL _strayintr(SB); BYTE $0x9F
994         CALL _strayintr(SB); BYTE $0xA0
995         CALL _strayintr(SB); BYTE $0xA1
996         CALL _strayintr(SB); BYTE $0xA2
997         CALL _strayintr(SB); BYTE $0xA3
998         CALL _strayintr(SB); BYTE $0xA4
999         CALL _strayintr(SB); BYTE $0xA5
1000         CALL _strayintr(SB); BYTE $0xA6
1001         CALL _strayintr(SB); BYTE $0xA7
1002         CALL _strayintr(SB); BYTE $0xA8
1003         CALL _strayintr(SB); BYTE $0xA9
1004         CALL _strayintr(SB); BYTE $0xAA
1005         CALL _strayintr(SB); BYTE $0xAB
1006         CALL _strayintr(SB); BYTE $0xAC
1007         CALL _strayintr(SB); BYTE $0xAD
1008         CALL _strayintr(SB); BYTE $0xAE
1009         CALL _strayintr(SB); BYTE $0xAF
1010         CALL _strayintr(SB); BYTE $0xB0
1011         CALL _strayintr(SB); BYTE $0xB1
1012         CALL _strayintr(SB); BYTE $0xB2
1013         CALL _strayintr(SB); BYTE $0xB3
1014         CALL _strayintr(SB); BYTE $0xB4
1015         CALL _strayintr(SB); BYTE $0xB5
1016         CALL _strayintr(SB); BYTE $0xB6
1017         CALL _strayintr(SB); BYTE $0xB7
1018         CALL _strayintr(SB); BYTE $0xB8
1019         CALL _strayintr(SB); BYTE $0xB9
1020         CALL _strayintr(SB); BYTE $0xBA
1021         CALL _strayintr(SB); BYTE $0xBB
1022         CALL _strayintr(SB); BYTE $0xBC
1023         CALL _strayintr(SB); BYTE $0xBD
1024         CALL _strayintr(SB); BYTE $0xBE
1025         CALL _strayintr(SB); BYTE $0xBF
1026         CALL _strayintr(SB); BYTE $0xC0
1027         CALL _strayintr(SB); BYTE $0xC1
1028         CALL _strayintr(SB); BYTE $0xC2
1029         CALL _strayintr(SB); BYTE $0xC3
1030         CALL _strayintr(SB); BYTE $0xC4
1031         CALL _strayintr(SB); BYTE $0xC5
1032         CALL _strayintr(SB); BYTE $0xC6
1033         CALL _strayintr(SB); BYTE $0xC7
1034         CALL _strayintr(SB); BYTE $0xC8
1035         CALL _strayintr(SB); BYTE $0xC9
1036         CALL _strayintr(SB); BYTE $0xCA
1037         CALL _strayintr(SB); BYTE $0xCB
1038         CALL _strayintr(SB); BYTE $0xCC
1039         CALL _strayintr(SB); BYTE $0xCD
1040         CALL _strayintr(SB); BYTE $0xCE
1041         CALL _strayintr(SB); BYTE $0xCF
1042         CALL _strayintr(SB); BYTE $0xD0
1043         CALL _strayintr(SB); BYTE $0xD1
1044         CALL _strayintr(SB); BYTE $0xD2
1045         CALL _strayintr(SB); BYTE $0xD3
1046         CALL _strayintr(SB); BYTE $0xD4
1047         CALL _strayintr(SB); BYTE $0xD5
1048         CALL _strayintr(SB); BYTE $0xD6
1049         CALL _strayintr(SB); BYTE $0xD7
1050         CALL _strayintr(SB); BYTE $0xD8
1051         CALL _strayintr(SB); BYTE $0xD9
1052         CALL _strayintr(SB); BYTE $0xDA
1053         CALL _strayintr(SB); BYTE $0xDB
1054         CALL _strayintr(SB); BYTE $0xDC
1055         CALL _strayintr(SB); BYTE $0xDD
1056         CALL _strayintr(SB); BYTE $0xDE
1057         CALL _strayintr(SB); BYTE $0xDF
1058         CALL _strayintr(SB); BYTE $0xE0
1059         CALL _strayintr(SB); BYTE $0xE1
1060         CALL _strayintr(SB); BYTE $0xE2
1061         CALL _strayintr(SB); BYTE $0xE3
1062         CALL _strayintr(SB); BYTE $0xE4
1063         CALL _strayintr(SB); BYTE $0xE5
1064         CALL _strayintr(SB); BYTE $0xE6
1065         CALL _strayintr(SB); BYTE $0xE7
1066         CALL _strayintr(SB); BYTE $0xE8
1067         CALL _strayintr(SB); BYTE $0xE9
1068         CALL _strayintr(SB); BYTE $0xEA
1069         CALL _strayintr(SB); BYTE $0xEB
1070         CALL _strayintr(SB); BYTE $0xEC
1071         CALL _strayintr(SB); BYTE $0xED
1072         CALL _strayintr(SB); BYTE $0xEE
1073         CALL _strayintr(SB); BYTE $0xEF
1074         CALL _strayintr(SB); BYTE $0xF0
1075         CALL _strayintr(SB); BYTE $0xF1
1076         CALL _strayintr(SB); BYTE $0xF2
1077         CALL _strayintr(SB); BYTE $0xF3
1078         CALL _strayintr(SB); BYTE $0xF4
1079         CALL _strayintr(SB); BYTE $0xF5
1080         CALL _strayintr(SB); BYTE $0xF6
1081         CALL _strayintr(SB); BYTE $0xF7
1082         CALL _strayintr(SB); BYTE $0xF8
1083         CALL _strayintr(SB); BYTE $0xF9
1084         CALL _strayintr(SB); BYTE $0xFA
1085         CALL _strayintr(SB); BYTE $0xFB
1086         CALL _strayintr(SB); BYTE $0xFC
1087         CALL _strayintr(SB); BYTE $0xFD
1088         CALL _strayintr(SB); BYTE $0xFE
1089         CALL _strayintr(SB); BYTE $0xFF