mirror of https://gitee.com/openkylin/linux.git
- Fix for a Haswell regression in nested virtualization, introduced during
the merge window. - A fix from Oleg to async page faults. - A bunch of small ARM changes. - A trivial patch to use the new MSI-X API introduced during the merge window. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTY5anAAoJEBvWZb6bTYby6EQQAIWbOJCrLO3NQxwE9M7d8YvN oviaLFv7vJh1vaXVo7SNjBRXTq4pzWrhg9rwWlHBg1KnxJ0/sc9Tn07Fe+0bxWDh 1XIFXNEkO9+Bpl43VnKGC7sbkYE9m3+jpGCWjF01vBCh+BY73wUOsPD0Zw9YQojN TKBtiQEjb8avuoTUR0JSOTwLZw4DlDRmRLHkNwlqqvbPdvuIWI/LG2wFUvY7/eq8 dWxIPBjLKaIv2aUs9wGNNiz4Kb92uyH5L6bI6SK8VxphRA+51BOjMcBbzdY+Q1XL c4CTaL9ybAyUi4SRv41qWnM09YbI1FayUW93k9xz/vEplXOHp5R/lyUdZETd/d83 GxaooTLcy9nOYeZ75buiH/0EG5HxI7On/QfUBEE3qIf8KfGgxb479HbRw6RnX4bf EhQzf7eyZvvk43Xk3OYwq8Ux1SOiXQEo+8TpCSaM/KN57cJbjGB4GCUK6JX8qJCx 7MfXBdrhkAdw5V4lEBQMYKp4pdUdgYKRXavhLevm0qFjX1Swl6LIHxLtjFTKyX9S Xfxi09J7EUs7SsI35pdlMtPQkklEUXE96S/W3RCEpR+OfgbVMkYkcQI8TGb7ib3l xLNJrSgFDSlP5F3rN5SYIItAqboXb7iLp7SiF2ByXV43yexIrzTH0bwdwPwpZHhk 2ziVieX5WXEX4tgzZkRj =+bLo -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm Pull KVM fixes from Paolo Bonzini: - Fix for a Haswell regression in nested virtualization, introduced during the merge window. - A fix from Oleg to async page faults. - A bunch of small ARM changes. - A trivial patch to use the new MSI-X API introduced during the merge window. * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: ARM: vgic: Fix the overlap check action about setting the GICD & GICC base address. KVM: arm/arm64: vgic: fix GICD_ICFGR register accesses KVM: async_pf: mm->mm_users can not pin apf->mm KVM: ARM: vgic: Fix sgi dispatch problem MAINTAINERS: co-maintainance of KVM/{arm,arm64} arm: KVM: fix possible misalignment of PGDs and bounce page KVM: x86: Check for host supported fields in shadow vmcs kvm: Use pci_enable_msix_exact() instead of pci_enable_msix() ARM: KVM: disable KVM in Kconfig on big-endian systems
This commit is contained in:
commit
e7e6d2a4a1
|
@ -5114,14 +5114,19 @@ F: drivers/s390/kvm/
|
||||||
|
|
||||||
KERNEL VIRTUAL MACHINE (KVM) FOR ARM
|
KERNEL VIRTUAL MACHINE (KVM) FOR ARM
|
||||||
M: Christoffer Dall <christoffer.dall@linaro.org>
|
M: Christoffer Dall <christoffer.dall@linaro.org>
|
||||||
|
M: Marc Zyngier <marc.zyngier@arm.com>
|
||||||
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
L: kvmarm@lists.cs.columbia.edu
|
L: kvmarm@lists.cs.columbia.edu
|
||||||
W: http://systems.cs.columbia.edu/projects/kvm-arm
|
W: http://systems.cs.columbia.edu/projects/kvm-arm
|
||||||
S: Supported
|
S: Supported
|
||||||
F: arch/arm/include/uapi/asm/kvm*
|
F: arch/arm/include/uapi/asm/kvm*
|
||||||
F: arch/arm/include/asm/kvm*
|
F: arch/arm/include/asm/kvm*
|
||||||
F: arch/arm/kvm/
|
F: arch/arm/kvm/
|
||||||
|
F: virt/kvm/arm/
|
||||||
|
F: include/kvm/arm_*
|
||||||
|
|
||||||
KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
|
KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
|
||||||
|
M: Christoffer Dall <christoffer.dall@linaro.org>
|
||||||
M: Marc Zyngier <marc.zyngier@arm.com>
|
M: Marc Zyngier <marc.zyngier@arm.com>
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
L: kvmarm@lists.cs.columbia.edu
|
L: kvmarm@lists.cs.columbia.edu
|
||||||
|
|
|
@ -23,7 +23,7 @@ config KVM
|
||||||
select HAVE_KVM_CPU_RELAX_INTERCEPT
|
select HAVE_KVM_CPU_RELAX_INTERCEPT
|
||||||
select KVM_MMIO
|
select KVM_MMIO
|
||||||
select KVM_ARM_HOST
|
select KVM_ARM_HOST
|
||||||
depends on ARM_VIRT_EXT && ARM_LPAE
|
depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN
|
||||||
---help---
|
---help---
|
||||||
Support hosting virtualized guest machines. You will also
|
Support hosting virtualized guest machines. You will also
|
||||||
need to select one or more of the processor modules below.
|
need to select one or more of the processor modules below.
|
||||||
|
|
|
@ -42,6 +42,8 @@ static unsigned long hyp_idmap_start;
|
||||||
static unsigned long hyp_idmap_end;
|
static unsigned long hyp_idmap_end;
|
||||||
static phys_addr_t hyp_idmap_vector;
|
static phys_addr_t hyp_idmap_vector;
|
||||||
|
|
||||||
|
#define pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
|
||||||
|
|
||||||
#define kvm_pmd_huge(_x) (pmd_huge(_x) || pmd_trans_huge(_x))
|
#define kvm_pmd_huge(_x) (pmd_huge(_x) || pmd_trans_huge(_x))
|
||||||
|
|
||||||
static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
|
static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
|
||||||
|
@ -293,14 +295,14 @@ void free_boot_hyp_pgd(void)
|
||||||
if (boot_hyp_pgd) {
|
if (boot_hyp_pgd) {
|
||||||
unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
|
unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
|
||||||
unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
|
unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
|
||||||
kfree(boot_hyp_pgd);
|
free_pages((unsigned long)boot_hyp_pgd, pgd_order);
|
||||||
boot_hyp_pgd = NULL;
|
boot_hyp_pgd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hyp_pgd)
|
if (hyp_pgd)
|
||||||
unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
|
unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
|
||||||
|
|
||||||
kfree(init_bounce_page);
|
free_page((unsigned long)init_bounce_page);
|
||||||
init_bounce_page = NULL;
|
init_bounce_page = NULL;
|
||||||
|
|
||||||
mutex_unlock(&kvm_hyp_pgd_mutex);
|
mutex_unlock(&kvm_hyp_pgd_mutex);
|
||||||
|
@ -330,7 +332,7 @@ void free_hyp_pgds(void)
|
||||||
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
|
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
|
||||||
unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
|
unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
|
||||||
|
|
||||||
kfree(hyp_pgd);
|
free_pages((unsigned long)hyp_pgd, pgd_order);
|
||||||
hyp_pgd = NULL;
|
hyp_pgd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,7 +1026,7 @@ int kvm_mmu_init(void)
|
||||||
size_t len = __hyp_idmap_text_end - __hyp_idmap_text_start;
|
size_t len = __hyp_idmap_text_end - __hyp_idmap_text_start;
|
||||||
phys_addr_t phys_base;
|
phys_addr_t phys_base;
|
||||||
|
|
||||||
init_bounce_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
init_bounce_page = (void *)__get_free_page(GFP_KERNEL);
|
||||||
if (!init_bounce_page) {
|
if (!init_bounce_page) {
|
||||||
kvm_err("Couldn't allocate HYP init bounce page\n");
|
kvm_err("Couldn't allocate HYP init bounce page\n");
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
@ -1050,8 +1052,9 @@ int kvm_mmu_init(void)
|
||||||
(unsigned long)phys_base);
|
(unsigned long)phys_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
|
hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);
|
||||||
boot_hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
|
boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);
|
||||||
|
|
||||||
if (!hyp_pgd || !boot_hyp_pgd) {
|
if (!hyp_pgd || !boot_hyp_pgd) {
|
||||||
kvm_err("Hyp mode PGD not allocated\n");
|
kvm_err("Hyp mode PGD not allocated\n");
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
|
|
@ -503,7 +503,7 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
|
||||||
[number##_HIGH] = VMCS12_OFFSET(name)+4
|
[number##_HIGH] = VMCS12_OFFSET(name)+4
|
||||||
|
|
||||||
|
|
||||||
static const unsigned long shadow_read_only_fields[] = {
|
static unsigned long shadow_read_only_fields[] = {
|
||||||
/*
|
/*
|
||||||
* We do NOT shadow fields that are modified when L0
|
* We do NOT shadow fields that are modified when L0
|
||||||
* traps and emulates any vmx instruction (e.g. VMPTRLD,
|
* traps and emulates any vmx instruction (e.g. VMPTRLD,
|
||||||
|
@ -526,10 +526,10 @@ static const unsigned long shadow_read_only_fields[] = {
|
||||||
GUEST_LINEAR_ADDRESS,
|
GUEST_LINEAR_ADDRESS,
|
||||||
GUEST_PHYSICAL_ADDRESS
|
GUEST_PHYSICAL_ADDRESS
|
||||||
};
|
};
|
||||||
static const int max_shadow_read_only_fields =
|
static int max_shadow_read_only_fields =
|
||||||
ARRAY_SIZE(shadow_read_only_fields);
|
ARRAY_SIZE(shadow_read_only_fields);
|
||||||
|
|
||||||
static const unsigned long shadow_read_write_fields[] = {
|
static unsigned long shadow_read_write_fields[] = {
|
||||||
GUEST_RIP,
|
GUEST_RIP,
|
||||||
GUEST_RSP,
|
GUEST_RSP,
|
||||||
GUEST_CR0,
|
GUEST_CR0,
|
||||||
|
@ -558,7 +558,7 @@ static const unsigned long shadow_read_write_fields[] = {
|
||||||
HOST_FS_SELECTOR,
|
HOST_FS_SELECTOR,
|
||||||
HOST_GS_SELECTOR
|
HOST_GS_SELECTOR
|
||||||
};
|
};
|
||||||
static const int max_shadow_read_write_fields =
|
static int max_shadow_read_write_fields =
|
||||||
ARRAY_SIZE(shadow_read_write_fields);
|
ARRAY_SIZE(shadow_read_write_fields);
|
||||||
|
|
||||||
static const unsigned short vmcs_field_to_offset_table[] = {
|
static const unsigned short vmcs_field_to_offset_table[] = {
|
||||||
|
@ -3009,6 +3009,41 @@ static void free_kvm_area(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_vmcs_shadow_fields(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/* No checks for read only fields yet */
|
||||||
|
|
||||||
|
for (i = j = 0; i < max_shadow_read_write_fields; i++) {
|
||||||
|
switch (shadow_read_write_fields[i]) {
|
||||||
|
case GUEST_BNDCFGS:
|
||||||
|
if (!vmx_mpx_supported())
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j < i)
|
||||||
|
shadow_read_write_fields[j] =
|
||||||
|
shadow_read_write_fields[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
max_shadow_read_write_fields = j;
|
||||||
|
|
||||||
|
/* shadowed fields guest access without vmexit */
|
||||||
|
for (i = 0; i < max_shadow_read_write_fields; i++) {
|
||||||
|
clear_bit(shadow_read_write_fields[i],
|
||||||
|
vmx_vmwrite_bitmap);
|
||||||
|
clear_bit(shadow_read_write_fields[i],
|
||||||
|
vmx_vmread_bitmap);
|
||||||
|
}
|
||||||
|
for (i = 0; i < max_shadow_read_only_fields; i++)
|
||||||
|
clear_bit(shadow_read_only_fields[i],
|
||||||
|
vmx_vmread_bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
static __init int alloc_kvm_area(void)
|
static __init int alloc_kvm_area(void)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
|
@ -3039,6 +3074,8 @@ static __init int hardware_setup(void)
|
||||||
enable_vpid = 0;
|
enable_vpid = 0;
|
||||||
if (!cpu_has_vmx_shadow_vmcs())
|
if (!cpu_has_vmx_shadow_vmcs())
|
||||||
enable_shadow_vmcs = 0;
|
enable_shadow_vmcs = 0;
|
||||||
|
if (enable_shadow_vmcs)
|
||||||
|
init_vmcs_shadow_fields();
|
||||||
|
|
||||||
if (!cpu_has_vmx_ept() ||
|
if (!cpu_has_vmx_ept() ||
|
||||||
!cpu_has_vmx_ept_4levels()) {
|
!cpu_has_vmx_ept_4levels()) {
|
||||||
|
@ -8803,14 +8840,6 @@ static int __init vmx_init(void)
|
||||||
|
|
||||||
memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
|
memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
|
||||||
memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
|
memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
|
||||||
/* shadowed read/write fields */
|
|
||||||
for (i = 0; i < max_shadow_read_write_fields; i++) {
|
|
||||||
clear_bit(shadow_read_write_fields[i], vmx_vmwrite_bitmap);
|
|
||||||
clear_bit(shadow_read_write_fields[i], vmx_vmread_bitmap);
|
|
||||||
}
|
|
||||||
/* shadowed read only fields */
|
|
||||||
for (i = 0; i < max_shadow_read_only_fields; i++)
|
|
||||||
clear_bit(shadow_read_only_fields[i], vmx_vmread_bitmap);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow direct access to the PC debug port (it is often used for I/O
|
* Allow direct access to the PC debug port (it is often used for I/O
|
||||||
|
|
|
@ -548,11 +548,10 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
|
||||||
u32 val;
|
u32 val;
|
||||||
u32 *reg;
|
u32 *reg;
|
||||||
|
|
||||||
offset >>= 1;
|
|
||||||
reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg,
|
reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg,
|
||||||
vcpu->vcpu_id, offset);
|
vcpu->vcpu_id, offset >> 1);
|
||||||
|
|
||||||
if (offset & 2)
|
if (offset & 4)
|
||||||
val = *reg >> 16;
|
val = *reg >> 16;
|
||||||
else
|
else
|
||||||
val = *reg & 0xffff;
|
val = *reg & 0xffff;
|
||||||
|
@ -561,13 +560,13 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
|
||||||
vgic_reg_access(mmio, &val, offset,
|
vgic_reg_access(mmio, &val, offset,
|
||||||
ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
|
ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
|
||||||
if (mmio->is_write) {
|
if (mmio->is_write) {
|
||||||
if (offset < 4) {
|
if (offset < 8) {
|
||||||
*reg = ~0U; /* Force PPIs/SGIs to 1 */
|
*reg = ~0U; /* Force PPIs/SGIs to 1 */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = vgic_cfg_compress(val);
|
val = vgic_cfg_compress(val);
|
||||||
if (offset & 2) {
|
if (offset & 4) {
|
||||||
*reg &= 0xffff;
|
*reg &= 0xffff;
|
||||||
*reg |= val << 16;
|
*reg |= val << 16;
|
||||||
} else {
|
} else {
|
||||||
|
@ -916,6 +915,7 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)
|
||||||
case 0:
|
case 0:
|
||||||
if (!target_cpus)
|
if (!target_cpus)
|
||||||
return;
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
target_cpus = ((1 << nrcpus) - 1) & ~(1 << vcpu_id) & 0xff;
|
target_cpus = ((1 << nrcpus) - 1) & ~(1 << vcpu_id) & 0xff;
|
||||||
|
@ -1667,10 +1667,11 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
|
||||||
if (addr + size < addr)
|
if (addr + size < addr)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
*ioaddr = addr;
|
||||||
ret = vgic_ioaddr_overlap(kvm);
|
ret = vgic_ioaddr_overlap(kvm);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
*ioaddr = VGIC_ADDR_UNDEF;
|
||||||
*ioaddr = addr;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -395,7 +395,8 @@ static int assigned_device_enable_host_msix(struct kvm *kvm,
|
||||||
if (dev->entries_nr == 0)
|
if (dev->entries_nr == 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = pci_enable_msix(dev->dev, dev->host_msix_entries, dev->entries_nr);
|
r = pci_enable_msix_exact(dev->dev,
|
||||||
|
dev->host_msix_entries, dev->entries_nr);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ static void async_pf_execute(struct work_struct *work)
|
||||||
if (waitqueue_active(&vcpu->wq))
|
if (waitqueue_active(&vcpu->wq))
|
||||||
wake_up_interruptible(&vcpu->wq);
|
wake_up_interruptible(&vcpu->wq);
|
||||||
|
|
||||||
mmdrop(mm);
|
mmput(mm);
|
||||||
kvm_put_kvm(vcpu->kvm);
|
kvm_put_kvm(vcpu->kvm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
|
||||||
flush_work(&work->work);
|
flush_work(&work->work);
|
||||||
#else
|
#else
|
||||||
if (cancel_work_sync(&work->work)) {
|
if (cancel_work_sync(&work->work)) {
|
||||||
mmdrop(work->mm);
|
mmput(work->mm);
|
||||||
kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */
|
kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */
|
||||||
kmem_cache_free(async_pf_cache, work);
|
kmem_cache_free(async_pf_cache, work);
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
|
||||||
work->addr = hva;
|
work->addr = hva;
|
||||||
work->arch = *arch;
|
work->arch = *arch;
|
||||||
work->mm = current->mm;
|
work->mm = current->mm;
|
||||||
atomic_inc(&work->mm->mm_count);
|
atomic_inc(&work->mm->mm_users);
|
||||||
kvm_get_kvm(work->vcpu->kvm);
|
kvm_get_kvm(work->vcpu->kvm);
|
||||||
|
|
||||||
/* this can't really happen otherwise gfn_to_pfn_async
|
/* this can't really happen otherwise gfn_to_pfn_async
|
||||||
|
@ -201,7 +201,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
|
||||||
return 1;
|
return 1;
|
||||||
retry_sync:
|
retry_sync:
|
||||||
kvm_put_kvm(work->vcpu->kvm);
|
kvm_put_kvm(work->vcpu->kvm);
|
||||||
mmdrop(work->mm);
|
mmput(work->mm);
|
||||||
kmem_cache_free(async_pf_cache, work);
|
kmem_cache_free(async_pf_cache, work);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue