diff options
author | Sigrid <ftrvxmtrx@gmail.com> | 2020-12-06 18:48:32 +0100 |
---|---|---|
committer | Sigrid <ftrvxmtrx@gmail.com> | 2020-12-06 18:48:32 +0100 |
commit | 66b6185845e85258f1408271d5f705aacfa6ffdb (patch) | |
tree | 3229e05ec37577d706d3d1efe9732244c55a92fc /sys/src/9/pc64 | |
parent | 753a35b52ac098985aff5e22a069d30d16903385 (diff) |
amd64, vmx: support avx/avx2 for host/guest; use *noavx= in plan9.ini to disable
Diffstat (limited to 'sys/src/9/pc64')
-rw-r--r-- | sys/src/9/pc64/dat.h | 29 | ||||
-rw-r--r-- | sys/src/9/pc64/fns.h | 10 | ||||
-rw-r--r-- | sys/src/9/pc64/fpu.c | 51 | ||||
-rw-r--r-- | sys/src/9/pc64/l.s | 48 | ||||
-rw-r--r-- | sys/src/9/pc64/main.c | 42 | ||||
-rw-r--r-- | sys/src/9/pc64/mem.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc64/mkfile | 1 |
7 files changed, 173 insertions, 9 deletions
diff --git a/sys/src/9/pc64/dat.h b/sys/src/9/pc64/dat.h index 84efe9a2c..7cfc6e5c2 100644 --- a/sys/src/9/pc64/dat.h +++ b/sys/src/9/pc64/dat.h @@ -2,6 +2,8 @@ typedef struct BIOS32si BIOS32si; typedef struct BIOS32ci BIOS32ci; typedef struct Conf Conf; typedef struct Confmem Confmem; +typedef struct FPssestate FPssestate; +typedef struct FPavxstate FPavxstate; typedef struct FPsave FPsave; typedef struct PFPU PFPU; typedef struct ISAConf ISAConf; @@ -49,7 +51,7 @@ struct Label uintptr pc; }; -struct FPsave +struct FPssestate { u16int fcw; /* x87 control word */ u16int fsw; /* x87 status word */ @@ -65,6 +67,18 @@ struct FPsave uchar ign[96]; /* reserved, ignored */ }; +struct FPavxstate +{ + FPssestate; + uchar header[64]; /* XSAVE header */ + uchar ymm[256]; /* upper 128-bit regs (AVX) */ +}; + +struct FPsave +{ + FPavxstate; +}; + enum { /* this is a state */ @@ -224,9 +238,12 @@ struct Mach int havewatchpt8; int havenx; uvlong tscticks; - + u64int dr7; /* shadow copy of dr7 */ - + u64int xcr0; + u32int fpsavesz; + u32int fpalign; + void* vmx; uintptr stack[1]; @@ -270,8 +287,14 @@ struct PCArch /* cpuid instruction result register bits */ enum { + /* ax */ + Xsaveopt = 1<<0, + Xsaves = 1<<3, + /* cx */ Monitor = 1<<3, + Xsave = 1<<26, + Avx = 1<<28, /* dx */ Fpuonchip = 1<<0, diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index ad5315b5e..9e07b33d8 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -15,7 +15,8 @@ void clockintr(Ureg*, void*); int (*cmpswap)(long*, long, long); int cmpswap486(long*, long, long); void (*coherence)(void); -void cpuid(int, ulong regs[]); +void cpuid(int, int, ulong regs[]); +void fpuinit(void); int cpuidentify(void); void cpuidprint(void); void (*cycles)(uvlong*); @@ -40,6 +41,11 @@ void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); void fpsserestore(FPsave*); void fpssesave(FPsave*); +void fpxrestore(FPsave*); +void fpxrestores(FPsave*); +void fpxsave(FPsave*); +void fpxsaveopt(FPsave*); +void fpxsaves(FPsave*); void fpx87restore(FPsave*); void fpx87save(FPsave*); int fpusave(void); @@ -48,6 +54,7 @@ u64int getcr0(void); u64int getcr2(void); u64int getcr3(void); u64int getcr4(void); +u64int getxcr0(void); u64int getdr6(void); char* getconf(char*); void guesscpuhz(int); @@ -138,6 +145,7 @@ void putcr0(u64int); void putcr2(u64int); void putcr3(u64int); void putcr4(u64int); +void putxcr0(u64int); void putdr(u64int*); void putdr01236(u64int*); void putdr6(u64int); diff --git a/sys/src/9/pc64/fpu.c b/sys/src/9/pc64/fpu.c new file mode 100644 index 000000000..4326f51a7 --- /dev/null +++ b/sys/src/9/pc64/fpu.c @@ -0,0 +1,51 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +enum { + CR4Osfxsr = 1 << 9, + CR4Oxmmex = 1 << 10, + CR4Oxsave = 1 << 18, +}; + +void +fpuinit(void) +{ + uintptr cr4; + ulong regs[4]; + + m->fpsavesz = sizeof(FPssestate); + m->fpalign = 16; + if((m->cpuiddx & (Sse|Fxsr)) == (Sse|Fxsr)){ /* have sse fp? */ + cr4 = getcr4() | CR4Osfxsr|CR4Oxmmex; + putcr4(cr4); + fpsave = fpssesave; + fprestore = fpsserestore; + + if((m->cpuidcx & (Xsave|Avx)) == (Xsave|Avx) && getconf("*noavx") == nil){ + cr4 |= CR4Oxsave; + putcr4(cr4); + m->xcr0 = 7; /* x87, sse, avx */ + putxcr0(m->xcr0); + fpsave = fpxsave; + fprestore = fpxrestore; + + cpuid(0xd, 0, regs); + m->fpsavesz = regs[1]; + m->fpalign = 64; + + cpuid(0xd, 1, regs); + if(regs[0] & Xsaveopt) + fpsave = fpxsaveopt; + if(regs[0] & Xsaves){ + fpsave = fpxsaves; + fprestore = fpxrestores; + } + } + } else { + fpsave = fpx87save; + fprestore = fpx87restore; + } +} diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index c00a24fc7..76aa2e241 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -249,9 +249,10 @@ _idle: */ TEXT cpuid(SB), $-4 MOVL RARG, AX /* function in AX */ + MOVL cx+8(FP), CX /* sub-level in CX */ CPUID - MOVQ info+8(FP), BP + MOVQ info+16(FP), BP MOVL AX, 0(BP) MOVL BX, 4(BP) MOVL CX, 8(BP) @@ -399,6 +400,21 @@ TEXT putcr4(SB), 1, $-4 MOVQ RARG, CR4 RET +TEXT getxcr0(SB), 1, $-4 /* XCR0 - extended control */ + XORQ CX, CX + WORD $0x010f; BYTE $0xd0 // XGETBV + SHLQ $32, DX + ORQ DX, AX + RET + +TEXT putxcr0(SB), 1, $-4 + XORQ CX, CX + MOVL RARG, DX + SHRQ $32, DX + MOVL RARG, AX + WORD $0x010f; BYTE $0xd1 // XSETBV + RET + TEXT mb386(SB), 1, $-4 /* hack */ TEXT mb586(SB), 1, $-4 XORL AX, AX @@ -626,6 +642,36 @@ TEXT _fxsave(SB), 1, $-4 FXSAVE64 (RARG) RET +TEXT _xrstor(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x6d; BYTE $0x00 // XRSTOR (RARG) + RET + +TEXT _xrstors(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xc7; BYTE $0x5d; BYTE $0x00 // XRSTORS (RARG) + RET + +TEXT _xsave(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x65; BYTE $0x00 // XSAVE (RARG) + RET + +TEXT _xsaveopt(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xae; BYTE $0x75; BYTE $0x00 // XSAVEOPT (RARG) + RET + +TEXT _xsaves(SB), 1, $-4 + MOVL $7, AX + XORL DX, DX + BYTE $0x48; BYTE $0x0f; BYTE $0xc7; BYTE $0x6d; BYTE $0x00 // XSAVES (RARG) + RET + TEXT _fwait(SB), 1, $-4 WAIT RET diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 5ece4cfd8..4026ee151 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -304,6 +304,9 @@ extern void _fnclex(void); extern void _fninit(void); extern void _fxrstor(void*); extern void _fxsave(void*); +extern void _xrstor(void*); +extern void _xsave(void*); +extern void _xsaveopt(void*); extern void _fwait(void); extern void _ldmxcsr(u32int); extern void _stts(void); @@ -333,6 +336,39 @@ fpsserestore(FPsave *s) _fxrstor(s); } +void +fpxsave(FPsave *s) +{ + _xsave(s); + _stts(); +} +void +fpxrestore(FPsave *s) +{ + _clts(); + _xrstor(s); +} + +void +fpxsaves(FPsave *s) +{ + _xsaveopt(s); + _stts(); +} +void +fpxrestores(FPsave *s) +{ + _clts(); + _xrstor(s); +} + +void +fpxsaveopt(FPsave *s) +{ + _xsaveopt(s); + _stts(); +} + static char* mathmsg[] = { nil, /* handled below */ @@ -452,7 +488,7 @@ mathemu(Ureg *ureg, void*) up->fpstate |= FPkernel; } while(up->fpslot[index] == nil) - up->fpslot[index] = mallocalign(sizeof(FPsave), FPalign, 0, 0); + up->fpslot[index] = mallocalign(m->fpsavesz, m->fpalign, 0, 0); up->fpsave = up->fpslot[index]; up->fpstate = FPactive | (up->fpstate & (FPnouser|FPkernel|FPindexm)); break; @@ -538,8 +574,8 @@ procfork(Proc *p) case FPinactive | FPpush: case FPinactive: while(p->fpslot[0] == nil) - p->fpslot[0] = mallocalign(sizeof(FPsave), FPalign, 0, 0); - memmove(p->fpsave = p->fpslot[0], up->fpslot[0], sizeof(FPsave)); + p->fpslot[0] = mallocalign(m->fpsavesz, m->fpalign, 0, 0); + memmove(p->fpsave = p->fpslot[0], up->fpslot[0], m->fpsavesz); p->fpstate = FPinactive; } splx(s); diff --git a/sys/src/9/pc64/mem.h b/sys/src/9/pc64/mem.h index c6f9bba70..f02e042a6 100644 --- a/sys/src/9/pc64/mem.h +++ b/sys/src/9/pc64/mem.h @@ -26,7 +26,6 @@ #define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) #define PGROUND(s) ROUND(s, BY2PG) #define BLOCKALIGN 8 -#define FPalign 16 #define MAXMACH 128 /* max # cpus system can run */ diff --git a/sys/src/9/pc64/mkfile b/sys/src/9/pc64/mkfile index f34201e0d..083ab92f9 100644 --- a/sys/src/9/pc64/mkfile +++ b/sys/src/9/pc64/mkfile @@ -47,6 +47,7 @@ PORT=\ OBJ=\ l.$O\ cga.$O\ + fpu.$O\ i8253.$O\ i8259.$O\ main.$O\ |