[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v8 08/12] x86emul: support FLDENV and FRSTOR
On 05/05/2020 09:16, Jan Beulich wrote: > While the Intel SDM claims that FRSTOR itself may raise #MF upon > completion, this was confirmed by Intel to be a doc error which will be > corrected in due course; behavior is like FLDENV, and like old hard copy > manuals describe it. Otherwise we'd have to emulate the insn by filling > st(N) in suitable order, followed by FLDENV. I wouldn't bother calling this out at all. We know the doc is going to be corrected in the next revision, and "what we would have done if the docs error was in fact accurate" only adds confusion to an already complicated change. > --- a/xen/arch/x86/x86_emulate/x86_emulate.c > +++ b/xen/arch/x86/x86_emulate/x86_emulate.c > @@ -857,6 +857,7 @@ struct x86_emulate_state { > blk_NONE, > blk_enqcmd, > #ifndef X86EMUL_NO_FPU > + blk_fld, /* FLDENV, FRSTOR */ > blk_fst, /* FNSTENV, FNSAVE */ > #endif > blk_movdir, > @@ -4948,21 +4949,14 @@ x86_emulate( > dst.bytes = 4; > emulate_fpu_insn_memdst(b, modrm_reg & 7, dst.val); > break; > - case 4: /* fldenv - TODO */ > - state->fpu_ctrl = true; > - goto unimplemented_insn; > - case 5: /* fldcw m2byte */ > - state->fpu_ctrl = true; > - fpu_memsrc16: > - if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val, > - 2, ctxt)) != X86EMUL_OKAY ) > - goto done; > - emulate_fpu_insn_memsrc(b, modrm_reg & 7, src.val); > - break; The commit message should however note that the larger-than-expected diff is purely code motion for case 5, to arrange fldenv to fall though into fstenv. Alternatively, could be pulled out into an earlier patch. > + case 4: /* fldenv */ > + /* Raise #MF now if there are pending unmasked exceptions. */ > + emulate_fpu_insn_stub(0xd9, 0xd0 /* fnop */); > + /* fall through */ > case 6: /* fnstenv */ > fail_if(!ops->blk); > - state->blk = blk_fst; > - /* REX is meaningless for this insn by this point. */ > + state->blk = modrm_reg & 2 ? blk_fst : blk_fld; > + /* REX is meaningless for these insns by this point. */ > rex_prefix = in_protmode(ctxt, ops); > if ( (rc = ops->blk(ea.mem.seg, ea.mem.off, NULL, > op_bytes > 2 ? sizeof(struct x87_env32) > @@ -4972,6 +4966,14 @@ x86_emulate( > goto done; > state->fpu_ctrl = true; > break; > + case 5: /* fldcw m2byte */ > + state->fpu_ctrl = true; > + fpu_memsrc16: > + if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val, > + 2, ctxt)) != X86EMUL_OKAY ) > + goto done; > + emulate_fpu_insn_memsrc(b, modrm_reg & 7, src.val); > + break; > case 7: /* fnstcw m2byte */ > state->fpu_ctrl = true; > fpu_memdst16: > @@ -5124,13 +5126,14 @@ x86_emulate( > dst.bytes = 8; > emulate_fpu_insn_memdst(b, modrm_reg & 7, dst.val); > break; > - case 4: /* frstor - TODO */ > - state->fpu_ctrl = true; > - goto unimplemented_insn; > + case 4: /* frstor */ > + /* Raise #MF now if there are pending unmasked exceptions. */ > + emulate_fpu_insn_stub(0xd9, 0xd0 /* fnop */); > + /* fall through */ > case 6: /* fnsave */ > fail_if(!ops->blk); > - state->blk = blk_fst; > - /* REX is meaningless for this insn by this point. */ > + state->blk = modrm_reg & 2 ? blk_fst : blk_fld; > + /* REX is meaningless for these insns by this point. */ > rex_prefix = in_protmode(ctxt, ops); > if ( (rc = ops->blk(ea.mem.seg, ea.mem.off, NULL, > op_bytes > 2 ? sizeof(struct x87_env32) > + 80 > @@ -11648,6 +11651,89 @@ int x86_emul_blk( > > #ifndef X86EMUL_NO_FPU > > + case blk_fld: > + ASSERT(!data); > + > + /* state->rex_prefix carries CR0.PE && !EFLAGS.VM setting */ > + switch ( bytes ) > + { > + case sizeof(fpstate.env): > + case sizeof(fpstate): > + memcpy(&fpstate.env, ptr, sizeof(fpstate.env)); > + if ( !state->rex_prefix ) > + { > + unsigned int fip = fpstate.env.mode.real.fip_lo + > + (fpstate.env.mode.real.fip_hi << 16); > + unsigned int fdp = fpstate.env.mode.real.fdp_lo + > + (fpstate.env.mode.real.fdp_hi << 16); > + unsigned int fop = fpstate.env.mode.real.fop; > + > + fpstate.env.mode.prot.fip = fip & 0xf; > + fpstate.env.mode.prot.fcs = fip >> 4; > + fpstate.env.mode.prot.fop = fop; > + fpstate.env.mode.prot.fdp = fdp & 0xf; > + fpstate.env.mode.prot.fds = fdp >> 4; The same comments about comments apply here from the previous patch. ~Andrew
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |