diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/kvm/mmio.c | 6 | ||||
-rw-r--r-- | arch/ia64/kvm/vcpu.c | 6 | ||||
-rw-r--r-- | arch/ia64/kvm/vcpu.h | 13 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 2 | ||||
-rw-r--r-- | arch/x86/kvm/i8254.c | 3 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.c | 48 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 6 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 6 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 44 |
10 files changed, 101 insertions, 35 deletions
diff --git a/arch/ia64/kvm/mmio.c b/arch/ia64/kvm/mmio.c index 21f63fffc379..9bf55afd08d0 100644 --- a/arch/ia64/kvm/mmio.c +++ b/arch/ia64/kvm/mmio.c | |||
@@ -247,7 +247,8 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma) | |||
247 | vcpu_get_fpreg(vcpu, inst.M9.f2, &v); | 247 | vcpu_get_fpreg(vcpu, inst.M9.f2, &v); |
248 | /* Write high word. FIXME: this is a kludge! */ | 248 | /* Write high word. FIXME: this is a kludge! */ |
249 | v.u.bits[1] &= 0x3ffff; | 249 | v.u.bits[1] &= 0x3ffff; |
250 | mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE); | 250 | mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1], 8, |
251 | ma, IOREQ_WRITE); | ||
251 | data = v.u.bits[0]; | 252 | data = v.u.bits[0]; |
252 | size = 3; | 253 | size = 3; |
253 | } else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) { | 254 | } else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) { |
@@ -265,7 +266,8 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma) | |||
265 | 266 | ||
266 | /* Write high word.FIXME: this is a kludge! */ | 267 | /* Write high word.FIXME: this is a kludge! */ |
267 | v.u.bits[1] &= 0x3ffff; | 268 | v.u.bits[1] &= 0x3ffff; |
268 | mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE); | 269 | mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1], |
270 | 8, ma, IOREQ_WRITE); | ||
269 | data = v.u.bits[0]; | 271 | data = v.u.bits[0]; |
270 | size = 3; | 272 | size = 3; |
271 | } else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) { | 273 | } else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) { |
diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c index 46b02cbcc874..cc406d064a09 100644 --- a/arch/ia64/kvm/vcpu.c +++ b/arch/ia64/kvm/vcpu.c | |||
@@ -461,7 +461,7 @@ void setreg(unsigned long regnum, unsigned long val, | |||
461 | u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg) | 461 | u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg) |
462 | { | 462 | { |
463 | struct kvm_pt_regs *regs = vcpu_regs(vcpu); | 463 | struct kvm_pt_regs *regs = vcpu_regs(vcpu); |
464 | u64 val; | 464 | unsigned long val; |
465 | 465 | ||
466 | if (!reg) | 466 | if (!reg) |
467 | return 0; | 467 | return 0; |
@@ -469,7 +469,7 @@ u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg) | |||
469 | return val; | 469 | return val; |
470 | } | 470 | } |
471 | 471 | ||
472 | void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 value, int nat) | 472 | void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg, u64 value, int nat) |
473 | { | 473 | { |
474 | struct kvm_pt_regs *regs = vcpu_regs(vcpu); | 474 | struct kvm_pt_regs *regs = vcpu_regs(vcpu); |
475 | long sof = (regs->cr_ifs) & 0x7f; | 475 | long sof = (regs->cr_ifs) & 0x7f; |
@@ -1072,7 +1072,7 @@ void kvm_ttag(struct kvm_vcpu *vcpu, INST64 inst) | |||
1072 | vcpu_set_gr(vcpu, inst.M46.r1, tag, 0); | 1072 | vcpu_set_gr(vcpu, inst.M46.r1, tag, 0); |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, u64 *padr) | 1075 | int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, unsigned long *padr) |
1076 | { | 1076 | { |
1077 | struct thash_data *data; | 1077 | struct thash_data *data; |
1078 | union ia64_isr visr, pt_isr; | 1078 | union ia64_isr visr, pt_isr; |
diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h index 042af92ced83..360724d3ae69 100644 --- a/arch/ia64/kvm/vcpu.h +++ b/arch/ia64/kvm/vcpu.h | |||
@@ -686,14 +686,15 @@ static inline int highest_inservice_irq(struct kvm_vcpu *vcpu) | |||
686 | return highest_bits((int *)&(VMX(vcpu, insvc[0]))); | 686 | return highest_bits((int *)&(VMX(vcpu, insvc[0]))); |
687 | } | 687 | } |
688 | 688 | ||
689 | extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, u64 reg, | 689 | extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, unsigned long reg, |
690 | struct ia64_fpreg *val); | 690 | struct ia64_fpreg *val); |
691 | extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, u64 reg, | 691 | extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, unsigned long reg, |
692 | struct ia64_fpreg *val); | 692 | struct ia64_fpreg *val); |
693 | extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, u64 reg); | 693 | extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg); |
694 | extern void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 val, int nat); | 694 | extern void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg, |
695 | extern u64 vcpu_get_psr(struct kvm_vcpu *vcpu); | 695 | u64 val, int nat); |
696 | extern void vcpu_set_psr(struct kvm_vcpu *vcpu, u64 val); | 696 | extern unsigned long vcpu_get_psr(struct kvm_vcpu *vcpu); |
697 | extern void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val); | ||
697 | extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr); | 698 | extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr); |
698 | extern void vcpu_bsw0(struct kvm_vcpu *vcpu); | 699 | extern void vcpu_bsw0(struct kvm_vcpu *vcpu); |
699 | extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte, | 700 | extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte, |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index dfdf13c9fefd..fddc3ed715fa 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -34,7 +34,7 @@ | |||
34 | #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 | 34 | #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 |
35 | 35 | ||
36 | /* We don't currently support large pages. */ | 36 | /* We don't currently support large pages. */ |
37 | #define KVM_PAGES_PER_HPAGE (1<<31) | 37 | #define KVM_PAGES_PER_HPAGE (1UL << 31) |
38 | 38 | ||
39 | struct kvm; | 39 | struct kvm; |
40 | struct kvm_run; | 40 | struct kvm_run; |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index f04f5301b1b4..4d613415c435 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -386,7 +386,7 @@ no_timer: | |||
386 | } | 386 | } |
387 | __unset_cpu_idle(vcpu); | 387 | __unset_cpu_idle(vcpu); |
388 | __set_current_state(TASK_RUNNING); | 388 | __set_current_state(TASK_RUNNING); |
389 | remove_wait_queue(&vcpu->wq, &wait); | 389 | remove_wait_queue(&vcpu->arch.local_int.wq, &wait); |
390 | spin_unlock_bh(&vcpu->arch.local_int.lock); | 390 | spin_unlock_bh(&vcpu->arch.local_int.lock); |
391 | spin_unlock(&vcpu->arch.local_int.float_int->lock); | 391 | spin_unlock(&vcpu->arch.local_int.float_int->lock); |
392 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); | 392 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); |
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 4d6f0d293ee2..21f68e00524f 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -104,6 +104,9 @@ static s64 __kpit_elapsed(struct kvm *kvm) | |||
104 | ktime_t remaining; | 104 | ktime_t remaining; |
105 | struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; | 105 | struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; |
106 | 106 | ||
107 | if (!ps->pit_timer.period) | ||
108 | return 0; | ||
109 | |||
107 | /* | 110 | /* |
108 | * The Counter does not stop when it reaches zero. In | 111 | * The Counter does not stop when it reaches zero. In |
109 | * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to | 112 | * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 7030b5f911bf..0ef5bb2b4043 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -489,16 +489,20 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int lpage) | |||
489 | * | 489 | * |
490 | * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc | 490 | * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc |
491 | * containing more mappings. | 491 | * containing more mappings. |
492 | * | ||
493 | * Returns the number of rmap entries before the spte was added or zero if | ||
494 | * the spte was not added. | ||
495 | * | ||
492 | */ | 496 | */ |
493 | static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage) | 497 | static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage) |
494 | { | 498 | { |
495 | struct kvm_mmu_page *sp; | 499 | struct kvm_mmu_page *sp; |
496 | struct kvm_rmap_desc *desc; | 500 | struct kvm_rmap_desc *desc; |
497 | unsigned long *rmapp; | 501 | unsigned long *rmapp; |
498 | int i; | 502 | int i, count = 0; |
499 | 503 | ||
500 | if (!is_rmap_pte(*spte)) | 504 | if (!is_rmap_pte(*spte)) |
501 | return; | 505 | return count; |
502 | gfn = unalias_gfn(vcpu->kvm, gfn); | 506 | gfn = unalias_gfn(vcpu->kvm, gfn); |
503 | sp = page_header(__pa(spte)); | 507 | sp = page_header(__pa(spte)); |
504 | sp->gfns[spte - sp->spt] = gfn; | 508 | sp->gfns[spte - sp->spt] = gfn; |
@@ -515,8 +519,10 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage) | |||
515 | } else { | 519 | } else { |
516 | rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte); | 520 | rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte); |
517 | desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul); | 521 | desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul); |
518 | while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) | 522 | while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) { |
519 | desc = desc->more; | 523 | desc = desc->more; |
524 | count += RMAP_EXT; | ||
525 | } | ||
520 | if (desc->shadow_ptes[RMAP_EXT-1]) { | 526 | if (desc->shadow_ptes[RMAP_EXT-1]) { |
521 | desc->more = mmu_alloc_rmap_desc(vcpu); | 527 | desc->more = mmu_alloc_rmap_desc(vcpu); |
522 | desc = desc->more; | 528 | desc = desc->more; |
@@ -525,6 +531,7 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage) | |||
525 | ; | 531 | ; |
526 | desc->shadow_ptes[i] = spte; | 532 | desc->shadow_ptes[i] = spte; |
527 | } | 533 | } |
534 | return count; | ||
528 | } | 535 | } |
529 | 536 | ||
530 | static void rmap_desc_remove_entry(unsigned long *rmapp, | 537 | static void rmap_desc_remove_entry(unsigned long *rmapp, |
@@ -754,6 +761,19 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp) | |||
754 | return young; | 761 | return young; |
755 | } | 762 | } |
756 | 763 | ||
764 | #define RMAP_RECYCLE_THRESHOLD 1000 | ||
765 | |||
766 | static void rmap_recycle(struct kvm_vcpu *vcpu, gfn_t gfn, int lpage) | ||
767 | { | ||
768 | unsigned long *rmapp; | ||
769 | |||
770 | gfn = unalias_gfn(vcpu->kvm, gfn); | ||
771 | rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage); | ||
772 | |||
773 | kvm_unmap_rmapp(vcpu->kvm, rmapp); | ||
774 | kvm_flush_remote_tlbs(vcpu->kvm); | ||
775 | } | ||
776 | |||
757 | int kvm_age_hva(struct kvm *kvm, unsigned long hva) | 777 | int kvm_age_hva(struct kvm *kvm, unsigned long hva) |
758 | { | 778 | { |
759 | return kvm_handle_hva(kvm, hva, kvm_age_rmapp); | 779 | return kvm_handle_hva(kvm, hva, kvm_age_rmapp); |
@@ -1407,24 +1427,25 @@ static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp) | |||
1407 | */ | 1427 | */ |
1408 | void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages) | 1428 | void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages) |
1409 | { | 1429 | { |
1430 | int used_pages; | ||
1431 | |||
1432 | used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages; | ||
1433 | used_pages = max(0, used_pages); | ||
1434 | |||
1410 | /* | 1435 | /* |
1411 | * If we set the number of mmu pages to be smaller be than the | 1436 | * If we set the number of mmu pages to be smaller be than the |
1412 | * number of actived pages , we must to free some mmu pages before we | 1437 | * number of actived pages , we must to free some mmu pages before we |
1413 | * change the value | 1438 | * change the value |
1414 | */ | 1439 | */ |
1415 | 1440 | ||
1416 | if ((kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages) > | 1441 | if (used_pages > kvm_nr_mmu_pages) { |
1417 | kvm_nr_mmu_pages) { | 1442 | while (used_pages > kvm_nr_mmu_pages) { |
1418 | int n_used_mmu_pages = kvm->arch.n_alloc_mmu_pages | ||
1419 | - kvm->arch.n_free_mmu_pages; | ||
1420 | |||
1421 | while (n_used_mmu_pages > kvm_nr_mmu_pages) { | ||
1422 | struct kvm_mmu_page *page; | 1443 | struct kvm_mmu_page *page; |
1423 | 1444 | ||
1424 | page = container_of(kvm->arch.active_mmu_pages.prev, | 1445 | page = container_of(kvm->arch.active_mmu_pages.prev, |
1425 | struct kvm_mmu_page, link); | 1446 | struct kvm_mmu_page, link); |
1426 | kvm_mmu_zap_page(kvm, page); | 1447 | kvm_mmu_zap_page(kvm, page); |
1427 | n_used_mmu_pages--; | 1448 | used_pages--; |
1428 | } | 1449 | } |
1429 | kvm->arch.n_free_mmu_pages = 0; | 1450 | kvm->arch.n_free_mmu_pages = 0; |
1430 | } | 1451 | } |
@@ -1740,6 +1761,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
1740 | { | 1761 | { |
1741 | int was_rmapped = 0; | 1762 | int was_rmapped = 0; |
1742 | int was_writeble = is_writeble_pte(*shadow_pte); | 1763 | int was_writeble = is_writeble_pte(*shadow_pte); |
1764 | int rmap_count; | ||
1743 | 1765 | ||
1744 | pgprintk("%s: spte %llx access %x write_fault %d" | 1766 | pgprintk("%s: spte %llx access %x write_fault %d" |
1745 | " user_fault %d gfn %lx\n", | 1767 | " user_fault %d gfn %lx\n", |
@@ -1781,9 +1803,11 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
1781 | 1803 | ||
1782 | page_header_update_slot(vcpu->kvm, shadow_pte, gfn); | 1804 | page_header_update_slot(vcpu->kvm, shadow_pte, gfn); |
1783 | if (!was_rmapped) { | 1805 | if (!was_rmapped) { |
1784 | rmap_add(vcpu, shadow_pte, gfn, largepage); | 1806 | rmap_count = rmap_add(vcpu, shadow_pte, gfn, largepage); |
1785 | if (!is_rmap_pte(*shadow_pte)) | 1807 | if (!is_rmap_pte(*shadow_pte)) |
1786 | kvm_release_pfn_clean(pfn); | 1808 | kvm_release_pfn_clean(pfn); |
1809 | if (rmap_count > RMAP_RECYCLE_THRESHOLD) | ||
1810 | rmap_recycle(vcpu, gfn, largepage); | ||
1787 | } else { | 1811 | } else { |
1788 | if (was_writeble) | 1812 | if (was_writeble) |
1789 | kvm_release_pfn_dirty(pfn); | 1813 | kvm_release_pfn_dirty(pfn); |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 71510e07e69e..b1f658ad2f06 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -711,6 +711,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
711 | svm->vmcb->control.tsc_offset += delta; | 711 | svm->vmcb->control.tsc_offset += delta; |
712 | vcpu->cpu = cpu; | 712 | vcpu->cpu = cpu; |
713 | kvm_migrate_timers(vcpu); | 713 | kvm_migrate_timers(vcpu); |
714 | svm->asid_generation = 0; | ||
714 | } | 715 | } |
715 | 716 | ||
716 | for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++) | 717 | for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++) |
@@ -1031,7 +1032,6 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data) | |||
1031 | svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID; | 1032 | svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID; |
1032 | } | 1033 | } |
1033 | 1034 | ||
1034 | svm->vcpu.cpu = svm_data->cpu; | ||
1035 | svm->asid_generation = svm_data->asid_generation; | 1035 | svm->asid_generation = svm_data->asid_generation; |
1036 | svm->vmcb->control.asid = svm_data->next_asid++; | 1036 | svm->vmcb->control.asid = svm_data->next_asid++; |
1037 | } | 1037 | } |
@@ -2300,8 +2300,8 @@ static void pre_svm_run(struct vcpu_svm *svm) | |||
2300 | struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); | 2300 | struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); |
2301 | 2301 | ||
2302 | svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING; | 2302 | svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING; |
2303 | if (svm->vcpu.cpu != cpu || | 2303 | /* FIXME: handle wraparound of asid_generation */ |
2304 | svm->asid_generation != svm_data->asid_generation) | 2304 | if (svm->asid_generation != svm_data->asid_generation) |
2305 | new_asid(svm, svm_data); | 2305 | new_asid(svm, svm_data); |
2306 | } | 2306 | } |
2307 | 2307 | ||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 356a0ce85c68..29f912927a58 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3157,8 +3157,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, | |||
3157 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 3157 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
3158 | enum emulation_result err = EMULATE_DONE; | 3158 | enum emulation_result err = EMULATE_DONE; |
3159 | 3159 | ||
3160 | preempt_enable(); | ||
3161 | local_irq_enable(); | 3160 | local_irq_enable(); |
3161 | preempt_enable(); | ||
3162 | 3162 | ||
3163 | while (!guest_state_valid(vcpu)) { | 3163 | while (!guest_state_valid(vcpu)) { |
3164 | err = emulate_instruction(vcpu, kvm_run, 0, 0, 0); | 3164 | err = emulate_instruction(vcpu, kvm_run, 0, 0, 0); |
@@ -3168,7 +3168,7 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, | |||
3168 | 3168 | ||
3169 | if (err != EMULATE_DONE) { | 3169 | if (err != EMULATE_DONE) { |
3170 | kvm_report_emulation_failure(vcpu, "emulation failure"); | 3170 | kvm_report_emulation_failure(vcpu, "emulation failure"); |
3171 | return; | 3171 | break; |
3172 | } | 3172 | } |
3173 | 3173 | ||
3174 | if (signal_pending(current)) | 3174 | if (signal_pending(current)) |
@@ -3177,8 +3177,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, | |||
3177 | schedule(); | 3177 | schedule(); |
3178 | } | 3178 | } |
3179 | 3179 | ||
3180 | local_irq_disable(); | ||
3181 | preempt_disable(); | 3180 | preempt_disable(); |
3181 | local_irq_disable(); | ||
3182 | 3182 | ||
3183 | vmx->invalid_state_emulation_result = err; | 3183 | vmx->invalid_state_emulation_result = err; |
3184 | } | 3184 | } |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fe5474aec41a..3d4529011828 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -704,11 +704,48 @@ static bool msr_mtrr_valid(unsigned msr) | |||
704 | return false; | 704 | return false; |
705 | } | 705 | } |
706 | 706 | ||
707 | static bool valid_pat_type(unsigned t) | ||
708 | { | ||
709 | return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */ | ||
710 | } | ||
711 | |||
712 | static bool valid_mtrr_type(unsigned t) | ||
713 | { | ||
714 | return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */ | ||
715 | } | ||
716 | |||
717 | static bool mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) | ||
718 | { | ||
719 | int i; | ||
720 | |||
721 | if (!msr_mtrr_valid(msr)) | ||
722 | return false; | ||
723 | |||
724 | if (msr == MSR_IA32_CR_PAT) { | ||
725 | for (i = 0; i < 8; i++) | ||
726 | if (!valid_pat_type((data >> (i * 8)) & 0xff)) | ||
727 | return false; | ||
728 | return true; | ||
729 | } else if (msr == MSR_MTRRdefType) { | ||
730 | if (data & ~0xcff) | ||
731 | return false; | ||
732 | return valid_mtrr_type(data & 0xff); | ||
733 | } else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) { | ||
734 | for (i = 0; i < 8 ; i++) | ||
735 | if (!valid_mtrr_type((data >> (i * 8)) & 0xff)) | ||
736 | return false; | ||
737 | return true; | ||
738 | } | ||
739 | |||
740 | /* variable MTRRs */ | ||
741 | return valid_mtrr_type(data & 0xff); | ||
742 | } | ||
743 | |||
707 | static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data) | 744 | static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data) |
708 | { | 745 | { |
709 | u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges; | 746 | u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges; |
710 | 747 | ||
711 | if (!msr_mtrr_valid(msr)) | 748 | if (!mtrr_valid(vcpu, msr, data)) |
712 | return 1; | 749 | return 1; |
713 | 750 | ||
714 | if (msr == MSR_MTRRdefType) { | 751 | if (msr == MSR_MTRRdefType) { |
@@ -1079,14 +1116,13 @@ long kvm_arch_dev_ioctl(struct file *filp, | |||
1079 | if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) | 1116 | if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) |
1080 | goto out; | 1117 | goto out; |
1081 | r = -E2BIG; | 1118 | r = -E2BIG; |
1082 | if (n < num_msrs_to_save) | 1119 | if (n < msr_list.nmsrs) |
1083 | goto out; | 1120 | goto out; |
1084 | r = -EFAULT; | 1121 | r = -EFAULT; |
1085 | if (copy_to_user(user_msr_list->indices, &msrs_to_save, | 1122 | if (copy_to_user(user_msr_list->indices, &msrs_to_save, |
1086 | num_msrs_to_save * sizeof(u32))) | 1123 | num_msrs_to_save * sizeof(u32))) |
1087 | goto out; | 1124 | goto out; |
1088 | if (copy_to_user(user_msr_list->indices | 1125 | if (copy_to_user(user_msr_list->indices + num_msrs_to_save, |
1089 | + num_msrs_to_save * sizeof(u32), | ||
1090 | &emulated_msrs, | 1126 | &emulated_msrs, |
1091 | ARRAY_SIZE(emulated_msrs) * sizeof(u32))) | 1127 | ARRAY_SIZE(emulated_msrs) * sizeof(u32))) |
1092 | goto out; | 1128 | goto out; |