| From 3039f36e15846e3e231af1f018be9dcf639bf93c Mon Sep 17 00:00:00 2001 |
| From: Oliver Upton <oupton@google.com> |
| Date: Tue, 4 Feb 2020 15:26:31 -0800 |
| Subject: [PATCH] KVM: nVMX: Check IO instruction VM-exit conditions |
| |
| commit 35a571346a94fb93b5b3b6a599675ef3384bc75c upstream. |
| |
| Consult the 'unconditional IO exiting' and 'use IO bitmaps' VM-execution |
| controls when checking instruction interception. If the 'use IO bitmaps' |
| VM-execution control is 1, check the instruction access against the IO |
| bitmaps to determine if the instruction causes a VM-exit. |
| |
| Signed-off-by: Oliver Upton <oupton@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c |
| index 95ab9d7b1960..736ceceb2ebe 100644 |
| --- a/arch/x86/kvm/vmx/nested.c |
| +++ b/arch/x86/kvm/vmx/nested.c |
| @@ -4935,7 +4935,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu, |
| struct vmcs12 *vmcs12) |
| { |
| unsigned long exit_qualification; |
| - unsigned int port; |
| + unsigned short port; |
| int size; |
| |
| if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS)) |
| diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c |
| index 9e5a4d5b3025..c6b597e13f46 100644 |
| --- a/arch/x86/kvm/vmx/vmx.c |
| +++ b/arch/x86/kvm/vmx/vmx.c |
| @@ -7009,6 +7009,39 @@ static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu) |
| to_vmx(vcpu)->req_immediate_exit = true; |
| } |
| |
| +static int vmx_check_intercept_io(struct kvm_vcpu *vcpu, |
| + struct x86_instruction_info *info) |
| +{ |
| + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); |
| + unsigned short port; |
| + bool intercept; |
| + int size; |
| + |
| + if (info->intercept == x86_intercept_in || |
| + info->intercept == x86_intercept_ins) { |
| + port = info->src_val; |
| + size = info->dst_bytes; |
| + } else { |
| + port = info->dst_val; |
| + size = info->src_bytes; |
| + } |
| + |
| + /* |
| + * If the 'use IO bitmaps' VM-execution control is 0, IO instruction |
| + * VM-exits depend on the 'unconditional IO exiting' VM-execution |
| + * control. |
| + * |
| + * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps. |
| + */ |
| + if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS)) |
| + intercept = nested_cpu_has(vmcs12, |
| + CPU_BASED_UNCOND_IO_EXITING); |
| + else |
| + intercept = nested_vmx_check_io_bitmaps(vcpu, port, size); |
| + |
| + return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; |
| +} |
| + |
| static int vmx_check_intercept(struct kvm_vcpu *vcpu, |
| struct x86_instruction_info *info, |
| enum x86_intercept_stage stage) |
| @@ -7016,18 +7049,30 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu, |
| struct vmcs12 *vmcs12 = get_vmcs12(vcpu); |
| struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt; |
| |
| + switch (info->intercept) { |
| /* |
| * RDPID causes #UD if disabled through secondary execution controls. |
| * Because it is marked as EmulateOnUD, we need to intercept it here. |
| */ |
| - if (info->intercept == x86_intercept_rdtscp && |
| - !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) { |
| - ctxt->exception.vector = UD_VECTOR; |
| - ctxt->exception.error_code_valid = false; |
| - return X86EMUL_PROPAGATE_FAULT; |
| - } |
| + case x86_intercept_rdtscp: |
| + if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) { |
| + ctxt->exception.vector = UD_VECTOR; |
| + ctxt->exception.error_code_valid = false; |
| + return X86EMUL_PROPAGATE_FAULT; |
| + } |
| + break; |
| + |
| + case x86_intercept_in: |
| + case x86_intercept_ins: |
| + case x86_intercept_out: |
| + case x86_intercept_outs: |
| + return vmx_check_intercept_io(vcpu, info); |
| |
| /* TODO: check more intercepts... */ |
| + default: |
| + break; |
| + } |
| + |
| return X86EMUL_UNHANDLEABLE; |
| } |
| |
| -- |
| 2.7.4 |
| |