On 04/10/21 01:02, Josh Poimboeuf wrote:
That said, I have no idea what's going in that code or why kvm_fastop_exception() is clearing %esi.
It's handled here (which definitely qualifies as "funky sh*t"): asm("push %[flags]; popf; " CALL_NOSPEC " ; pushf; pop %[flags]\n" : "+a"(ctxt->dst.val), "+d"(ctxt->src.val), [flags]"+D"(flags), [thunk_target]"+S"(fop), ASM_CALL_CONSTRAINT : "c"(ctxt->src2.val)); ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK); if (!fop) /* exception is returned in fop variable */ return emulate_de(ctxt); and documented here: /* * fastop functions have a special calling convention: * * dst: rax (in/out) * src: rdx (in/out) * src2: rcx (in) * flags: rflags (in/out) * ex: rsi (in:fastop pointer, out:zero if exception) * * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for * different operand sizes can be reached by calculation, rather than a jump * table (which would be bigger than the code). */ The fastop stuff saves quite a few clock cycles and lines of code, by avoiding complicated emulation of x86 flags. I'll check out the .global annotations, since they are indeed unnecessary. Paolo