plan9fox/sys/src/9/pc/l.s

1200 lines
27 KiB
ArmAsm
Raw Normal View History

#include "mem.h"
#undef DELAY
#define PADDR(a) ((a) & ~KZERO)
#define KADDR(a) (KZERO|(a))
/*
* Some machine instructions not handled by 8[al].
*/
#define OP16 BYTE $0x66
#define DELAY BYTE $0xEB; BYTE $0x00 /* JMP .+2 */
#define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */
#define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */
#define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */
#define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */
#define HLT BYTE $0xF4
#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
* the '<<2'.
*/
#define PDO(a) (((((a))>>22) & 0x03FF)<<2)
#define PTO(a) (((((a))>>12) & 0x03FF)<<2)
/*
* For backwards compatiblity with 9load - should go away when 9load is changed
* 9load currently sets up the mmu, however the first 16MB of memory is identity
* mapped, so behave as if the mmu was not setup
*/
TEXT _startKADDR(SB), $0
MOVL $_startPADDR(SB), AX
ANDL $~KZERO, AX
JMP* AX
/*
* Must be 4-byte aligned.
*/
TEXT _multibootheader(SB), $0
LONG $0x1BADB002 /* magic */
LONG $0x00010003 /* flags */
LONG $-(0x1BADB002 + 0x00010003) /* 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 */
2012-07-13 16:09:42 +00:00
LONG $_multibootentry-KZERO(SB) /* entry_addr */
LONG $0 /* mode_type */
LONG $0 /* width */
LONG $0 /* height */
LONG $0 /* depth */
2012-07-13 16:52:39 +00:00
/*
* the kernel expects the data segment to be page-aligned
* multiboot bootloaders put the data segment right behind text
*/
2012-07-13 16:09:42 +00:00
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 */
2012-07-13 16:09:42 +00:00
STD
REP; MOVSB
2012-07-13 16:52:39 +00:00
ADDL $KZERO, BX
MOVL BX, multiboot-KZERO(SB)
2012-07-13 16:09:42 +00:00
MOVL $_startPADDR(SB), AX
ANDL $~KZERO, AX
JMP* AX
2012-07-13 16:52:39 +00:00
/* multiboot structure pointer */
TEXT multiboot(SB), $0
LONG $0
/*
* In protected mode with paging turned off and segment registers setup
* to linear map all memory. Entered via a jump to PADDR(entry),
* the physical address of the virtual kernel entry point of KADDR(entry).
* Make the basic page tables for processor 0. Six pages are needed for
* the basic set:
* a page directory;
* page tables for mapping the first 8MB of physical memory to KZERO;
* a page for the GDT;
* virtual and physical pages for mapping the Mach structure.
* The remaining PTEs will be allocated later when memory is sized.
* An identity mmu map is also needed for the switch to virtual mode.
* This identity mapping is removed once the MMU is going and the JMP has
* been made to virtual memory.
*/
TEXT _startPADDR(SB), $0
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 (AX), GDTR
MOVW $1, AX
MOVW AX, MSW
/* clear prefetch queue (weird code to avoid optimizations) */
DELAY
/* set segs to something sane (avoid traps later) */
MOVW $(1<<3), AX
MOVW AX, DS
MOVW AX, SS
MOVW AX, ES
MOVW AX, FS
MOVW AX, GS
/* JMP $(2<<3):$mode32bit(SB) /**/
BYTE $0xEA
LONG $mode32bit-KZERO(SB)
WORD $(2<<3)
/*
* gdt to get us to 32-bit/segmented/unpaged mode
*/
TEXT tgdt(SB), $0
/* null descriptor */
LONG $0
LONG $0
/* data segment descriptor for 4 gigabytes (PL 0) */
LONG $(0xFFFF)
LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
/* exec segment descriptor for 4 gigabytes (PL 0) */
LONG $(0xFFFF)
LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
/*
* pointer to initial gdt
* Note the -KZERO which puts the physical address in the gdtptr.
* that's needed as we start executing in physical addresses.
*/
TEXT tgdtptr(SB), $0
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 mode32bit(SB), $0
/* At this point, the GDT setup is done. */
MOVL $((CPU0END-CPU0PDB)>>2), CX
MOVL $PADDR(CPU0PDB), DI
XORL AX, AX
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 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 $end-KZERO(SB), CX
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 DX, (AX)
ADDL $BY2PG, DX
ADDL $4, AX
LOOP _setpte
MOVL $PADDR(CPU0PTE), AX
ADDL $PTO(MACHADDR), AX /* page table entry offset for MACHADDR */
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.
* It is necessary on some processors to immediately follow mode switching with a JMP instruction
* to clear the prefetch queues.
*/
MOVL $PADDR(CPU0PDB), CX /* load address of page directory */
MOVL (PDO(KZERO))(CX), DX /* double-map KZERO at 0 */
MOVL DX, (PDO(0))(CX)
MOVL CX, CR3
DELAY /* JMP .+2 */
MOVL CR0, DX
ORL $0x80010000, DX /* PG|WP */
ANDL $~0x6000000A, DX /* ~(CD|NW|TS|MP) */
MOVL $_startpg(SB), AX /* this is a virtual address */
MOVL DX, CR0 /* turn on paging */
JMP* AX /* jump to the virtual nirvana */
/*
* Basic machine environment set, can clear BSS and create a stack.
* The stack starts at the top of the page containing the Mach structure.
* The x86 architecture forces the use of the same virtual address for
* each processor's Mach structure, so the global Mach pointer 'm' can
* be initialised here.
*/
TEXT _startpg(SB), $0
MOVL $0, (PDO(0))(CX) /* undo double-map of KZERO at 0 */
MOVL CX, CR3 /* load and flush the mmu */
_clearbss:
MOVL $edata(SB), DI
XORL AX, AX
MOVL $end(SB), CX
SUBL DI, CX /* end-edata bytes */
SHRL $2, CX /* end-edata doublewords */
CLD
REP; STOSL /* clear BSS */
MOVL $MACHADDR, SP
MOVL SP, m(SB) /* initialise global Mach pointer */
MOVL $0, 0(SP) /* initialise m->machno */
ADDL $(MACHSIZE-4), SP /* initialise stack */
/*
* Need to do one final thing to ensure a clean machine environment,
* clear the EFLAGS register, which can only be done once there is a stack.
*/
MOVL $0, AX
PUSHL AX
POPFL
CALL main(SB)
/*
* Park a processor. Should never fall through a return from main to here,
* should only be called by application processors when shutting down.
*/
TEXT idle(SB), $0
_idle:
STI
HLT
JMP _idle
2011-07-12 13:46:22 +00:00
TEXT load_fs(SB), $0
MOVW fs+0(FP), AX
MOVW AX, FS
RET
TEXT load_gs(SB), $0
MOVW gs+0(FP), AX
MOVW AX, GS
RET
/*
* BIOS32.
*/
TEXT bios32call(SB), $0
MOVL ci+0(FP), BP
MOVL 0(BP), AX
MOVL 4(BP), BX
MOVL 8(BP), CX
MOVL 12(BP), DX
MOVL 16(BP), SI
MOVL 20(BP), DI
PUSHL BP
MOVL 12(SP), BP /* ptr */
BYTE $0xFF; BYTE $0x5D; BYTE $0x00 /* CALL FAR 0(BP) */
POPL BP
MOVL DI, 20(BP)
MOVL SI, 16(BP)
MOVL DX, 12(BP)
MOVL CX, 8(BP)
MOVL BX, 4(BP)
MOVL AX, 0(BP)
XORL AX, AX
JCC _bios32xxret
INCL AX
_bios32xxret:
RET
/*
* Port I/O.
* in[bsl] input a byte|short|long
* ins[bsl] input a string of bytes|shorts|longs
* out[bsl] output a byte|short|long
* outs[bsl] output a string of bytes|shorts|longs
*/
TEXT inb(SB), $0
MOVL port+0(FP), DX
XORL AX, AX
INB
RET
TEXT insb(SB), $0
MOVL port+0(FP), DX
MOVL address+4(FP), DI
MOVL count+8(FP), CX
CLD
REP; INSB
RET
TEXT ins(SB), $0
MOVL port+0(FP), DX
XORL AX, AX
OP16; INL
RET
TEXT inss(SB), $0
MOVL port+0(FP), DX
MOVL address+4(FP), DI
MOVL count+8(FP), CX
CLD
REP; OP16; INSL
RET
TEXT inl(SB), $0
MOVL port+0(FP), DX
INL
RET
TEXT insl(SB), $0
MOVL port+0(FP), DX
MOVL address+4(FP), DI
MOVL count+8(FP), CX
CLD
REP; INSL
RET
TEXT outb(SB), $0
MOVL port+0(FP), DX
MOVL byte+4(FP), AX
OUTB
RET
TEXT outsb(SB), $0
MOVL port+0(FP), DX
MOVL address+4(FP), SI
MOVL count+8(FP), CX
CLD
REP; OUTSB
RET
TEXT outs(SB), $0
MOVL port+0(FP), DX
MOVL short+4(FP), AX
OP16; OUTL
RET
TEXT outss(SB), $0
MOVL port+0(FP), DX
MOVL address+4(FP), SI
MOVL count+8(FP), CX
CLD
REP; OP16; OUTSL
RET
TEXT outl(SB), $0
MOVL port+0(FP), DX
MOVL long+4(FP), AX
OUTL
RET
TEXT outsl(SB), $0
MOVL port+0(FP), DX
MOVL address+4(FP), SI
MOVL count+8(FP), CX
CLD
REP; OUTSL
RET
/*
* Read/write various system registers.
* CR4 and the 'model specific registers' should only be read/written
* after it has been determined the processor supports them
*/
TEXT lgdt(SB), $0 /* GDTR - global descriptor table */
MOVL gdtptr+0(FP), AX
MOVL (AX), GDTR
RET
2011-07-12 13:46:22 +00:00
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
RET
TEXT ltr(SB), $0 /* TR - task register */
MOVL tptr+0(FP), AX
MOVW AX, TASK
RET
TEXT getcr0(SB), $0 /* CR0 - processor control */
MOVL CR0, AX
RET
TEXT getcr2(SB), $0 /* CR2 - page fault linear address */
MOVL CR2, AX
RET
TEXT getcr3(SB), $0 /* CR3 - page directory base */
MOVL CR3, AX
RET
TEXT putcr0(SB), $0
MOVL cr0+0(FP), AX
MOVL AX, CR0
RET
TEXT putcr3(SB), $0
MOVL cr3+0(FP), AX
MOVL AX, CR3
RET
TEXT getcr4(SB), $0 /* CR4 - extensions */
MOVL CR4, AX
RET
TEXT putcr4(SB), $0
MOVL cr4+0(FP), AX
MOVL AX, CR4
RET
TEXT invlpg(SB), $0
/* 486+ only */
MOVL va+0(FP), CX
INVLPG
RET
TEXT wbinvd(SB), $0
WBINVD
RET
TEXT _cycles(SB), $0 /* time stamp counter */
RDTSC
MOVL vlong+0(FP), CX /* &vlong */
MOVL AX, 0(CX) /* lo */
MOVL DX, 4(CX) /* hi */
RET
/*
* stub for:
* time stamp counter; low-order 32 bits of 64-bit cycle counter
* Runs at fasthz/4 cycles per second (m->clkin>>3)
*/
TEXT lcycles(SB),1,$0
RDTSC
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
/*
* Try to determine the CPU type which requires fiddling with EFLAGS.
* If the Id bit can be toggled then the CPUID instruction can be used
* to determine CPU identity and features. First have to check if it's
* 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]);
*/
TEXT cpuid(SB), $0
MOVL $0x240000, AX
PUSHL AX
POPFL /* set Id|Ac */
PUSHFL
POPL BX /* retrieve value */
MOVL $0, AX
PUSHL AX
POPFL /* clear Id|Ac, EFLAGS initialised */
PUSHFL
POPL AX /* retrieve value */
XORL BX, AX
TESTL $0x040000, AX /* Ac */
JZ _cpu386 /* can't set this bit on 386 */
TESTL $0x200000, AX /* Id */
JZ _cpu486 /* can't toggle this bit on some 486 */
MOVL fn+0(FP), AX
CPUID
JMP _cpuid
_cpu486:
MOVL $0x400, AX
JMP _maybezapax
_cpu386:
MOVL $0x300, AX
_maybezapax:
CMPL fn+0(FP), $1
JE _zaprest
XORL AX, AX
_zaprest:
XORL BX, BX
XORL CX, CX
XORL DX, DX
_cpuid:
MOVL regs+4(FP), BP
MOVL AX, 0(BP)
MOVL BX, 4(BP)
MOVL CX, 8(BP)
MOVL DX, 12(BP)
RET
/*
* Basic timing loop to determine CPU frequency.
*/
TEXT aamloop(SB), $0
MOVL count+0(FP), CX
_aamloop:
AAM
LOOP _aamloop
RET
/*
* Floating point.
* Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW
* instructions do NOT have the WAIT prefix byte (i.e. they act like their
* FNxxx variations) so WAIT instructions must be explicitly placed in the
* code as necessary.
*/
#define FPOFF ;\
MOVL CR0, AX ;\
ORL $0x28, AX /* NE=1, TS=1 */ ;\
MOVL AX, CR0
#define FPON ;\
MOVL CR0, AX ;\
ANDL $~0xC, AX /* EM=0, TS=0 */ ;\
MOVL AX, CR0
TEXT fpoff(SB), $0 /* disable */
FPOFF
RET
TEXT fpinit(SB), $0 /* enable and init */
FPON
FINIT
WAIT
/* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
/* note that low 6 bits are masks, not enables, on this chip */
PUSHW $0x0232
FLDCW 0(SP)
POPW AX
WAIT
RET
TEXT fpx87save0(SB), $0 /* save state and disable */
MOVL p+0(FP), AX
FSAVE 0(AX) /* no WAIT */
FPOFF
RET
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
RET
TEXT fpenv(SB), $0 /* save state without waiting */
MOVL p+0(FP), AX
FSTENV 0(AX)
RET
TEXT fpclear(SB), $0 /* clear pending exceptions */
FPON
FCLEX /* no WAIT */
FPOFF
RET
2013-05-22 18:17:05 +00:00
TEXT fpssesave0(SB), $0 /* save state and disable */
MOVL p+0(FP), AX
FXSAVE 0(AX) /* no WAIT */
FPOFF
2013-05-22 18:17:05 +00:00
RET
TEXT fpsserestore0(SB), $0 /* enable and restore state */
FPON
MOVL p+0(FP), AX
FXRSTOR 0(AX)
WAIT
RET
2014-05-11 03:59:10 +00:00
TEXT ldmxcsr(SB), $0 /* Load MXCSR */
LDMXCSR mxcsr+0(FP)
RET
/*
*/
TEXT splhi(SB), $0
shi:
PUSHFL
POPL AX
TESTL $0x200, AX
JZ alreadyhi
MOVL $(MACHADDR+0x04), CX /* save PC in m->splpc */
MOVL (SP), BX
MOVL BX, (CX)
alreadyhi:
CLI
RET
TEXT spllo(SB), $0
slo:
PUSHFL
POPL AX
TESTL $0x200, AX
JNZ alreadylo
MOVL $(MACHADDR+0x04), CX /* clear m->splpc */
MOVL $0, (CX)
alreadylo:
STI
RET
TEXT splx(SB), $0
MOVL s+0(FP), AX
TESTL $0x200, AX
JNZ slo
JMP shi
TEXT spldone(SB), $0
RET
TEXT islo(SB), $0
PUSHFL
POPL AX
ANDL $0x200, AX /* interrupt enable flag */
RET
/*
* Test-And-Set
*/
TEXT tas(SB), $0
MOVL $0xDEADDEAD, AX
MOVL lock+0(FP), BX
XCHGL AX, (BX) /* lock->key */
RET
TEXT mb386(SB), $0
POPL AX /* return PC */
PUSHFL
PUSHL CS
PUSHL AX
IRETL
TEXT mb586(SB), $0
XORL AX, AX
CPUID
RET
TEXT sfence(SB), $0
BYTE $0x0f
BYTE $0xae
BYTE $0xf8
RET
TEXT lfence(SB), $0
BYTE $0x0f
BYTE $0xae
BYTE $0xe8
RET
TEXT mfence(SB), $0
BYTE $0x0f
BYTE $0xae
BYTE $0xf0
RET
TEXT xchgw(SB), $0
MOVL v+4(FP), AX
MOVL p+0(FP), BX
XCHGW AX, (BX)
RET
TEXT cmpswap486(SB), $0
MOVL addr+0(FP), BX
MOVL old+4(FP), AX
MOVL new+8(FP), CX
LOCK
BYTE $0x0F; BYTE $0xB1; BYTE $0x0B /* CMPXCHGL CX, (BX) */
JNZ didnt
MOVL $1, AX
RET
didnt:
XORL AX,AX
RET
TEXT mul64fract(SB), $0
/*
* Multiply two 64-bit number s and keep the middle 64 bits from the 128-bit result
* See ../port/tod.c for motivation.
*/
MOVL r+0(FP), CX
XORL BX, BX /* BX = 0 */
MOVL a+8(FP), AX
MULL b+16(FP) /* a1*b1 */
MOVL AX, 4(CX) /* r2 = lo(a1*b1) */
MOVL a+8(FP), AX
MULL b+12(FP) /* a1*b0 */
MOVL AX, 0(CX) /* r1 = lo(a1*b0) */
ADDL DX, 4(CX) /* r2 += hi(a1*b0) */
MOVL a+4(FP), AX
MULL b+16(FP) /* a0*b1 */
ADDL AX, 0(CX) /* r1 += lo(a0*b1) */
ADCL DX, 4(CX) /* r2 += hi(a0*b1) + carry */
MOVL a+4(FP), AX
MULL b+12(FP) /* a0*b0 */
ADDL DX, 0(CX) /* r1 += hi(a0*b0) */
ADCL BX, 4(CX) /* r2 += carry */
RET
/*
* label consists of a stack pointer and a PC
*/
TEXT gotolabel(SB), $0
MOVL label+0(FP), AX
MOVL 0(AX), SP /* restore sp */
MOVL 4(AX), AX /* put return pc on the stack */
MOVL AX, 0(SP)
MOVL $1, AX /* return 1 */
RET
TEXT setlabel(SB), $0
MOVL label+0(FP), AX
MOVL SP, 0(AX) /* store sp */
MOVL 0(SP), BX /* store return pc */
MOVL BX, 4(AX)
MOVL $0, AX /* return 0 */
RET
/*
* Attempt at power saving. -rsc
*/
TEXT halt(SB), $0
CLI
CMPL nrdy(SB), $0
JEQ _nothingready
STI
RET
_nothingready:
STI
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
2013-05-08 17:57:58 +00:00
#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
/*
* 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
* on whether an error code has been automatically pushed onto the stack
* (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
* the trap type from the vector table entry and placing it on the stack as part
* of the Ureg structure.
* The size of each entry in the vector table (6 bytes) is known in trapinit().
*/
TEXT _strayintr(SB), $0
PUSHL AX /* save AX */
MOVL 4(SP), AX /* return PC from vectortable(SB) */
JMP intrcommon
TEXT _strayintrx(SB), $0
XCHGL AX, (SP) /* swap AX with vectortable CALL PC */
intrcommon:
PUSHL DS /* save DS */
PUSHL $(KDSEL)
POPL DS /* fix up DS */
MOVBLZX (AX), AX /* trap type -> AX */
XCHGL AX, 4(SP) /* exchange trap type with saved AX */
PUSHL ES /* save ES */
PUSHL $(KDSEL)
POPL ES /* fix up ES */
PUSHL FS /* save the rest of the Ureg struct */
PUSHL GS
PUSHAL
PUSHL SP /* Ureg* argument to trap */
CALL trap(SB)
TEXT forkret(SB), $0
POPL AX
POPAL
2011-07-20 05:48:33 +00:00
TEXT _forkretpopgs(SB), $0
POPL GS
2011-07-20 05:48:33 +00:00
TEXT _forkretpopfs(SB), $0
POPL FS
2011-07-20 05:48:33 +00:00
TEXT _forkretpopes(SB), $0
POPL ES
2011-07-20 05:48:33 +00:00
TEXT _forkretpopds(SB), $0
POPL DS
ADDL $8, SP /* pop error code and trap type */
2011-07-20 05:48:33 +00:00
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 $0x02 /* NMI interrupt */
CALL _strayintr(SB); BYTE $0x03 /* breakpoint */
CALL _strayintr(SB); BYTE $0x04 /* overflow */
CALL _strayintr(SB); BYTE $0x05 /* bound */
CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */
CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */
CALL _strayintrx(SB); BYTE $0x08 /* double fault */
CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */
CALL _strayintrx(SB); BYTE $0x0B /* segment not available */
CALL _strayintrx(SB); BYTE $0x0C /* stack exception */
CALL _strayintrx(SB); BYTE $0x0D /* general protection error */
CALL _strayintrx(SB); BYTE $0x0E /* page fault */
CALL _strayintr(SB); BYTE $0x0F /* */
CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
CALL _strayintr(SB); BYTE $0x12 /* machine check */
2014-05-11 03:59:10 +00:00
CALL _strayintr(SB); BYTE $0x13 /* simd error */
CALL _strayintr(SB); BYTE $0x14
CALL _strayintr(SB); BYTE $0x15
CALL _strayintr(SB); BYTE $0x16
CALL _strayintr(SB); BYTE $0x17
CALL _strayintr(SB); BYTE $0x18
CALL _strayintr(SB); BYTE $0x19
CALL _strayintr(SB); BYTE $0x1A
CALL _strayintr(SB); BYTE $0x1B
CALL _strayintr(SB); BYTE $0x1C
CALL _strayintr(SB); BYTE $0x1D
CALL _strayintr(SB); BYTE $0x1E
CALL _strayintr(SB); BYTE $0x1F
CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */
CALL _strayintr(SB); BYTE $0x21
CALL _strayintr(SB); BYTE $0x22
CALL _strayintr(SB); BYTE $0x23
CALL _strayintr(SB); BYTE $0x24
CALL _strayintr(SB); BYTE $0x25
CALL _strayintr(SB); BYTE $0x26
CALL _strayintr(SB); BYTE $0x27
CALL _strayintr(SB); BYTE $0x28
CALL _strayintr(SB); BYTE $0x29
CALL _strayintr(SB); BYTE $0x2A
CALL _strayintr(SB); BYTE $0x2B
CALL _strayintr(SB); BYTE $0x2C
CALL _strayintr(SB); BYTE $0x2D
CALL _strayintr(SB); BYTE $0x2E
CALL _strayintr(SB); BYTE $0x2F
CALL _strayintr(SB); BYTE $0x30
CALL _strayintr(SB); BYTE $0x31
CALL _strayintr(SB); BYTE $0x32
CALL _strayintr(SB); BYTE $0x33
CALL _strayintr(SB); BYTE $0x34
CALL _strayintr(SB); BYTE $0x35
CALL _strayintr(SB); BYTE $0x36
CALL _strayintr(SB); BYTE $0x37
CALL _strayintr(SB); BYTE $0x38
CALL _strayintr(SB); BYTE $0x39
CALL _strayintr(SB); BYTE $0x3A
CALL _strayintr(SB); BYTE $0x3B
CALL _strayintr(SB); BYTE $0x3C
CALL _strayintr(SB); BYTE $0x3D
CALL _strayintr(SB); BYTE $0x3E
CALL _strayintr(SB); BYTE $0x3F
CALL _syscallintr(SB); BYTE $0x40 /* VectorSYSCALL */
CALL _strayintr(SB); BYTE $0x41
CALL _strayintr(SB); BYTE $0x42
CALL _strayintr(SB); BYTE $0x43
CALL _strayintr(SB); BYTE $0x44
CALL _strayintr(SB); BYTE $0x45
CALL _strayintr(SB); BYTE $0x46
CALL _strayintr(SB); BYTE $0x47
CALL _strayintr(SB); BYTE $0x48
CALL _strayintr(SB); BYTE $0x49
CALL _strayintr(SB); BYTE $0x4A
CALL _strayintr(SB); BYTE $0x4B
CALL _strayintr(SB); BYTE $0x4C
CALL _strayintr(SB); BYTE $0x4D
CALL _strayintr(SB); BYTE $0x4E
CALL _strayintr(SB); BYTE $0x4F
CALL _strayintr(SB); BYTE $0x50
CALL _strayintr(SB); BYTE $0x51
CALL _strayintr(SB); BYTE $0x52
CALL _strayintr(SB); BYTE $0x53
CALL _strayintr(SB); BYTE $0x54
CALL _strayintr(SB); BYTE $0x55
CALL _strayintr(SB); BYTE $0x56
CALL _strayintr(SB); BYTE $0x57
CALL _strayintr(SB); BYTE $0x58
CALL _strayintr(SB); BYTE $0x59
CALL _strayintr(SB); BYTE $0x5A
CALL _strayintr(SB); BYTE $0x5B
CALL _strayintr(SB); BYTE $0x5C
CALL _strayintr(SB); BYTE $0x5D
CALL _strayintr(SB); BYTE $0x5E
CALL _strayintr(SB); BYTE $0x5F
CALL _strayintr(SB); BYTE $0x60
CALL _strayintr(SB); BYTE $0x61
CALL _strayintr(SB); BYTE $0x62
CALL _strayintr(SB); BYTE $0x63
CALL _strayintr(SB); BYTE $0x64
CALL _strayintr(SB); BYTE $0x65
CALL _strayintr(SB); BYTE $0x66
CALL _strayintr(SB); BYTE $0x67
CALL _strayintr(SB); BYTE $0x68
CALL _strayintr(SB); BYTE $0x69
CALL _strayintr(SB); BYTE $0x6A
CALL _strayintr(SB); BYTE $0x6B
CALL _strayintr(SB); BYTE $0x6C
CALL _strayintr(SB); BYTE $0x6D
CALL _strayintr(SB); BYTE $0x6E
CALL _strayintr(SB); BYTE $0x6F
CALL _strayintr(SB); BYTE $0x70
CALL _strayintr(SB); BYTE $0x71
CALL _strayintr(SB); BYTE $0x72
CALL _strayintr(SB); BYTE $0x73
CALL _strayintr(SB); BYTE $0x74
CALL _strayintr(SB); BYTE $0x75
CALL _strayintr(SB); BYTE $0x76
CALL _strayintr(SB); BYTE $0x77
CALL _strayintr(SB); BYTE $0x78
CALL _strayintr(SB); BYTE $0x79
CALL _strayintr(SB); BYTE $0x7A
CALL _strayintr(SB); BYTE $0x7B
CALL _strayintr(SB); BYTE $0x7C
CALL _strayintr(SB); BYTE $0x7D
CALL _strayintr(SB); BYTE $0x7E
CALL _strayintr(SB); BYTE $0x7F
CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
CALL _strayintr(SB); BYTE $0x81
CALL _strayintr(SB); BYTE $0x82
CALL _strayintr(SB); BYTE $0x83
CALL _strayintr(SB); BYTE $0x84
CALL _strayintr(SB); BYTE $0x85
CALL _strayintr(SB); BYTE $0x86
CALL _strayintr(SB); BYTE $0x87
CALL _strayintr(SB); BYTE $0x88
CALL _strayintr(SB); BYTE $0x89
CALL _strayintr(SB); BYTE $0x8A
CALL _strayintr(SB); BYTE $0x8B
CALL _strayintr(SB); BYTE $0x8C
CALL _strayintr(SB); BYTE $0x8D
CALL _strayintr(SB); BYTE $0x8E
CALL _strayintr(SB); BYTE $0x8F
CALL _strayintr(SB); BYTE $0x90
CALL _strayintr(SB); BYTE $0x91
CALL _strayintr(SB); BYTE $0x92
CALL _strayintr(SB); BYTE $0x93
CALL _strayintr(SB); BYTE $0x94
CALL _strayintr(SB); BYTE $0x95
CALL _strayintr(SB); BYTE $0x96
CALL _strayintr(SB); BYTE $0x97
CALL _strayintr(SB); BYTE $0x98
CALL _strayintr(SB); BYTE $0x99
CALL _strayintr(SB); BYTE $0x9A
CALL _strayintr(SB); BYTE $0x9B
CALL _strayintr(SB); BYTE $0x9C
CALL _strayintr(SB); BYTE $0x9D
CALL _strayintr(SB); BYTE $0x9E
CALL _strayintr(SB); BYTE $0x9F
CALL _strayintr(SB); BYTE $0xA0
CALL _strayintr(SB); BYTE $0xA1
CALL _strayintr(SB); BYTE $0xA2
CALL _strayintr(SB); BYTE $0xA3
CALL _strayintr(SB); BYTE $0xA4
CALL _strayintr(SB); BYTE $0xA5
CALL _strayintr(SB); BYTE $0xA6
CALL _strayintr(SB); BYTE $0xA7
CALL _strayintr(SB); BYTE $0xA8
CALL _strayintr(SB); BYTE $0xA9
CALL _strayintr(SB); BYTE $0xAA
CALL _strayintr(SB); BYTE $0xAB
CALL _strayintr(SB); BYTE $0xAC
CALL _strayintr(SB); BYTE $0xAD
CALL _strayintr(SB); BYTE $0xAE
CALL _strayintr(SB); BYTE $0xAF
CALL _strayintr(SB); BYTE $0xB0
CALL _strayintr(SB); BYTE $0xB1
CALL _strayintr(SB); BYTE $0xB2
CALL _strayintr(SB); BYTE $0xB3
CALL _strayintr(SB); BYTE $0xB4
CALL _strayintr(SB); BYTE $0xB5
CALL _strayintr(SB); BYTE $0xB6
CALL _strayintr(SB); BYTE $0xB7
CALL _strayintr(SB); BYTE $0xB8
CALL _strayintr(SB); BYTE $0xB9
CALL _strayintr(SB); BYTE $0xBA
CALL _strayintr(SB); BYTE $0xBB
CALL _strayintr(SB); BYTE $0xBC
CALL _strayintr(SB); BYTE $0xBD
CALL _strayintr(SB); BYTE $0xBE
CALL _strayintr(SB); BYTE $0xBF
CALL _strayintr(SB); BYTE $0xC0
CALL _strayintr(SB); BYTE $0xC1
CALL _strayintr(SB); BYTE $0xC2
CALL _strayintr(SB); BYTE $0xC3
CALL _strayintr(SB); BYTE $0xC4
CALL _strayintr(SB); BYTE $0xC5
CALL _strayintr(SB); BYTE $0xC6
CALL _strayintr(SB); BYTE $0xC7
CALL _strayintr(SB); BYTE $0xC8
CALL _strayintr(SB); BYTE $0xC9
CALL _strayintr(SB); BYTE $0xCA
CALL _strayintr(SB); BYTE $0xCB
CALL _strayintr(SB); BYTE $0xCC
CALL _strayintr(SB); BYTE $0xCD
CALL _strayintr(SB); BYTE $0xCE
CALL _strayintr(SB); BYTE $0xCF
CALL _strayintr(SB); BYTE $0xD0
CALL _strayintr(SB); BYTE $0xD1
CALL _strayintr(SB); BYTE $0xD2
CALL _strayintr(SB); BYTE $0xD3
CALL _strayintr(SB); BYTE $0xD4
CALL _strayintr(SB); BYTE $0xD5
CALL _strayintr(SB); BYTE $0xD6
CALL _strayintr(SB); BYTE $0xD7
CALL _strayintr(SB); BYTE $0xD8
CALL _strayintr(SB); BYTE $0xD9
CALL _strayintr(SB); BYTE $0xDA
CALL _strayintr(SB); BYTE $0xDB
CALL _strayintr(SB); BYTE $0xDC
CALL _strayintr(SB); BYTE $0xDD
CALL _strayintr(SB); BYTE $0xDE
CALL _strayintr(SB); BYTE $0xDF
CALL _strayintr(SB); BYTE $0xE0
CALL _strayintr(SB); BYTE $0xE1
CALL _strayintr(SB); BYTE $0xE2
CALL _strayintr(SB); BYTE $0xE3
CALL _strayintr(SB); BYTE $0xE4
CALL _strayintr(SB); BYTE $0xE5
CALL _strayintr(SB); BYTE $0xE6
CALL _strayintr(SB); BYTE $0xE7
CALL _strayintr(SB); BYTE $0xE8
CALL _strayintr(SB); BYTE $0xE9
CALL _strayintr(SB); BYTE $0xEA
CALL _strayintr(SB); BYTE $0xEB
CALL _strayintr(SB); BYTE $0xEC
CALL _strayintr(SB); BYTE $0xED
CALL _strayintr(SB); BYTE $0xEE
CALL _strayintr(SB); BYTE $0xEF
CALL _strayintr(SB); BYTE $0xF0
CALL _strayintr(SB); BYTE $0xF1
CALL _strayintr(SB); BYTE $0xF2
CALL _strayintr(SB); BYTE $0xF3
CALL _strayintr(SB); BYTE $0xF4
CALL _strayintr(SB); BYTE $0xF5
CALL _strayintr(SB); BYTE $0xF6
CALL _strayintr(SB); BYTE $0xF7
CALL _strayintr(SB); BYTE $0xF8
CALL _strayintr(SB); BYTE $0xF9
CALL _strayintr(SB); BYTE $0xFA
CALL _strayintr(SB); BYTE $0xFB
CALL _strayintr(SB); BYTE $0xFC
CALL _strayintr(SB); BYTE $0xFD
CALL _strayintr(SB); BYTE $0xFE
CALL _strayintr(SB); BYTE $0xFF