diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/kvm/irq.c | 2 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 52 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 4 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 2 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 13 | ||||
-rw-r--r-- | arch/x86/xen/grant-table.c | 60 | ||||
-rw-r--r-- | arch/x86/xen/p2m.c | 5 |
8 files changed, 64 insertions, 75 deletions
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 287e4c85fff9..f9d16ff56c6b 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -27,6 +27,7 @@ config KVM select MMU_NOTIFIER select ANON_INODES select HAVE_KVM_IRQCHIP + select HAVE_KVM_IRQFD select HAVE_KVM_IRQ_ROUTING select HAVE_KVM_EVENTFD select KVM_APIC_ARCHITECTURE diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c index bd0da433e6d7..a1ec6a50a05a 100644 --- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -108,7 +108,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) vector = kvm_cpu_get_extint(v); - if (kvm_apic_vid_enabled(v->kvm) || vector != -1) + if (vector != -1) return vector; /* PIC */ return kvm_get_apic_interrupt(v); /* APIC */ diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 3855103f71fd..08e8a899e005 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -352,25 +352,46 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic) static inline void apic_clear_irr(int vec, struct kvm_lapic *apic) { - apic->irr_pending = false; + struct kvm_vcpu *vcpu; + + vcpu = apic->vcpu; + apic_clear_vector(vec, apic->regs + APIC_IRR); - if (apic_search_irr(apic) != -1) - apic->irr_pending = true; + if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) + /* try to update RVI */ + kvm_make_request(KVM_REQ_EVENT, vcpu); + else { + vec = apic_search_irr(apic); + apic->irr_pending = (vec != -1); + } } static inline void apic_set_isr(int vec, struct kvm_lapic *apic) { - /* Note that we never get here with APIC virtualization enabled. */ + struct kvm_vcpu *vcpu; + + if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) + return; + + vcpu = apic->vcpu; - if (!__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) - ++apic->isr_count; - BUG_ON(apic->isr_count > MAX_APIC_VECTOR); /* - * ISR (in service register) bit is set when injecting an interrupt. - * The highest vector is injected. Thus the latest bit set matches - * the highest bit in ISR. + * With APIC virtualization enabled, all caching is disabled + * because the processor can modify ISR under the hood. Instead + * just set SVI. */ - apic->highest_isr_cache = vec; + if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) + kvm_x86_ops->hwapic_isr_update(vcpu->kvm, vec); + else { + ++apic->isr_count; + BUG_ON(apic->isr_count > MAX_APIC_VECTOR); + /* + * ISR (in service register) bit is set when injecting an interrupt. + * The highest vector is injected. Thus the latest bit set matches + * the highest bit in ISR. + */ + apic->highest_isr_cache = vec; + } } static inline int apic_find_highest_isr(struct kvm_lapic *apic) @@ -1627,11 +1648,16 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu) int vector = kvm_apic_has_interrupt(vcpu); struct kvm_lapic *apic = vcpu->arch.apic; - /* Note that we never get here with APIC virtualization enabled. */ - if (vector == -1) return -1; + /* + * We get here even with APIC virtualization enabled, if doing + * nested virtualization and L1 runs with the "acknowledge interrupt + * on exit" mode. Then we cannot inject the interrupt via RVI, + * because the process would deliver it through the IDT. + */ + apic_set_isr(vector, apic); apic_update_ppr(apic); apic_clear_irr(vector, apic); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e618f34bde2d..bfe11cf124a1 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8754,6 +8754,8 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info, exit_qualification); + vmx_load_vmcs01(vcpu); + if ((exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT) && nested_exit_intr_ack_set(vcpu)) { int irq = kvm_cpu_get_interrupt(vcpu); @@ -8769,8 +8771,6 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, vmcs12->vm_exit_intr_error_code, KVM_ISA_VMX); - vmx_load_vmcs01(vcpu); - vm_entry_controls_init(vmx, vmcs_read32(VM_ENTRY_CONTROLS)); vm_exit_controls_init(vmx, vmcs_read32(VM_EXIT_CONTROLS)); vmx_segment_cache_clear(vmx); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ca3d760dd581..8f1e22d3b286 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2636,7 +2636,7 @@ out: return r; } -int kvm_dev_ioctl_check_extension(long ext) +int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 94813515fdd6..c0cb11fb5008 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1828,8 +1828,19 @@ static void __init xen_hvm_guest_init(void) xen_hvm_init_mmu_ops(); } +static bool xen_nopv = false; +static __init int xen_parse_nopv(char *arg) +{ + xen_nopv = true; + return 0; +} +early_param("xen_nopv", xen_parse_nopv); + static uint32_t __init xen_hvm_platform(void) { + if (xen_nopv) + return 0; + if (xen_pv_domain()) return 0; @@ -1838,6 +1849,8 @@ static uint32_t __init xen_hvm_platform(void) bool xen_hvm_need_lapic(void) { + if (xen_nopv) + return false; if (xen_pv_domain()) return false; if (!xen_hvm_domain()) diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index ebfa9b2c871d..c0413046483a 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c @@ -49,7 +49,7 @@ static struct gnttab_vm_area { struct vm_struct *area; pte_t **ptes; -} gnttab_shared_vm_area, gnttab_status_vm_area; +} gnttab_shared_vm_area; int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, unsigned long max_nr_gframes, @@ -73,43 +73,16 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, return 0; } -int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes, - unsigned long max_nr_gframes, - grant_status_t **__shared) -{ - grant_status_t *shared = *__shared; - unsigned long addr; - unsigned long i; - - if (shared == NULL) - *__shared = shared = gnttab_status_vm_area.area->addr; - - addr = (unsigned long)shared; - - for (i = 0; i < nr_gframes; i++) { - set_pte_at(&init_mm, addr, gnttab_status_vm_area.ptes[i], - mfn_pte(frames[i], PAGE_KERNEL)); - addr += PAGE_SIZE; - } - - return 0; -} - void arch_gnttab_unmap(void *shared, unsigned long nr_gframes) { - pte_t **ptes; unsigned long addr; unsigned long i; - if (shared == gnttab_status_vm_area.area->addr) - ptes = gnttab_status_vm_area.ptes; - else - ptes = gnttab_shared_vm_area.ptes; - addr = (unsigned long)shared; for (i = 0; i < nr_gframes; i++) { - set_pte_at(&init_mm, addr, ptes[i], __pte(0)); + set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i], + __pte(0)); addr += PAGE_SIZE; } } @@ -129,35 +102,12 @@ static int arch_gnttab_valloc(struct gnttab_vm_area *area, unsigned nr_frames) return 0; } -static void arch_gnttab_vfree(struct gnttab_vm_area *area) +int arch_gnttab_init(unsigned long nr_shared) { - free_vm_area(area->area); - kfree(area->ptes); -} - -int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status) -{ - int ret; - if (!xen_pv_domain()) return 0; - ret = arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared); - if (ret < 0) - return ret; - - /* - * Always allocate the space for the status frames in case - * we're migrated to a host with V2 support. - */ - ret = arch_gnttab_valloc(&gnttab_status_vm_area, nr_status); - if (ret < 0) - goto err; - - return 0; - err: - arch_gnttab_vfree(&gnttab_shared_vm_area); - return -ENOMEM; + return arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared); } #ifdef CONFIG_XEN_PVH diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 9bb3d82ffec8..3172692381ae 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -841,10 +841,9 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s, pfn = ALIGN(pfn, P2M_PER_PAGE); } - if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s), + WARN((pfn - pfn_s) != (pfn_e - pfn_s), "Identity mapping failed. We are %ld short of 1-1 mappings!\n", - (pfn_e - pfn_s) - (pfn - pfn_s))) - printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn); + (pfn_e - pfn_s) - (pfn - pfn_s)); return pfn - pfn_s; } |