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 | ||