@@ -1183,6 +1183,121 @@ static void svm_vcpu_destroy(struct vcpu *v)
passive_domain_destroy(v);
}
=20
+/*
+ * Emulate enough of interrupt injection to cover the DPL check (omitted b=
y
+ * hardware), and to work out whether it is safe to move %rip fowards for
+ * architectural trap vs fault semantics in the exception frame (which
+ * hardware won't cope with).
+ *
+ * The event parameter will be modified to a fault if necessary.
+ */
+static void svm_emul_swint_injection(struct x86_event *event)
+{
+ struct vcpu *curr =3D current;
+ const struct vmcb_struct *vmcb =3D curr->arch.hvm_svm.vmcb;
+ const struct cpu_user_regs *regs =3D guest_cpu_user_regs();
+ unsigned int trap =3D event->vector, type =3D event->type;
+ unsigned int fault =3D TRAP_gp_fault, ec =3D 0;
+ pagefault_info_t pfinfo;
+ struct segment_register cs, idtr;
+ unsigned int idte_size, idte_offset;
+ unsigned long idte_linear_addr;
+ struct { uint32_t a, b, c, d; } idte =3D {};
+ bool lm =3D vmcb_get_efer(vmcb) & EFER_LMA;
+ int rc;
+
+ if ( !(vmcb_get_cr0(vmcb) & X86_CR0_PE) )
+ goto raise_exception; /* TODO: support real-mode injection? */
+
+ idte_size =3D lm ? 16 : 8;
+ idte_offset =3D trap * idte_size;
+
+ /* ICEBP sets the External Event bit despite being an instruction. */
+ ec =3D (trap << 3) | X86_XEC_IDT |
+ (type =3D=3D X86_EVENTTYPE_PRI_SW_EXCEPTION ? X86_XEC_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 ( (regs->eflags & X86_EFLAGS_VM) &&
+ MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) !=3D 3 )
+ goto raise_exception;
+
+ /*
+ * Read all 8/16 bytes so the idtr limit check is applied properly to
+ * this entry, even though we don't look at all the words read.
+ */
+ hvm_get_segment_register(curr, x86_seg_cs, &cs);
+ hvm_get_segment_register(curr, x86_seg_idtr, &idtr);
+ if ( !hvm_virtual_to_linear_addr(x86_seg_idtr, &idtr, idte_offset,
+ idte_size, hvm_access_read,
+ &cs, &idte_linear_addr) )
+ goto raise_exception;
+
+ =20
----- Message truncated -----