@@ -320,6 +320,10 @@ struct nested_vmx {
struct vmcs *l1_vmcs;
/* L2 must run next, and mustn't decide to exit to L1. */
bool nested_run_pending;
+ /* true if last exit was of L2, and had a valid idt_vectoring_info */
+ bool valid_idt_vectoring_info;
+ /* These are saved if valid_idt_vectoring_info */
+ u32 vm_exit_instruction_len, idt_vectoring_error_code;
};
enum vmcs_field_type {
@@ -5460,6 +5464,22 @@ static void fixup_rmode_irq(struct vcpu_
| vmx->rmode.irq.vector;
}
+static void nested_handle_valid_idt_vectoring_info(struct vcpu_vmx *vmx)
+{
+ int irq = vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
+ int type = vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
+ int errCodeValid = vmx->idt_vectoring_info &
+ VECTORING_INFO_DELIVER_CODE_MASK;
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ irq | type | INTR_INFO_VALID_MASK | errCodeValid);
+
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+ vmx->nested.vm_exit_instruction_len);
+ if (errCodeValid)
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
+ vmx->nested.idt_vectoring_error_code);
+}
+
static inline void sync_cached_regs_to_vmcs(struct kvm_vcpu *vcpu)
{
if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
@@ -5481,6 +5501,9 @@ static void vmx_vcpu_run(struct kvm_vcpu
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ if (vmx->nested.nested_mode && vmx->nested.valid_idt_vectoring_info)
+ nested_handle_valid_idt_vectoring_info(vmx);
+
/* Record the guest's net vcpu time for enforced NMI injections. */
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
vmx->entry_time = ktime_get();
@@ -5600,6 +5623,16 @@ static void vmx_vcpu_run(struct kvm_vcpu
| (1 << VCPU_EXREG_PDPTR));
vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+
+ vmx->nested.valid_idt_vectoring_info = vmx->nested.nested_mode &&
+ (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+ if (vmx->nested.valid_idt_vectoring_info) {
+ vmx->nested.vm_exit_instruction_len =
+ vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ vmx->nested.idt_vectoring_error_code =
+ vmcs_read32(IDT_VECTORING_ERROR_CODE);
+ }
+
if (vmx->rmode.irq.pending)
fixup_rmode_irq(vmx);