x86/emul: Drop swint_emulate infrastructure

With the SVM injection logic capable of doing its own emulation, there is no
need for this hardware-specific assistance in the common emulator.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Tim Deegan <tim@xen.org>
This commit is contained in:
Andrew Cooper committed 2017-04-06 18:12:59 +01:00
1 parent 897d59a426
commit 52053d5fc2
6 files changed
+30 -238

No files matched your search

@@ -536,8 +536,7 @@ enum {
HOOK_put_fpu,
HOOK_invlpg,
HOOK_vmfunc,
OPTION_swint_emulation, /* Two bits */
CANONICALIZE_rip = OPTION_swint_emulation + 2,
CANONICALIZE_rip,
CANONICALIZE_rsp,
CANONICALIZE_rbp
};
@@ -577,19 +576,6 @@ static void disable_hooks(void)
MAYBE_DISABLE_HOOK(invlpg);
}
static void set_swint_support(struct x86_emulate_ctxt *ctxt)
{
unsigned int swint_opt = (input.options >> OPTION_swint_emulation) & 3;
static const enum x86_swint_emulation map[4] = {
x86_swint_emulate_none,
x86_swint_emulate_none,
x86_swint_emulate_icebp,
x86_swint_emulate_all
};
ctxt->swint_emulate = map[swint_opt];
}
/*
* Constrain input to architecturally-possible states where
* the emulator relies on these
@@ -693,8 +679,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
disable_hooks();
set_swint_support(&ctxt);
do {
/* FIXME: Until we actually implement SIGFPE handling properly */
setup_fpu_exception_handler();
-7
View File
@@ -2033,13 +2033,6 @@ void hvm_emulate_init_once(
hvmemul_ctxt->ctxt.regs = regs;
hvmemul_ctxt->ctxt.vendor = curr->domain->arch.cpuid->x86_vendor;
hvmemul_ctxt->ctxt.force_writeback = true;
if ( cpu_has_vmx )
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
else if ( cpu_has_svm_nrips )
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_icebp;
else
hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_all;
}
void hvm_emulate_init_per_insn(
-2
View File
@@ -5412,7 +5412,6 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
.vendor = d->arch.cpuid->x86_vendor,
.addr_size = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
.sp_size = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
.swint_emulate = x86_swint_emulate_none,
},
};
int rc;
@@ -5567,7 +5566,6 @@ int mmio_ro_do_page_fault(struct vcpu *v, unsigned long addr,
.vendor = v->domain->arch.cpuid->x86_vendor,
.addr_size = addr_size,
.sp_size = addr_size,
.swint_emulate = x86_swint_emulate_none,
.data = &mmio_ro_ctxt
};
int rc;
-1
View File
@@ -326,7 +326,6 @@ const struct x86_emulate_ops *shadow_init_emulation(
sh_ctxt->ctxt.regs = regs;
sh_ctxt->ctxt.vendor = v->domain->arch.cpuid->x86_vendor;
sh_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
/* Segment cache initialisation. Primed with CS. */
creg = hvm_get_seg_reg(x86_seg_cs, sh_ctxt);
+29 -158
View File
@@ -1999,142 +1999,6 @@ static bool umip_active(struct x86_emulate_ctxt *ctxt,
(cr4 & X86_CR4_UMIP);
}
/* Inject a software interrupt/exception, emulating if needed. */
static int inject_swint(enum x86_swint_type type,
uint8_t vector, uint8_t insn_len,
struct x86_emulate_ctxt *ctxt,
const struct x86_emulate_ops *ops)
{
int rc, error_code, fault_type = EXC_GP;
/*
* Without hardware support, injecting software interrupts/exceptions is
* problematic.
*
* All software methods of generating exceptions (other than BOUND) yield
* traps, so eip in the exception frame needs to point after the
* instruction, not at it.
*
* However, if injecting it as a hardware exception causes a fault during
* delivery, our adjustment of eip will cause the fault to be reported
* after the faulting instruction, not pointing to it.
*
* Therefore, eip can only safely be wound forwards if we are certain that
* injecting an equivalent hardware exception won't fault, which means
* emulating everything the processor would do on a control transfer.
*
* However, emulation of complete control transfers is very complicated.
* All we care about is that guest userspace cannot avoid the descriptor
* DPL check by using the Xen emulator, and successfully invoke DPL=0
* descriptors.
*
* Any OS which would further fault during injection is going to receive a
* double fault anyway, and won't be in a position to care that the
* faulting eip is incorrect.
*/
if ( (ctxt->swint_emulate == x86_swint_emulate_all) ||
((ctxt->swint_emulate == x86_swint_emulate_icebp) &&
(type == x86_swint_icebp)) )
{
if ( !in_realmode(ctxt, ops) )
{
unsigned int idte_size, idte_offset;
struct { uint32_t a, b, c, d; } idte = {};
int lm = in_longmode(ctxt, ops);
if ( lm < 0 )
return X86EMUL_UNHANDLEABLE;
idte_size = lm ? 16 : 8;
idte_offset = vector * idte_size;
/* icebp sets the External Event bit despite being an instruction. */
error_code = (vector << 3) | ECODE_IDT |
(type == x86_swint_icebp ? ECODE_EXT : 0);
/*
* TODO - this does not cover the v8086 mode with CR4.VME case
* correctly, but falls on the safe side from the point of view of
* a 32bit OS. Someone with many TUITs can see about reading the
* TSS Software Interrupt Redirection bitmap.
*/
if ( (ctxt->regs->eflags & X86_EFLAGS_VM) &&
((ctxt->regs->eflags & X86_EFLAGS_IOPL) != X86_EFLAGS_IOPL) )
goto raise_exn;
/*
* Read all 8/16 bytes so the idtr limit check is applied properly
* to this entry, even though we only end up looking at the 2nd
* word.
*/
switch ( rc = ops->read(x86_seg_idtr, idte_offset,
&idte, idte_size, ctxt) )
{
case X86EMUL_OKAY:
break;
case X86EMUL_EXCEPTION:
if ( !ctxt->event_pending )
goto raise_exn;
/* fallthrough */
default:
return rc;
}
/* This must be an interrupt, trap, or task gate. */
#ifdef __XEN__
switch ( (idte.b >> 8) & 0x1f )
{
case SYS_DESC_irq_gate:
case SYS_DESC_trap_gate:
break;
case SYS_DESC_irq_gate16:
case SYS_DESC_trap_gate16:
case SYS_DESC_task_gate:
if ( !lm )
break;
/* fall through */
default:
goto raise_exn;
}
#endif
/* The 64-bit high half's type must be zero. */
if ( idte.d & 0x1f00 )
goto raise_exn;
/* icebp counts as a hardware event, and bypasses the dpl check. */
if ( type != x86_swint_icebp )
{
int cpl = get_cpl(ctxt, ops);
fail_if(cpl < 0);
if ( cpl > ((idte.b >> 13) & 3) )
goto raise_exn;
}
/* Is this entry present? */
if ( !(idte.b & (1u << 15)) )
{
fault_type = EXC_NP;
goto raise_exn;
}
}
}
x86_emul_software_event(type, vector, insn_len, ctxt);
rc = X86EMUL_OKAY;
done:
return rc;
raise_exn:
generate_exception(fault_type, error_code);
}
static void adjust_bnd(struct x86_emulate_ctxt *ctxt,
const struct x86_emulate_ops *ops, enum vex_pfx pfx)
{
@@ -3101,7 +2965,6 @@ x86_emulate(
struct operand src = { .reg = PTR_POISON };
struct operand dst = { .reg = PTR_POISON };
unsigned long cr4;
enum x86_swint_type swint_type;
struct fpu_insn_ctxt fic = { .type = X86EMUL_FPU_none, .exn_raised = -1 };
struct x86_emulate_stub stub = {};
DECLARE_ALIGNED(mmval_t, mmval);
@@ -4103,25 +3966,38 @@ x86_emulate(
goto done;
break;
case 0xcc: /* int3 */
src.val = EXC_BP;
swint_type = x86_swint_int3;
goto swint;
case 0xcd: /* int imm8 */
swint_type = x86_swint_int;
swint:
rc = inject_swint(swint_type, (uint8_t)src.val,
_regs.r(ip) - ctxt->regs->r(ip),
ctxt, ops) ? : X86EMUL_EXCEPTION;
goto done;
case 0xce: /* into */
if ( !(_regs.eflags & X86_EFLAGS_OF) )
break;
src.val = EXC_OF;
swint_type = x86_swint_into;
goto swint;
/* Fallthrough */
case 0xcc: /* int3 */
case 0xcd: /* int imm8 */
case 0xf1: /* int1 (icebp) */
ASSERT(!ctxt->event_pending);
switch ( ctxt->opcode )
{
case 0xcc: /* int3 */
ctxt->event.vector = EXC_BP;
ctxt->event.type = X86_EVENTTYPE_SW_EXCEPTION;
break;
case 0xcd: /* int imm8 */
ctxt->event.vector = imm1;
ctxt->event.type = X86_EVENTTYPE_SW_INTERRUPT;
break;
case 0xce: /* into */
ctxt->event.vector = EXC_OF;
ctxt->event.type = X86_EVENTTYPE_SW_EXCEPTION;
break;
case 0xf1: /* icebp */
ctxt->event.vector = EXC_DB;
ctxt->event.type = X86_EVENTTYPE_PRI_SW_EXCEPTION;
break;
}
ctxt->event.error_code = X86_EVENT_NO_EC;
ctxt->event.insn_len = _regs.r(ip) - ctxt->regs->r(ip);
ctxt->event_pending = true;
rc = X86EMUL_EXCEPTION;
goto done;
case 0xcf: /* iret */ {
unsigned long sel, eip, eflags;
@@ -4782,11 +4658,6 @@ x86_emulate(
goto done;
break;
case 0xf1: /* int1 (icebp) */
src.val = EXC_DB;
swint_type = x86_swint_icebp;
goto swint;
case 0xf4: /* hlt */
generate_exception_if(!mode_ring0(), EXC_GP, 0);
ctxt->retire.hlt = true;
-53
View File
@@ -60,27 +60,6 @@ static inline bool is_x86_system_segment(enum x86_segment seg)
return seg >= x86_seg_tr && seg < x86_seg_none;
}
/* Classification of the types of software generated interrupts/exceptions. */
enum x86_swint_type {
x86_swint_icebp, /* 0xf1 */
x86_swint_int3, /* 0xcc */
x86_swint_into, /* 0xce */
x86_swint_int, /* 0xcd $n */
};
/*
* How much help is required with software event injection?
*
* All software events return from x86_emulate() with X86EMUL_EXCEPTION and
* fault-like semantics. This just controls whether the emulator performs
* presence/dpl/etc checks and possibly raises exceptions instead.
*/
enum x86_swint_emulation {
x86_swint_emulate_none, /* Hardware supports all software injection properly */
x86_swint_emulate_icebp,/* Help needed with `icebp` (0xf1) */
x86_swint_emulate_all, /* Help needed with all software events */
};
/*
* x86 event types. This enumeration is valid for:
* Intel VMX: {VM_ENTRY,VM_EXIT,IDT_VECTORING}_INTR_INFO[10:8]
@@ -472,9 +451,6 @@ struct x86_emulate_ctxt
* Input-only state:
*/
/* Software event injection support. */
enum x86_swint_emulation swint_emulate;
/* CPU vendor (X86_VENDOR_UNKNOWN for "don't care") */
unsigned char vendor;
@@ -699,35 +675,6 @@ static inline void x86_emul_pagefault(
ctxt->event_pending = true;
}
static inline void x86_emul_software_event(
enum x86_swint_type type, uint8_t vector, uint8_t insn_len,
struct x86_emulate_ctxt *ctxt)
{
ASSERT(!ctxt->event_pending);
switch ( type )
{
case x86_swint_icebp:
ctxt->event.type = X86_EVENTTYPE_PRI_SW_EXCEPTION;
break;
case x86_swint_int3:
case x86_swint_into:
ctxt->event.type = X86_EVENTTYPE_SW_EXCEPTION;
break;
case x86_swint_int:
ctxt->event.type = X86_EVENTTYPE_SW_INTERRUPT;
break;
}
ctxt->event.vector = vector;
ctxt->event.error_code = X86_EVENT_NO_EC;
ctxt->event.insn_len = insn_len;
ctxt->event_pending = true;
}
static inline void x86_emul_reset_event(struct x86_emulate_ctxt *ctxt)
{
ctxt->event_pending = false;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.