FPU context switching support by Evgeniy Ivanov.
This commit is contained in:
parent
fce9fd4b4e
commit
bd42705433
25 changed files with 434 additions and 147 deletions
|
@ -78,7 +78,11 @@ typedef enum opcode { /* 80486 opcodes, from the i486 reference manual.
|
||||||
FLDCW,
|
FLDCW,
|
||||||
FLDENV,
|
FLDENV,
|
||||||
FMULD, FMULS, FMULP, FIMULL, FIMULS,
|
FMULD, FMULS, FMULP, FIMULL, FIMULS,
|
||||||
|
FNINIT,
|
||||||
FNOP,
|
FNOP,
|
||||||
|
FNSAVE,
|
||||||
|
FNSTCW,
|
||||||
|
FNSTSW,
|
||||||
FPATAN,
|
FPATAN,
|
||||||
FPREM,
|
FPREM,
|
||||||
FPREM1,
|
FPREM1,
|
||||||
|
@ -86,6 +90,9 @@ typedef enum opcode { /* 80486 opcodes, from the i486 reference manual.
|
||||||
FRNDINT,
|
FRNDINT,
|
||||||
FRSTOR,
|
FRSTOR,
|
||||||
FSAVE,
|
FSAVE,
|
||||||
|
FWAIT,
|
||||||
|
FXRSTOR,
|
||||||
|
FXSAVE,
|
||||||
FSCALE,
|
FSCALE,
|
||||||
FSIN,
|
FSIN,
|
||||||
FSINCOS,
|
FSINCOS,
|
||||||
|
|
|
@ -138,7 +138,11 @@ static mnemonic_t mnemtab[] = {
|
||||||
{ FMULD, "fmuld" },
|
{ FMULD, "fmuld" },
|
||||||
{ FMULP, "fmulp" },
|
{ FMULP, "fmulp" },
|
||||||
{ FMULS, "fmuls" },
|
{ FMULS, "fmuls" },
|
||||||
|
{ FNINIT, "fninit" },
|
||||||
{ FNOP, "fnop" },
|
{ FNOP, "fnop" },
|
||||||
|
{ FNSAVE, "fnsave" },
|
||||||
|
{ FNSTCW, "fnstcw" },
|
||||||
|
{ FNSTSW, "fnstsw" },
|
||||||
{ FPATAN, "fpatan" },
|
{ FPATAN, "fpatan" },
|
||||||
{ FPREM, "fprem" },
|
{ FPREM, "fprem" },
|
||||||
{ FPREM1, "fprem1" },
|
{ FPREM1, "fprem1" },
|
||||||
|
@ -146,6 +150,9 @@ static mnemonic_t mnemtab[] = {
|
||||||
{ FRNDINT, "frndint" },
|
{ FRNDINT, "frndint" },
|
||||||
{ FRSTOR, "frstor" },
|
{ FRSTOR, "frstor" },
|
||||||
{ FSAVE, "fsave" },
|
{ FSAVE, "fsave" },
|
||||||
|
{ FWAIT, "fwait" },
|
||||||
|
{ FXRSTOR, "fxrstor" },
|
||||||
|
{ FXSAVE, "fxsave" },
|
||||||
{ FSCALE, "fscale" },
|
{ FSCALE, "fscale" },
|
||||||
{ FSIN, "fsin" },
|
{ FSIN, "fsin" },
|
||||||
{ FSINCOS, "fsincos" },
|
{ FSINCOS, "fsincos" },
|
||||||
|
@ -611,6 +618,53 @@ void ack_emit_instruction(asm86_t *a)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (a->opcode == RDMSR) {
|
||||||
|
ack_printf(".data1 0x0f, 0x32\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (a->opcode == WRMSR) {
|
||||||
|
ack_printf(".data1 0x0f, 0x30\n");
|
||||||
|
}
|
||||||
|
/* unsupported fninit */
|
||||||
|
if (a->opcode == FNINIT) {
|
||||||
|
ack_printf(".data1 0xDB, 0xE3\n"); /* FNINIT */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* unsupported fnsave */
|
||||||
|
if (a->opcode == FNSAVE) {
|
||||||
|
ack_printf(".data1 0xDD, 0x30\n"); /* FNSAVE [eax] */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* unsupported fnstcw */
|
||||||
|
if (a->opcode == FNSTCW) {
|
||||||
|
ack_printf(".data1 0xD9, 0x38\n"); /* FNSTCW [eax] */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* unsupported fnstsw */
|
||||||
|
if (a->opcode == FNSTSW) {
|
||||||
|
ack_printf(".data1 0xDF, 0xD0\n"); /* FNSTSW [eax] */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* unsupported frstor */
|
||||||
|
if (a->opcode == FRSTOR) {
|
||||||
|
ack_printf(".data1 0xDD, 0x20\n"); /* FRSTOR [eax] */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* unsupported fwait */
|
||||||
|
if (a->opcode == FWAIT) {
|
||||||
|
ack_printf(".data1 0x9B\n"); /* FWAIT */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* unsupported fxrstor */
|
||||||
|
if (a->opcode == FXRSTOR) {
|
||||||
|
ack_printf(".data1 0x0F, 0xAE, 0x08\n"); /* FXRSTOR [eax] */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* unsupported fxsave */
|
||||||
|
if (a->opcode == FXSAVE) {
|
||||||
|
ack_printf(".data1 0x0F, 0xAE, 0x00\n"); /* FXSAVE [eax] */
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* we are translating from GNU */
|
/* we are translating from GNU */
|
||||||
if (a->args && a->args->operator == ','
|
if (a->args && a->args->operator == ','
|
||||||
/* don't swap ljmp prefixed with segment */
|
/* don't swap ljmp prefixed with segment */
|
||||||
|
|
|
@ -142,6 +142,7 @@ static mnemonic_t mnemtab[] = { /* This array is sorted. */
|
||||||
{ "fimull", FIMULL, WORD },
|
{ "fimull", FIMULL, WORD },
|
||||||
{ "fimuls", FIMULS, WORD },
|
{ "fimuls", FIMULS, WORD },
|
||||||
{ "fincstp", FINCSTP, WORD },
|
{ "fincstp", FINCSTP, WORD },
|
||||||
|
{ "finit", FINIT, WORD },
|
||||||
{ "fistl", FISTL, WORD },
|
{ "fistl", FISTL, WORD },
|
||||||
{ "fistp", FISTP, WORD },
|
{ "fistp", FISTP, WORD },
|
||||||
{ "fists", FISTS, WORD },
|
{ "fists", FISTS, WORD },
|
||||||
|
@ -165,10 +166,11 @@ static mnemonic_t mnemtab[] = { /* This array is sorted. */
|
||||||
{ "fmulp", FMULP, WORD },
|
{ "fmulp", FMULP, WORD },
|
||||||
{ "fmuls", FMULS, WORD },
|
{ "fmuls", FMULS, WORD },
|
||||||
{ "fnclex", FCLEX, WORD },
|
{ "fnclex", FCLEX, WORD },
|
||||||
{ "fninit", FINIT, WORD },
|
{ "fninit", FNINIT, NONE },
|
||||||
{ "fnop", FNOP, WORD },
|
{ "fnop", FNOP, WORD },
|
||||||
{ "fnsave", FSAVE, WORD },
|
{ "fnsave", FNSAVE, WORD },
|
||||||
{ "fnstcw", FSTCW, WORD },
|
{ "fnstcw", FNSTCW, WORD },
|
||||||
|
{ "fnstsw", FNSTSW, WORD },
|
||||||
{ "fnstenv", FSTENV, WORD },
|
{ "fnstenv", FSTENV, WORD },
|
||||||
{ "fpatan", FPATAN, WORD },
|
{ "fpatan", FPATAN, WORD },
|
||||||
{ "fprem", FPREM, WORD },
|
{ "fprem", FPREM, WORD },
|
||||||
|
@ -176,6 +178,7 @@ static mnemonic_t mnemtab[] = { /* This array is sorted. */
|
||||||
{ "fptan", FPTAN, WORD },
|
{ "fptan", FPTAN, WORD },
|
||||||
{ "frndint", FRNDINT, WORD },
|
{ "frndint", FRNDINT, WORD },
|
||||||
{ "frstor", FRSTOR, WORD },
|
{ "frstor", FRSTOR, WORD },
|
||||||
|
{ "fsave", FSAVE, WORD },
|
||||||
{ "fscale", FSCALE, WORD },
|
{ "fscale", FSCALE, WORD },
|
||||||
{ "fsin", FSIN, WORD },
|
{ "fsin", FSIN, WORD },
|
||||||
{ "fsincos", FSINCOS, WORD },
|
{ "fsincos", FSINCOS, WORD },
|
||||||
|
@ -185,6 +188,7 @@ static mnemonic_t mnemtab[] = { /* This array is sorted. */
|
||||||
{ "fstps", FSTPS, WORD },
|
{ "fstps", FSTPS, WORD },
|
||||||
{ "fstpx", FSTPX, WORD },
|
{ "fstpx", FSTPX, WORD },
|
||||||
{ "fsts", FSTS, WORD },
|
{ "fsts", FSTS, WORD },
|
||||||
|
{ "fstcw", FSTCW, WORD },
|
||||||
{ "fstsw", FSTSW, WORD },
|
{ "fstsw", FSTSW, WORD },
|
||||||
{ "fsubd", FSUBD, WORD },
|
{ "fsubd", FSUBD, WORD },
|
||||||
{ "fsubp", FSUBP, WORD },
|
{ "fsubp", FSUBP, WORD },
|
||||||
|
@ -196,8 +200,11 @@ static mnemonic_t mnemtab[] = { /* This array is sorted. */
|
||||||
{ "fucom", FUCOM, WORD },
|
{ "fucom", FUCOM, WORD },
|
||||||
{ "fucomp", FUCOMP, WORD },
|
{ "fucomp", FUCOMP, WORD },
|
||||||
{ "fucompp", FUCOMPP, WORD },
|
{ "fucompp", FUCOMPP, WORD },
|
||||||
|
{ "fwait", FWAIT, NONE },
|
||||||
{ "fxam", FXAM, WORD },
|
{ "fxam", FXAM, WORD },
|
||||||
{ "fxch", FXCH, WORD },
|
{ "fxch", FXCH, WORD },
|
||||||
|
{ "fxrstor", FXRSTOR, WORD },
|
||||||
|
{ "fxsave", FXSAVE, WORD },
|
||||||
{ "fxtract", FXTRACT, WORD },
|
{ "fxtract", FXTRACT, WORD },
|
||||||
{ "fyl2x", FYL2X, WORD },
|
{ "fyl2x", FYL2X, WORD },
|
||||||
{ "fyl2xp1", FYL2XP1, WORD },
|
{ "fyl2xp1", FYL2XP1, WORD },
|
||||||
|
|
|
@ -103,10 +103,13 @@ cards()
|
||||||
"1186:1340" "11DB:1234" "1259:A117" "1259:A11E" "126C:1211" \
|
"1186:1340" "11DB:1234" "1259:A117" "1259:A11E" "126C:1211" \
|
||||||
"13D1:AB06" "1432:9130" "14EA:AB06" "14EA:AB07" "1500:1360" \
|
"13D1:AB06" "1432:9130" "14EA:AB06" "14EA:AB07" "1500:1360" \
|
||||||
"1743:8139" "4033:1360"
|
"1743:8139" "4033:1360"
|
||||||
card 4 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029"
|
card 4 "Realtek 8169 based card" \
|
||||||
card 5 "NE2000, 3com 503 or WD based card (also emulated by Bochs)"
|
"10EC:8129" "10EC:8167" "10EC:8169" "1186:4300" "1259:C107" \
|
||||||
card 6 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000"
|
"1385:8169" "16EC:0116" "1737:1032"
|
||||||
card 7 "Different Ethernet card (no networking)"
|
card 5 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029"
|
||||||
|
card 6 "NE2000, 3com 503 or WD based card (also emulated by Bochs)"
|
||||||
|
card 7 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000"
|
||||||
|
card 8 "Different Ethernet card (no networking)"
|
||||||
}
|
}
|
||||||
|
|
||||||
warn()
|
warn()
|
||||||
|
@ -143,15 +146,16 @@ drv_params()
|
||||||
test "$v" = 1 && echo ""
|
test "$v" = 1 && echo ""
|
||||||
test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
|
test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
|
||||||
;;
|
;;
|
||||||
|
4) driver=rtl8169; ;;
|
||||||
3) driver=rtl8139; ;;
|
3) driver=rtl8139; ;;
|
||||||
4) driver=dp8390; driverargs="dp8390_arg='DPETH0=pci'"; ;;
|
5) driver=dp8390; driverargs="dp8390_arg='DPETH0=pci'"; ;;
|
||||||
5) driver=dp8390; driverargs="dp8390_arg='DPETH0=240:9'";
|
6) driver=dp8390; driverargs="dp8390_arg='DPETH0=240:9'";
|
||||||
test "$v" = 1 && echo ""
|
test "$v" = 1 && echo ""
|
||||||
test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
|
test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
|
||||||
test "$v" = 1 && echo " chose option 4, the defaults for emulation by Bochs have been set."
|
test "$v" = 1 && echo " chose option 4, the defaults for emulation by Bochs have been set."
|
||||||
;;
|
;;
|
||||||
6) driver="lance"; ;;
|
7) driver="lance"; ;;
|
||||||
7) driver="psip0"; ;;
|
8) driver="psip0"; ;;
|
||||||
*) warn "choose a number"
|
*) warn "choose a number"
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,19 @@
|
||||||
#ifndef _MINIX_CPUFEATURE_H
|
#ifndef _MINIX_CPUFEATURE_H
|
||||||
#define _MINIX_CPUFEATURE_H 1
|
#define _MINIX_CPUFEATURE_H 1
|
||||||
|
|
||||||
|
#define _CPUF_I386_FPU 0 /* FPU-x87 FPU on Chip */
|
||||||
#define _CPUF_I386_PSE 1 /* Page Size Extension */
|
#define _CPUF_I386_PSE 1 /* Page Size Extension */
|
||||||
#define _CPUF_I386_PGE 2 /* Page Global Enable */
|
#define _CPUF_I386_PGE 2 /* Page Global Enable */
|
||||||
#define _CPUF_I386_APIC_ON_CHIP 3 /* APIC is present on the chip */
|
#define _CPUF_I386_APIC_ON_CHIP 3 /* APIC is present on the chip */
|
||||||
#define _CPUF_I386_TSC 4 /* Timestamp counter present */
|
#define _CPUF_I386_TSC 4 /* Timestamp counter present */
|
||||||
|
#define _CPUF_I386_SSEx 5 /* Support for SSE/SSE2/SSE3/SSSE3/SSE4 Extensions and FXSR */
|
||||||
|
#define _CPUF_I386_FXSR 6
|
||||||
|
#define _CPUF_I386_SSE 7
|
||||||
|
#define _CPUF_I386_SSE2 8
|
||||||
|
#define _CPUF_I386_SSE3 9
|
||||||
|
#define _CPUF_I386_SSSE3 10
|
||||||
|
#define _CPUF_I386_SSE4_1 11
|
||||||
|
#define _CPUF_I386_SSE4_2 12
|
||||||
|
|
||||||
_PROTOTYPE(int _cpufeature, (int featureno));
|
_PROTOTYPE(int _cpufeature, (int featureno));
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,17 @@ struct sigaction {
|
||||||
#define SIG_UNBLOCK 1 /* for unblocking signals */
|
#define SIG_UNBLOCK 1 /* for unblocking signals */
|
||||||
#define SIG_SETMASK 2 /* for setting the signal mask */
|
#define SIG_SETMASK 2 /* for setting the signal mask */
|
||||||
#define SIG_INQUIRE 4 /* for internal use only */
|
#define SIG_INQUIRE 4 /* for internal use only */
|
||||||
|
|
||||||
|
/* codes for SIGFPE */
|
||||||
|
#define FPE_INTOVF 1 /* integer divide by zero */
|
||||||
|
#define FPE_INTDIV 2 /* integer overflow */
|
||||||
|
#define FPE_FLTDIV 3 /* floating-point divide by zero */
|
||||||
|
#define FPE_FLTOVF 4 /* floating-point overflow */
|
||||||
|
#define FPE_FLTUND 5 /* floating-point underflow */
|
||||||
|
#define FPE_FLTRES 6 /* floating-point inexact result */
|
||||||
|
#define FPE_FLTINV 7 /* floating-point invalid operation */
|
||||||
|
#define FPE_FLTSUB 8 /* subscript out of range */
|
||||||
|
|
||||||
#endif /* _POSIX_SOURCE */
|
#endif /* _POSIX_SOURCE */
|
||||||
|
|
||||||
/* POSIX and ANSI function prototypes. */
|
/* POSIX and ANSI function prototypes. */
|
||||||
|
|
|
@ -23,30 +23,10 @@
|
||||||
* be added in a different struct.
|
* be added in a different struct.
|
||||||
*/
|
*/
|
||||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
struct sigregs {
|
#include <sys/stackframe.h>
|
||||||
#if _WORD_SIZE == 4
|
#include <sys/fpu.h>
|
||||||
short sr_gs;
|
|
||||||
short sr_fs;
|
|
||||||
#endif /* _WORD_SIZE == 4 */
|
|
||||||
short sr_es;
|
|
||||||
short sr_ds;
|
|
||||||
int sr_di;
|
|
||||||
int sr_si;
|
|
||||||
int sr_bp;
|
|
||||||
int sr_st; /* stack top -- used in kernel */
|
|
||||||
int sr_bx;
|
|
||||||
int sr_dx;
|
|
||||||
int sr_cx;
|
|
||||||
int sr_retreg;
|
|
||||||
int sr_retadr; /* return address to caller of save -- used
|
|
||||||
* in kernel */
|
|
||||||
int sr_pc;
|
|
||||||
int sr_cs;
|
|
||||||
int sr_psw;
|
|
||||||
int sr_sp;
|
|
||||||
int sr_ss;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
typedef struct stackframe_s sigregs;
|
||||||
struct sigframe { /* stack frame created for signalled process */
|
struct sigframe { /* stack frame created for signalled process */
|
||||||
_PROTOTYPE( void (*sf_retadr), (void) );
|
_PROTOTYPE( void (*sf_retadr), (void) );
|
||||||
int sf_signo;
|
int sf_signo;
|
||||||
|
@ -57,85 +37,43 @@ struct sigframe { /* stack frame created for signalled process */
|
||||||
struct sigcontext *sf_scpcopy;
|
struct sigcontext *sf_scpcopy;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
|
||||||
#if (_MINIX_CHIP == _CHIP_M68000)
|
|
||||||
struct sigregs {
|
|
||||||
long sr_retreg; /* d0 */
|
|
||||||
long sr_d1;
|
|
||||||
long sr_d2;
|
|
||||||
long sr_d3;
|
|
||||||
long sr_d4;
|
|
||||||
long sr_d5;
|
|
||||||
long sr_d6;
|
|
||||||
long sr_d7;
|
|
||||||
long sr_a0;
|
|
||||||
long sr_a1;
|
|
||||||
long sr_a2;
|
|
||||||
long sr_a3;
|
|
||||||
long sr_a4;
|
|
||||||
long sr_a5;
|
|
||||||
long sr_a6;
|
|
||||||
long sr_sp; /* also known as a7 */
|
|
||||||
long sr_pc;
|
|
||||||
short sr_psw;
|
|
||||||
short sr_dummy; /* make size multiple of 4 for system.c */
|
|
||||||
};
|
|
||||||
#else
|
#else
|
||||||
#include "error, _MINIX_CHIP is not supported"
|
#include "error, _MINIX_CHIP is not supported"
|
||||||
#endif
|
|
||||||
#endif /* _MINIX_CHIP == _CHIP_INTEL */
|
#endif /* _MINIX_CHIP == _CHIP_INTEL */
|
||||||
|
|
||||||
struct sigcontext {
|
struct sigcontext {
|
||||||
int sc_flags; /* sigstack state to restore */
|
int sc_flags; /* sigstack state to restore (including MF_FPU_INITIALIZED) */
|
||||||
long sc_mask; /* signal mask to restore */
|
long sc_mask; /* signal mask to restore */
|
||||||
struct sigregs sc_regs; /* register set to restore */
|
sigregs sc_regs; /* register set to restore */
|
||||||
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
|
union fpu_state_u fpu_state;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
#if _WORD_SIZE == 4
|
#if _WORD_SIZE == 4
|
||||||
#define sc_gs sc_regs.sr_gs
|
#define sc_gs sc_regs.gs
|
||||||
#define sc_fs sc_regs.sr_fs
|
#define sc_fs sc_regs.fs
|
||||||
#endif /* _WORD_SIZE == 4 */
|
#endif /* _WORD_SIZE == 4 */
|
||||||
#define sc_es sc_regs.sr_es
|
#define sc_es sc_regs.es
|
||||||
#define sc_ds sc_regs.sr_ds
|
#define sc_ds sc_regs.ds
|
||||||
#define sc_di sc_regs.sr_di
|
#define sc_di sc_regs.di
|
||||||
#define sc_si sc_regs.sr_si
|
#define sc_si sc_regs.si
|
||||||
#define sc_fp sc_regs.sr_bp
|
#define sc_fp sc_regs.bp
|
||||||
#define sc_st sc_regs.sr_st /* stack top -- used in kernel */
|
#define sc_st sc_regs.st /* stack top -- used in kernel */
|
||||||
#define sc_bx sc_regs.sr_bx
|
#define sc_bx sc_regs.bx
|
||||||
#define sc_dx sc_regs.sr_dx
|
#define sc_dx sc_regs.dx
|
||||||
#define sc_cx sc_regs.sr_cx
|
#define sc_cx sc_regs.cx
|
||||||
#define sc_retreg sc_regs.sr_retreg
|
#define sc_retreg sc_regs.retreg
|
||||||
#define sc_retadr sc_regs.sr_retadr /* return address to caller of
|
#define sc_retadr sc_regs.retadr /* return address to caller of
|
||||||
save -- used in kernel */
|
save -- used in kernel */
|
||||||
#define sc_pc sc_regs.sr_pc
|
#define sc_pc sc_regs.pc
|
||||||
#define sc_cs sc_regs.sr_cs
|
#define sc_cs sc_regs.cs
|
||||||
#define sc_psw sc_regs.sr_psw
|
#define sc_psw sc_regs.psw
|
||||||
#define sc_sp sc_regs.sr_sp
|
#define sc_sp sc_regs.sp
|
||||||
#define sc_ss sc_regs.sr_ss
|
#define sc_ss sc_regs.ss
|
||||||
#endif /* _MINIX_CHIP == _CHIP_INTEL */
|
#endif /* _MINIX_CHIP == _CHIP_INTEL */
|
||||||
|
|
||||||
#if (_MINIX_CHIP == M68000)
|
|
||||||
#define sc_retreg sc_regs.sr_retreg
|
|
||||||
#define sc_d1 sc_regs.sr_d1
|
|
||||||
#define sc_d2 sc_regs.sr_d2
|
|
||||||
#define sc_d3 sc_regs.sr_d3
|
|
||||||
#define sc_d4 sc_regs.sr_d4
|
|
||||||
#define sc_d5 sc_regs.sr_d5
|
|
||||||
#define sc_d6 sc_regs.sr_d6
|
|
||||||
#define sc_d7 sc_regs.sr_d7
|
|
||||||
#define sc_a0 sc_regs.sr_a0
|
|
||||||
#define sc_a1 sc_regs.sr_a1
|
|
||||||
#define sc_a2 sc_regs.sr_a2
|
|
||||||
#define sc_a3 sc_regs.sr_a3
|
|
||||||
#define sc_a4 sc_regs.sr_a4
|
|
||||||
#define sc_a5 sc_regs.sr_a5
|
|
||||||
#define sc_fp sc_regs.sr_a6
|
|
||||||
#define sc_sp sc_regs.sr_sp
|
|
||||||
#define sc_pc sc_regs.sr_pc
|
|
||||||
#define sc_psw sc_regs.sr_psw
|
|
||||||
#endif /* _MINIX_CHIP == M68000 */
|
|
||||||
|
|
||||||
_PROTOTYPE( int sigreturn, (struct sigcontext *_scp) );
|
_PROTOTYPE( int sigreturn, (struct sigcontext *_scp) );
|
||||||
|
|
||||||
#endif /* _SIGCONTEXT_H */
|
#endif /* _SIGCONTEXT_H */
|
||||||
|
|
|
@ -70,9 +70,17 @@ sys/vm_i386.h
|
||||||
#define I386_VM_PFE_U 0x04 /* CPU in user mode (otherwise supervisor) */
|
#define I386_VM_PFE_U 0x04 /* CPU in user mode (otherwise supervisor) */
|
||||||
|
|
||||||
/* CPUID flags */
|
/* CPUID flags */
|
||||||
|
#define CPUID1_EDX_FPU (1L) /* FPU presence */
|
||||||
#define CPUID1_EDX_PSE (1L << 3) /* Page Size Extension */
|
#define CPUID1_EDX_PSE (1L << 3) /* Page Size Extension */
|
||||||
#define CPUID1_EDX_PGE (1L << 13) /* Page Global (bit) Enable */
|
#define CPUID1_EDX_PGE (1L << 13) /* Page Global (bit) Enable */
|
||||||
#define CPUID1_EDX_APIC_ON_CHIP (1L << 9) /* APIC is present on the chip */
|
#define CPUID1_EDX_APIC_ON_CHIP (1L << 9) /* APIC is present on the chip */
|
||||||
#define CPUID1_EDX_TSC (1L << 4) /* Timestamp counter present */
|
#define CPUID1_EDX_TSC (1L << 4) /* Timestamp counter present */
|
||||||
|
#define CPUID1_EDX_FXSR (1L << 24)
|
||||||
|
#define CPUID1_EDX_SSE (1L << 25)
|
||||||
|
#define CPUID1_EDX_SSE2 (1L << 26)
|
||||||
|
#define CPUID1_ECX_SSE3 (1L)
|
||||||
|
#define CPUID1_ECX_SSSE3 (1L << 9)
|
||||||
|
#define CPUID1_ECX_SSE4_1 (1L << 19)
|
||||||
|
#define CPUID1_ECX_SSE4_2 (1L << 20)
|
||||||
|
|
||||||
#endif /* __SYS_VM_386_H__ */
|
#endif /* __SYS_VM_386_H__ */
|
||||||
|
|
|
@ -133,6 +133,9 @@ struct proc *t;
|
||||||
{ "Page fault", SIGSEGV, 386 }, /* not close */
|
{ "Page fault", SIGSEGV, 386 }, /* not close */
|
||||||
{ NIL_PTR, SIGILL, 0 }, /* probably software trap */
|
{ NIL_PTR, SIGILL, 0 }, /* probably software trap */
|
||||||
{ "Coprocessor error", SIGFPE, 386 },
|
{ "Coprocessor error", SIGFPE, 386 },
|
||||||
|
{ "Alignment check", SIGBUS, 386 },
|
||||||
|
{ "Machine check", SIGBUS, 386 },
|
||||||
|
{ "SIMD exception", SIGFPE, 386 },
|
||||||
};
|
};
|
||||||
register struct ex_s *ep;
|
register struct ex_s *ep;
|
||||||
struct proc *saved_proc;
|
struct proc *saved_proc;
|
||||||
|
|
|
@ -109,6 +109,9 @@
|
||||||
/* Exception vector numbers. */
|
/* Exception vector numbers. */
|
||||||
#define PAGE_FAULT_VECTOR 14
|
#define PAGE_FAULT_VECTOR 14
|
||||||
#define COPROC_ERR_VECTOR 16 /* coprocessor error */
|
#define COPROC_ERR_VECTOR 16 /* coprocessor error */
|
||||||
|
#define ALIGNMENT_CHECK_VECTOR 17
|
||||||
|
#define MACHINE_CHECK_VECTOR 18
|
||||||
|
#define SIMD_EXCEPTION_VECTOR 19 /* SIMD Floating-Point Exception (#XM) */
|
||||||
|
|
||||||
/* Descriptor structure offsets. */
|
/* Descriptor structure offsets. */
|
||||||
#define DESC_GRANULARITY 6 /* to granularity byte */
|
#define DESC_GRANULARITY 6 /* to granularity byte */
|
||||||
|
@ -152,6 +155,7 @@
|
||||||
#define AMD_CPUID_GEN_EDX 0x69746e65 /* ASCII value of "enti" */
|
#define AMD_CPUID_GEN_EDX 0x69746e65 /* ASCII value of "enti" */
|
||||||
#define AMD_CPUID_GEN_ECX 0x444d4163 /* ASCII value of "cAMD" */
|
#define AMD_CPUID_GEN_ECX 0x444d4163 /* ASCII value of "cAMD" */
|
||||||
|
|
||||||
|
/* fpu context should be saved in 16-byte aligned memory */
|
||||||
|
#define FPUALIGN 16
|
||||||
|
|
||||||
#endif /* _I386_ACONST_H */
|
#endif /* _I386_ACONST_H */
|
||||||
|
|
|
@ -4,38 +4,8 @@
|
||||||
|
|
||||||
#include <minix/sys_config.h>
|
#include <minix/sys_config.h>
|
||||||
#include "archconst.h"
|
#include "archconst.h"
|
||||||
|
#include <sys/stackframe.h>
|
||||||
typedef unsigned reg_t; /* machine register */
|
#include <sys/fpu.h>
|
||||||
typedef reg_t segdesc_t;
|
|
||||||
|
|
||||||
/* The stack frame layout is determined by the software, but for efficiency
|
|
||||||
* it is laid out so the assembly code to use it is as simple as possible.
|
|
||||||
* 80286 protected mode and all real modes use the same frame, built with
|
|
||||||
* 16-bit registers. Real mode lacks an automatic stack switch, so little
|
|
||||||
* is lost by using the 286 frame for it. The 386 frame differs only in
|
|
||||||
* having 32-bit registers and more segment registers. The same names are
|
|
||||||
* used for the larger registers to avoid differences in the code.
|
|
||||||
*/
|
|
||||||
struct stackframe_s { /* proc_ptr points here */
|
|
||||||
u16_t gs; /* last item pushed by save */
|
|
||||||
u16_t fs; /* ^ */
|
|
||||||
u16_t es; /* | */
|
|
||||||
u16_t ds; /* | */
|
|
||||||
reg_t di; /* di through cx are not accessed in C */
|
|
||||||
reg_t si; /* order is to match pusha/popa */
|
|
||||||
reg_t fp; /* bp */
|
|
||||||
reg_t st; /* hole for another copy of sp */
|
|
||||||
reg_t bx; /* | */
|
|
||||||
reg_t dx; /* | */
|
|
||||||
reg_t cx; /* | */
|
|
||||||
reg_t retreg; /* ax and above are all pushed by save */
|
|
||||||
reg_t retadr; /* return address for assembly code save() */
|
|
||||||
reg_t pc; /* ^ last item pushed by interrupt */
|
|
||||||
reg_t cs; /* | */
|
|
||||||
reg_t psw; /* | */
|
|
||||||
reg_t sp; /* | */
|
|
||||||
reg_t ss; /* these are pushed by CPU during interrupt */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct segdesc_s { /* segment descriptor for protected mode */
|
struct segdesc_s { /* segment descriptor for protected mode */
|
||||||
u16_t limit_low;
|
u16_t limit_low;
|
||||||
|
@ -68,6 +38,17 @@ struct pagefault
|
||||||
u32_t pf_flags; /* Pagefault flags on stack. */
|
u32_t pf_flags; /* Pagefault flags on stack. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* fpu_state_s is used in kernel proc table.
|
||||||
|
* Any changes in this structure requires changes in sconst.h,
|
||||||
|
* since this structure is used in proc structure. */
|
||||||
|
struct fpu_state_s {
|
||||||
|
union fpu_state_u *fpu_save_area_p; /* 16-aligned fpu_save_area */
|
||||||
|
/* fpu_image includes 512 bytes of image itself and
|
||||||
|
* additional 15 bytes required for manual 16-byte alignment. */
|
||||||
|
char fpu_image[527];
|
||||||
|
};
|
||||||
|
|
||||||
#define INMEMORY(p) (!p->p_seg.p_cr3 || ptproc == p)
|
#define INMEMORY(p) (!p->p_seg.p_cr3 || ptproc == p)
|
||||||
|
|
||||||
#endif /* #ifndef _I386_TYPES_H */
|
#endif /* #ifndef _I386_TYPES_H */
|
||||||
|
|
|
@ -47,6 +47,10 @@
|
||||||
.globl read_ss
|
.globl read_ss
|
||||||
.globl idt_reload /* reload idt when returning to monitor. */
|
.globl idt_reload /* reload idt when returning to monitor. */
|
||||||
|
|
||||||
|
.globl fninit /* non-waiting FPU initialization */
|
||||||
|
.globl fnstsw /* store status word (non-waiting) */
|
||||||
|
.globl fnstcw /* store control word (non-waiting) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The routines only guarantee to preserve the registers the C compiler
|
* The routines only guarantee to preserve the registers the C compiler
|
||||||
* expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
|
* expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
|
||||||
|
@ -536,6 +540,25 @@ read_ss:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* fpu_routines */
|
||||||
|
/*===========================================================================*/
|
||||||
|
fninit:
|
||||||
|
fninit
|
||||||
|
ret
|
||||||
|
|
||||||
|
fnstsw:
|
||||||
|
xor %eax, %eax
|
||||||
|
fnstsw %ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
fnstcw:
|
||||||
|
push %eax
|
||||||
|
mov 8(%esp), %eax
|
||||||
|
fnstcw (%eax)
|
||||||
|
pop %eax
|
||||||
|
ret
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* read_cr0 */
|
/* read_cr0 */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
|
@ -68,6 +68,7 @@ begbss:
|
||||||
#include <ibm/interrupt.h>
|
#include <ibm/interrupt.h>
|
||||||
#include <archconst.h>
|
#include <archconst.h>
|
||||||
#include "../../const.h"
|
#include "../../const.h"
|
||||||
|
#include "../../proc.h"
|
||||||
#include "sconst.h"
|
#include "sconst.h"
|
||||||
|
|
||||||
/* Selected 386 tss offsets. */
|
/* Selected 386 tss offsets. */
|
||||||
|
@ -101,11 +102,15 @@ begbss:
|
||||||
.globl general_protection
|
.globl general_protection
|
||||||
.globl page_fault
|
.globl page_fault
|
||||||
.globl copr_error
|
.globl copr_error
|
||||||
|
.globl alignment_check
|
||||||
|
.globl machine_check
|
||||||
|
.globl simd_exception
|
||||||
.globl params_size
|
.globl params_size
|
||||||
.globl params_offset
|
.globl params_offset
|
||||||
.globl mon_ds
|
.globl mon_ds
|
||||||
.globl schedcheck
|
.globl schedcheck
|
||||||
.globl dirtypde
|
.globl dirtypde
|
||||||
|
.globl lazy_fpu
|
||||||
|
|
||||||
.globl hwint00 /* handlers for hardware interrupts */
|
.globl hwint00 /* handlers for hardware interrupts */
|
||||||
.globl hwint01
|
.globl hwint01
|
||||||
|
@ -522,7 +527,33 @@ inval_opcode:
|
||||||
EXCEPTION_NO_ERR_CODE(INVAL_OP_VECTOR)
|
EXCEPTION_NO_ERR_CODE(INVAL_OP_VECTOR)
|
||||||
|
|
||||||
copr_not_available:
|
copr_not_available:
|
||||||
EXCEPTION_NO_ERR_CODE(COPROC_NOT_VECTOR)
|
TEST_INT_IN_KERNEL(4, copr_not_available_in_kernel)
|
||||||
|
clts
|
||||||
|
cld /* set direction flag to a known value */
|
||||||
|
SAVE_PROCESS_CTX_NON_LAZY(0)
|
||||||
|
lea P_MISC_FLAGS(%ebp), %ebx
|
||||||
|
movw (%ebx), %cx
|
||||||
|
and $MF_FPU_INITIALIZED, %cx
|
||||||
|
jnz 0f /* jump if FPU is already initialized */
|
||||||
|
orw $MF_FPU_INITIALIZED, (%ebx)
|
||||||
|
fninit
|
||||||
|
jmp copr_return
|
||||||
|
0: /* load FPU context for current process */
|
||||||
|
mov %ss:FP_SAVE_AREA_P(%ebp), %eax
|
||||||
|
cmp $0, osfxsr_feature
|
||||||
|
jz fp_l_no_fxsr /* FXSR is not avaible. */
|
||||||
|
fxrstor (%eax)
|
||||||
|
jmp copr_return
|
||||||
|
fp_l_no_fxsr:
|
||||||
|
frstor (%eax)
|
||||||
|
copr_return:
|
||||||
|
orw $MF_USED_FPU, (%ebx) /* fpu was used during last execution */
|
||||||
|
jmp restart
|
||||||
|
|
||||||
|
copr_not_available_in_kernel:
|
||||||
|
movl $NO_NUM, 4(%esp)
|
||||||
|
movl $0, (%esp)
|
||||||
|
call minix_panic
|
||||||
|
|
||||||
double_fault:
|
double_fault:
|
||||||
EXCEPTION_ERR_CODE(DOUBLE_FAULT_VECTOR)
|
EXCEPTION_ERR_CODE(DOUBLE_FAULT_VECTOR)
|
||||||
|
@ -548,6 +579,56 @@ page_fault:
|
||||||
copr_error:
|
copr_error:
|
||||||
EXCEPTION_NO_ERR_CODE(COPROC_ERR_VECTOR)
|
EXCEPTION_NO_ERR_CODE(COPROC_ERR_VECTOR)
|
||||||
|
|
||||||
|
alignment_check:
|
||||||
|
EXCEPTION_NO_ERR_CODE(ALIGNMENT_CHECK_VECTOR)
|
||||||
|
|
||||||
|
machine_check:
|
||||||
|
EXCEPTION_NO_ERR_CODE(MACHINE_CHECK_VECTOR)
|
||||||
|
|
||||||
|
simd_exception:
|
||||||
|
EXCEPTION_NO_ERR_CODE(SIMD_EXCEPTION_VECTOR)
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* lazy_fpu */
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* void lazy_fpu(struct proc *pptr)
|
||||||
|
* It's called, when we are on kernel stack.
|
||||||
|
* Actualy lazy code is just few lines, which check MF_USED_FPU,
|
||||||
|
* another part is save_init_fpu().
|
||||||
|
*/
|
||||||
|
lazy_fpu:
|
||||||
|
push %ebp
|
||||||
|
mov %esp, %ebp
|
||||||
|
push %eax
|
||||||
|
push %ebx
|
||||||
|
push %ecx
|
||||||
|
cmp $0, fpu_presence /* Do we have FPU? */
|
||||||
|
jz no_fpu_available
|
||||||
|
mov 8(%ebp), %eax /* Get pptr */
|
||||||
|
lea P_MISC_FLAGS(%eax), %ebx
|
||||||
|
movw (%ebx), %cx
|
||||||
|
and $MF_USED_FPU, %cx
|
||||||
|
jz 0f /* Don't save FPU */
|
||||||
|
mov %ss:FP_SAVE_AREA_P(%eax), %eax
|
||||||
|
cmp $0, osfxsr_feature
|
||||||
|
jz fp_s_no_fxsr /* FXSR is not avaible. */
|
||||||
|
fxsave (%eax)
|
||||||
|
fninit
|
||||||
|
jmp fp_saved
|
||||||
|
fp_s_no_fxsr:
|
||||||
|
fnsave (%eax)
|
||||||
|
fwait /* required for compatibility with processors prior pentium */
|
||||||
|
fp_saved:
|
||||||
|
andw $~MF_USED_FPU, (%ebx)
|
||||||
|
0: mov %cr0, %eax
|
||||||
|
or $0x00000008, %eax /* Set TS flag */
|
||||||
|
mov %eax, %cr0
|
||||||
|
no_fpu_available:
|
||||||
|
pop %ecx
|
||||||
|
pop %ebx
|
||||||
|
pop %eax
|
||||||
|
pop %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* write_cr3 */
|
/* write_cr3 */
|
||||||
|
|
|
@ -215,6 +215,9 @@ PUBLIC void idt_init(void)
|
||||||
{ general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
|
{ general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
|
||||||
{ page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
|
{ page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
|
||||||
{ copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
|
{ copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
|
||||||
|
{ alignment_check, ALIGNMENT_CHECK_VECTOR, INTR_PRIVILEGE },
|
||||||
|
{ machine_check, MACHINE_CHECK_VECTOR, INTR_PRIVILEGE },
|
||||||
|
{ simd_exception, SIMD_EXCEPTION_VECTOR, INTR_PRIVILEGE },
|
||||||
{ syscall_entry, SYS386_VECTOR, USER_PRIVILEGE },/* 386 system call */
|
{ syscall_entry, SYS386_VECTOR, USER_PRIVILEGE },/* 386 system call */
|
||||||
{ level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
|
{ level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
|
||||||
{ NULL, 0, 0}
|
{ NULL, 0, 0}
|
||||||
|
|
|
@ -37,6 +37,9 @@ void _PROTOTYPE( stack_exception, (void) );
|
||||||
void _PROTOTYPE( general_protection, (void) );
|
void _PROTOTYPE( general_protection, (void) );
|
||||||
void _PROTOTYPE( page_fault, (void) );
|
void _PROTOTYPE( page_fault, (void) );
|
||||||
void _PROTOTYPE( copr_error, (void) );
|
void _PROTOTYPE( copr_error, (void) );
|
||||||
|
void _PROTOTYPE( alignment_check, (void) );
|
||||||
|
void _PROTOTYPE( machine_check, (void) );
|
||||||
|
void _PROTOTYPE( simd_exception, (void) );
|
||||||
|
|
||||||
/* Software interrupt handlers, in numerical order. */
|
/* Software interrupt handlers, in numerical order. */
|
||||||
_PROTOTYPE( void trp, (void) );
|
_PROTOTYPE( void trp, (void) );
|
||||||
|
@ -84,6 +87,9 @@ _PROTOTYPE( void phys_memset, (phys_bytes ph, u32_t c, phys_bytes bytes));
|
||||||
_PROTOTYPE( void reload_ds, (void) );
|
_PROTOTYPE( void reload_ds, (void) );
|
||||||
_PROTOTYPE( void ia32_msr_read, (u32_t reg, u32_t * hi, u32_t * lo) );
|
_PROTOTYPE( void ia32_msr_read, (u32_t reg, u32_t * hi, u32_t * lo) );
|
||||||
_PROTOTYPE( void ia32_msr_write, (u32_t reg, u32_t hi, u32_t lo) );
|
_PROTOTYPE( void ia32_msr_write, (u32_t reg, u32_t hi, u32_t lo) );
|
||||||
|
_PROTOTYPE( void fninit, (void));
|
||||||
|
_PROTOTYPE( unsigned short fnstsw, (void));
|
||||||
|
_PROTOTYPE( void fnstcw, (unsigned short* cw));
|
||||||
|
|
||||||
/* protect.c */
|
/* protect.c */
|
||||||
struct tss_s {
|
struct tss_s {
|
||||||
|
|
|
@ -27,9 +27,11 @@
|
||||||
SPREG = PSWREG+W
|
SPREG = PSWREG+W
|
||||||
SSREG = SPREG+W
|
SSREG = SPREG+W
|
||||||
P_STACKTOP = SSREG+W
|
P_STACKTOP = SSREG+W
|
||||||
P_LDT_SEL = P_STACKTOP
|
FP_SAVE_AREA_P = P_STACKTOP
|
||||||
|
P_LDT_SEL = FP_SAVE_AREA_P + 532
|
||||||
P_CR3 = P_LDT_SEL+W
|
P_CR3 = P_LDT_SEL+W
|
||||||
P_LDT = P_CR3+W
|
P_LDT = P_CR3+W
|
||||||
|
P_MISC_FLAGS = P_LDT + 50
|
||||||
Msize = 9 /* size of a message in 32-bit words*/
|
Msize = 9 /* size of a message in 32-bit words*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,7 +117,7 @@
|
||||||
* displ is the stack displacement. In case of an exception, there are two extra
|
* displ is the stack displacement. In case of an exception, there are two extra
|
||||||
* value on the stack - error code and the exception number
|
* value on the stack - error code and the exception number
|
||||||
*/
|
*/
|
||||||
#define SAVE_PROCESS_CTX(displ) \
|
#define SAVE_PROCESS_CTX_NON_LAZY(displ) \
|
||||||
push %ebp ;\
|
push %ebp ;\
|
||||||
;\
|
;\
|
||||||
movl (CURR_PROC_PTR + 4 + displ)(%esp), %ebp ;\
|
movl (CURR_PROC_PTR + 4 + displ)(%esp), %ebp ;\
|
||||||
|
@ -130,4 +132,10 @@
|
||||||
RESTORE_KERNEL_SEGS ;\
|
RESTORE_KERNEL_SEGS ;\
|
||||||
SAVE_TRAP_CTX(displ, %ebp, %esi) ;
|
SAVE_TRAP_CTX(displ, %ebp, %esi) ;
|
||||||
|
|
||||||
|
#define SAVE_PROCESS_CTX(displ) \
|
||||||
|
SAVE_PROCESS_CTX_NON_LAZY(displ) ;\
|
||||||
|
push %ebp ;\
|
||||||
|
call lazy_fpu ;\
|
||||||
|
add $4, %esp ;
|
||||||
|
|
||||||
#endif /* __SCONST_H__ */
|
#endif /* __SCONST_H__ */
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#include <ibm/bios.h>
|
#include <ibm/bios.h>
|
||||||
#include <minix/portio.h>
|
#include <minix/portio.h>
|
||||||
#include <minix/u64.h>
|
#include <minix/u64.h>
|
||||||
|
#include <minix/cpufeature.h>
|
||||||
#include <a.out.h>
|
#include <a.out.h>
|
||||||
|
#include <archconst.h>
|
||||||
|
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "../../proc.h"
|
#include "../../proc.h"
|
||||||
|
@ -19,7 +21,12 @@
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CR0_EM 0x0004 /* set to enable trap on any FP instruction */
|
/* set MP and NE flags to handle FPU exceptions in native mode. */
|
||||||
|
#define CR0_MP_NE 0x0022
|
||||||
|
/* set CR4.OSFXSR[bit 9] if FXSR is supported. */
|
||||||
|
#define CR4_OSFXSR (1L<<9)
|
||||||
|
/* set OSXMMEXCPT[bit 10] if we provide #XM handler. */
|
||||||
|
#define CR4_OSXMMEXCPT (1L<<10)
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void ser_debug, (int c));
|
FORWARD _PROTOTYPE( void ser_debug, (int c));
|
||||||
|
|
||||||
|
@ -130,6 +137,51 @@ PUBLIC void tss_init(struct tss_s * tss, void * kernel_stack, unsigned cpu)
|
||||||
|
|
||||||
PUBLIC void arch_init(void)
|
PUBLIC void arch_init(void)
|
||||||
{
|
{
|
||||||
|
unsigned short cw, sw;
|
||||||
|
|
||||||
|
fninit();
|
||||||
|
sw = fnstsw();
|
||||||
|
fnstcw(&cw);
|
||||||
|
|
||||||
|
if((sw & 0xff) == 0 &&
|
||||||
|
(cw & 0x103f) == 0x3f) {
|
||||||
|
/* We have some sort of FPU, but don't check exact model.
|
||||||
|
* Set CR0_NE and CR0_MP to handle fpu exceptions
|
||||||
|
* in native mode. */
|
||||||
|
write_cr0(read_cr0() | CR0_MP_NE);
|
||||||
|
fpu_presence = 1;
|
||||||
|
if(_cpufeature(_CPUF_I386_FXSR)) {
|
||||||
|
register struct proc *rp;
|
||||||
|
phys_bytes aligned_fp_area;
|
||||||
|
|
||||||
|
/* Enable FXSR feature usage. */
|
||||||
|
write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT);
|
||||||
|
osfxsr_feature = 1;
|
||||||
|
|
||||||
|
for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; ++rp) {
|
||||||
|
/* FXSR requires 16-byte alignment of memory image,
|
||||||
|
* but unfortunately some old tools (probably linker)
|
||||||
|
* ignores ".balign 16" applied to our memory image.
|
||||||
|
* Thus we have to do manual alignment.
|
||||||
|
*/
|
||||||
|
aligned_fp_area = (phys_bytes) &rp->fpu_state.fpu_image;
|
||||||
|
if(aligned_fp_area % FPUALIGN) {
|
||||||
|
aligned_fp_area += FPUALIGN -
|
||||||
|
(aligned_fp_area % FPUALIGN);
|
||||||
|
}
|
||||||
|
rp->fpu_state.fpu_save_area_p =
|
||||||
|
(void *) aligned_fp_area;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
osfxsr_feature = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No FPU presents. */
|
||||||
|
fpu_presence = 0;
|
||||||
|
osfxsr_feature = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_APIC
|
#ifdef CONFIG_APIC
|
||||||
/*
|
/*
|
||||||
* this is setting kernel segments to cover most of the phys memory. The
|
* this is setting kernel segments to cover most of the phys memory. The
|
||||||
|
@ -153,11 +205,6 @@ PUBLIC void arch_init(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Set CR0_EM until we get FP context switching */
|
|
||||||
write_cr0(read_cr0() | CR0_EM);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COM1_BASE 0x3F8
|
#define COM1_BASE 0x3F8
|
||||||
|
|
|
@ -53,6 +53,8 @@ EXTERN time_t boottime;
|
||||||
EXTERN char params_buffer[512]; /* boot monitor parameters */
|
EXTERN char params_buffer[512]; /* boot monitor parameters */
|
||||||
EXTERN int minix_panicing;
|
EXTERN int minix_panicing;
|
||||||
EXTERN int locklevel;
|
EXTERN int locklevel;
|
||||||
|
EXTERN char fpu_presence;
|
||||||
|
EXTERN char osfxsr_feature; /* FXSAVE/FXRSTOR instructions support (SSEx) */
|
||||||
#define MAGICTEST 0xC0FFEE23
|
#define MAGICTEST 0xC0FFEE23
|
||||||
EXTERN u32_t magictest; /* global magic number */
|
EXTERN u32_t magictest; /* global magic number */
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
struct proc {
|
struct proc {
|
||||||
struct stackframe_s p_reg; /* process' registers saved in stack frame */
|
struct stackframe_s p_reg; /* process' registers saved in stack frame */
|
||||||
|
struct fpu_state_s fpu_state; /* process' fpu_regs saved lazily */
|
||||||
struct segframe p_seg; /* segment descriptors */
|
struct segframe p_seg; /* segment descriptors */
|
||||||
proc_nr_t p_nr; /* number of this process (for fast access) */
|
proc_nr_t p_nr; /* number of this process (for fast access) */
|
||||||
struct priv *p_priv; /* system privileges structure */
|
struct priv *p_priv; /* system privileges structure */
|
||||||
|
@ -214,6 +215,9 @@ struct proc {
|
||||||
#define MF_SC_ACTIVE 0x100 /* Syscall tracing: in a system call now */
|
#define MF_SC_ACTIVE 0x100 /* Syscall tracing: in a system call now */
|
||||||
#define MF_SC_DEFER 0x200 /* Syscall tracing: deferred system call */
|
#define MF_SC_DEFER 0x200 /* Syscall tracing: deferred system call */
|
||||||
#define MF_SC_TRACE 0x400 /* Syscall tracing: trigger syscall events */
|
#define MF_SC_TRACE 0x400 /* Syscall tracing: trigger syscall events */
|
||||||
|
#define MF_USED_FPU 0x800 /* process used fpu during last execution run */
|
||||||
|
#define MF_FPU_INITIALIZED 0x1000 /* process already used math, so fpu
|
||||||
|
* regs are significant (initialized)*/
|
||||||
|
|
||||||
/* Scheduling priorities for p_priority. Values must start at zero (highest
|
/* Scheduling priorities for p_priority. Values must start at zero (highest
|
||||||
* priority) and increment. Priorities of the processes in the boot image
|
* priority) and increment. Priorities of the processes in the boot image
|
||||||
|
|
|
@ -47,6 +47,9 @@ register message *m_ptr; /* pointer to request message */
|
||||||
/* No reply to EXEC call */
|
/* No reply to EXEC call */
|
||||||
RTS_LOCK_UNSET(rp, RTS_RECEIVING);
|
RTS_LOCK_UNSET(rp, RTS_RECEIVING);
|
||||||
|
|
||||||
|
/* Mark fpu_regs contents as not significant, so fpu
|
||||||
|
* will be initialized, when it's used next time. */
|
||||||
|
rp->p_misc_flags &= ~MF_FPU_INITIALIZED;
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
#endif /* USE_EXEC */
|
#endif /* USE_EXEC */
|
||||||
|
|
|
@ -73,9 +73,10 @@ register struct proc *rc; /* slot of process to clean up */
|
||||||
reset_timer(&priv(rc)->s_alarm_timer);
|
reset_timer(&priv(rc)->s_alarm_timer);
|
||||||
|
|
||||||
/* Make sure that the exiting process is no longer scheduled,
|
/* Make sure that the exiting process is no longer scheduled,
|
||||||
* and mark slot as FREE.
|
* and mark slot as FREE. Also mark saved fpu contents as not significant.
|
||||||
*/
|
*/
|
||||||
RTS_LOCK_SETFLAGS(rc, RTS_SLOT_FREE);
|
RTS_LOCK_SETFLAGS(rc, RTS_SLOT_FREE);
|
||||||
|
rc->p_misc_flags &= ~MF_FPU_INITIALIZED;
|
||||||
|
|
||||||
/* Release the process table slot. If this is a system process, also
|
/* Release the process table slot. If this is a system process, also
|
||||||
* release its privilege structure. Further cleanup is not needed at
|
* release its privilege structure. Further cleanup is not needed at
|
||||||
|
|
|
@ -25,6 +25,7 @@ register message *m_ptr; /* pointer to request message */
|
||||||
/* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */
|
/* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */
|
||||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
reg_t old_ldt_sel;
|
reg_t old_ldt_sel;
|
||||||
|
void *old_fpu_save_area_p;
|
||||||
#endif
|
#endif
|
||||||
register struct proc *rpc; /* child process pointer */
|
register struct proc *rpc; /* child process pointer */
|
||||||
struct proc *rpp; /* parent process pointer */
|
struct proc *rpp; /* parent process pointer */
|
||||||
|
@ -59,10 +60,16 @@ register message *m_ptr; /* pointer to request message */
|
||||||
gen = _ENDPOINT_G(rpc->p_endpoint);
|
gen = _ENDPOINT_G(rpc->p_endpoint);
|
||||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
old_ldt_sel = rpc->p_seg.p_ldt_sel; /* backup local descriptors */
|
old_ldt_sel = rpc->p_seg.p_ldt_sel; /* backup local descriptors */
|
||||||
|
old_fpu_save_area_p = rpc->fpu_state.fpu_save_area_p;
|
||||||
#endif
|
#endif
|
||||||
*rpc = *rpp; /* copy 'proc' struct */
|
*rpc = *rpp; /* copy 'proc' struct */
|
||||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */
|
rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */
|
||||||
|
rpc->fpu_state.fpu_save_area_p = old_fpu_save_area_p;
|
||||||
|
if(rpp->p_misc_flags & MF_FPU_INITIALIZED)
|
||||||
|
memcpy(rpc->fpu_state.fpu_save_area_p,
|
||||||
|
rpp->fpu_state.fpu_save_area_p,
|
||||||
|
FPU_XFP_SIZE);
|
||||||
#endif
|
#endif
|
||||||
if(++gen >= _ENDPOINT_MAX_GENERATION) /* increase generation */
|
if(++gen >= _ENDPOINT_MAX_GENERATION) /* increase generation */
|
||||||
gen = 1; /* generation number wraparound */
|
gen = 1; /* generation number wraparound */
|
||||||
|
|
|
@ -54,7 +54,14 @@ message *m_ptr; /* pointer to request message */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Restore the registers. */
|
/* Restore the registers. */
|
||||||
memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct sigregs));
|
memcpy(&rp->p_reg, &sc.sc_regs, sizeof(sigregs));
|
||||||
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
|
if(sc.sc_flags & MF_FPU_INITIALIZED)
|
||||||
|
{
|
||||||
|
memcpy(rp->fpu_state.fpu_save_area_p, &sc.fpu_state, FPU_XFP_SIZE);
|
||||||
|
rp->p_misc_flags |= MF_FPU_INITIALIZED; /* Restore math usage flag. */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ message *m_ptr; /* pointer to request message */
|
||||||
struct sigcontext sc, *scp;
|
struct sigcontext sc, *scp;
|
||||||
struct sigframe fr, *frp;
|
struct sigframe fr, *frp;
|
||||||
int proc_nr, r;
|
int proc_nr, r;
|
||||||
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
|
unsigned short int fp_error;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL);
|
if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL);
|
||||||
if (iskerneln(proc_nr)) return(EPERM);
|
if (iskerneln(proc_nr)) return(EPERM);
|
||||||
|
@ -43,11 +46,15 @@ message *m_ptr; /* pointer to request message */
|
||||||
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
|
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
|
||||||
|
|
||||||
/* Copy the registers to the sigcontext structure. */
|
/* Copy the registers to the sigcontext structure. */
|
||||||
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
|
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(sigregs));
|
||||||
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
|
if(rp->p_misc_flags & MF_FPU_INITIALIZED)
|
||||||
|
memcpy(&sc.fpu_state, rp->fpu_state.fpu_save_area_p, FPU_XFP_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Finish the sigcontext initialization. */
|
/* Finish the sigcontext initialization. */
|
||||||
sc.sc_flags = 0; /* unused at this time */
|
|
||||||
sc.sc_mask = smsg.sm_mask;
|
sc.sc_mask = smsg.sm_mask;
|
||||||
|
sc.sc_flags = 0 | rp->p_misc_flags & MF_FPU_INITIALIZED;
|
||||||
|
|
||||||
/* Copy the sigcontext structure to the user's stack. */
|
/* Copy the sigcontext structure to the user's stack. */
|
||||||
if((r=data_copy_vmcheck(SYSTEM, (vir_bytes) &sc, m_ptr->SIG_ENDPT,
|
if((r=data_copy_vmcheck(SYSTEM, (vir_bytes) &sc, m_ptr->SIG_ENDPT,
|
||||||
|
@ -61,7 +68,40 @@ message *m_ptr; /* pointer to request message */
|
||||||
fr.sf_fp = rp->p_reg.fp;
|
fr.sf_fp = rp->p_reg.fp;
|
||||||
rp->p_reg.fp = (reg_t) &frp->sf_fp;
|
rp->p_reg.fp = (reg_t) &frp->sf_fp;
|
||||||
fr.sf_scp = scp;
|
fr.sf_scp = scp;
|
||||||
fr.sf_code = 0; /* XXX - should be used for type of FP exception */
|
|
||||||
|
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||||
|
if (osfxsr_feature == 1) {
|
||||||
|
fp_error = sc.fpu_state.xfp_regs.fp_status &
|
||||||
|
~sc.fpu_state.xfp_regs.fp_control;
|
||||||
|
} else {
|
||||||
|
fp_error = sc.fpu_state.fpu_regs.fp_status &
|
||||||
|
~sc.fpu_state.fpu_regs.fp_control;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp_error & 0x001) { /* Invalid op */
|
||||||
|
/*
|
||||||
|
* swd & 0x240 == 0x040: Stack Underflow
|
||||||
|
* swd & 0x240 == 0x240: Stack Overflow
|
||||||
|
* User must clear the SF bit (0x40) if set
|
||||||
|
*/
|
||||||
|
fr.sf_code = FPE_FLTINV;
|
||||||
|
} else if (fp_error & 0x004) {
|
||||||
|
fr.sf_code = FPE_FLTDIV; /* Divide by Zero */
|
||||||
|
} else if (fp_error & 0x008) {
|
||||||
|
fr.sf_code = FPE_FLTOVF; /* Overflow */
|
||||||
|
} else if (fp_error & 0x012) {
|
||||||
|
fr.sf_code = FPE_FLTUND; /* Denormal, Underflow */
|
||||||
|
} else if (fp_error & 0x020) {
|
||||||
|
fr.sf_code = FPE_FLTRES; /* Precision */
|
||||||
|
} else {
|
||||||
|
fr.sf_code = 0; /* XXX - probably should be used for FPE_INTOVF or
|
||||||
|
* FPE_INTDIV */
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
fr.sf_code = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
fr.sf_signo = smsg.sm_signo;
|
fr.sf_signo = smsg.sm_signo;
|
||||||
fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
|
fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
|
||||||
|
|
||||||
|
@ -75,6 +115,9 @@ message *m_ptr; /* pointer to request message */
|
||||||
rp->p_reg.sp = (reg_t) frp;
|
rp->p_reg.sp = (reg_t) frp;
|
||||||
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
||||||
|
|
||||||
|
/* Signal handler should get clean FPU. */
|
||||||
|
rp->p_misc_flags &= ~MF_FPU_INITIALIZED;
|
||||||
|
|
||||||
if(!RTS_ISSET(rp, RTS_PROC_STOP)) {
|
if(!RTS_ISSET(rp, RTS_PROC_STOP)) {
|
||||||
struct proc *caller;
|
struct proc *caller;
|
||||||
caller = proc_addr(who_p);
|
caller = proc_addr(who_p);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
int _cpufeature(int cpufeature)
|
int _cpufeature(int cpufeature)
|
||||||
{
|
{
|
||||||
u32_t cpuid_feature_edx = 0;
|
u32_t cpuid_feature_edx = 0;
|
||||||
|
u32_t cpuid_feature_ecx = 0;
|
||||||
int proc;
|
int proc;
|
||||||
|
|
||||||
proc = getprocessor();
|
proc = getprocessor();
|
||||||
|
@ -18,7 +19,8 @@ int _cpufeature(int cpufeature)
|
||||||
u32_t params, a, b, c, d;
|
u32_t params, a, b, c, d;
|
||||||
_cpuid(0, ¶ms, &b, &c, &d);
|
_cpuid(0, ¶ms, &b, &c, &d);
|
||||||
if(params > 0) {
|
if(params > 0) {
|
||||||
_cpuid(1, &a, &b, &c, &cpuid_feature_edx);
|
_cpuid(1, &a, &b, &cpuid_feature_ecx,
|
||||||
|
&cpuid_feature_edx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +33,30 @@ int _cpufeature(int cpufeature)
|
||||||
return cpuid_feature_edx & CPUID1_EDX_APIC_ON_CHIP;
|
return cpuid_feature_edx & CPUID1_EDX_APIC_ON_CHIP;
|
||||||
case _CPUF_I386_TSC:
|
case _CPUF_I386_TSC:
|
||||||
return cpuid_feature_edx & CPUID1_EDX_TSC;
|
return cpuid_feature_edx & CPUID1_EDX_TSC;
|
||||||
|
case _CPUF_I386_FPU:
|
||||||
|
return cpuid_feature_edx & CPUID1_EDX_FPU;
|
||||||
|
case _CPUF_I386_SSEx:
|
||||||
|
return (cpuid_feature_edx & (CPUID1_EDX_FXSR |
|
||||||
|
CPUID1_EDX_SSE |
|
||||||
|
CPUID1_EDX_SSE2)) &&
|
||||||
|
(cpuid_feature_ecx & (CPUID1_ECX_SSE3 |
|
||||||
|
CPUID1_ECX_SSSE3 |
|
||||||
|
CPUID1_ECX_SSE4_1 |
|
||||||
|
CPUID1_ECX_SSE4_2));
|
||||||
|
case _CPUF_I386_FXSR:
|
||||||
|
return cpuid_feature_edx & CPUID1_EDX_FXSR;
|
||||||
|
case _CPUF_I386_SSE:
|
||||||
|
return cpuid_feature_edx & CPUID1_EDX_SSE;
|
||||||
|
case _CPUF_I386_SSE2:
|
||||||
|
return cpuid_feature_edx & CPUID1_EDX_SSE2;
|
||||||
|
case _CPUF_I386_SSE3:
|
||||||
|
return cpuid_feature_ecx & CPUID1_ECX_SSE3;
|
||||||
|
case _CPUF_I386_SSSE3:
|
||||||
|
return cpuid_feature_ecx & CPUID1_ECX_SSSE3;
|
||||||
|
case _CPUF_I386_SSE4_1:
|
||||||
|
return cpuid_feature_ecx & CPUID1_ECX_SSE4_1;
|
||||||
|
case _CPUF_I386_SSE4_2:
|
||||||
|
return cpuid_feature_ecx & CPUID1_ECX_SSE4_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue