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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
00a418faef
commit
679b9c333a
|
@ -4281,7 +4281,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
|
||||||
struct vmcs12 *vmcs12)
|
struct vmcs12 *vmcs12)
|
||||||
{
|
{
|
||||||
unsigned long exit_qualification;
|
unsigned long exit_qualification;
|
||||||
unsigned int port;
|
unsigned short port;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
|
if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
|
||||||
|
@ -10754,6 +10754,39 @@ static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
|
||||||
to_vmx(vcpu)->nested.sync_shadow_vmcs = true;
|
to_vmx(vcpu)->nested.sync_shadow_vmcs = 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,
|
static int vmx_check_intercept(struct kvm_vcpu *vcpu,
|
||||||
struct x86_instruction_info *info,
|
struct x86_instruction_info *info,
|
||||||
enum x86_intercept_stage stage)
|
enum x86_intercept_stage stage)
|
||||||
|
@ -10761,18 +10794,30 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
|
||||||
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
|
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
|
||||||
struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
|
struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
|
||||||
|
|
||||||
|
switch (info->intercept) {
|
||||||
/*
|
/*
|
||||||
* RDPID causes #UD if disabled through secondary execution controls.
|
* RDPID causes #UD if disabled through secondary execution controls.
|
||||||
* Because it is marked as EmulateOnUD, we need to intercept it here.
|
* Because it is marked as EmulateOnUD, we need to intercept it here.
|
||||||
*/
|
*/
|
||||||
if (info->intercept == x86_intercept_rdtscp &&
|
case x86_intercept_rdtscp:
|
||||||
!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
|
if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
|
||||||
ctxt->exception.vector = UD_VECTOR;
|
ctxt->exception.vector = UD_VECTOR;
|
||||||
ctxt->exception.error_code_valid = false;
|
ctxt->exception.error_code_valid = false;
|
||||||
return X86EMUL_PROPAGATE_FAULT;
|
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... */
|
/* TODO: check more intercepts... */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return X86EMUL_UNHANDLEABLE;
|
return X86EMUL_UNHANDLEABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user