From 7b31442c78f0be63fb022f2b245b473022b9de41 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sun, 11 Dec 2022 20:43:38 +0500 Subject: [PATCH] cpu: completely remove PM fpu state Let back-ends to deal with save/restore. --- src/base/emu-i386/cpu.c | 21 +++++++++-------- src/base/emu-i386/do_vm86.c | 4 ++-- src/base/emu-i386/kvm.c | 4 +++- src/base/emu-i386/simx86/codegen-x86.h | 2 -- src/base/emu-i386/simx86/cpu-emu.c | 29 ++++++++++++------------ src/base/emu-i386/simx86/interp.c | 2 ++ src/base/emu-i386/simx86/syncpu.h | 11 +++++---- src/base/init/config.c | 2 +- src/dosext/dpmi/dnative.c | 12 ++++++---- src/dosext/dpmi/dpmi.c | 6 ----- src/include/cpu.h | 31 ++++++++++---------------- 11 files changed, 58 insertions(+), 66 deletions(-) diff --git a/src/base/emu-i386/cpu.c b/src/base/emu-i386/cpu.c index 5f9c098db2..9d9eef67ad 100644 --- a/src/base/emu-i386/cpu.c +++ b/src/base/emu-i386/cpu.c @@ -93,7 +93,7 @@ static unsigned int TRs[2] = #endif /* fpu_state needs to be paragraph aligned for fxrstor/fxsave */ -fpregset_t vm86_fpu_state; +struct emu_fpstate vm86_fpu_state __attribute__((aligned(16))); fenv_t dosemu_fenv; static void fpu_reset(void); @@ -242,13 +242,13 @@ static void fpu_init(void) static void fpu_reset(void) { #ifdef __x86_64__ - vm86_fpu_state->cwd = 0x0040; - vm86_fpu_state->swd = 0; - vm86_fpu_state->ftw = 0x5555; //bochs + vm86_fpu_state.cwd = 0x0040; + vm86_fpu_state.swd = 0; + vm86_fpu_state.ftw = 0x5555; //bochs #else - vm86_fpu_state->cw = 0x40; - vm86_fpu_state->sw = 0; - vm86_fpu_state->tag = 0x5555; // bochs + vm86_fpu_state.cw = 0x40; + vm86_fpu_state.sw = 0; + vm86_fpu_state.tag = 0x5555; // bochs #endif } @@ -263,9 +263,9 @@ static void fpu_io_write(ioport_t port, Bit8u val) case 0xf0: /* not sure about this */ #ifdef __x86_64__ - vm86_fpu_state->swd &= ~0x8000; + vm86_fpu_state.swd &= ~0x8000; #else - vm86_fpu_state->sw &= ~0x8000; + vm86_fpu_state.sw &= ~0x8000; #endif break; case 0xf1: @@ -300,8 +300,7 @@ void cpu_setup(void) io_dev.handler_name = "Math Coprocessor"; port_register_handler(io_dev, 0); - vm86_fpu_state = aligned_alloc(16, sizeof(*vm86_fpu_state)); - savefpstate(*vm86_fpu_state); + savefpstate(vm86_fpu_state); #ifdef FE_NOMASK_ENV feenableexcept(FE_DIVBYZERO | FE_OVERFLOW); #endif diff --git a/src/base/emu-i386/do_vm86.c b/src/base/emu-i386/do_vm86.c index 43a87d54c7..8395874b9e 100644 --- a/src/base/emu-i386/do_vm86.c +++ b/src/base/emu-i386/do_vm86.c @@ -446,7 +446,7 @@ static int true_vm86(union vm86_union *x) int ret; uint32_t old_flags = REG(eflags); - loadfpstate(*vm86_fpu_state); + loadfpstate(vm86_fpu_state); again: #if 0 ret = vm86(&x->vm86ps); @@ -464,7 +464,7 @@ static int true_vm86(union vm86_union *x) * TODO: check kernel version */ REG(eflags) |= (old_flags & VIP); - savefpstate(*vm86_fpu_state); + savefpstate(vm86_fpu_state); /* there is no real need to save and restore the FPU state of the emulator itself: savefpstate (fnsave) also resets the current FPU state using fninit; fesetenv then restores trapping of division by diff --git a/src/base/emu-i386/kvm.c b/src/base/emu-i386/kvm.c index f11fddfde5..3526830587 100644 --- a/src/base/emu-i386/kvm.c +++ b/src/base/emu-i386/kvm.c @@ -1075,6 +1075,7 @@ int kvm_dpmi(cpuctx_t *scp) } if (_trapno == 0x10) { +#if 0 struct kvm_fpu fpu; ioctl(vcpufd, KVM_GET_FPU, &fpu); #ifdef __x86_64__ @@ -1095,9 +1096,10 @@ int kvm_dpmi(cpuctx_t *scp) __fpstate->cssel = _cs; __fpstate->dataoff = fpu.last_dp; __fpstate->datasel = _ds; +#endif + print_exception_info(scp); #endif dbug_printf("coprocessor exception, calling IRQ13\n"); -// print_exception_info(scp); pic_untrigger(13); pic_request(13); ret = DPMI_RET_DOSEMU; diff --git a/src/base/emu-i386/simx86/codegen-x86.h b/src/base/emu-i386/simx86/codegen-x86.h index a7f98916dd..602dc861fd 100644 --- a/src/base/emu-i386/simx86/codegen-x86.h +++ b/src/base/emu-i386/simx86/codegen-x86.h @@ -39,8 +39,6 @@ #include "trees.h" #include "vgaemu.h" -#define HOST_ARCH_X86 - #define TAILSIZE 7 #define TAILFIX 1 diff --git a/src/base/emu-i386/simx86/cpu-emu.c b/src/base/emu-i386/simx86/cpu-emu.c index 3b2d8c4ca2..3d8ad9feba 100644 --- a/src/base/emu-i386/simx86/cpu-emu.c +++ b/src/base/emu-i386/simx86/cpu-emu.c @@ -523,6 +523,8 @@ static void Reg2Cpu (int mode) SetSegReal(SREG(gs),Ofs_GS); trans_addr = LONG_CS + TheCPU.eip; + /* FPU state is loaded later on demand for JIT, not used for simulator */ + TheCPU.fpstate = &vm86_fpu_state; if (debug_level('e')>1) { if (debug_level('e')==9) e_printf("Reg2Cpu< vm86=%08x dpm=%08x emu=%08x\n%s\n", REG(eflags),get_FLAGS(TheCPU.eflags),TheCPU.eflags, @@ -567,6 +569,14 @@ void Cpu2Reg (void) clear_IF(); REG(eflags) |= EFLAGS_IF; + if (TheCPU.fpstate == NULL) { + if (!CONFIG_CPUSIM) + savefpstate(vm86_fpu_state); +#ifdef HOST_ARCH_X86 + fesetenv(&dosemu_fenv); +#endif + } + if (debug_level('e')>1) e_printf("Cpu2Reg< vm86=%08x dpm=%08x emu=%08x\n", REG(eflags),get_FLAGS(TheCPU.eflags),TheCPU.eflags); } @@ -600,9 +610,7 @@ static void Scp2Cpu (cpuctx_t *scp) TheCPU.cr2 = _cr2; TheCPU.df_increments = (TheCPU.eflags&DF)?0xfcfeff:0x040201; - /* __fpstate is loaded later on demand for JIT, not used for simulator */ - TheCPU.fpstate = &TheCPU._fpstate; - TheCPU._fpstate = *__fpstate; + TheCPU.fpstate = &vm86_fpu_state; } /* @@ -642,17 +650,17 @@ static void Cpu2Scp (cpuctx_t *scp, int trapno) */ if (!TheCPU.err) _err = 0; //??? if (TheCPU.fpstate == NULL) { - if (!CONFIG_CPUSIM) { - savefpstate(TheCPU._fpstate); - *get_fpstate(scp) = TheCPU._fpstate; - } + if (!CONFIG_CPUSIM) + savefpstate(vm86_fpu_state); /* there is no real need to save and restore the FPU state of the emulator itself: savefpstate (fnsave) also resets the current FPU state using fninit; fesetenv then restores trapping of division by zero and overflow which is good enough for calling FPU-using routines. */ +#ifdef HOST_ARCH_X86 fesetenv(&dosemu_fenv); +#endif } /* push running flags - same as eflags, RF is cosmetic */ @@ -966,8 +974,6 @@ int e_vm86(void) e_sigpa_count = 0; mode = ADDR16 | DATA16 | MREALA; TheCPU.StackMask = 0x0000ffff; - /* FPU state is loaded later on demand for JIT, not used for simulator */ - TheCPU.fpstate = vm86_fpu_state; #ifdef SKIP_VM86_TRACE demusav=debug_level('e'); if (debug_level('e')) set_debug_level('e', 1); #endif @@ -1053,11 +1059,6 @@ int e_vm86(void) while (retval < 0); /* ------ OUTER LOOP -- exit to user level ---------------------- */ - if (TheCPU.fpstate == NULL) { - if (!CONFIG_CPUSIM) savefpstate(*vm86_fpu_state); - fesetenv(&dosemu_fenv); - } - if (debug_level('e')>1) e_printf("EMU86: retval=%s\n", retdescs[retval&7]); diff --git a/src/base/emu-i386/simx86/interp.c b/src/base/emu-i386/simx86/interp.c index 38b328b708..b673d1eefd 100644 --- a/src/base/emu-i386/simx86/interp.c +++ b/src/base/emu-i386/simx86/interp.c @@ -2725,6 +2725,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; } } b &= 7; +#ifdef HOST_ARCH_X86 if (TheCPU.fpstate) { /* For simulator, only need to mask all exceptions; for JIT, load emulated FPU state @@ -2735,6 +2736,7 @@ intop3b: { int op = ArOpsFR[D_MO(opc)]; loadfpstate(*TheCPU.fpstate); TheCPU.fpstate = NULL; } +#endif if (sim) { if (Fp87_op(exop,b)) { TheCPU.err = -96; return P0; } } diff --git a/src/base/emu-i386/simx86/syncpu.h b/src/base/emu-i386/simx86/syncpu.h index b5ae879da1..10381fdbda 100644 --- a/src/base/emu-i386/simx86/syncpu.h +++ b/src/base/emu-i386/simx86/syncpu.h @@ -147,18 +147,17 @@ typedef struct { unsigned short TR_SEL; DTR TR; - /* if not NULL, points to emulated FPU state - if NULL, emulator uses FPU instructions, so flags that - dosemu needs to restore its own FPU environment. */ - fpregset_t fpstate; - void (*stub_read_8)(void); void (*stub_read_16)(void); void (*stub_read_32)(void); /* should be moved to TSS once implemented */ struct revectored_struct int_revectored; - struct _libc_fpstate _fpstate __attribute__((aligned(16))); + + /* if not NULL, points to emulated FPU state + if NULL, emulator uses FPU instructions, so flags that + dosemu needs to restore its own FPU environment. */ + emu_fpregset_t fpstate; } SynCPU; union _SynCPU { diff --git a/src/base/init/config.c b/src/base/init/config.c index 8c286794dc..30072984c1 100644 --- a/src/base/init/config.c +++ b/src/base/init/config.c @@ -728,7 +728,7 @@ static void read_cpu_info(void) #endif #ifdef __i386__ if (cpuflags && (strstr(cpuflags, "fxsr")) && - sizeof(*vm86_fpu_state) == (112+512)) { + sizeof(vm86_fpu_state) == (112+512)) { config.cpufxsr = 1; if (cpuflags && strstr(cpuflags, "sse")) config.cpusse = 1; diff --git a/src/dosext/dpmi/dnative.c b/src/dosext/dpmi/dnative.c index 7050eaf97a..9a26750533 100644 --- a/src/dosext/dpmi/dnative.c +++ b/src/dosext/dpmi/dnative.c @@ -85,8 +85,9 @@ static void copy_to_dpmi(sigcontext_t *scp, cpuctx_t *s) _C(trapno); _C(err); _C(cr2); - if (scp->fpstate) - memcpy(scp->fpstate, get_fpstate(s), sizeof(struct _fpstate)); + static_assert(sizeof(struct _fpstate) == sizeof(vm86_fpu_state), + "size mismatch"); + scp->fpstate = (struct _fpstate *)&vm86_fpu_state; } static void copy_to_emu(cpuctx_t *d, sigcontext_t *scp) @@ -111,8 +112,11 @@ static void copy_to_emu(cpuctx_t *d, sigcontext_t *scp) _D(trapno); _D(err); _D(cr2); - if (scp->fpstate) - memcpy(get_fpstate(d), _scp_fpstate, sizeof(*get_fpstate(d))); + if (scp->fpstate && scp->fpstate != (struct _fpstate *)&vm86_fpu_state) { + static_assert(sizeof(struct _fpstate) == sizeof(vm86_fpu_state), + "size mismatch"); + memcpy(&vm86_fpu_state, scp->fpstate, sizeof(struct _fpstate)); + } } #if WANT_SIGRETURN_WA diff --git a/src/dosext/dpmi/dpmi.c b/src/dosext/dpmi/dpmi.c index fa1b0d0a45..79b83a1721 100644 --- a/src/dosext/dpmi/dpmi.c +++ b/src/dosext/dpmi/dpmi.c @@ -3997,11 +3997,6 @@ void dpmi_init(void) _es = ES; _fs = 0; _gs = 0; -#ifdef __linux__ - /* fpu_state needs to be paragraph aligned for fxrstor/fxsave */ -// __fpstate = aligned_alloc(16, sizeof(*__fpstate)); - *__fpstate = *vm86_fpu_state; -#endif NOCARRY; rm_to_pm_regs(&DPMI_CLIENT.stack_frame, ~0); /* on cpu-emu we work with IOPL=3 to avoid doom work-around */ @@ -4611,7 +4606,6 @@ static void do_dpmi_hlt(cpuctx_t *scp, uint8_t *lina, void *sp) DPMI_CLIENT.in_dpmi_pm_stack); pm_to_rm_regs(scp, ~0); - old_ctx.fpregs = scp->fpregs; restore_pm_regs(&old_ctx); curscp = scp; scp = &old_ctx; diff --git a/src/include/cpu.h b/src/include/cpu.h index 6d786d96fb..64897855b8 100644 --- a/src/include/cpu.h +++ b/src/include/cpu.h @@ -61,22 +61,20 @@ union word { struct { Bit8u l, h; } b; } MAY_ALIAS; -#ifndef __linux__ #define __ctx(fld) fld #ifdef __x86_64__ /* taken from glibc, don't blame me :) */ -typedef long long int greg_t; -struct _libc_fpxreg +struct __fpxreg { unsigned short int __ctx(significand)[4]; unsigned short int __ctx(exponent); unsigned short int __glibc_reserved1[3]; }; -struct _libc_xmmreg +struct __xmmreg { __uint32_t __ctx(element)[4]; }; -struct _libc_fpstate +struct emu_fpstate { /* 64-bit FXSAVE format. */ uint16_t __ctx(cwd); @@ -87,20 +85,17 @@ struct _libc_fpstate uint64_t __ctx(rdp); uint32_t __ctx(mxcsr); uint32_t __ctx(mxcr_mask); - struct _libc_fpxreg _st[8]; - struct _libc_xmmreg _xmm[16]; + struct __fpxreg _st[8]; + struct __xmmreg _xmm[16]; uint32_t __glibc_reserved1[24]; }; -/* Structure to describe FPU registers. */ -typedef struct _libc_fpstate *fpregset_t; #else -typedef int greg_t; -struct _libc_fpreg +struct __fpreg { unsigned short int __ctx(significand)[4]; unsigned short int __ctx(exponent); }; -struct _libc_fpstate +struct emu_fpstate { unsigned long int __ctx(cw); unsigned long int __ctx(sw); @@ -109,11 +104,12 @@ struct _libc_fpstate unsigned long int __ctx(cssel); unsigned long int __ctx(dataoff); unsigned long int __ctx(datasel); - struct _libc_fpreg _st[8]; + struct __fpreg _st[8]; unsigned long int __ctx(status); }; #endif -#endif +/* Structure to describe FPU registers. */ +typedef struct emu_fpstate *emu_fpregset_t; union g_reg { greg_t reg; @@ -245,7 +241,7 @@ static inline dosaddr_t FAR2ADDR(far_t ptr) { #define peek(seg, off) (READ_WORD(SEGOFF2LINEAR(seg, off))) -extern fpregset_t vm86_fpu_state; +extern struct emu_fpstate vm86_fpu_state; extern fenv_t dosemu_fenv; /* @@ -490,10 +486,9 @@ struct pm_regs { unsigned trapno; unsigned err; unsigned long cr2; - struct _libc_fpstate fpregs; }; typedef struct pm_regs cpuctx_t; -#define REGS_SIZE offsetof(struct pm_regs, fpregs) +#define REGS_SIZE offsetof(struct pm_regs, trapno) #define _es (scp->es) #define _ds (scp->ds) @@ -518,7 +513,6 @@ typedef struct pm_regs cpuctx_t; #define get_trapno(s) ((s)->trapno) #define get_err(s) ((s)->err) #define get_cr2(s) ((s)->cr2) -#define get_fpstate(s) (&(s)->fpregs) #define _edi get_edi(scp) #define _esi get_esi(scp) #define _ebp get_ebp(scp) @@ -547,7 +541,6 @@ typedef struct pm_regs cpuctx_t; #define _eflags_ (scp->eflags) #define _cr2 (scp->cr2) #define _trapno (scp->trapno) -#define __fpstate (&scp->fpregs) /* compatibility */ #define _rdi _edi #define _rsi _esi