On 2013-02-18 10:36, Gleb Natapov wrote: > On Mon, Feb 18, 2013 at 10:17:14AM +0100, Jan Kiszka wrote: >> From: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> >> >> This prevents trapping L2 I/O exits if L1 has neither unconditional nor >> bitmap-based exiting enabled. Furthermore, it implements I/O bitmap >> handling. We still exit unconditionally in case the CPU does not provide >> information for ins/outs. >> >> Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> >> --- >> >> Changes in v5: >> - still exit unconditionally if CPU refuses to provide exit >> information on ins/outs >> >> arch/x86/kvm/vmx.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++- >> 1 files changed, 56 insertions(+), 2 deletions(-) >> >> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c >> index 6667042..ccc7c17 100644 >> --- a/arch/x86/kvm/vmx.c >> +++ b/arch/x86/kvm/vmx.c >> @@ -651,6 +651,7 @@ static struct vmcs_config { >> int size; >> int order; >> u32 revision_id; >> + u32 vmx_basic_high; >> u32 pin_based_exec_ctrl; >> u32 cpu_based_exec_ctrl; >> u32 cpu_based_2nd_exec_ctrl; >> @@ -752,6 +753,11 @@ static inline bool vm_need_tpr_shadow(struct kvm *kvm) >> return (cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm)); >> } >> >> +static inline bool cpu_has_stringio_exit_info(void) >> +{ >> + return vmcs_config.vmx_basic_high & (VMX_BASIC_INOUT >> 32); >> +} >> + >> static inline bool cpu_has_secondary_exec_ctrls(void) >> { >> return vmcs_config.cpu_based_exec_ctrl & >> @@ -2635,6 +2641,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) >> vmcs_conf->size = vmx_msr_high & 0x1fff; >> vmcs_conf->order = get_order(vmcs_config.size); >> vmcs_conf->revision_id = vmx_msr_low; >> + vmcs_conf->vmx_basic_high = vmx_msr_high; >> >> vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control; >> vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control; >> @@ -5908,6 +5915,54 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { >> static const int kvm_vmx_max_exit_handlers = >> ARRAY_SIZE(kvm_vmx_exit_handlers); >> >> +static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu, >> + struct vmcs12 *vmcs12) >> +{ >> + unsigned long exit_qualification; >> + gpa_t bitmap, last_bitmap; >> + u16 port; >> + int size; >> + u8 b; >> + >> + if (nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING)) >> + return 1; >> + >> + if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS)) >> + return 0; >> + >> + /* TODO: for older CPUs, derive access width from instruction */ >> + if (!cpu_has_stringio_exit_info()) >> + return 1; >> + > > Sigh, actually I am stupid :( The information that is not available > on older cpus is address size in "VM-exit instruction information", > not operand size on exit qualification, so your v4 is correct. Except > handling of port wrap around: > > If the “use I/O bitmaps” VM-execution control is 1, the instruction > causes a VM exit if it attempts to access an I/O port corresponding to a > bit set to 1 in the appropriate I/O bitmap (see Section 24.6.4). If an > I/O operation “wraps around” the 16-bit I/O-port space (accesses > ports FFFFH and 0000H), the I/O instruction causes a VM exit (the > “unconditional I/O exiting” VM-execution control is ignored if the > “use I/O bitmaps” VM-execution control is 1). Ah, indeed. OK, let's see if this "simple" patch manages to reach two-digit revision numbers... Jan
Attachment:
signature.asc
Description: OpenPGP digital signature