}
break;
}
+ case X86EMUL_UNIMPLEMENTED:
+ ASSERT_UNREACHABLE();
+ /* Fall-through */
default:
BUG();
}
+ ASSERT(rc != X86EMUL_UNIMPLEMENTED);
+
if ( rc != X86EMUL_OKAY )
return rc;
rc = hvmemul_do_io(is_mmio, addr, reps, size, dir, df, 0,
(uintptr_t)buffer);
+
+ ASSERT(rc != X86EMUL_UNIMPLEMENTED);
+
if ( rc == X86EMUL_UNHANDLEABLE && dir == IOREQ_READ )
memset(buffer, 0xff, size);
rc = hvmemul_do_io(is_mmio, addr, &count, size, dir, df, 1,
ram_gpa);
+ ASSERT(rc != X86EMUL_UNIMPLEMENTED);
+
if ( rc == X86EMUL_OKAY )
v->arch.hvm_vcpu.hvm_io.mmio_retry = (count < *reps);
switch ( rc )
{
case X86EMUL_UNHANDLEABLE:
+ case X86EMUL_UNIMPLEMENTED:
hvm_dump_emulation_state(XENLOG_G_WARNING, "MMCFG", &ctxt);
break;
case X86EMUL_EXCEPTION:
* consistent with X86EMUL_RETRY.
*/
return;
+ case X86EMUL_UNIMPLEMENTED:
case X86EMUL_UNHANDLEABLE:
hvm_dump_emulation_state(XENLOG_G_DEBUG, "Mem event", &ctx);
hvm_inject_hw_exception(trapnr, errcode);
stub.func); \
generate_exception_if(res_.fields.trapnr == EXC_UD, EXC_UD); \
domain_crash(current->domain); \
- goto cannot_emulate; \
+ rc = X86EMUL_UNHANDLEABLE; \
+ goto done; \
} \
} while (0)
#else
d = twobyte_table[0x3a].desc;
break;
default:
- rc = X86EMUL_UNHANDLEABLE;
+ rc = X86EMUL_UNRECOGNIZED;
goto done;
}
}
}
else
{
- rc = X86EMUL_UNHANDLEABLE;
+ rc = X86EMUL_UNRECOGNIZED;
goto done;
}
default:
ASSERT_UNREACHABLE();
- return X86EMUL_UNHANDLEABLE;
+ return X86EMUL_UNIMPLEMENTED;
}
if ( ea.type == OP_MEM )
break;
case 4: /* fldenv - TODO */
state->fpu_ctrl = true;
- goto cannot_emulate;
+ goto unimplemented_insn;
case 5: /* fldcw m2byte */
state->fpu_ctrl = true;
if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val,
break;
case 6: /* fnstenv - TODO */
state->fpu_ctrl = true;
- goto cannot_emulate;
+ goto unimplemented_insn;
case 7: /* fnstcw m2byte */
state->fpu_ctrl = true;
emulate_fpu_insn_memdst("fnstcw", dst.val);
case 4: /* frstor - TODO */
case 6: /* fnsave - TODO */
state->fpu_ctrl = true;
- goto cannot_emulate;
+ goto unimplemented_insn;
case 7: /* fnstsw m2byte */
state->fpu_ctrl = true;
emulate_fpu_insn_memdst("fnstsw", dst.val);
#undef _GRP7
default:
- goto cannot_emulate;
+ goto unimplemented_insn;
}
break;
}
/* vpsll{w,d} $imm8,{x,y}mm,{x,y}mm */
break;
default:
- goto cannot_emulate;
+ goto unrecognized_insn;
}
simd_0f_shift_imm:
generate_exception_if(ea.type != OP_REG, EXC_UD);
case 6: /* psllq $imm8,mm */
goto simd_0f_shift_imm;
}
- goto cannot_emulate;
+ goto unrecognized_insn;
case X86EMUL_OPC_66(0x0f, 0x73):
case X86EMUL_OPC_VEX_66(0x0f, 0x73):
/* vpslldq $imm8,{x,y}mm,{x,y}mm */
goto simd_0f_shift_imm;
}
- goto cannot_emulate;
+ goto unrecognized_insn;
case X86EMUL_OPC(0x0f, 0x77): /* emms */
case X86EMUL_OPC_VEX(0x0f, 0x77): /* vzero{all,upper} */
case 0: /* extrq $imm8,$imm8,xmm */
break;
default:
- goto cannot_emulate;
+ goto unrecognized_insn;
}
/* fall through */
case X86EMUL_OPC_F2(0x0f, 0x78): /* insertq $imm8,$imm8,xmm,xmm */
goto done;
break;
default:
- goto cannot_emulate;
+ goto unimplemented_insn;
}
break;
vcpu_must_have(avx);
goto stmxcsr;
}
- goto cannot_emulate;
+ goto unrecognized_insn;
case X86EMUL_OPC_F3(0x0f, 0xae): /* Grp15 */
fail_if(modrm_mod != 3);
switch ( modrm_reg & 7 )
{
default:
- goto cannot_emulate;
+ goto unrecognized_insn;
-#ifdef HAVE_GAS_RDRAND
case 6: /* rdrand */
+#ifdef HAVE_GAS_RDRAND
generate_exception_if(rep_prefix(), EXC_UD);
host_and_vcpu_must_have(rdrand);
dst = ea;
if ( carry )
_regs.eflags |= X86_EFLAGS_CF;
break;
+#else
+ goto unimplemented_insn;
#endif
case 7: /* rdseed / rdpid */
host_and_vcpu_must_have(bmi1);
break;
default:
- goto cannot_emulate;
+ goto unrecognized_insn;
}
generate_exception_if(vex.l, EXC_UD);
host_and_vcpu_must_have(tbm);
break;
default:
- goto cannot_emulate;
+ goto unrecognized_insn;
}
xop_09_rm_rv:
host_and_vcpu_must_have(tbm);
goto xop_09_rm_rv;
}
- goto cannot_emulate;
+ goto unrecognized_insn;
case X86EMUL_OPC_XOP(0a, 0x10): /* bextr imm,r/m,r */
{
}
default:
- cannot_emulate:
- rc = X86EMUL_UNHANDLEABLE;
+ unimplemented_insn:
+ rc = X86EMUL_UNIMPLEMENTED;
+ goto done;
+ unrecognized_insn:
+ rc = X86EMUL_UNRECOGNIZED;
goto done;
}
if ( (d & DstMask) != DstMem )
{
ASSERT_UNREACHABLE();
- goto cannot_emulate;
+ rc = X86EMUL_UNHANDLEABLE;
+ goto done;
}
break;
}
* Undefined behavior when used anywhere else.
*/
#define X86EMUL_DONE 4
+ /*
+ * Current instruction is not implemented by the emulator.
+ * This value should only be returned by the core emulator when a valid
+ * opcode is found but the execution logic for that instruction is missing.
+ * It should NOT be returned by any of the x86_emulate_ops callbacks.
+ */
+#define X86EMUL_UNIMPLEMENTED 5
+ /*
+ * The current instruction's opcode is not valid.
+ * If this error code is returned by a function, an #UD trap should be
+ * raised by the final consumer of it.
+ *
+ * TODO: For the moment X86EMUL_UNRECOGNIZED and X86EMUL_UNIMPLEMENTED
+ * can be used interchangeably therefore raising an #UD trap is not
+ * strictly expected for now.
+ */
+#define X86EMUL_UNRECOGNIZED X86EMUL_UNIMPLEMENTED
/* FPU sub-types which may be requested via ->get_fpu(). */
enum x86_emulate_fpu_type {