KVM: VMX: Add Posted Interrupt supporting
v7 cover KVM: VMX: Add Posted Interrupt supporting
From: Yang Zhang <[email protected]>
The follwoing patches are adding the Posted Interrupt supporting to KVM:
The first patch enables the feature 'acknowledge interrupt on vmexit'.Since it is required by Posted interrupt, we need to enable it firstly.
And the subsequent patches are adding the posted interrupt supporting:
Posted Interrupt allows APIC interrupts to inject into guest directly without any vmexit.
- When delivering a interrupt to guest, if target vcpu is running, update Posted-interrupt requests bitmap and send a notification event to the vcpu. Then the vcpu will handle this interrupt automatically, without any software involvemnt.
- If target vcpu is not running or there already a notification event pending in the vcpu, do nothing. The interrupt will be handled by next vm entry
Changes from v6 to v7:
* Update TMR when ioapic/lapic's id/ldr/dfr is changed. According to SDM, Software should not touch virual apic page when target vcpu in non-root mode. Obviously, set TMR when delivering interrupt is break the rule. So only update TMR when in target vcpu's context.
* Clear outstanding notification bit before sync pir to irr.
* Sync pit to irr before touch irr.
Changes from v5 to v6:
* Split sync_pir_to_irr into two functions one to query whether PIR is empty and the other to perform the sync.
* Add comments to explain how vmx_sync_pir_to_irr() work.
* Rebase on top of KVM upstream.
Changes from v4 to v5:
* Add per cpu count for posted IPI handler.
* Dont' check irr when delivering interrupt. Since we can not get interrupt coalesced info with Posted Interrupt. So there is no need to check the irr. There is another patch will changed current interrupt coalesced logic. Before it, we will not turn on Posted Interrupt.
* Clear outstanding notification bit after call local_irq_disable, but before check request. As Marcelo suggested, we can ensure the IPI not lost in this way
* Remove the spinlock. Same as item 2, if not need to get coalesced info, then no need the lock.
* Rebase on top of KVM upstream.
Yang Zhang (7):
KVM: VMX: Enable acknowledge interupt on vmexit
KVM: VMX: Register a new IPI for posted interrupt
KVM: VMX: Check the posted interrupt capability
KVM: Call common update function when ioapic entry changed.
KVM: Set TMR when programming ioapic entry
KVM: VMX: Add the algorithm of deliver posted interrupt
KVM: VMX: Use posted interrupt to deliver virtual interrupt
arch/ia64/kvm/lapic.h | 6 - arch/x86/include/asm/entry_arch.h | 4 + arch/x86/include/asm/hardirq.h | 3 + arch/x86/include/asm/hw_irq.h | 1 + arch/x86/include/asm/irq_vectors.h | 5 + arch/x86/include/asm/kvm_host.h | 3 + arch/x86/include/asm/vmx.h | 4 + arch/x86/kernel/entry_64.S | 5 + arch/x86/kernel/irq.c | 22 ++++ arch/x86/kernel/irqinit.c | 4 + arch/x86/kvm/lapic.c | 59 +++++++--- arch/x86/kvm/lapic.h | 2 + arch/x86/kvm/svm.c | 12 ++ arch/x86/kvm/vmx.c | 208 +++++++++++++++++++++++++++++++----- arch/x86/kvm/x86.c | 20 +++- include/linux/kvm_host.h | 4 +- virt/kvm/ioapic.c | 33 ++++-- virt/kvm/ioapic.h | 8 +- virt/kvm/irq_comm.c | 4 +- virt/kvm/kvm_main.c | 5 +- 20 files changed, 336 insertions(+), 76 deletions(-)
PATCH v7 1/7 KVM: VMX: Enable acknowledge interupt on vmexit
From: Yang Zhang <[email protected]>
The "acknowledge interrupt on exit" feature controls processor behavior for external interrupt acknowledgement. When this control is set, the processor acknowledges the interrupt controller to acquire the interrupt vector on VM exit.
After enabling this feature, an interrupt which arrived when target cpu is running in vmx non-root mode will be handled by vmx handler instead of handler in idt. Currently, vmx handler only fakes an interrupt stack and jump to idt table to let real handler to handle it. Further, we will recognize the interrupt and only delivery the interrupt which not belong to current vcpu through idt table. The interrupt which belonged to current vcpu will be handled inside vmx handler. This will reduce the interrupt handle cost of KVM.
Also, interrupt enable logic is changed if this feature is turnning on:
Before this patch, hypervior call local_irq_enable() to enable it directly. Now IF bit is set on interrupt stack frame, and will be enabled on a return from interrupt handler if exterrupt interrupt exists. If no external interrupt, still call local_irq_enable() to enable it.
Refer to Intel SDM volum 3, chapter 33.2.
--- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/svm.c | 6 ++++ arch/x86/kvm/vmx.c | 58 ++++++++++++++++++++++++++++++++++++--- arch/x86/kvm/x86.c | 4 ++- 4 files changed, 64 insertions(+), 5 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -730,6 +730,7 @@ struct kvm_x86_ops {int (*check_intercept)(struct kvm_vcpu *vcpu,struct x86_instruction_info *info,enum x86_intercept_stage stage); +void (*handle_external_intr)(struct kvm_vcpu *vcpu); };struct kvm_arch_async_pf {
arch/x86/kvm/svm.c +6 -0
@@ -4233,6 +4233,11 @@ out:return ret; } +static void svm_handle_external_intr (struct kvm_vcpu *vcpu) +{ +local_irq_enable (); +} +static struct kvm_x86_ops svm_x86_ops = { .cpu_has_kvm_support = has_svm, .disabled_by_bios = is_disabled,
@@ -4328,6 +4333,7 @@ static struct kvm_x86_ops svm_x86_ops = { .set_tdp_cr3 = set_tdp_cr3, .check_intercept = svm_check_intercept, + .handle_external_intr = svm_handle_external_intr, };static int __init svm_init (void )
arch/x86/kvm/vmx.c +54 -4
106 lines not on this page · raw message
arch/x86/kvm/x86.c +3 -1
@@ -5806,7 +5806,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) vcpu->mode =OUTSIDE_GUEST_MODE ;smp_wmb (); -local_irq_enable (); + +/* Interrupt is enabled by handle_external_intr() */ + kvm_x86_ops->handle_external_intr (vcpu); ++vcpu->stat.exits;
Signature · 1 line
1.7.1
PATCH v7 2/7 KVM: VMX: Register a new IPI for posted interrupt
In reply to Yang ZhangFrom: Yang Zhang <[email protected]>
Posted Interrupt feature requires a special IPI to deliver posted interrupt to guest. And it should has a high priority so the interrupt will not be blocked by others.
Normally, the posted interrupt will be consumed by vcpu if target vcpu is running and transparent to OS. But in some cases, the interrupt will arrive when target vcpu is scheduled out. And host will see it. So we need to register a dump handler to handle it.
--- arch/x86/include/asm/entry_arch.h | 4 ++++ arch/x86/include/asm/hardirq.h | 3 +++ arch/x86/include/asm/hw_irq.h | 1 + arch/x86/include/asm/irq_vectors.h | 5 +++++ arch/x86/kernel/entry_64.S | 5 +++++ arch/x86/kernel/irq.c | 22 ++++++++++++++++++++++ arch/x86/kernel/irqinit.c | 4 ++++ 7 files changed, 44 insertions(+), 0 deletions(-)
arch/x86/include/asm/entry_arch.h +4 -0
@@ -19,6 +19,10 @@ BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR) BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR) +#ifdef CONFIG_HAVE_KVM +BUILD_INTERRUPT(kvm_posted_intr_ipi, POSTED_INTR_VECTOR) +#endif +/* * every pentium local APIC has two 'local interrupts', with a * soft-definable vector attached to both interrupts, one of
arch/x86/include/asm/hardirq.h +3 -0
@@ -12,6 +12,9 @@ typedef struct {unsigned int irq_spurious_count;unsigned int icr_read_retry_count;#endif +#ifdef CONFIG_HAVE_KVM +unsigned int kvm_posted_intr_ipis; +#endif unsigned int x86_platform_ipis;/* arch dependent */ unsigned int apic_perf_irqs;unsigned int apic_irq_work_irqs;
arch/x86/include/asm/hw_irq.h +1 -0
@@ -28,6 +28,7 @@/* Interrupt handlers registered during init_IRQ */ extern void apic_timer_interrupt (void );extern void x86_platform_ipi (void ); +extern void kvm_posted_intr_ipi (void );extern void error_interrupt (void );extern void irq_work_interrupt (void );
arch/x86/include/asm/irq_vectors.h +5 -0
@@ -102,6 +102,11 @@*/ #define X86_PLATFORM_IPI_VECTOR 0xf7 +/* Vector for KVM to deliver posted interrupt IPI */ +#ifdef CONFIG_HAVE_KVM +#define POSTED_INTR_VECTOR 0xf2 +#endif +/* * IRQ work vector: */
arch/x86/kernel/entry_64.S +5 -0
@@ -1166,6 +1166,11 @@ apicinterrupt LOCAL_TIMER_VECTOR \ apicinterrupt X86_PLATFORM_IPI_VECTOR \ x86_platform_ipi smp_x86_platform_ipi +#ifdef CONFIG_HAVE_KVM +apicinterrupt POSTED_INTR_VECTOR \ + kvm_posted_intr_ipi smp_kvm_posted_intr_ipi +#endif + apicinterrupt THRESHOLD_APIC_VECTOR \ threshold_interrupt smp_threshold_interrupt apicinterrupt THERMAL_APIC_VECTOR \
arch/x86/kernel/irq.c +22 -0
@@ -228,6 +228,28 @@ void smp_x86_platform_ipi(struct pt_regs *regs)set_irq_regs (old_regs); } +#ifdef CONFIG_HAVE_KVM +/* +* Handler for POSTED_INTERRUPT_VECTOR. +*/ +void smp_kvm_posted_intr_ipi (struct pt_regs *regs) +{ +struct pt_regs *old_regs =set_irq_regs (regs); + +ack_APIC_irq (); + +irq_enter (); + +exit_idle (); + +inc_irq_stat (kvm_posted_intr_ipis); + +irq_exit (); + +set_irq_regs (old_regs); +} +#endif +EXPORT_SYMBOL_GPL (vector_used_by_percpu_irq);#ifdef CONFIG_HOTPLUG_CPU
arch/x86/kernel/irqinit.c +4 -0
@@ -172,6 +172,10 @@ static void __init apic_intr_init(void)/* IPI for X86 platform specific use */ alloc_intr_gate (X86_PLATFORM_IPI_VECTOR , x86_platform_ipi); +#ifdef CONFIG_HAVE_KVM +/* IPI for KVM to deliver posted interrupt */ +alloc_intr_gate (POSTED_INTR_VECTOR , kvm_posted_intr_ipi); +#endif /* IPI vectors for APIC spurious and error interrupts */ alloc_intr_gate (SPURIOUS_APIC_VECTOR , spurious_interrupt);
Signature · 1 line
1.7.1
PATCH v7 3/7 KVM: VMX: Check the posted interrupt capability
In reply to Yang ZhangFrom: Yang Zhang <[email protected]>
Detect the posted interrupt feature. If it exists, then set it in vmcs_config.
--- arch/x86/include/asm/vmx.h | 4 ++ arch/x86/kvm/vmx.c | 87 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 20 deletions(-)
arch/x86/include/asm/vmx.h +4 -0
@@ -71,6 +71,7 @@#define PIN_BASED_NMI_EXITING 0x00000008#define PIN_BASED_VIRTUAL_NMIS 0x00000020#define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040 +#define PIN_BASED_POSTED_INTR 0x00000080#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016
@@ -102,6 +103,7 @@/* VMCS Encodings */ enum vmcs_field {VIRTUAL_PROCESSOR_ID =0x00000000 , +POSTED_INTR_NV =0x00000002 ,GUEST_ES_SELECTOR =0x00000800 ,GUEST_CS_SELECTOR =0x00000802 ,GUEST_SS_SELECTOR =0x00000804 ,
@@ -136,6 +138,8 @@ enum vmcs_field {VIRTUAL_APIC_PAGE_ADDR_HIGH =0x00002013 ,APIC_ACCESS_ADDR =0x00002014 ,APIC_ACCESS_ADDR_HIGH =0x00002015 , +POSTED_INTR_DESC_ADDR =0x00002016 , +POSTED_INTR_DESC_ADDR_HIGH =0x00002017 ,EPT_POINTER =0x0000201a ,EPT_POINTER_HIGH =0x0000201b , EOI_EXIT_BITMAP0 = 0x0000201c,
arch/x86/kvm/vmx.c +67 -20
178 lines not on this page · raw message
Signature · 1 line
1.7.1
Re: [PATCH v7 3/7] KVM: VMX: Check the posted interrupt capability
Quoted 54 lines · Yang Zhang
From: Yang Zhang <[email protected]>
Detect the posted interrupt feature. If it exists, then set it in
vmcs_config.Signed-off-by Yang Zhang <[email protected]>--- arch/x86/include/asm/vmx.h | 4 ++ arch/x86/kvm/vmx.c | 87 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 20 deletions(-)arch/x86/include/asm/vmx.h +4
-0@@ -71,6 +71,7 @@#define PIN_BASED_NMI_EXITING 0x00000008#define PIN_BASED_VIRTUAL_NMIS 0x00000020#define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040 +#define PIN_BASED_POSTED_INTR 0x00000080#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016@@ -102,6 +103,7 @@/* VMCS Encodings */ enum vmcs_field {VIRTUAL_PROCESSOR_ID =0x00000000 , +POSTED_INTR_NV =0x00000002 ,GUEST_ES_SELECTOR =0x00000800 ,GUEST_CS_SELECTOR =0x00000802 ,GUEST_SS_SELECTOR =0x00000804 ,@@ -136,6 +138,8 @@ enum vmcs_field {VIRTUAL_APIC_PAGE_ADDR_HIGH =0x00002013 ,APIC_ACCESS_ADDR =0x00002014 ,APIC_ACCESS_ADDR_HIGH =0x00002015 , +POSTED_INTR_DESC_ADDR =0x00002016 , +POSTED_INTR_DESC_ADDR_HIGH =0x00002017 ,EPT_POINTER =0x0000201a ,EPT_POINTER_HIGH =0x0000201b , EOI_EXIT_BITMAP0 = 0x0000201c,arch/x86/kvm/vmx.c +2
-1@@ -84,7 +84,8 @@ module_param(vmm_exclusive, bool, S_IRUGO);static bool __read_mostly fasteoi =1 ;module_param (fasteoi, bool,S_IRUGO ); -static bool __read_mostly enable_apicv_reg_vid; +static bool __read_mostly enable_apicv; +module_param (enable_apicv, bool,S_IRUGO );/* * If nested=1, nested virtualization is supported, i.e., guests may use
arch/x86/kvm/vmx.c struct nested_vmx { · line 376
Quoted 10 lines
arch/x86/kvm/vmx.c +7
-0@@ -366,6 +367,19 @@ struct nested_vmx {struct page *apic_access_page; }; +#define POSTED_INTR_ON 0 +/* Posted-Interrupt Descriptor */ +struct pi_desc { + u32 pir[8]; /* Posted interrupt requested */ + union { + struct { + u8 on:1,
Do you actually use the 'on' member of the bit field? As far as I can tell the paths always access control with (set|clear)_bit(). And C does not guaranty layout of the bit field, so on may not point to what you think it points to.
Quoted 173 lines
arch/x86/kvm/vmx.c +58
-19+ rsvd:7 ; + } control; +u32 rsvd[8 ]; + } u; +}__aligned(64) ; +struct vcpu_vmx {struct kvm_vcpu vcpu;unsigned long host_rsp;@@ -430,6 +444,9 @@ struct vcpu_vmx {bool rdtscp_enabled; +/* Posted interrupt descriptor */ +struct pi_desc pi_desc; +/* Support for a guest hypervisor (nested VMX) */ struct nested_vmx nested; };@@ -785,6 +802,18 @@ static inline bool cpu_has_vmx_virtual_intr_delivery(void)SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY ; } +static inline bool cpu_has_vmx_posted_intr (void ) +{ +return vmcs_config.pin_based_exec_ctrl &PIN_BASED_POSTED_INTR ; +} + +static inline bool cpu_has_vmx_apicv (void ) +{ +return cpu_has_vmx_apic_register_virt () && +cpu_has_vmx_virtual_intr_delivery () && +cpu_has_vmx_posted_intr (); +} +static inline bool cpu_has_vmx_flexpriority (void ) { return cpu_has_vmx_tpr_shadow() &&@@ -2552,12 +2581,6 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)u32 _vmexit_control =0 ;u32 _vmentry_control =0 ; - min =PIN_BASED_EXT_INTR_MASK |PIN_BASED_NMI_EXITING ; - opt =PIN_BASED_VIRTUAL_NMIS ; -if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_PINBASED_CTLS , - &_pin_based_exec_control) <0 ) -return -EIO ; - min = CPU_BASED_HLT_EXITING |#ifdef CONFIG_X86_64 CPU_BASED_CR8_LOAD_EXITING |@@ -2634,6 +2657,17 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) &_vmexit_control) < 0)return -EIO ; + min =PIN_BASED_EXT_INTR_MASK |PIN_BASED_NMI_EXITING ; + opt =PIN_BASED_VIRTUAL_NMIS |PIN_BASED_POSTED_INTR ; +if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_PINBASED_CTLS , + &_pin_based_exec_control) <0 ) +return -EIO ; + +if (!(_cpu_based_2nd_exec_control & +SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY ) || + !(_vmexit_control &VM_EXIT_ACK_INTR_ON_EXIT )) + _pin_based_exec_control &= ~PIN_BASED_POSTED_INTR ; + min =0 ; opt =VM_ENTRY_LOAD_IA32_PAT ; if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,@@ -2812,11 +2846,10 @@ static __init int hardware_setup(void)if (!cpu_has_vmx_ple ()) ple_gap =0 ; -if (!cpu_has_vmx_apic_register_virt () || - !cpu_has_vmx_virtual_intr_delivery ()) - enable_apicv_reg_vid =0 ; +if (!cpu_has_vmx_apicv ()) + enable_apicv =0 ; -if (enable_apicv_reg_vid) +if (enable_apicv) kvm_x86_ops->update_cr8_intercept =NULL ;else kvm_x86_ops->hwapic_irr_update =NULL ;@@ -3875,6 +3908,11 @@ static void vmx_disable_intercept_msr_write_x2apic(u32 msr) msr, MSR_TYPE_W); } +static int vmx_vm_has_apicv (struct kvm *kvm) +{ +return enable_apicv &&irqchip_in_kernel (kvm); +} +/* * Set up the vmcs's constant host-state fields, i.e., host-state fields that * will not change in the lifetime of the guest. @@ -3935,6 +3973,15 @@ static void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)vmcs_writel (CR4_GUEST_HOST_MASK , ~vmx->vcpu.arch.cr4_guest_owned_bits); } +static u32 vmx_pin_based_exec_ctrl (struct vcpu_vmx *vmx) +{ +u32 pin_based_exec_ctrl = vmcs_config.pin_based_exec_ctrl; + +if (!vmx_vm_has_apicv (vmx->vcpu.kvm)) + pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR ; +return pin_based_exec_ctrl; +} +static u32 vmx_exec_control (struct vcpu_vmx *vmx) {u32 exec_control = vmcs_config.cpu_based_exec_ctrl;@@ -3952,11 +3999,6 @@ static u32 vmx_exec_control(struct vcpu_vmx *vmx)return exec_control; } -static int vmx_vm_has_apicv (struct kvm *kvm) -{ -return enable_apicv_reg_vid &&irqchip_in_kernel (kvm); -} -static u32 vmx_secondary_exec_control (struct vcpu_vmx *vmx) {u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;@@ -4012,8 +4054,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)vmcs_write64 (VMCS_LINK_POINTER ,-1ull );/* 22.3.1.5 */ /* Control */ -vmcs_write32 (PIN_BASED_VM_EXEC_CONTROL , - vmcs_config.pin_based_exec_ctrl); +vmcs_write32 (PIN_BASED_VM_EXEC_CONTROL ,vmx_pin_based_exec_ctrl (vmx));vmcs_write32 (CPU_BASED_VM_EXEC_CONTROL ,vmx_exec_control (vmx));@@ -4022,13 +4063,16 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) vmx_secondary_exec_control(vmx)); } -if (enable_apicv_reg_vid) { +if (vmx_vm_has_apicv (vmx->vcpu.kvm)) {vmcs_write64 (EOI_EXIT_BITMAP0 ,0 );vmcs_write64 (EOI_EXIT_BITMAP1 ,0 );vmcs_write64 (EOI_EXIT_BITMAP2 ,0 );vmcs_write64 (EOI_EXIT_BITMAP3 ,0 );vmcs_write16 (GUEST_INTR_STATUS ,0 ); + +vmcs_write64 (POSTED_INTR_NV ,POSTED_INTR_VECTOR ); +vmcs_write64 (POSTED_INTR_DESC_ADDR ,__pa ((&vmx->pi_desc))); }if (ple_gap) {@@ -4170,6 +4214,9 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu)vmcs_write64 (APIC_ACCESS_ADDR ,page_to_phys (vmx->vcpu.kvm->arch.apic_access_page)); +if (vmx_vm_has_apicv (vcpu->kvm)) +memset (&vmx->pi_desc,0 ,sizeof (struct pi_desc )); +if (vmx->vpid !=0 )vmcs_write16 (VIRTUAL_PROCESSOR_ID , vmx->vpid);@@ -7809,7 +7856,7 @@ static int __init vmx_init(void)memcpy (vmx_msr_bitmap_longmode_x2apic, vmx_msr_bitmap_longmode,PAGE_SIZE ); -if (enable_apicv_reg_vid) { +if (enable_apicv) {for (msr =0x800 ; msr <=0x8ff ; msr++)vmx_disable_intercept_msr_read_x2apic (msr);Signature · 1 line
1.7.1
--
Gleb.
RE: [PATCH v7 3/7] KVM: VMX: Check the posted interrupt capability
Gleb Natapov wrote on 2013-04-07:
Quoted 45 lines · Yang Zhang
Quoted 44 lines
From: Yang Zhang <[email protected]>
Detect the posted interrupt feature. If it exists, then set it in
vmcs_config.Signed-off-by Yang Zhang <[email protected]>--- arch/x86/include/asm/vmx.h | 4 ++ arch/x86/kvm/vmx.c | 87++++++++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 20 deletions(-)
arch/x86/include/asm/vmx.h +3
-0@@ -71,6 +71,7 @@#define PIN_BASED_NMI_EXITING 0x00000008#define PIN_BASED_VIRTUAL_NMIS 0x00000020#define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040 +#define PIN_BASED_POSTED_INTR 0x00000080#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016@@ -102,6 +103,7 @@ /* VMCS Encodings */ enum vmcs_field { VIRTUAL_PROCESSOR_ID = 0x00000000, + POSTED_INTR_NV = 0x00000002, GUEST_ES_SELECTOR = 0x00000800, GUEST_CS_SELECTOR = 0x00000802, GUEST_SS_SELECTOR = 0x00000804, @@ -136,6 +138,8 @@ enum vmcs_field { VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013, APIC_ACCESS_ADDR = 0x00002014, APIC_ACCESS_ADDR_HIGH = 0x00002015, + POSTED_INTR_DESC_ADDR = 0x00002016, + POSTED_INTR_DESC_ADDR_HIGH = 0x00002017, EPT_POINTER = 0x0000201a, EPT_POINTER_HIGH = 0x0000201b, EOI_EXIT_BITMAP0 = 0x0000201c,arch/x86/kvm/vmx.c +2
-1@@ -84,7 +84,8 @@ module_param(vmm_exclusive, bool, S_IRUGO);static bool __read_mostly fasteoi =1 ;module_param (fasteoi, bool,S_IRUGO ); -static bool __read_mostly enable_apicv_reg_vid; +static bool __read_mostly enable_apicv; +module_param (enable_apicv, bool,S_IRUGO );
Quoted 13 lines
arch/x86/kvm/vmx.c struct nested_vmx { · line 375
Quoted 12 lines
arch/x86/kvm/vmx.c +7
-0/* * If nested=1, nested virtualization is supported, i.e., guests may use @@ -366,6 +367,19 @@ struct nested_vmx {struct page *apic_access_page; }; +#define POSTED_INTR_ON 0 +/* Posted-Interrupt Descriptor */ +struct pi_desc { + u32 pir[8]; /* Posted interrupt requested */ + union { + struct { + u8 on:1,Do you actually use the 'on' member of the bit field? As far as I can
'on' is just an indicator to easy for code review. I don't use it.
Quoted 3 lines
tell the paths always access control with (set|clear)_bit(). And C does not guaranty layout of the bit field, so on may not point to what you think it points to.
You are right. I will remove it and comments it instead.
Best regards,
Yang
PATCH v7 4/7 KVM: Call common update function when ioapic entry changed.
In reply to Yang ZhangFrom: Yang Zhang <[email protected]>
Both TMR and EOI exit bitmap need to be updated when ioapic changed or vcpu's id/ldr/dfr changed. So use common function instead eoi exit bitmap specific function.
--- arch/ia64/kvm/lapic.h | 6 ------ arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/vmx.c | 3 +++ arch/x86/kvm/x86.c | 11 +++++++---- include/linux/kvm_host.h | 4 ++-- virt/kvm/ioapic.c | 26 +++++++++++++++----------- virt/kvm/ioapic.h | 7 +++---- virt/kvm/irq_comm.c | 4 ++-- virt/kvm/kvm_main.c | 4 ++-- 9 files changed, 35 insertions(+), 32 deletions(-)
arch/ia64/kvm/lapic.h +0 -6
@@ -27,10 +27,4 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);#define kvm_apic_present (x) (true)#define kvm_lapic_enabled (x) (true) -static inline bool kvm_apic_vid_enabled (void ) -{ -/* IA64 has no apicv supporting, do nothing here */ -return false; -} -#endif
arch/x86/kvm/lapic.c +1 -1
@@ -209,7 +209,7 @@ out:if (old)kfree_rcu (old, rcu); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }static inline void kvm_apic_set_id (struct kvm_lapic *apic,u8 id)
arch/x86/kvm/vmx.c +3 -0
@@ -6420,6 +6420,9 @@ static void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)static void vmx_load_eoi_exitmap (struct kvm_vcpu *vcpu,u64 *eoi_exit_bitmap) { +if (!vmx_vm_has_apicv (vcpu->kvm)) +return ; +vmcs_write64 (EOI_EXIT_BITMAP0 , eoi_exit_bitmap[0 ]);vmcs_write64 (EOI_EXIT_BITMAP1 , eoi_exit_bitmap[1 ]);vmcs_write64 (EOI_EXIT_BITMAP2 , eoi_exit_bitmap[2 ]);
arch/x86/kvm/x86.c +7 -4
@@ -5647,13 +5647,16 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)#endif } -static void update_eoi_exitmap (struct kvm_vcpu *vcpu) +static void vcpu_scan_ioapic (struct kvm_vcpu *vcpu) {u64 eoi_exit_bitmap[4 ]; +if (!kvm_lapic_enabled (vcpu)) +return ; +memset (eoi_exit_bitmap,0 ,32 ); -kvm_ioapic_calculate_eoi_exitmap (vcpu, eoi_exit_bitmap); +kvm_ioapic_scan_entry (vcpu, (unsigned long *)eoi_exit_bitmap); kvm_x86_ops->load_eoi_exitmap (vcpu, eoi_exit_bitmap); }
@@ -5710,8 +5713,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)kvm_handle_pmu_event (vcpu);if (kvm_check_request (KVM_REQ_PMI , vcpu))kvm_deliver_pmi (vcpu); -if (kvm_check_request (KVM_REQ_EOIBITMAP , vcpu)) -update_eoi_exitmap (vcpu); +if (kvm_check_request (KVM_REQ_SCAN_IOAPIC , vcpu)) +vcpu_scan_ioapic (vcpu); }if (kvm_check_request (KVM_REQ_EVENT , vcpu) || req_int_win) {
include/linux/kvm_host.h +2 -2
@@ -126,7 +126,7 @@ static inline bool is_error_page(struct page *page)#define KVM_REQ_MASTERCLOCK_UPDATE 19#define KVM_REQ_MCLOCK_INPROGRESS 20#define KVM_REQ_EPR_EXIT 21 -#define KVM_REQ_EOIBITMAP 22 +#define KVM_REQ_SCAN_IOAPIC 22#define KVM_USERSPACE_IRQ_SOURCE_ID 0#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
@@ -571,7 +571,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);void kvm_flush_remote_tlbs (struct kvm *kvm);void kvm_reload_remote_mmus (struct kvm *kvm);void kvm_make_mclock_inprogress_request (struct kvm *kvm); -void kvm_make_update_eoibitmap_request (struct kvm *kvm); +void kvm_make_scan_ioapic_request (struct kvm *kvm);long kvm_arch_dev_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg);
virt/kvm/ioapic.c +15 -11
@@ -119,8 +119,8 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic)smp_wmb (); } -void kvm_ioapic_calculate_eoi_exitmap (struct kvm_vcpu *vcpu, -u64 *eoi_exit_bitmap) +void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, +unsigned long *eoi_exit_bitmap) {struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;union kvm_ioapic_redirect_entry *e;
@@ -128,7 +128,6 @@ void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,int index;spin_lock (&ioapic->lock); -/* traverse ioapic entry to set eoi exit bitmap*/ for (index =0 ; index <IOAPIC_NUM_PINS ; index++) { e = &ioapic->redirtbl[index]; if (!e->fields.mask &&
@@ -137,22 +136,27 @@ void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu, index))) {if (kvm_apic_match_dest (vcpu,NULL ,0 , e->fields.dest_id, e->fields.dest_mode)) -__set_bit (irqe.vector, - (unsigned long *)eoi_exit_bitmap); +__set_bit (irqe.vector, eoi_exit_bitmap); } }spin_unlock (&ioapic->lock); } -EXPORT_SYMBOL_GPL (kvm_ioapic_calculate_eoi_exitmap); -void kvm_ioapic_make_eoibitmap_request (struct kvm *kvm) +#ifdef CONFIG_X86 +void kvm_vcpu_scan_ioapic (struct kvm *kvm) {struct kvm_ioapic *ioapic = kvm->arch.vioapic; -if (!kvm_apic_vid_enabled (kvm) || !ioapic) +if (!ioapic)return ; -kvm_make_update_eoibitmap_request (kvm); +kvm_make_scan_ioapic_request (kvm); } +#else +void kvm_vcpu_scan_ioapic (struct kvm *kvm) +{ +return ; +} +#endif static void ioapic_write_indirect (struct kvm_ioapic *ioapic,u32 val) {
@@ -195,7 +199,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)if (e->fields.trig_mode ==IOAPIC_LEVEL_TRIG && ioapic->irr & (1 << index))ioapic_service (ioapic, index); -kvm_ioapic_make_eoibitmap_request (ioapic->kvm); +kvm_vcpu_scan_ioapic (ioapic->kvm);break ; } }
@@ -495,7 +499,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)spin_lock (&ioapic->lock);memcpy (ioapic, state,sizeof (struct kvm_ioapic_state ));update_handled_vectors (ioapic); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm);spin_unlock (&ioapic->lock);return 0 ; }
virt/kvm/ioapic.h +3 -4
@@ -82,9 +82,8 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, struct kvm_lapic_irq *irq);int kvm_get_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state);int kvm_set_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state); -void kvm_ioapic_make_eoibitmap_request (struct kvm *kvm); -void kvm_ioapic_calculate_eoi_exitmap (struct kvm_vcpu *vcpu, -u64 *eoi_exit_bitmap); - +void kvm_vcpu_scan_ioapic (struct kvm *kvm); +void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, +unsigned long *eoi_exit_bitmap);#endif
virt/kvm/irq_comm.c +2 -2
@@ -280,7 +280,7 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm,mutex_lock (&kvm->irq_lock);hlist_add_head_rcu (&kian->link, &kvm->irq_ack_notifier_list);mutex_unlock (&kvm->irq_lock); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); } void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
@@ -290,7 +290,7 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm,hlist_del_init_rcu (&kian->link);mutex_unlock (&kvm->irq_lock);synchronize_rcu (); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }int kvm_request_irq_source_id (struct kvm *kvm)
virt/kvm/kvm_main.c +2 -2
@@ -217,9 +217,9 @@ void kvm_make_mclock_inprogress_request(struct kvm *kvm)make_all_cpus_request (kvm,KVM_REQ_MCLOCK_INPROGRESS ); } -void kvm_make_update_eoibitmap_request (struct kvm *kvm) +void kvm_make_scan_ioapic_request (struct kvm *kvm) { -make_all_cpus_request (kvm,KVM_REQ_EOIBITMAP ); +make_all_cpus_request (kvm,KVM_REQ_SCAN_IOAPIC ); }int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id)
Signature · 1 line
1.7.1
Re: [PATCH v7 4/7] KVM: Call common update function when ioapic entry changed.
Quoted 67 lines · Yang Zhang
From: Yang Zhang <[email protected]>
Both TMR and EOI exit bitmap need to be updated when ioapic changed or vcpu's id/ldr/dfr changed. So use common function instead eoi exit bitmap specific function.
Signed-off-by Yang Zhang <[email protected]>--- arch/ia64/kvm/lapic.h | 6 ------ arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/vmx.c | 3 +++ arch/x86/kvm/x86.c | 11 +++++++---- include/linux/kvm_host.h | 4 ++-- virt/kvm/ioapic.c | 26 +++++++++++++++----------- virt/kvm/ioapic.h | 7 +++---- virt/kvm/irq_comm.c | 4 ++-- virt/kvm/kvm_main.c | 4 ++-- 9 files changed, 35 insertions(+), 32 deletions(-)arch/ia64/kvm/lapic.h +0
-6@@ -27,10 +27,4 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);#define kvm_apic_present (x) (true)#define kvm_lapic_enabled (x) (true) -static inline bool kvm_apic_vid_enabled (void ) -{ -/* IA64 has no apicv supporting, do nothing here */ -return false; -} -#endif arch/x86/kvm/lapic.c +1
-1@@ -209,7 +209,7 @@ out:if (old)kfree_rcu (old, rcu); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }static inline void kvm_apic_set_id (struct kvm_lapic *apic,u8 id)arch/x86/kvm/vmx.c +3
-0@@ -6420,6 +6420,9 @@ static void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)static void vmx_load_eoi_exitmap (struct kvm_vcpu *vcpu,u64 *eoi_exit_bitmap) { +if (!vmx_vm_has_apicv (vcpu->kvm)) +return ; +vmcs_write64 (EOI_EXIT_BITMAP0 , eoi_exit_bitmap[0 ]);vmcs_write64 (EOI_EXIT_BITMAP1 , eoi_exit_bitmap[1 ]);vmcs_write64 (EOI_EXIT_BITMAP2 , eoi_exit_bitmap[2 ]);arch/x86/kvm/x86.c +0
-0@@ -5647,13 +5647,16 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)#endif
arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct kvm *kvm) · line 5656
Quoted 10 lines
arch/x86/kvm/x86.c +4
-1} -static void update_eoi_exitmap (struct kvm_vcpu *vcpu) +static void vcpu_scan_ioapic (struct kvm_vcpu *vcpu) {u64 eoi_exit_bitmap[4 ]; +if (!kvm_lapic_enabled (vcpu)) +return ; +
Why is this needed here?
Quoted 64 lines
arch/x86/kvm/x86.c +3
-3memset (eoi_exit_bitmap,0 ,32 ); -kvm_ioapic_calculate_eoi_exitmap (vcpu, eoi_exit_bitmap); +kvm_ioapic_scan_entry (vcpu, (unsigned long *)eoi_exit_bitmap); kvm_x86_ops->load_eoi_exitmap (vcpu, eoi_exit_bitmap); }@@ -5710,8 +5713,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)kvm_handle_pmu_event (vcpu);if (kvm_check_request (KVM_REQ_PMI , vcpu))kvm_deliver_pmi (vcpu); -if (kvm_check_request (KVM_REQ_EOIBITMAP , vcpu)) -update_eoi_exitmap (vcpu); +if (kvm_check_request (KVM_REQ_SCAN_IOAPIC , vcpu)) +vcpu_scan_ioapic (vcpu); }if (kvm_check_request (KVM_REQ_EVENT , vcpu) || req_int_win) {include/linux/kvm_host.h +2
-2@@ -126,7 +126,7 @@ static inline bool is_error_page(struct page *page)#define KVM_REQ_MASTERCLOCK_UPDATE 19#define KVM_REQ_MCLOCK_INPROGRESS 20#define KVM_REQ_EPR_EXIT 21 -#define KVM_REQ_EOIBITMAP 22 +#define KVM_REQ_SCAN_IOAPIC 22#define KVM_USERSPACE_IRQ_SOURCE_ID 0#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1@@ -571,7 +571,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);void kvm_flush_remote_tlbs (struct kvm *kvm);void kvm_reload_remote_mmus (struct kvm *kvm);void kvm_make_mclock_inprogress_request (struct kvm *kvm); -void kvm_make_update_eoibitmap_request (struct kvm *kvm); +void kvm_make_scan_ioapic_request (struct kvm *kvm);long kvm_arch_dev_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg);virt/kvm/ioapic.c +2
-3@@ -119,8 +119,8 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic)smp_wmb (); } -void kvm_ioapic_calculate_eoi_exitmap (struct kvm_vcpu *vcpu, -u64 *eoi_exit_bitmap) +void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, +unsigned long *eoi_exit_bitmap) {struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;union kvm_ioapic_redirect_entry *e;@@ -128,7 +128,6 @@ void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,int index;spin_lock (&ioapic->lock); -/* traverse ioapic entry to set eoi exit bitmap*/ for (index =0 ; index <IOAPIC_NUM_PINS ; index++) { e = &ioapic->redirtbl[index]; if (!e->fields.mask &&
virt/kvm/ioapic.c void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu, · line 139
Quoted 6 lines
virt/kvm/ioapic.c +1
-2@@ -137,22 +136,27 @@ void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu, index))) {if (kvm_apic_match_dest (vcpu,NULL ,0 , e->fields.dest_id, e->fields.dest_mode)) -__set_bit (irqe.vector, - (unsigned long *)eoi_exit_bitmap); +__set_bit (irqe.vector, eoi_exit_bitmap);
I prefer the old way of casting as deep in the call chain as possible.
virt/kvm/ioapic.c void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu, · line 146
Quoted 9 lines
virt/kvm/ioapic.c +2
-2} }spin_unlock (&ioapic->lock); } -EXPORT_SYMBOL_GPL (kvm_ioapic_calculate_eoi_exitmap); -void kvm_ioapic_make_eoibitmap_request (struct kvm *kvm) +#ifdef CONFIG_X86 +void kvm_vcpu_scan_ioapic (struct kvm *kvm)
The name is too similar to vcpu_scan_ioapic and does not describe well that the function does not actually scan anything, but only makes a request. Call it kvm_vcpu_request_scan_ioapic();
Quoted 93 lines
virt/kvm/ioapic.c +10
-4{struct kvm_ioapic *ioapic = kvm->arch.vioapic; -if (!kvm_apic_vid_enabled (kvm) || !ioapic) +if (!ioapic)return ; -kvm_make_update_eoibitmap_request (kvm); +kvm_make_scan_ioapic_request (kvm); } +#else +void kvm_vcpu_scan_ioapic (struct kvm *kvm) +{ +return ; +} +#endif static void ioapic_write_indirect (struct kvm_ioapic *ioapic,u32 val) {@@ -195,7 +199,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)if (e->fields.trig_mode ==IOAPIC_LEVEL_TRIG && ioapic->irr & (1 << index))ioapic_service (ioapic, index); -kvm_ioapic_make_eoibitmap_request (ioapic->kvm); +kvm_vcpu_scan_ioapic (ioapic->kvm);break ; } }@@ -495,7 +499,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)spin_lock (&ioapic->lock);memcpy (ioapic, state,sizeof (struct kvm_ioapic_state ));update_handled_vectors (ioapic); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm);spin_unlock (&ioapic->lock);return 0 ; }virt/kvm/ioapic.h +3
-4@@ -82,9 +82,8 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, struct kvm_lapic_irq *irq);int kvm_get_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state);int kvm_set_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state); -void kvm_ioapic_make_eoibitmap_request (struct kvm *kvm); -void kvm_ioapic_calculate_eoi_exitmap (struct kvm_vcpu *vcpu, -u64 *eoi_exit_bitmap); - +void kvm_vcpu_scan_ioapic (struct kvm *kvm); +void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, +unsigned long *eoi_exit_bitmap);#endif virt/kvm/irq_comm.c +2
-2@@ -280,7 +280,7 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm,mutex_lock (&kvm->irq_lock);hlist_add_head_rcu (&kian->link, &kvm->irq_ack_notifier_list);mutex_unlock (&kvm->irq_lock); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); } void kvm_unregister_irq_ack_notifier(struct kvm *kvm,@@ -290,7 +290,7 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm,hlist_del_init_rcu (&kian->link);mutex_unlock (&kvm->irq_lock);synchronize_rcu (); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }int kvm_request_irq_source_id (struct kvm *kvm)virt/kvm/kvm_main.c +2
-2@@ -217,9 +217,9 @@ void kvm_make_mclock_inprogress_request(struct kvm *kvm)make_all_cpus_request (kvm,KVM_REQ_MCLOCK_INPROGRESS ); } -void kvm_make_update_eoibitmap_request (struct kvm *kvm) +void kvm_make_scan_ioapic_request (struct kvm *kvm) { -make_all_cpus_request (kvm,KVM_REQ_EOIBITMAP ); +make_all_cpus_request (kvm,KVM_REQ_SCAN_IOAPIC ); }int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id)Signature · 1 line
1.7.1
--
Gleb.
RE: [PATCH v7 4/7] KVM: Call common update function when ioapic entry changed.
Gleb Natapov wrote on 2013-04-07:
Quoted 65 lines · Yang Zhang
arch/ia64/kvm/lapic.h int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct
Quoted 23 lines
From: Yang Zhang <[email protected]>
Both TMR and EOI exit bitmap need to be updated when ioapic changed or vcpu's id/ldr/dfr changed. So use common function instead eoi exit bitmap specific function.
Signed-off-by Yang Zhang <[email protected]>--- arch/ia64/kvm/lapic.h | 6 ------ arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/vmx.c | 3 +++ arch/x86/kvm/x86.c | 11 +++++++---- include/linux/kvm_host.h | 4 ++-- virt/kvm/ioapic.c | 26 +++++++++++++++----------- virt/kvm/ioapic.h | 7 +++---- virt/kvm/irq_comm.c | 4 ++-- virt/kvm/kvm_main.c | 4 ++-- 9 files changed, 35 insertions(+), 32 deletions(-)arch/ia64/kvm/lapic.h +0
-0@@ -27,10 +27,4 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct
kvm_lapic_irq*irq);arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct
Quoted 39 lines
arch/ia64/kvm/lapic.h +0
-6#define kvm_apic_present (x) (true)#define kvm_lapic_enabled (x) (true) -static inline bool kvm_apic_vid_enabled (void ) -{ -/* IA64 has no apicv supporting, do nothing here */ -return false; -} -#endif arch/x86/kvm/lapic.c +1
-1@@ -209,7 +209,7 @@ out:if (old)kfree_rcu (old, rcu); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }static inline void kvm_apic_set_id (struct kvm_lapic *apic,u8 id)arch/x86/kvm/vmx.c index renamed from arch/x86/kvm/vmx.c +0
-0b2e95bc..edfc87a 100644 ---
a/arch/x86/kvm/vmx.c+++b/arch/x86/kvm/vmx.c@@ -6420,6 +6420,9 @@ static voidvmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)static void
vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap){arch/x86/kvm/vmx.c index renamed from arch/x86/kvm/vmx.c +3
-0+ if (!vmx_vm_has_apicv(vcpu->kvm)) + return; + vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]);arch/x86/kvm/x86.c +0
-0@@ -5647,13 +5647,16 @@ static void kvm_gen_update_masterclock(structkvm *kvm)
Quoted 10 lines
arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct kvm *kvm) · line 5656
Quoted 9 lines
arch/x86/kvm/x86.c +4
-1#endif } -static void update_eoi_exitmap (struct kvm_vcpu *vcpu) +static void vcpu_scan_ioapic (struct kvm_vcpu *vcpu) {u64 eoi_exit_bitmap[4 ]; +if (!kvm_lapic_enabled (vcpu)) +return ; +Why is this needed here?
We don't need to calculate eoi_exit_bitmap and TMR if lapic is not enabled. Also, ioapic is meaningless for the vcpu that doesn't enable the lapic.
Quoted 63 lines
virt/kvm/ioapic.c static void update_handled_vectors(struct kvm_ioapic
Quoted 44 lines
arch/x86/kvm/x86.c +3
-3memset (eoi_exit_bitmap,0 ,32 ); -kvm_ioapic_calculate_eoi_exitmap (vcpu, eoi_exit_bitmap); +kvm_ioapic_scan_entry (vcpu, (unsigned long *)eoi_exit_bitmap); kvm_x86_ops->load_eoi_exitmap (vcpu, eoi_exit_bitmap); }@@ -5710,8 +5713,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)kvm_handle_pmu_event (vcpu);if (kvm_check_request (KVM_REQ_PMI , vcpu))kvm_deliver_pmi (vcpu); -if (kvm_check_request (KVM_REQ_EOIBITMAP , vcpu)) -update_eoi_exitmap (vcpu); +if (kvm_check_request (KVM_REQ_SCAN_IOAPIC , vcpu)) +vcpu_scan_ioapic (vcpu); }if (kvm_check_request (KVM_REQ_EVENT , vcpu) || req_int_win) {include/linux/kvm_host.h +1
-1@@ -126,7 +126,7 @@ static inline bool is_error_page(struct page *page)#define KVM_REQ_MASTERCLOCK_UPDATE 19#define KVM_REQ_MCLOCK_INPROGRESS 20#define KVM_REQ_EPR_EXIT 21 -#define KVM_REQ_EOIBITMAP 22 +#define KVM_REQ_SCAN_IOAPIC 22#define KVM_USERSPACE_IRQ_SOURCE_ID 0 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1 @@ -571,7 +571,7 @@ void
kvm_put_guest_fpu(struct kvm_vcpu *vcpu); voidkvm_flush_remote_tlbs(struct kvm *kvm); voidkvm_reload_remote_mmus(struct kvm *kvm); voidkvm_make_mclock_inprogress_request(struct kvm *kvm);include/linux/kvm_host.h +1
-1-void kvm_make_update_eoibitmap_request (struct kvm *kvm); +void kvm_make_scan_ioapic_request (struct kvm *kvm);long kvm_arch_dev_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg);virt/kvm/ioapic.c +0
-0@@ -119,8 +119,8 @@ static void update_handled_vectors(struct kvm_ioapic*ioapic)
virt/kvm/ioapic.c void kvm_ioapic_calculate_eoi_exitmap(struct
Quoted 10 lines
virt/kvm/ioapic.c +2
-2smp_wmb (); } -void kvm_ioapic_calculate_eoi_exitmap (struct kvm_vcpu *vcpu, -u64 *eoi_exit_bitmap) +void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, +unsigned long *eoi_exit_bitmap) {struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;union kvm_ioapic_redirect_entry *e;@@ -128,7 +128,6 @@ void kvm_ioapic_calculate_eoi_exitmap(struct
kvm_vcpu*vcpu,virt/kvm/ioapic.c void kvm_ioapic_calculate_eoi_exitmap(struct
Quoted 6 lines
virt/kvm/ioapic.c +0
-0int index;spin_lock (&ioapic->lock); -/* traverse ioapic entry to set eoi exit bitmap*/ for (index = 0; index < IOAPIC_NUM_PINS; index++) { e = &ioapic->redirtbl[index]; if (!e->fields.mask &&@@ -137,22 +136,27 @@ void kvm_ioapic_calculate_eoi_exitmap(struct
kvm_vcpu*vcpu,
Quoted 7 lines
virt/kvm/ioapic.c void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu, · line 139
Quoted 6 lines
virt/kvm/ioapic.c +1
-2index))) {if (kvm_apic_match_dest (vcpu,NULL ,0 , e->fields.dest_id, e->fields.dest_mode)) -__set_bit (irqe.vector, - (unsigned long *)eoi_exit_bitmap); +__set_bit (irqe.vector, eoi_exit_bitmap);I prefer the old way of casting as deep in the call chain as possible.
Sure. It make sense.
Quoted 7 lines
Quoted 7 lines
virt/kvm/ioapic.c +0
-1} }spin_unlock (&ioapic->lock); } -EXPORT_SYMBOL_GPL (kvm_ioapic_calculate_eoi_exitmap);
Quoted 6 lines
virt/kvm/ioapic.c void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu, · line 146
Quoted 3 lines
virt/kvm/ioapic.c +2
-1-void kvm_ioapic_make_eoibitmap_request (struct kvm *kvm) +#ifdef CONFIG_X86 +void kvm_vcpu_scan_ioapic (struct kvm *kvm)The name is too similar to
vcpu_scan_ioapicand does not describe well that the function does not actually scan anything, but only makes a request. Call itkvm_vcpu_request_scan_ioapic();
Sure.
Quoted 92 lines
virt/kvm/ioapic.c static void ioapic_write_indirect(struct kvm_ioapic
Quoted 19 lines
virt/kvm/ioapic.c +8
-2{struct kvm_ioapic *ioapic = kvm->arch.vioapic; -if (!kvm_apic_vid_enabled (kvm) || !ioapic) +if (!ioapic)return ; -kvm_make_update_eoibitmap_request (kvm); +kvm_make_scan_ioapic_request (kvm); } +#else +void kvm_vcpu_scan_ioapic (struct kvm *kvm) +{ +return ; +} +#endif static void ioapic_write_indirect (struct kvm_ioapic *ioapic,u32 val) {@@ -195,7 +199,7 @@ static void ioapic_write_indirect(struct kvm_ioapic*ioapic, u32 val)
virt/kvm/ioapic.c int kvm_set_ioapic(struct kvm *kvm, struct
Quoted 9 lines
virt/kvm/ioapic.c +1
-1if (e->fields.trig_mode ==IOAPIC_LEVEL_TRIG && ioapic->irr & (1 << index))ioapic_service (ioapic, index); -kvm_ioapic_make_eoibitmap_request (ioapic->kvm); +kvm_vcpu_scan_ioapic (ioapic->kvm);break ; } }@@ -495,7 +499,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct
kvm_ioapic_state*state)virt/kvm/ioapic.h int kvm_irq_delivery_to_apic(struct kvm *kvm, struct
Quoted 13 lines
virt/kvm/ioapic.c +1
-1spin_lock (&ioapic->lock);memcpy (ioapic, state,sizeof (struct kvm_ioapic_state ));update_handled_vectors (ioapic); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm);spin_unlock (&ioapic->lock);return 0 ; }virt/kvm/ioapic.h +0
-0@@ -82,9 +82,8 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct
kvm_lapic*src,virt/kvm/kvm_main.c void kvm_make_mclock_inprogress_request(struct
Quoted 38 lines
virt/kvm/ioapic.h +3
-4struct kvm_lapic_irq *irq);int kvm_get_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state);int kvm_set_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state); -void kvm_ioapic_make_eoibitmap_request (struct kvm *kvm); -void kvm_ioapic_calculate_eoi_exitmap (struct kvm_vcpu *vcpu, -u64 *eoi_exit_bitmap); - +void kvm_vcpu_scan_ioapic (struct kvm *kvm); +void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, +unsigned long *eoi_exit_bitmap);#endif virt/kvm/irq_comm.c +1
-1@@ -280,7 +280,7 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm,mutex_lock (&kvm->irq_lock);hlist_add_head_rcu (&kian->link, &kvm->irq_ack_notifier_list);mutex_unlock (&kvm->irq_lock); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); } void kvm_unregister_irq_ack_notifier(struct kvm *kvm, @@ -290,7 +290,7@@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
virt/kvm/irq_comm.c +1
-1hlist_del_init_rcu (&kian->link);mutex_unlock (&kvm->irq_lock);synchronize_rcu (); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }int kvm_request_irq_source_id (struct kvm *kvm)virt/kvm/kvm_main.c +0
-0@@ -217,9 +217,9 @@ void kvm_make_mclock_inprogress_request(structkvm *kvm)
Quoted 9 lines
virt/kvm/kvm_main.c +2
-2make_all_cpus_request (kvm,KVM_REQ_MCLOCK_INPROGRESS ); } -void kvm_make_update_eoibitmap_request (struct kvm *kvm) +void kvm_make_scan_ioapic_request (struct kvm *kvm) { -make_all_cpus_request (kvm,KVM_REQ_EOIBITMAP ); +make_all_cpus_request (kvm,KVM_REQ_SCAN_IOAPIC ); }
Quoted 6 lines
Quoted 3 lines
virt/kvm/kvm_main.c +0
-1int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id) --1.7.1
--
Gleb.
Best regards,
Yang
Re: [PATCH v7 4/7] KVM: Call common update function when ioapic entry changed.
Quoted 76 lines · Yang Z
Gleb Natapov wrote on 2013-04-07:
Quoted 65 lines · Yang Zhang
arch/ia64/kvm/lapic.h int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct
Quoted 23 lines
From: Yang Zhang <[email protected]>
Both TMR and EOI exit bitmap need to be updated when ioapic changed or vcpu's id/ldr/dfr changed. So use common function instead eoi exit bitmap specific function.
Signed-off-by Yang Zhang <[email protected]>--- arch/ia64/kvm/lapic.h | 6 ------ arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/vmx.c | 3 +++ arch/x86/kvm/x86.c | 11 +++++++---- include/linux/kvm_host.h | 4 ++-- virt/kvm/ioapic.c | 26 +++++++++++++++----------- virt/kvm/ioapic.h | 7 +++---- virt/kvm/irq_comm.c | 4 ++-- virt/kvm/kvm_main.c | 4 ++-- 9 files changed, 35 insertions(+), 32 deletions(-)arch/ia64/kvm/lapic.h +0
-0@@ -27,10 +27,4 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct
kvm_lapic_irq*irq);arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct
Quoted 39 lines
arch/ia64/kvm/lapic.h +0
-6#define kvm_apic_present (x) (true)#define kvm_lapic_enabled (x) (true) -static inline bool kvm_apic_vid_enabled (void ) -{ -/* IA64 has no apicv supporting, do nothing here */ -return false; -} -#endif arch/x86/kvm/lapic.c +1
-1@@ -209,7 +209,7 @@ out:if (old)kfree_rcu (old, rcu); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }static inline void kvm_apic_set_id (struct kvm_lapic *apic,u8 id)arch/x86/kvm/vmx.c index renamed from arch/x86/kvm/vmx.c +0
-0b2e95bc..edfc87a 100644 ---
a/arch/x86/kvm/vmx.c+++b/arch/x86/kvm/vmx.c@@ -6420,6 +6420,9 @@ static voidvmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)static void
vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap){arch/x86/kvm/vmx.c index renamed from arch/x86/kvm/vmx.c +3
-0+ if (!vmx_vm_has_apicv(vcpu->kvm)) + return; + vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]);arch/x86/kvm/x86.c +0
-0@@ -5647,13 +5647,16 @@ static void kvm_gen_update_masterclock(structkvm *kvm)
Quoted 10 lines
arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct kvm *kvm) · line 5656
Quoted 9 lines
arch/x86/kvm/x86.c +4
-1#endif } -static void update_eoi_exitmap (struct kvm_vcpu *vcpu) +static void vcpu_scan_ioapic (struct kvm_vcpu *vcpu) {u64 eoi_exit_bitmap[4 ]; +if (!kvm_lapic_enabled (vcpu)) +return ; +Why is this needed here?
Quoted 2 lines
We don't need to calculate
eoi_exit_bitmapand TMR if lapic is not enabled. Also, ioapic is meaningless for the vcpu that doesn't enable the lapic.
OK, but then let's use apic_enabled() since kvm_lapic_enabled() also checks for in kernel apic and we should not be here if apic is not emulated in kernel. Also please make sure that we rescan ioapic on all apic state changes.
--
Gleb.
RE: [PATCH v7 4/7] KVM: Call common update function when ioapic entry changed.
Gleb Natapov wrote on 2013-04-07:
Quoted 77 lines · Yang Z
Quoted 76 lines
Gleb Natapov wrote on 2013-04-07:
Quoted 75 lines · Yang Zhang
arch/ia64/kvm/lapic.h int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct
Quoted 23 lines
From: Yang Zhang <[email protected]>
Both TMR and EOI exit bitmap need to be updated when ioapic changed or vcpu's id/ldr/dfr changed. So use common function instead eoi exit bitmap specific function.
Signed-off-by Yang Zhang <[email protected]>--- arch/ia64/kvm/lapic.h | 6 ------ arch/x86/kvm/lapic.c | 2 +- arch/x86/kvm/vmx.c | 3 +++ arch/x86/kvm/x86.c | 11 +++++++---- include/linux/kvm_host.h | 4 ++-- virt/kvm/ioapic.c | 26 +++++++++++++++----------- virt/kvm/ioapic.h | 7 +++---- virt/kvm/irq_comm.c | 4 ++-- virt/kvm/kvm_main.c | 4 ++-- 9 files changed, 35 insertions(+), 32 deletions(-)arch/ia64/kvm/lapic.h +0
-0@@ -27,10 +27,4 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct
kvm_lapic_irq*irq);arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct
Quoted 39 lines
arch/ia64/kvm/lapic.h +0
-6#define kvm_apic_present (x) (true)#define kvm_lapic_enabled (x) (true) -static inline bool kvm_apic_vid_enabled (void ) -{ -/* IA64 has no apicv supporting, do nothing here */ -return false; -} -#endif arch/x86/kvm/lapic.c +1
-1@@ -209,7 +209,7 @@ out:if (old)kfree_rcu (old, rcu); -kvm_ioapic_make_eoibitmap_request (kvm); +kvm_vcpu_scan_ioapic (kvm); }static inline void kvm_apic_set_id (struct kvm_lapic *apic,u8 id)arch/x86/kvm/vmx.c index renamed from arch/x86/kvm/vmx.c +0
-0b2e95bc..edfc87a 100644 ---
a/arch/x86/kvm/vmx.c+++b/arch/x86/kvm/vmx.c@@ -6420,6 +6420,9 @@ static voidvmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)static void
vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap){arch/x86/kvm/vmx.c index renamed from arch/x86/kvm/vmx.c +3
-0+ if (!vmx_vm_has_apicv(vcpu->kvm)) + return; + vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]); vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]); vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]);arch/x86/kvm/x86.c +0
-0@@ -5647,13 +5647,16 @@ static void kvm_gen_update_masterclock(structkvm *kvm)
arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct kvm *kvm) · line 5656
Quoted 9 lines
arch/x86/kvm/x86.c +4
-1#endif } -static void update_eoi_exitmap (struct kvm_vcpu *vcpu) +static void vcpu_scan_ioapic (struct kvm_vcpu *vcpu) {u64 eoi_exit_bitmap[4 ]; +if (!kvm_lapic_enabled (vcpu)) +return ; +Why is this needed here?
Quoted 6 lines
Quoted 4 lines
We don't need to calculate
eoi_exit_bitmapand TMR if lapic is not enabled. Also, ioapic is meaningless for the vcpu that doesn't enable the lapic.OK, but then let's use
apic_enabled()sincekvm_lapic_enabled()also checks for in kernel apic and we should not be here if apic is not
Sure.
Quoted 2 lines
emulated in kernel. Also please make sure that we rescan ioapic on all apic state changes.
Yes. recalculate_apic_map() is called on all apic state changes, so request ioapic scan in recalculate_apic_map is enough.
Best regards,
Yang
PATCH v7 5/7 KVM: Set TMR when programming ioapic entry
In reply to Yang ZhangFrom: Yang Zhang <[email protected]>
We already know the trigger mode of a given interrupt when programming the ioapice entry. So it's not necessary to set it in each interrupt delivery.
--- arch/x86/kvm/lapic.c | 15 +++++++++------ arch/x86/kvm/lapic.h | 1 + arch/x86/kvm/x86.c | 6 +++++- virt/kvm/ioapic.c | 9 +++++++-- virt/kvm/ioapic.h | 3 ++- 5 files changed, 24 insertions(+), 10 deletions(-)
arch/x86/kvm/lapic.c +9 -6
@@ -458,6 +458,15 @@ static inline int apic_find_highest_isr(struct kvm_lapic *apic)return result; } +void kvm_apic_update_tmr (struct kvm_vcpu *vcpu,u32 *tmr) +{ +struct kvm_lapic *apic = vcpu->arch.apic; +int i; + +for (i =0 ; i <8 ; i++) +apic_set_reg (apic,APIC_TMR +0x10 * i, tmr[i]); +} +static void apic_update_ppr (struct kvm_lapic *apic) {u32 tpr, isrv, ppr, old_ppr;
@@ -647,12 +656,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,if (unlikely (!apic_enabled (apic)))break ; -if (trig_mode) { -apic_debug ("level trig mode for vector %d" , vector); -apic_set_vector (vector, apic->regs +APIC_TMR ); - }else -apic_clear_vector (vector, apic->regs +APIC_TMR ); - result = !apic_test_and_set_irr (vector, apic);trace_kvm_apic_accept_irq (vcpu->vcpu_id, delivery_mode, trig_mode, vector, !result);
arch/x86/kvm/lapic.h +1 -0
@@ -53,6 +53,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);u64 kvm_lapic_get_base (struct kvm_vcpu *vcpu);void kvm_apic_set_version (struct kvm_vcpu *vcpu); +void kvm_apic_update_tmr (struct kvm_vcpu *vcpu,u32 *tmr);int kvm_apic_match_physical_addr (struct kvm_lapic *apic,u16 dest);int kvm_apic_match_logical_addr (struct kvm_lapic *apic,u8 mda);int kvm_apic_set_irq (struct kvm_vcpu *vcpu,struct kvm_lapic_irq *irq);
arch/x86/kvm/x86.c +5 -1
@@ -5650,14 +5650,18 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)static void vcpu_scan_ioapic (struct kvm_vcpu *vcpu) {u64 eoi_exit_bitmap[4 ]; +u64 tmr[4 ];if (!kvm_lapic_enabled (vcpu))return ;memset (eoi_exit_bitmap,0 ,32 ); +memset (tmr,0 ,32 ); -kvm_ioapic_scan_entry (vcpu, (unsigned long *)eoi_exit_bitmap); +kvm_ioapic_scan_entry (vcpu, (unsigned long *)eoi_exit_bitmap, + (unsigned long *)tmr); kvm_x86_ops->load_eoi_exitmap (vcpu, eoi_exit_bitmap); +kvm_apic_update_tmr (vcpu, (u32 *)tmr); }static int vcpu_enter_guest (struct kvm_vcpu *vcpu)
virt/kvm/ioapic.c +7 -2
@@ -120,7 +120,8 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic) }void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, -unsigned long *eoi_exit_bitmap) +unsigned long *eoi_exit_bitmap, +unsigned long *tmr) {struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;union kvm_ioapic_redirect_entry *e;
@@ -135,8 +136,12 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index))) {if (kvm_apic_match_dest (vcpu,NULL ,0 , - e->fields.dest_id, e->fields.dest_mode)) + e->fields.dest_id, e->fields.dest_mode)) { +__set_bit (irqe.vector, eoi_exit_bitmap); +if (e->fields.trig_mode ==IOAPIC_LEVEL_TRIG ) +__set_bit (irqe.vector, tmr); + } } }spin_unlock (&ioapic->lock);
virt/kvm/ioapic.h +2 -1
@@ -84,6 +84,7 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);int kvm_set_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state);void kvm_vcpu_scan_ioapic (struct kvm *kvm);void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, -unsigned long *eoi_exit_bitmap); +unsigned long *eoi_exit_bitmap, +unsigned long *tmr);#endif
Signature · 1 line
1.7.1
Re: [PATCH v7 5/7] KVM: Set TMR when programming ioapic entry
Quoted 71 lines · Yang Zhang
From: Yang Zhang <[email protected]>
We already know the trigger mode of a given interrupt when programming the ioapice entry. So it's not necessary to set it in each interrupt delivery.
Signed-off-by Yang Zhang <[email protected]>--- arch/x86/kvm/lapic.c | 15 +++++++++------ arch/x86/kvm/lapic.h | 1 + arch/x86/kvm/x86.c | 6 +++++- virt/kvm/ioapic.c | 9 +++++++-- virt/kvm/ioapic.h | 3 ++- 5 files changed, 24 insertions(+), 10 deletions(-)arch/x86/kvm/lapic.c +9
-6@@ -458,6 +458,15 @@ static inline int apic_find_highest_isr(struct kvm_lapic *apic)return result; } +void kvm_apic_update_tmr (struct kvm_vcpu *vcpu,u32 *tmr) +{ +struct kvm_lapic *apic = vcpu->arch.apic; +int i; + +for (i =0 ; i <8 ; i++) +apic_set_reg (apic,APIC_TMR +0x10 * i, tmr[i]); +} +static void apic_update_ppr (struct kvm_lapic *apic) {u32 tpr, isrv, ppr, old_ppr;@@ -647,12 +656,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,if (unlikely (!apic_enabled (apic)))break ; -if (trig_mode) { -apic_debug ("level trig mode for vector %d" , vector); -apic_set_vector (vector, apic->regs +APIC_TMR ); - }else -apic_clear_vector (vector, apic->regs +APIC_TMR ); - result = !apic_test_and_set_irr (vector, apic);trace_kvm_apic_accept_irq (vcpu->vcpu_id, delivery_mode, trig_mode, vector, !result);arch/x86/kvm/lapic.h +1
-0@@ -53,6 +53,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);u64 kvm_lapic_get_base (struct kvm_vcpu *vcpu);void kvm_apic_set_version (struct kvm_vcpu *vcpu); +void kvm_apic_update_tmr (struct kvm_vcpu *vcpu,u32 *tmr);int kvm_apic_match_physical_addr (struct kvm_lapic *apic,u16 dest);int kvm_apic_match_logical_addr (struct kvm_lapic *apic,u8 mda);int kvm_apic_set_irq (struct kvm_vcpu *vcpu,struct kvm_lapic_irq *irq);arch/x86/kvm/x86.c +1
-0@@ -5650,14 +5650,18 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)static void vcpu_scan_ioapic (struct kvm_vcpu *vcpu) {u64 eoi_exit_bitmap[4 ]; +u64 tmr[4 ];if (!kvm_lapic_enabled (vcpu))
arch/x86/kvm/x86.c static void kvm_gen_update_masterclock(struct kvm *kvm) · line 5664
Quoted 10 lines
arch/x86/kvm/x86.c +4
-1return ;memset (eoi_exit_bitmap,0 ,32 ); +memset (tmr,0 ,32 ); -kvm_ioapic_scan_entry (vcpu, (unsigned long *)eoi_exit_bitmap); +kvm_ioapic_scan_entry (vcpu, (unsigned long *)eoi_exit_bitmap, + (unsigned long *)tmr); kvm_x86_ops->load_eoi_exitmap (vcpu, eoi_exit_bitmap); +kvm_apic_update_tmr (vcpu, (u32 *)tmr);
Again, cast it inside if needed.
Quoted 46 lines
arch/x86/kvm/x86.c +0
-0}static int vcpu_enter_guest (struct kvm_vcpu *vcpu)virt/kvm/ioapic.c +7
-2@@ -120,7 +120,8 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic) }void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, -unsigned long *eoi_exit_bitmap) +unsigned long *eoi_exit_bitmap, +unsigned long *tmr) {struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;union kvm_ioapic_redirect_entry *e;@@ -135,8 +136,12 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index))) {if (kvm_apic_match_dest (vcpu,NULL ,0 , - e->fields.dest_id, e->fields.dest_mode)) + e->fields.dest_id, e->fields.dest_mode)) { +__set_bit (irqe.vector, eoi_exit_bitmap); +if (e->fields.trig_mode ==IOAPIC_LEVEL_TRIG ) +__set_bit (irqe.vector, tmr); + } } }spin_unlock (&ioapic->lock);virt/kvm/ioapic.h +2
-1@@ -84,6 +84,7 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);int kvm_set_ioapic (struct kvm *kvm,struct kvm_ioapic_state *state);void kvm_vcpu_scan_ioapic (struct kvm *kvm);void kvm_ioapic_scan_entry (struct kvm_vcpu *vcpu, -unsigned long *eoi_exit_bitmap); +unsigned long *eoi_exit_bitmap, +unsigned long *tmr);#endif Signature · 1 line
1.7.1
--
Gleb.
PATCH v7 6/7 KVM: VMX: Add the algorithm of deliver posted interrupt
In reply to Yang ZhangFrom: Yang Zhang <[email protected]>
Only deliver the posted interrupt when target vcpu is running and there is no previous interrupt pending in pir.
--- arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/lapic.c | 13 ++++++++ arch/x86/kvm/lapic.h | 1 + arch/x86/kvm/svm.c | 6 ++++ arch/x86/kvm/vmx.c | 60 ++++++++++++++++++++++++++++++++++++++- virt/kvm/kvm_main.c | 1 + 6 files changed, 82 insertions(+), 1 deletions(-)
arch/x86/include/asm/kvm_host.h +2 -0
@@ -704,6 +704,8 @@ struct kvm_x86_ops {void (*hwapic_isr_update)(struct kvm *kvm,int isr);void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu,u64 *eoi_exit_bitmap);void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu,bool set); +void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu,int vector); +void (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);int (*set_tss_addr)(struct kvm *kvm,unsigned int addr);int (*get_tdp_level)(void );u64 (*get_mt_mask)(struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio);
arch/x86/kvm/lapic.c +13 -0
@@ -310,6 +310,19 @@ static u8 count_vectors(void *bitmap)return count; } +void kvm_apic_update_irr (struct kvm_vcpu *vcpu,u32 *pir) +{ +u32 i, pir_val; +struct kvm_lapic *apic = vcpu->arch.apic; + +for (i =0 ; i <=7 ; i++) { + pir_val =xchg (&pir[i],0 ); +if (pir_val) + *((u32 *)(apic->regs +APIC_IRR + i *0x10 )) |= pir_val; + } +} +EXPORT_SYMBOL_GPL (kvm_apic_update_irr); +static inline int apic_test_and_set_irr (int vec,struct kvm_lapic *apic) { apic->irr_pending = true;
arch/x86/kvm/lapic.h +1 -0
@@ -54,6 +54,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);void kvm_apic_set_version (struct kvm_vcpu *vcpu);void kvm_apic_update_tmr (struct kvm_vcpu *vcpu,u32 *tmr); +void kvm_apic_update_irr (struct kvm_vcpu *vcpu,u32 *pir);int kvm_apic_match_physical_addr (struct kvm_lapic *apic,u16 dest);int kvm_apic_match_logical_addr (struct kvm_lapic *apic,u8 mda);int kvm_apic_set_irq (struct kvm_vcpu *vcpu,struct kvm_lapic_irq *irq);
arch/x86/kvm/svm.c +6 -0
@@ -3577,6 +3577,11 @@ static void svm_hwapic_isr_update(struct kvm *kvm, int isr)return ; } +static void svm_sync_pir_to_irr (struct kvm_vcpu *vcpu) +{ +return ; +} +static int svm_nmi_allowed (struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu);
@@ -4305,6 +4310,7 @@ static struct kvm_x86_ops svm_x86_ops = { .vm_has_apicv = svm_vm_has_apicv, .load_eoi_exitmap = svm_load_eoi_exitmap, .hwapic_isr_update = svm_hwapic_isr_update, + .sync_pir_to_irr = svm_sync_pir_to_irr, .set_tss_addr = svm_set_tss_addr, .get_tdp_level = get_npt_level,
arch/x86/kvm/vmx.c +59 -1
85 lines not on this page · raw message
virt/kvm/kvm_main.c +1 -0
@@ -1671,6 +1671,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)smp_send_reschedule (cpu); put_cpu(); } +EXPORT_SYMBOL_GPL (kvm_vcpu_kick);#endif /* !CONFIG_S390 */ void kvm_resched (struct kvm_vcpu *vcpu)
Signature · 1 line
1.7.1
Re: [PATCH v7 6/7] KVM: VMX: Add the algorithm of deliver posted interrupt
Quoted 152 lines · Yang Zhang
From: Yang Zhang <[email protected]>
Only deliver the posted interrupt when target vcpu is running and there is no previous interrupt pending in pir.
Signed-off-by Yang Zhang <[email protected]>--- arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kvm/lapic.c | 13 ++++++++ arch/x86/kvm/lapic.h | 1 + arch/x86/kvm/svm.c | 6 ++++ arch/x86/kvm/vmx.c | 60 ++++++++++++++++++++++++++++++++++++++- virt/kvm/kvm_main.c | 1 + 6 files changed, 82 insertions(+), 1 deletions(-)arch/x86/include/asm/kvm_host.h +2
-0@@ -704,6 +704,8 @@ struct kvm_x86_ops {void (*hwapic_isr_update)(struct kvm *kvm,int isr);void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu,u64 *eoi_exit_bitmap);void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu,bool set); +void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu,int vector); +void (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);int (*set_tss_addr)(struct kvm *kvm,unsigned int addr);int (*get_tdp_level)(void );u64 (*get_mt_mask)(struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio);arch/x86/kvm/lapic.c +13
-0@@ -310,6 +310,19 @@ static u8 count_vectors(void *bitmap)return count; } +void kvm_apic_update_irr (struct kvm_vcpu *vcpu,u32 *pir) +{ +u32 i, pir_val; +struct kvm_lapic *apic = vcpu->arch.apic; + +for (i =0 ; i <=7 ; i++) { + pir_val =xchg (&pir[i],0 ); +if (pir_val) + *((u32 *)(apic->regs +APIC_IRR + i *0x10 )) |= pir_val; + } +} +EXPORT_SYMBOL_GPL (kvm_apic_update_irr); +static inline int apic_test_and_set_irr (int vec,struct kvm_lapic *apic) { apic->irr_pending = true;arch/x86/kvm/lapic.h +1
-0@@ -54,6 +54,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);void kvm_apic_set_version (struct kvm_vcpu *vcpu);void kvm_apic_update_tmr (struct kvm_vcpu *vcpu,u32 *tmr); +void kvm_apic_update_irr (struct kvm_vcpu *vcpu,u32 *pir);int kvm_apic_match_physical_addr (struct kvm_lapic *apic,u16 dest);int kvm_apic_match_logical_addr (struct kvm_lapic *apic,u8 mda);int kvm_apic_set_irq (struct kvm_vcpu *vcpu,struct kvm_lapic_irq *irq);arch/x86/kvm/svm.c +6
-0@@ -3577,6 +3577,11 @@ static void svm_hwapic_isr_update(struct kvm *kvm, int isr)return ; } +static void svm_sync_pir_to_irr (struct kvm_vcpu *vcpu) +{ +return ; +} +static int svm_nmi_allowed (struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu);@@ -4305,6 +4310,7 @@ static struct kvm_x86_ops svm_x86_ops = { .vm_has_apicv = svm_vm_has_apicv, .load_eoi_exitmap = svm_load_eoi_exitmap, .hwapic_isr_update = svm_hwapic_isr_update, + .sync_pir_to_irr = svm_sync_pir_to_irr, .set_tss_addr = svm_set_tss_addr, .get_tdp_level = get_npt_level,arch/x86/kvm/vmx.c +40
-1@@ -380,6 +380,23 @@ struct pi_desc { } u; }__aligned(64) ; +static bool pi_test_and_set_on (struct pi_desc *pi_desc) +{ +return test_and_set_bit (POSTED_INTR_ON , + (unsigned long *)&pi_desc->u.control); +} + +static bool pi_test_and_clear_on (struct pi_desc *pi_desc) +{ +return test_and_clear_bit (POSTED_INTR_ON , + (unsigned long *)&pi_desc->u.control); +} + +static int pi_test_and_set_pir (int vector,struct pi_desc *pi_desc) +{ +return test_and_set_bit (vector, (unsigned long *)pi_desc->pir); +} +struct vcpu_vmx {struct kvm_vcpu vcpu;unsigned long host_rsp;@@ -2851,8 +2868,10 @@ static __init int hardware_setup(void)if (enable_apicv) kvm_x86_ops->update_cr8_intercept =NULL ; -else +else { kvm_x86_ops->hwapic_irr_update =NULL ; + kvm_x86_ops->deliver_posted_interrupt =NULL ; + }if (nested)nested_vmx_setup_ctls_msrs ();@@ -3914,6 +3933,43 @@ static int vmx_vm_has_apicv(struct kvm *kvm) }/* +* Send interrupt to vcpu via posted interrupt way. +* 1. If target vcpu is running(non-root mode), send posted interrupt +* notification to vcpu and hardware will sync PIR to vIRR atomically. +* 2. If target vcpu isn't running(root mode), kick it to pick up the +* interrupt from PIR in next vmentry. +*/ +static void vmx_deliver_posted_interrupt (struct kvm_vcpu *vcpu,int vector) +{ +struct vcpu_vmx *vmx =to_vmx (vcpu); +int r; + +if (pi_test_and_set_pir (vector, &vmx->pi_desc)) +return ; + + r =pi_test_and_set_on (&vmx->pi_desc); +kvm_make_request (KVM_REQ_EVENT , vcpu); +if (!r && (vcpu->mode ==IN_GUEST_MODE )) { + apic->send_IPI_mask (get_cpu_mask (vcpu->cpu), +POSTED_INTR_VECTOR ); + }else
arch/x86/kvm/vmx.c static int vmx_vm_has_apicv(struct kvm *kvm) · line 3965
Quoted 10 lines
arch/x86/kvm/vmx.c +10
-0+kvm_vcpu_kick (vcpu); + +return ; +} + +static void vmx_sync_pir_to_irr (struct kvm_vcpu *vcpu) +{ +struct vcpu_vmx *vmx =to_vmx (vcpu); + + if (!vmx_vm_has_apicv(vcpu->kvm) ||
If we set kvm_ops->sync_pir_to_irr() to a function that does nothing if apicv is disabled we can drop this fast path check here.
Quoted 33 lines
arch/x86/kvm/vmx.c +9
-0+ !pi_test_and_clear_on(&vmx->pi_desc)) +return ; + +kvm_apic_update_irr (vcpu, vmx->pi_desc.pir); +} + +/* * Set up the vmcs's constant host-state fields, i.e., host-state fields that * will not change in the lifetime of the guest. * Note that host-state that does change is set elsewhere. E.g., host-state @@ -7756,6 +7812,8 @@ static struct kvm_x86_ops vmx_x86_ops = { .load_eoi_exitmap = vmx_load_eoi_exitmap, .hwapic_irr_update = vmx_hwapic_irr_update, .hwapic_isr_update = vmx_hwapic_isr_update, + .sync_pir_to_irr = vmx_sync_pir_to_irr, + .deliver_posted_interrupt = vmx_deliver_posted_interrupt, .set_tss_addr = vmx_set_tss_addr, .get_tdp_level = get_ept_level,virt/kvm/kvm_main.c +1
-0@@ -1671,6 +1671,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)smp_send_reschedule (cpu); put_cpu(); } +EXPORT_SYMBOL_GPL (kvm_vcpu_kick);#endif /* !CONFIG_S390 */ void kvm_resched (struct kvm_vcpu *vcpu)Signature · 1 line
1.7.1
--
Gleb.
RE: [PATCH v7 6/7] KVM: VMX: Add the algorithm of deliver posted interrupt
Gleb Natapov wrote on 2013-04-07:
Quoted 147 lines · Yang Zhang
arch/x86/kvm/svm.c static void svm_hwapic_isr_update(struct kvm *kvm,
Quoted 65 lines
From: Yang Zhang <[email protected]>
Only deliver the posted interrupt when target vcpu is running and there is no previous interrupt pending in pir.
Signed-off-by Yang Zhang <[email protected]>---
arch/x86/include/asm/kvm_host.h| 2 +arch/x86/kvm/lapic.c| 13 ++++++++ arch/x86/kvm/lapic.h | 1 + arch/x86/kvm/svm.c | 6 ++++ arch/x86/kvm/vmx.c | 60 ++++++++++++++++++++++++++++++++++++++-
virt/kvm/kvm_main.c| 1 + 6 files changed, 82
insertions(+), 1 deletions(-)(quoted diff) +0
-0
b/arch/x86/include/asm/kvm_host.hindex 8e95512..842ea5a 100644 ---a/arch/x86/include/asm/kvm_host.h+++b/arch/x86/include/asm/kvm_host.harch/x86/include/asm/kvm_host.h +2
-0@@ -704,6 +704,8 @@ struct kvm_x86_ops {void (*hwapic_isr_update)(struct kvm *kvm,int isr);void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu,u64 *eoi_exit_bitmap);void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu,bool set); +void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu,int vector); +void (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);int (*set_tss_addr)(struct kvm *kvm,unsigned int addr);int (*get_tdp_level)(void );u64 (*get_mt_mask)(struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio);arch/x86/kvm/lapic.c +13
-0@@ -310,6 +310,19 @@ static u8 count_vectors(void *bitmap)return count; } +void kvm_apic_update_irr (struct kvm_vcpu *vcpu,u32 *pir) +{ +u32 i, pir_val; +struct kvm_lapic *apic = vcpu->arch.apic; + +for (i =0 ; i <=7 ; i++) { + pir_val =xchg (&pir[i],0 ); +if (pir_val) + *((u32 *)(apic->regs +APIC_IRR + i *0x10 )) |= pir_val; + } +} +EXPORT_SYMBOL_GPL (kvm_apic_update_irr); +static inline int apic_test_and_set_irr (int vec,struct kvm_lapic *apic) { apic->irr_pending = true;arch/x86/kvm/lapic.h +0
-0@@ -54,6 +54,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);void kvm_apic_set_version (struct kvm_vcpu *vcpu); void kvm_apic_update_tmr(struct kvm_vcpu *vcpu, u32 *tmr); +void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir); intkvm_apic_match_physical_addr (struct kvm_lapic *apic,u16 dest);int kvm_apic_match_logical_addr (struct kvm_lapic *apic,u8 mda);int kvm_apic_set_irq (struct kvm_vcpu *vcpu,struct kvm_lapic_irq *irq);arch/x86/kvm/svm.c +0
-0@@ -3577,6 +3577,11 @@ static void svm_hwapic_isr_update(struct kvm *kvm,int isr)
Quoted 80 lines
arch/x86/kvm/svm.c +6
-0return ; } +static void svm_sync_pir_to_irr (struct kvm_vcpu *vcpu) +{ +return ; +} +static int svm_nmi_allowed (struct kvm_vcpu *vcpu) {struct vcpu_svm *svm = to_svm(vcpu); @@ -4305,6 +4310,7 @@ static struct kvm_x86_ops svm_x86_ops = { .vm_has_apicv = svm_vm_has_apicv, .load_eoi_exitmap = svm_load_eoi_exitmap, .hwapic_isr_update = svm_hwapic_isr_update, + .sync_pir_to_irr = svm_sync_pir_to_irr, .set_tss_addr = svm_set_tss_addr, .get_tdp_level = get_npt_level,arch/x86/kvm/vmx.c +20
-1@@ -380,6 +380,23 @@ struct pi_desc { } u; }__aligned(64) ; +static bool pi_test_and_set_on (struct pi_desc *pi_desc) +{ +return test_and_set_bit (POSTED_INTR_ON , + (unsigned long *)&pi_desc->u.control); +} + +static bool pi_test_and_clear_on (struct pi_desc *pi_desc) +{ +return test_and_clear_bit (POSTED_INTR_ON , + (unsigned long *)&pi_desc->u.control); +} + +static int pi_test_and_set_pir (int vector,struct pi_desc *pi_desc) +{ +return test_and_set_bit (vector, (unsigned long *)pi_desc->pir); +} +struct vcpu_vmx {struct kvm_vcpu vcpu;unsigned long host_rsp;@@ -2851,8 +2868,10 @@ static __init int hardware_setup(void)if (enable_apicv) kvm_x86_ops->update_cr8_intercept =NULL ; -else +else { kvm_x86_ops->hwapic_irr_update =NULL ; + kvm_x86_ops->deliver_posted_interrupt =NULL ; + } if (nested) nested_vmx_setup_ctls_msrs(); @@ -3914,6 +3933,43 @@ static int vmx_vm_has_apicv(struct kvm *kvm) }/*
+ * Send interrupt to vcpu via posted interrupt way.
+ * 1. If target vcpu is running(non-root mode), send posted interrupt
+ * notification to vcpu and hardware will sync PIR to vIRR atomically.
+ * 2. If target vcpu isn't running(root mode), kick it to pick up the
+ * interrupt from PIR in next vmentry.
+ */arch/x86/kvm/vmx.c +18
-0+static void vmx_deliver_posted_interrupt (struct kvm_vcpu *vcpu,int vector) +{ +struct vcpu_vmx *vmx =to_vmx (vcpu); +int r; + +if (pi_test_and_set_pir (vector, &vmx->pi_desc)) +return ; + + r =pi_test_and_set_on (&vmx->pi_desc); +kvm_make_request (KVM_REQ_EVENT , vcpu); +if (!r && (vcpu->mode ==IN_GUEST_MODE )) { + apic->send_IPI_mask (get_cpu_mask (vcpu->cpu), +POSTED_INTR_VECTOR ); + }else +kvm_vcpu_kick (vcpu); + +return ; +}
Quoted 8 lines
arch/x86/kvm/vmx.c static int vmx_vm_has_apicv(struct kvm *kvm) · line 3965
Quoted 6 lines
arch/x86/kvm/vmx.c +6
-0+ +static void vmx_sync_pir_to_irr (struct kvm_vcpu *vcpu) +{ +struct vcpu_vmx *vmx =to_vmx (vcpu); + + if (!vmx_vm_has_apicv(vcpu->kvm) ||If we set
kvm_ops->sync_pir_to_irr()to a function that does nothing if apicv is disabled we can drop this fast path check here.
Sure.
Best regards,
Yang
PATCH v7 7/7 KVM: VMX: Use posted interrupt to deliver virtual interrupt
In reply to Yang ZhangFrom: Yang Zhang <[email protected]>
If posted interrupt is avaliable, then uses it to inject virtual interrupt to guest.
--- arch/x86/kvm/lapic.c | 29 ++++++++++++++++++----------- arch/x86/kvm/vmx.c | 2 +- arch/x86/kvm/x86.c | 1 + 3 files changed, 20 insertions(+), 12 deletions(-)
arch/x86/kvm/lapic.c +18 -11
@@ -345,6 +345,7 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic)if (!apic->irr_pending)return -1 ; + kvm_x86_ops->sync_pir_to_irr (apic->vcpu); result =apic_search_irr (apic);ASSERT (result ==-1 || result >=16 );
@@ -669,18 +670,24 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,if (unlikely (!apic_enabled (apic)))break ; - result = !apic_test_and_set_irr (vector, apic); -trace_kvm_apic_accept_irq (vcpu->vcpu_id, delivery_mode, - trig_mode, vector, !result); -if (!result) { -if (trig_mode) -apic_debug ("level trig mode repeatedly for " -"vector %d" , vector); -break ; - } +if (kvm_x86_ops->deliver_posted_interrupt) { + result =1 ; + kvm_x86_ops->deliver_posted_interrupt (vcpu, vector); + }else { + result = !apic_test_and_set_irr (vector, apic); + +trace_kvm_apic_accept_irq (vcpu->vcpu_id, delivery_mode, + trig_mode, vector, !result); +if (!result) { +if (trig_mode) +apic_debug ("level trig mode repeatedly " +"for vector %d" , vector); +break ; + } -kvm_make_request (KVM_REQ_EVENT , vcpu); -kvm_vcpu_kick (vcpu); +kvm_make_request (KVM_REQ_EVENT , vcpu); +kvm_vcpu_kick (vcpu); + }break ;case APIC_DM_REMRD :
arch/x86/kvm/vmx.c +1 -1
@@ -84,7 +84,7 @@ module_param(vmm_exclusive, bool, S_IRUGO);static bool __read_mostly fasteoi =1 ;module_param (fasteoi, bool,S_IRUGO ); -static bool __read_mostly enable_apicv; +static bool __read_mostly enable_apicv =1 ;module_param (enable_apicv, bool,S_IRUGO );/*
arch/x86/kvm/x86.c +1 -0
@@ -2685,6 +2685,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)static int kvm_vcpu_ioctl_get_lapic (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s) { + kvm_x86_ops->sync_pir_to_irr (vcpu);memcpy (s->regs, vcpu->arch.apic->regs,sizeof *s);return 0 ;
Signature · 1 line
1.7.1