diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2014-04-30 15:25:09 -0400 |
|---|---|---|
| committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-04-30 15:25:09 -0400 |
| commit | a5a5aef451430dbd48f5bf32029b8b98b690074d (patch) | |
| tree | 02525913943b280d0e0ee26a950b92f9b0dc6eb0 | |
| parent | 41c22f626254b9dc0376928cae009e73d1b6a49a (diff) | |
| parent | 30c2117085bc4e05d091cee6eba79f069b41a9cd (diff) | |
Merge tag 'kvm-arm-for-3.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into kvm-master
First round of KVM/ARM Fixes for 3.15
Includes vgic fixes, a possible kernel corruption bug due to
misalignment of pages and disabling of KVM in KConfig on big-endian
systems, because the last one breaks the build.
| -rw-r--r-- | arch/arm/kvm/Kconfig | 2 | ||||
| -rw-r--r-- | arch/arm/kvm/mmu.c | 15 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic.c | 15 |
3 files changed, 18 insertions, 14 deletions
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 466bd299b1a8..4be5bb150bdd 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig | |||
| @@ -23,7 +23,7 @@ config KVM | |||
| 23 | select HAVE_KVM_CPU_RELAX_INTERCEPT | 23 | select HAVE_KVM_CPU_RELAX_INTERCEPT |
| 24 | select KVM_MMIO | 24 | select KVM_MMIO |
| 25 | select KVM_ARM_HOST | 25 | select KVM_ARM_HOST |
| 26 | depends on ARM_VIRT_EXT && ARM_LPAE | 26 | depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN |
| 27 | ---help--- | 27 | ---help--- |
| 28 | Support hosting virtualized guest machines. You will also | 28 | Support hosting virtualized guest machines. You will also |
| 29 | need to select one or more of the processor modules below. | 29 | need to select one or more of the processor modules below. |
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 80bb1e6c2c29..16f804938b8f 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c | |||
| @@ -42,6 +42,8 @@ static unsigned long hyp_idmap_start; | |||
| 42 | static unsigned long hyp_idmap_end; | 42 | static unsigned long hyp_idmap_end; |
| 43 | static phys_addr_t hyp_idmap_vector; | 43 | static phys_addr_t hyp_idmap_vector; |
| 44 | 44 | ||
| 45 | #define pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t)) | ||
| 46 | |||
| 45 | #define kvm_pmd_huge(_x) (pmd_huge(_x) || pmd_trans_huge(_x)) | 47 | #define kvm_pmd_huge(_x) (pmd_huge(_x) || pmd_trans_huge(_x)) |
| 46 | 48 | ||
| 47 | static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) | 49 | static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) |
| @@ -293,14 +295,14 @@ void free_boot_hyp_pgd(void) | |||
| 293 | if (boot_hyp_pgd) { | 295 | if (boot_hyp_pgd) { |
| 294 | unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE); | 296 | unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE); |
| 295 | unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); | 297 | unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); |
| 296 | kfree(boot_hyp_pgd); | 298 | free_pages((unsigned long)boot_hyp_pgd, pgd_order); |
| 297 | boot_hyp_pgd = NULL; | 299 | boot_hyp_pgd = NULL; |
| 298 | } | 300 | } |
| 299 | 301 | ||
| 300 | if (hyp_pgd) | 302 | if (hyp_pgd) |
| 301 | unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); | 303 | unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); |
| 302 | 304 | ||
| 303 | kfree(init_bounce_page); | 305 | free_page((unsigned long)init_bounce_page); |
| 304 | init_bounce_page = NULL; | 306 | init_bounce_page = NULL; |
| 305 | 307 | ||
| 306 | mutex_unlock(&kvm_hyp_pgd_mutex); | 308 | mutex_unlock(&kvm_hyp_pgd_mutex); |
| @@ -330,7 +332,7 @@ void free_hyp_pgds(void) | |||
| 330 | for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) | 332 | for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) |
| 331 | unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); | 333 | unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); |
| 332 | 334 | ||
| 333 | kfree(hyp_pgd); | 335 | free_pages((unsigned long)hyp_pgd, pgd_order); |
| 334 | hyp_pgd = NULL; | 336 | hyp_pgd = NULL; |
| 335 | } | 337 | } |
| 336 | 338 | ||
| @@ -1024,7 +1026,7 @@ int kvm_mmu_init(void) | |||
| 1024 | size_t len = __hyp_idmap_text_end - __hyp_idmap_text_start; | 1026 | size_t len = __hyp_idmap_text_end - __hyp_idmap_text_start; |
| 1025 | phys_addr_t phys_base; | 1027 | phys_addr_t phys_base; |
| 1026 | 1028 | ||
| 1027 | init_bounce_page = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1029 | init_bounce_page = (void *)__get_free_page(GFP_KERNEL); |
| 1028 | if (!init_bounce_page) { | 1030 | if (!init_bounce_page) { |
| 1029 | kvm_err("Couldn't allocate HYP init bounce page\n"); | 1031 | kvm_err("Couldn't allocate HYP init bounce page\n"); |
| 1030 | err = -ENOMEM; | 1032 | err = -ENOMEM; |
| @@ -1050,8 +1052,9 @@ int kvm_mmu_init(void) | |||
| 1050 | (unsigned long)phys_base); | 1052 | (unsigned long)phys_base); |
| 1051 | } | 1053 | } |
| 1052 | 1054 | ||
| 1053 | hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); | 1055 | hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order); |
| 1054 | boot_hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); | 1056 | boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order); |
| 1057 | |||
| 1055 | if (!hyp_pgd || !boot_hyp_pgd) { | 1058 | if (!hyp_pgd || !boot_hyp_pgd) { |
| 1056 | kvm_err("Hyp mode PGD not allocated\n"); | 1059 | kvm_err("Hyp mode PGD not allocated\n"); |
| 1057 | err = -ENOMEM; | 1060 | err = -ENOMEM; |
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 47b29834a6b6..56ff9bebb577 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
| @@ -548,11 +548,10 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu, | |||
| 548 | u32 val; | 548 | u32 val; |
| 549 | u32 *reg; | 549 | u32 *reg; |
| 550 | 550 | ||
| 551 | offset >>= 1; | ||
| 552 | reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg, | 551 | reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg, |
| 553 | vcpu->vcpu_id, offset); | 552 | vcpu->vcpu_id, offset >> 1); |
| 554 | 553 | ||
| 555 | if (offset & 2) | 554 | if (offset & 4) |
| 556 | val = *reg >> 16; | 555 | val = *reg >> 16; |
| 557 | else | 556 | else |
| 558 | val = *reg & 0xffff; | 557 | val = *reg & 0xffff; |
| @@ -561,13 +560,13 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu, | |||
| 561 | vgic_reg_access(mmio, &val, offset, | 560 | vgic_reg_access(mmio, &val, offset, |
| 562 | ACCESS_READ_VALUE | ACCESS_WRITE_VALUE); | 561 | ACCESS_READ_VALUE | ACCESS_WRITE_VALUE); |
| 563 | if (mmio->is_write) { | 562 | if (mmio->is_write) { |
| 564 | if (offset < 4) { | 563 | if (offset < 8) { |
| 565 | *reg = ~0U; /* Force PPIs/SGIs to 1 */ | 564 | *reg = ~0U; /* Force PPIs/SGIs to 1 */ |
| 566 | return false; | 565 | return false; |
| 567 | } | 566 | } |
| 568 | 567 | ||
| 569 | val = vgic_cfg_compress(val); | 568 | val = vgic_cfg_compress(val); |
| 570 | if (offset & 2) { | 569 | if (offset & 4) { |
| 571 | *reg &= 0xffff; | 570 | *reg &= 0xffff; |
| 572 | *reg |= val << 16; | 571 | *reg |= val << 16; |
| 573 | } else { | 572 | } else { |
| @@ -916,6 +915,7 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg) | |||
| 916 | case 0: | 915 | case 0: |
| 917 | if (!target_cpus) | 916 | if (!target_cpus) |
| 918 | return; | 917 | return; |
| 918 | break; | ||
| 919 | 919 | ||
| 920 | case 1: | 920 | case 1: |
| 921 | target_cpus = ((1 << nrcpus) - 1) & ~(1 << vcpu_id) & 0xff; | 921 | 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, | |||
| 1667 | if (addr + size < addr) | 1667 | if (addr + size < addr) |
| 1668 | return -EINVAL; | 1668 | return -EINVAL; |
| 1669 | 1669 | ||
| 1670 | *ioaddr = addr; | ||
| 1670 | ret = vgic_ioaddr_overlap(kvm); | 1671 | ret = vgic_ioaddr_overlap(kvm); |
| 1671 | if (ret) | 1672 | if (ret) |
| 1672 | return ret; | 1673 | *ioaddr = VGIC_ADDR_UNDEF; |
| 1673 | *ioaddr = addr; | 1674 | |
| 1674 | return ret; | 1675 | return ret; |
| 1675 | } | 1676 | } |
| 1676 | 1677 | ||
