summaryrefslogtreecommitdiff
path: root/sys/src/9/pc64
diff options
context:
space:
mode:
authorSigrid <ftrvxmtrx@gmail.com>2020-12-06 18:48:32 +0100
committerSigrid <ftrvxmtrx@gmail.com>2020-12-06 18:48:32 +0100
commit66b6185845e85258f1408271d5f705aacfa6ffdb (patch)
tree3229e05ec37577d706d3d1efe9732244c55a92fc /sys/src/9/pc64
parent753a35b52ac098985aff5e22a069d30d16903385 (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.h29
-rw-r--r--sys/src/9/pc64/fns.h10
-rw-r--r--sys/src/9/pc64/fpu.c51
-rw-r--r--sys/src/9/pc64/l.s48
-rw-r--r--sys/src/9/pc64/main.c42
-rw-r--r--sys/src/9/pc64/mem.h1
-rw-r--r--sys/src/9/pc64/mkfile1
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\