#include "mem.h"
-#include "/sys/src/boot/pc/x16.h"
#undef DELAY
#define PADDR(a) ((a) & ~KZERO)
#define INVLPG BYTE $0x0F; BYTE $0x01; BYTE $0x39 /* INVLPG (%ecx) */
#define WBINVD BYTE $0x0F; BYTE $0x09
+#define VectorSYSCALL 0x40
+
/*
* Macros for calculating offsets within the page directory base
* and page tables. Note that these are assembler-specific hence
*/
TEXT _multibootheader(SB), $0
LONG $0x1BADB002 /* magic */
- LONG $0x00010003 /* flags */
- LONG $-(0x1BADB002 + 0x00010003) /* checksum */
+ LONG $0x00010007 /* flags */
+ LONG $-(0x1BADB002 + 0x00010007) /* checksum */
LONG $_multibootheader-KZERO(SB) /* header_addr */
LONG $_startKADDR-KZERO(SB) /* load_addr */
LONG $edata-KZERO(SB) /* load_end_addr */
LONG $end-KZERO(SB) /* bss_end_addr */
- LONG $_startKADDR-KZERO(SB) /* entry_addr */
+ LONG $_multibootentry-KZERO(SB) /* entry_addr */
LONG $0 /* mode_type */
LONG $0 /* width */
LONG $0 /* height */
- LONG $0 /* depth */
+ LONG $32 /* depth */
+
+/*
+ * the kernel expects the data segment to be page-aligned
+ * multiboot bootloaders put the data segment right behind text
+ */
+TEXT _multibootentry(SB), $0
+ MOVL $etext-KZERO(SB), SI
+ MOVL SI, DI
+ ADDL $0xfff, DI
+ ANDL $~0xfff, DI
+ MOVL $edata-KZERO(SB), CX
+ SUBL DI, CX
+ ADDL CX, SI
+ ADDL CX, DI
+ INCL CX /* one more for post decrement */
+ STD
+ REP; MOVSB
+ MOVL BX, multibootptr-KZERO(SB)
+ MOVL $_startPADDR-KZERO(SB), AX
+ JMP* AX
+
+/* multiboot structure pointer (physical address) */
+TEXT multibootptr(SB), $0
+ LONG $0
/*
* In protected mode with paging turned off and segment registers setup
CLI /* make sure interrupts are off */
/* set up the gdt so we have sane plan 9 style gdts. */
- MOVL $tgdtptr(SB), AX
- ANDL $~KZERO, AX
+ MOVL $tgdtptr-KZERO(SB), AX
MOVL (AX), GDTR
MOVW $1, AX
MOVW AX, MSW
WORD $(3*8)
LONG $tgdt-KZERO(SB)
-TEXT m0rgdtptr(SB), $0
- WORD $(NGDT*8-1)
- LONG $(CPU0GDT-KZERO)
-
-TEXT m0gdtptr(SB), $0
- WORD $(NGDT*8-1)
- LONG $CPU0GDT
-
-TEXT m0idtptr(SB), $0
- WORD $(256*8-1)
- LONG $IDTADDR
+TEXT vtgdtptr(SB), $0
+ WORD $(3*8)
+ LONG $tgdt(SB)
TEXT mode32bit(SB), $0
- /* At this point, the GDT setup is done. */
-
- MOVL $PADDR(CPU0PDB), DI /* clear 4 pages for the tables etc. */
+ MOVL $((CPU0END-CPU0PDB)>>2), CX
+ MOVL $PADDR(CPU0PDB), DI
XORL AX, AX
- MOVL $(4*BY2PG), CX
- SHRL $2, CX
CLD
REP; STOSL
+ MOVL $PADDR(CPU0PTE), DX
+ MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
+ ORL BX, DX
+
MOVL $PADDR(CPU0PDB), AX
ADDL $PDO(KZERO), AX /* page directory offset for KZERO */
- MOVL $PADDR(CPU0PTE), (AX) /* PTE's for KZERO */
- MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
- ORL BX, (AX)
- ADDL $4, AX
- MOVL $PADDR(CPU0PTE1), (AX) /* PTE's for KZERO+4MB */
- MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
- ORL BX, (AX)
+ MOVL DX, 0(AX) /* PTE's for KZERO */
+ ADDL $BY2PG, DX
+ MOVL DX, 4(AX) /* PTE's for KZERO+4MB */
+ ADDL $BY2PG, DX
+ MOVL DX, 8(AX) /* PTE's for KZERO+8MB */
+ ADDL $BY2PG, DX
+ MOVL DX, 12(AX) /* PTE's for KZERO+12MB */
MOVL $PADDR(CPU0PTE), AX /* first page of page table */
- MOVL $1024, CX /* 1024 pages in 4MB */
+ MOVL $end-KZERO(SB), CX
+
+ ADDL $(16*1024), CX /* qemu puts multiboot data after the kernel */
+
+ ADDL $(BY2XPG-1), CX
+ ANDL $~(BY2XPG-1), CX /* round to 4MB */
+ MOVL CX, MemMin-KZERO(SB) /* see memory.c */
+ SHRL $PGSHIFT, CX
+ MOVL BX, DX
_setpte:
- MOVL BX, (AX)
- ADDL $(1<<PGSHIFT), BX
+ MOVL DX, (AX)
+ ADDL $BY2PG, DX
ADDL $4, AX
LOOP _setpte
- MOVL $PADDR(CPU0PTE1), AX /* second page of page table */
- MOVL $1024, CX /* 1024 pages in 4MB */
-_setpte1:
- MOVL BX, (AX)
- ADDL $(1<<PGSHIFT), BX
- ADDL $4, AX
- LOOP _setpte1
-
MOVL $PADDR(CPU0PTE), AX
ADDL $PTO(MACHADDR), AX /* page table entry offset for MACHADDR */
- MOVL $PADDR(CPU0MACH), (AX) /* PTE for Mach */
- MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
- ORL BX, (AX)
+ ORL $PADDR(CPU0MACH), BX
+ MOVL BX, (AX) /* PTE for Mach */
/*
* Now ready to use the new map. Make sure the processor options are what is wanted.
* be initialised here.
*/
TEXT _startpg(SB), $0
+ MOVL $vtgdtptr(SB), AX
+ MOVL (AX), GDTR
+
MOVL $0, (PDO(0))(CX) /* undo double-map of KZERO at 0 */
MOVL CX, CR3 /* load and flush the mmu */
HLT
JMP _idle
-/*
- * Save registers.
- */
-TEXT saveregs(SB), $0
- /* appease 8l */
- SUBL $32, SP
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
- POPL AX
-
- PUSHL AX
- PUSHL BX
- PUSHL CX
- PUSHL DX
- PUSHL BP
- PUSHL DI
- PUSHL SI
- PUSHFL
-
- XCHGL 32(SP), AX /* swap return PC and saved flags */
- XCHGL 0(SP), AX
- XCHGL 32(SP), AX
- RET
-
-TEXT restoreregs(SB), $0
- /* appease 8l */
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- PUSHL AX
- ADDL $32, SP
-
- XCHGL 32(SP), AX /* swap return PC and saved flags */
- XCHGL 0(SP), AX
- XCHGL 32(SP), AX
- POPFL
- POPL SI
- POPL DI
- POPL BP
- POPL DX
- POPL CX
- POPL BX
- POPL AX
+TEXT load_fs(SB), $0
+ MOVW fs+0(FP), AX
+ MOVW AX, FS
RET
-/*
- * Assumed to be in protected mode at time of call.
- * Switch to real mode, execute an interrupt, and
- * then switch back to protected mode.
- *
- * Assumes:
- *
- * - no device interrupts are going to come in
- * - 0-16MB is identity mapped in page tables
- * - realmode() has copied us down from 0x100000 to 0x8000
- * - can use code segment 0x0800 in real mode
- * to get at l.s code
- * - l.s code is less than 1 page
- */
-#define RELOC (RMCODE-KTZERO)
-
-TEXT realmodeidtptr(SB), $0
- WORD $(4*256-1)
- LONG $0
-
-TEXT realmode0(SB), $0
- CALL saveregs(SB)
-
- /* switch to low code address */
- LEAL physcode-KZERO(SB), AX
- JMP *AX
-
-TEXT physcode(SB), $0
-
- /* switch to low stack */
- MOVL SP, AX
- MOVL $0x7C00, SP
- PUSHL AX
-
- /* change gdt to physical pointer */
- MOVL m0rgdtptr-KZERO(SB), GDTR
-
- /* load IDT with real-mode version*/
- MOVL realmodeidtptr-KZERO(SB), IDTR
-
- /* edit INT $0x00 instruction below */
- MOVL $(RMUADDR-KZERO+48), AX /* &rmu.trap */
- MOVL (AX), AX
- MOVB AX, realmodeintrinst+(-KZERO+1+RELOC)(SB)
-
- /* disable paging */
- MOVL CR0, AX
- ANDL $0x7FFFFFFF, AX
- MOVL AX, CR0
- /* JMP .+2 to clear prefetch queue*/
- BYTE $0xEB; BYTE $0x00
-
- /* jump to 16-bit code segment */
-/* JMPFAR SELECTOR(KESEG16, SELGDT, 0):$again16bit(SB) /**/
- BYTE $0xEA
- LONG $again16bit-KZERO(SB)
- WORD $SELECTOR(KESEG16, SELGDT, 0)
-
-TEXT again16bit(SB), $0
- /*
- * Now in 16-bit compatibility mode.
- * These are 32-bit instructions being interpreted
- * as 16-bit instructions. I'm being lazy and
- * not using the macros because I know when
- * the 16- and 32-bit instructions look the same
- * or close enough.
- */
-
- /* disable protected mode and jump to real mode cs */
- OPSIZE; MOVL CR0, AX
- OPSIZE; XORL BX, BX
- OPSIZE; INCL BX
- OPSIZE; XORL BX, AX
- OPSIZE; MOVL AX, CR0
-
- /* JMPFAR 0x0800:now16real */
- BYTE $0xEA
- WORD $now16real-KZERO(SB)
- WORD $0x0800
-
-TEXT now16real(SB), $0
- /* copy the registers for the bios call */
- LWI(0x0000, rAX)
- MOVW AX,SS
- LWI(RMUADDR, rBP)
-
- /* offsets are in Ureg */
- LXW(44, xBP, rAX)
- MOVW AX, DS
- LXW(40, xBP, rAX)
- MOVW AX, ES
-
- OPSIZE; LXW(0, xBP, rDI)
- OPSIZE; LXW(4, xBP, rSI)
- OPSIZE; LXW(16, xBP, rBX)
- OPSIZE; LXW(20, xBP, rDX)
- OPSIZE; LXW(24, xBP, rCX)
- OPSIZE; LXW(28, xBP, rAX)
-
- CLC
-
-TEXT realmodeintrinst(SB), $0
- INT $0x00
-
- /* save the registers after the call */
-
- LWI(0x7bfc, rSP)
- OPSIZE; PUSHFL
- OPSIZE; PUSHL AX
-
- LWI(0, rAX)
- MOVW AX,SS
- LWI(RMUADDR, rBP)
-
- OPSIZE; SXW(rDI, 0, xBP)
- OPSIZE; SXW(rSI, 4, xBP)
- OPSIZE; SXW(rBX, 16, xBP)
- OPSIZE; SXW(rDX, 20, xBP)
- OPSIZE; SXW(rCX, 24, xBP)
- OPSIZE; POPL AX
- OPSIZE; SXW(rAX, 28, xBP)
-
- MOVW DS, AX
- OPSIZE; SXW(rAX, 44, xBP)
- MOVW ES, AX
- OPSIZE; SXW(rAX, 40, xBP)
-
- OPSIZE; POPL AX
- OPSIZE; SXW(rAX, 64, xBP) /* flags */
-
- /* re-enter protected mode and jump to 32-bit code */
- OPSIZE; MOVL $1, AX
- OPSIZE; MOVL AX, CR0
-
-/* JMPFAR SELECTOR(KESEG, SELGDT, 0):$again32bit(SB) /**/
- OPSIZE
- BYTE $0xEA
- LONG $again32bit-KZERO(SB)
- WORD $SELECTOR(KESEG, SELGDT, 0)
-
-TEXT again32bit(SB), $0
- MOVW $SELECTOR(KDSEG, SELGDT, 0),AX
- MOVW AX,DS
- MOVW AX,SS
- MOVW AX,ES
- MOVW AX,FS
- MOVW AX,GS
-
- /* enable paging and jump to kzero-address code */
- MOVL CR0, AX
- ORL $0x80010000, AX /* PG|WP */
- MOVL AX, CR0
- LEAL again32kzero(SB), AX
- JMP* AX
-
-TEXT again32kzero(SB), $0
- /* breathe a sigh of relief - back in 32-bit protected mode */
-
- /* switch to old stack */
- PUSHL AX /* match popl below for 8l */
- MOVL $0x7BFC, SP
- POPL SP
-
- /* restore idt */
- MOVL m0idtptr(SB),IDTR
-
- /* restore gdt */
- MOVL m0gdtptr(SB), GDTR
-
- CALL restoreregs(SB)
+TEXT load_gs(SB), $0
+ MOVW gs+0(FP), AX
+ MOVW AX, GS
RET
/*
MOVL (AX), GDTR
RET
+TEXT lldt(SB), $0 /* LDTR - local descriptor table */
+ MOVL sel+0(FP), AX
+ BYTE $0x0F; BYTE $0x00; BYTE $0xD0 /* LLDT AX */
+ RET
+
TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */
MOVL idtptr+0(FP), AX
MOVL (AX), IDTR
MOVL CR2, AX
RET
+TEXT putcr2(SB), $0
+ MOVL cr2+0(FP), AX
+ MOVL AX, CR2
+ RET
+
TEXT getcr3(SB), $0 /* CR3 - page directory base */
MOVL CR3, AX
RET
RET
TEXT rdmsr(SB), $0 /* model-specific register */
+ MOVL $0, BP
MOVL index+0(FP), CX
+TEXT _rdmsrinst(SB), $0
RDMSR
MOVL vlong+4(FP), CX /* &vlong */
MOVL AX, 0(CX) /* lo */
MOVL DX, 4(CX) /* hi */
+ MOVL BP, AX /* BP set to -1 if traped */
RET
TEXT wrmsr(SB), $0
+ MOVL $0, BP
MOVL index+0(FP), CX
MOVL lo+4(FP), AX
MOVL hi+8(FP), DX
+TEXT _wrmsrinst(SB), $0
WRMSR
+ MOVL BP, AX /* BP set to -1 if traped */
+ RET
+
+/* fault-proof memcpy */
+TEXT peek(SB), $0
+ MOVL src+0(FP), SI
+ MOVL dst+4(FP), DI
+ MOVL cnt+8(FP), CX
+ CLD
+TEXT _peekinst(SB), $0
+ REP; MOVSB
+ MOVL CX, AX
RET
/*
* a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be
* toggled then it's an older 486 of some kind.
*
- * cpuid(fun, regs[4]);
+ * cpuid(fn, sublvl, regs[4]);
*/
TEXT cpuid(SB), $0
MOVL $0x240000, AX
TESTL $0x200000, AX /* Id */
JZ _cpu486 /* can't toggle this bit on some 486 */
MOVL fn+0(FP), AX
+ MOVL sublvl+4(FP), CX
CPUID
JMP _cpuid
_cpu486:
XORL CX, CX
XORL DX, DX
_cpuid:
- MOVL regs+4(FP), BP
+ MOVL regs+8(FP), BP
MOVL AX, 0(BP)
MOVL BX, 4(BP)
MOVL CX, 8(BP)
* FNxxx variations) so WAIT instructions must be explicitly placed in the
* code as necessary.
*/
-#define FPOFF(l) ;\
- MOVL CR0, AX ;\
- ANDL $0xC, AX /* EM, TS */ ;\
- CMPL AX, $0x8 ;\
- JEQ l ;\
- WAIT ;\
-l: ;\
+#define FPOFF ;\
MOVL CR0, AX ;\
- ANDL $~0x4, AX /* EM=0 */ ;\
ORL $0x28, AX /* NE=1, TS=1 */ ;\
MOVL AX, CR0
MOVL CR0, AX ;\
ANDL $~0xC, AX /* EM=0, TS=0 */ ;\
MOVL AX, CR0
-
+
TEXT fpoff(SB), $0 /* disable */
- FPOFF(l1)
+ FPOFF
RET
TEXT fpinit(SB), $0 /* enable and init */
WAIT
RET
-TEXT fpsave(SB), $0 /* save state and disable */
+TEXT fpx87save0(SB), $0 /* save state and disable */
MOVL p+0(FP), AX
FSAVE 0(AX) /* no WAIT */
- FPOFF(l2)
+ FPOFF
RET
-TEXT fprestore(SB), $0 /* enable and restore state */
+TEXT fpx87restore0(SB), $0 /* enable and restore state */
FPON
MOVL p+0(FP), AX
FRSTOR 0(AX)
WAIT
RET
-TEXT fpstatus(SB), $0 /* get floating point status */
- FSTSW AX
+TEXT fpclear(SB), $0 /* clear pending exceptions */
+ FPON
+ FCLEX /* no WAIT */
+ FPOFF
RET
-TEXT fpenv(SB), $0 /* save state without waiting */
+TEXT fpssesave(SB), $0 /* save state and disable */
MOVL p+0(FP), AX
- FSTENV 0(AX)
+ FXSAVE 0(AX) /* no WAIT */
+ FPOFF
RET
-TEXT fpclear(SB), $0 /* clear pending exceptions */
+TEXT fpsserestore(SB), $0 /* enable and restore state */
FPON
- FCLEX /* no WAIT */
- FPOFF(l3)
+ MOVL p+0(FP), AX
+ FXRSTOR 0(AX)
+ WAIT
+ RET
+
+TEXT ldmxcsr(SB), $0 /* Load MXCSR */
+ LDMXCSR mxcsr+0(FP)
RET
/*
* Test-And-Set
*/
TEXT tas(SB), $0
+TEXT _tas(SB), $0
MOVL $0xDEADDEAD, AX
MOVL lock+0(FP), BX
XCHGL AX, (BX) /* lock->key */
RET
-TEXT _xinc(SB), $0 /* void _xinc(long*); */
- MOVL l+0(FP), AX
- LOCK; INCL 0(AX)
- RET
-
-TEXT _xdec(SB), $0 /* long _xdec(long*); */
- MOVL l+0(FP), BX
- XORL AX, AX
- LOCK; DECL 0(BX)
- JLT _xdeclt
- JGT _xdecgt
- RET
-_xdecgt:
- INCL AX
- RET
-_xdeclt:
- DECL AX
- RET
-
TEXT mb386(SB), $0
POPL AX /* return PC */
PUSHFL
HLT
RET
+TEXT mwait(SB), $0
+ MOVL addr+0(FP), AX
+ MOVL (AX), CX
+ ORL CX, CX
+ JNZ _mwaitdone
+ XORL DX, DX
+ BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */
+ MOVL (AX), CX
+ ORL CX, CX
+ JNZ _mwaitdone
+ XORL AX, AX
+ BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */
+_mwaitdone:
+ RET
+
+#define RDRANDAX BYTE $0x0f; BYTE $0xc7; BYTE $0xf0
+
+TEXT rdrand32(SB), $-4
+_rloop32:
+ RDRANDAX
+ JCC _rloop32
+ RET
+
+TEXT rdrandbuf(SB), $0
+ MOVL buf+0(FP), DI
+ MOVL cnt+4(FP), CX
+ CLD
+ MOVL CX, DX
+ SHRL $2, CX
+ CMPL CX, $0
+ JE _rndleft
+_rnddwords:
+ CALL rdrand32(SB)
+ STOSL
+ LOOP _rnddwords
+_rndleft:
+ MOVL DX, CX
+ ANDL $3, CX
+ CMPL CX, $0
+ JE _rnddone
+_rndbytes:
+ CALL rdrand32(SB)
+ STOSB
+ LOOP _rndbytes
+_rnddone:
+ RET
+
+/* debug register access */
+
+TEXT putdr(SB), $0
+ MOVL p+0(FP), SI
+ MOVL 28(SI), AX
+ MOVL AX, DR7
+_putdr01236:
+ MOVL 0(SI), AX
+ MOVL AX, DR0
+ MOVL 4(SI), AX
+ MOVL AX, DR1
+ MOVL 8(SI), AX
+ MOVL AX, DR2
+ MOVL 12(SI), AX
+ MOVL AX, DR3
+ MOVL 24(SI), AX
+ MOVL AX, DR6
+ RET
+
+TEXT putdr01236(SB), $0
+ MOVL p+0(FP), SI
+ JMP _putdr01236
+
+TEXT getdr6(SB), $0
+ MOVL DR6, AX
+ RET
+
+TEXT putdr6(SB), $0
+ MOVL p+0(FP), AX
+ MOVL AX, DR6
+ RET
+
+TEXT putdr7(SB), $0
+ MOVL p+0(FP), AX
+ MOVL AX, DR7
+ RET
+
+/* VMX instructions */
+TEXT vmxon(SB), $0
+ /* VMXON 4(SP) */
+ BYTE $0xf3; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
+ JMP _vmout
+
+TEXT vmxoff(SB), $0
+ BYTE $0x0f; BYTE $0x01; BYTE $0xc4
+ JMP _vmout
+
+TEXT vmclear(SB), $0
+ /* VMCLEAR 4(SP) */
+ BYTE $0x66; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
+ JMP _vmout
+
+TEXT vmlaunch(SB), $0
+ MOVL $0x6C14, DI
+ MOVL SP, DX
+ BYTE $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
+ JBE _vmout
+ MOVL $0x6C16, DI
+ MOVL $vmrestore(SB), DX
+ BYTE $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
+ JBE _vmout
+
+ MOVL resume+4(FP), AX
+ TESTL AX, AX
+ MOVL ureg+0(FP), DI
+ MOVL 4(DI), SI
+ MOVL 8(DI), BP
+ MOVL 16(DI), BX
+ MOVL 20(DI), DX
+ MOVL 24(DI), CX
+ MOVL 28(DI), AX
+ MOVL 0(DI), DI
+ JNE _vmresume
+ BYTE $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */
+ JMP _vmout
+_vmresume:
+ BYTE $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */
+ JMP _vmout
+
+TEXT vmrestore(SB), $0
+ PUSHL DI
+ MOVL ureg+0(FP), DI
+ POPL 0(DI)
+ MOVL SI, 4(DI)
+ MOVL BP, 8(DI)
+ MOVL BX, 16(DI)
+ MOVL DX, 20(DI)
+ MOVL CX, 24(DI)
+ MOVL AX, 28(DI)
+ XORL AX, AX
+ RET
+
+TEXT vmptrld(SB), $0
+ /* VMPTRLD 4(SP) */
+ BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x04
+ JMP _vmout
+
+TEXT vmwrite(SB), $0
+ MOVL addr+0(FP),DI
+ MOVL val+4(FP),DX
+ /* VMWRITE DX, DI */
+ BYTE $0x0f; BYTE $0x79; BYTE $0xfa
+ JMP _vmout
+
+TEXT vmread(SB), $0
+ MOVL addr+0(FP),DI
+ MOVL valp+4(FP),SI
+ /* VMREAD (SI), DI */
+ BYTE $0x0f; BYTE $0x78; BYTE $0x3e
+ JMP _vmout
+
+TEXT invept(SB), $0
+ MOVL type+0(FP), AX
+ /* INVEPT AX, 8(SP) */
+ BYTE $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x80; BYTE $0x44; BYTE $0x24; BYTE $0x08
+ JMP _vmout
+
+TEXT invvpid(SB), $0
+ MOVL type+0(FP), AX
+ /* INVVPID AX, 8(SP) */
+ BYTE $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x81; BYTE $0x44; BYTE $0x24; BYTE $0x08
+ JMP _vmout
+
+_vmout:
+ JC _vmout1
+ JZ _vmout2
+ XORL AX, AX
+ RET
+_vmout1:
+ MOVL $-1, AX
+ RET
+_vmout2:
+ MOVL $-2, AX
+ RET
+
+/*
+ * Used to get to the first process:
+ * set up an interrupt return frame and IRET to user level.
+ */
+TEXT touser(SB), $0
+ PUSHL $(UDSEL) /* old ss */
+ MOVL sp+0(FP), AX /* old sp */
+ PUSHL AX
+ MOVL $0x200, AX /* interrupt enable flag */
+ PUSHL AX /* old flags */
+ PUSHL $(UESEL) /* old cs */
+ PUSHL $(UTZERO+32) /* old pc */
+ MOVL $(UDSEL), AX
+ MOVW AX, DS
+ MOVW AX, ES
+ MOVW AX, GS
+ MOVW AX, FS
+ IRETL
+
/*
* Interrupt/exception handling.
* Each entry in the vector table calls either _strayintr or _strayintrx depending
TEXT forkret(SB), $0
POPL AX
POPAL
+TEXT _forkretpopgs(SB), $0
POPL GS
+TEXT _forkretpopfs(SB), $0
POPL FS
+TEXT _forkretpopes(SB), $0
POPL ES
+TEXT _forkretpopds(SB), $0
POPL DS
ADDL $8, SP /* pop error code and trap type */
+TEXT _forkretiret(SB), $0
IRETL
+/*
+ * This is merely _strayintr optimised to vector
+ * to syscall() without going through trap().
+ */
+TEXT _syscallintr(SB), $0
+ PUSHL $VectorSYSCALL /* trap type */
+
+ PUSHL DS
+ PUSHL ES
+ PUSHL FS
+ PUSHL GS
+ PUSHAL
+ MOVL $(KDSEL), AX
+ MOVW AX, DS
+ MOVW AX, ES
+
+ MOVL $syscall(SB), AX
+
+ PUSHL SP /* Ureg* argument to syscall */
+ PUSHL $forkret(SB) /* return pc */
+ JMP *AX
+
TEXT vectortable(SB), $0
CALL _strayintr(SB); BYTE $0x00 /* divide error */
CALL _strayintr(SB); BYTE $0x01 /* debug exception */
CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
CALL _strayintr(SB); BYTE $0x12 /* machine check */
- CALL _strayintr(SB); BYTE $0x13
+ CALL _strayintr(SB); BYTE $0x13 /* simd error */
CALL _strayintr(SB); BYTE $0x14
CALL _strayintr(SB); BYTE $0x15
CALL _strayintr(SB); BYTE $0x16