diff options
Diffstat (limited to 'arch/ia64/kvm/kvm-ia64.c')
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 263 |
1 files changed, 170 insertions, 93 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index d20a5db4c4dd..80c57b0a21c4 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -41,6 +41,9 @@ | |||
41 | #include <asm/div64.h> | 41 | #include <asm/div64.h> |
42 | #include <asm/tlb.h> | 42 | #include <asm/tlb.h> |
43 | #include <asm/elf.h> | 43 | #include <asm/elf.h> |
44 | #include <asm/sn/addrs.h> | ||
45 | #include <asm/sn/clksupport.h> | ||
46 | #include <asm/sn/shub_mmr.h> | ||
44 | 47 | ||
45 | #include "misc.h" | 48 | #include "misc.h" |
46 | #include "vti.h" | 49 | #include "vti.h" |
@@ -65,6 +68,16 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
65 | { NULL } | 68 | { NULL } |
66 | }; | 69 | }; |
67 | 70 | ||
71 | static unsigned long kvm_get_itc(struct kvm_vcpu *vcpu) | ||
72 | { | ||
73 | #if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC) | ||
74 | if (vcpu->kvm->arch.is_sn2) | ||
75 | return rtc_time(); | ||
76 | else | ||
77 | #endif | ||
78 | return ia64_getreg(_IA64_REG_AR_ITC); | ||
79 | } | ||
80 | |||
68 | static void kvm_flush_icache(unsigned long start, unsigned long len) | 81 | static void kvm_flush_icache(unsigned long start, unsigned long len) |
69 | { | 82 | { |
70 | int l; | 83 | int l; |
@@ -119,8 +132,7 @@ void kvm_arch_hardware_enable(void *garbage) | |||
119 | unsigned long saved_psr; | 132 | unsigned long saved_psr; |
120 | int slot; | 133 | int slot; |
121 | 134 | ||
122 | pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base), | 135 | pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base), PAGE_KERNEL)); |
123 | PAGE_KERNEL)); | ||
124 | local_irq_save(saved_psr); | 136 | local_irq_save(saved_psr); |
125 | slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT); | 137 | slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT); |
126 | local_irq_restore(saved_psr); | 138 | local_irq_restore(saved_psr); |
@@ -283,6 +295,18 @@ static int handle_sal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
283 | 295 | ||
284 | } | 296 | } |
285 | 297 | ||
298 | static int __apic_accept_irq(struct kvm_vcpu *vcpu, uint64_t vector) | ||
299 | { | ||
300 | struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); | ||
301 | |||
302 | if (!test_and_set_bit(vector, &vpd->irr[0])) { | ||
303 | vcpu->arch.irq_new_pending = 1; | ||
304 | kvm_vcpu_kick(vcpu); | ||
305 | return 1; | ||
306 | } | ||
307 | return 0; | ||
308 | } | ||
309 | |||
286 | /* | 310 | /* |
287 | * offset: address offset to IPI space. | 311 | * offset: address offset to IPI space. |
288 | * value: deliver value. | 312 | * value: deliver value. |
@@ -292,20 +316,20 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm, | |||
292 | { | 316 | { |
293 | switch (dm) { | 317 | switch (dm) { |
294 | case SAPIC_FIXED: | 318 | case SAPIC_FIXED: |
295 | kvm_apic_set_irq(vcpu, vector, 0); | ||
296 | break; | 319 | break; |
297 | case SAPIC_NMI: | 320 | case SAPIC_NMI: |
298 | kvm_apic_set_irq(vcpu, 2, 0); | 321 | vector = 2; |
299 | break; | 322 | break; |
300 | case SAPIC_EXTINT: | 323 | case SAPIC_EXTINT: |
301 | kvm_apic_set_irq(vcpu, 0, 0); | 324 | vector = 0; |
302 | break; | 325 | break; |
303 | case SAPIC_INIT: | 326 | case SAPIC_INIT: |
304 | case SAPIC_PMI: | 327 | case SAPIC_PMI: |
305 | default: | 328 | default: |
306 | printk(KERN_ERR"kvm: Unimplemented Deliver reserved IPI!\n"); | 329 | printk(KERN_ERR"kvm: Unimplemented Deliver reserved IPI!\n"); |
307 | break; | 330 | return; |
308 | } | 331 | } |
332 | __apic_accept_irq(vcpu, vector); | ||
309 | } | 333 | } |
310 | 334 | ||
311 | static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id, | 335 | static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id, |
@@ -413,6 +437,23 @@ static int handle_switch_rr6(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
413 | return 1; | 437 | return 1; |
414 | } | 438 | } |
415 | 439 | ||
440 | static int kvm_sn2_setup_mappings(struct kvm_vcpu *vcpu) | ||
441 | { | ||
442 | unsigned long pte, rtc_phys_addr, map_addr; | ||
443 | int slot; | ||
444 | |||
445 | map_addr = KVM_VMM_BASE + (1UL << KVM_VMM_SHIFT); | ||
446 | rtc_phys_addr = LOCAL_MMR_OFFSET | SH_RTC; | ||
447 | pte = pte_val(mk_pte_phys(rtc_phys_addr, PAGE_KERNEL_UC)); | ||
448 | slot = ia64_itr_entry(0x3, map_addr, pte, PAGE_SHIFT); | ||
449 | vcpu->arch.sn_rtc_tr_slot = slot; | ||
450 | if (slot < 0) { | ||
451 | printk(KERN_ERR "Mayday mayday! RTC mapping failed!\n"); | ||
452 | slot = 0; | ||
453 | } | ||
454 | return slot; | ||
455 | } | ||
456 | |||
416 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) | 457 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) |
417 | { | 458 | { |
418 | 459 | ||
@@ -426,7 +467,7 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu) | |||
426 | 467 | ||
427 | if (irqchip_in_kernel(vcpu->kvm)) { | 468 | if (irqchip_in_kernel(vcpu->kvm)) { |
428 | 469 | ||
429 | vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset; | 470 | vcpu_now_itc = kvm_get_itc(vcpu) + vcpu->arch.itc_offset; |
430 | 471 | ||
431 | if (time_after(vcpu_now_itc, vpd->itm)) { | 472 | if (time_after(vcpu_now_itc, vpd->itm)) { |
432 | vcpu->arch.timer_check = 1; | 473 | vcpu->arch.timer_check = 1; |
@@ -447,10 +488,10 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu) | |||
447 | hrtimer_cancel(p_ht); | 488 | hrtimer_cancel(p_ht); |
448 | vcpu->arch.ht_active = 0; | 489 | vcpu->arch.ht_active = 0; |
449 | 490 | ||
450 | if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests)) | 491 | if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests) || |
492 | kvm_cpu_has_pending_timer(vcpu)) | ||
451 | if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) | 493 | if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) |
452 | vcpu->arch.mp_state = | 494 | vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; |
453 | KVM_MP_STATE_RUNNABLE; | ||
454 | 495 | ||
455 | if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE) | 496 | if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE) |
456 | return -EINTR; | 497 | return -EINTR; |
@@ -551,22 +592,35 @@ static int kvm_insert_vmm_mapping(struct kvm_vcpu *vcpu) | |||
551 | if (r < 0) | 592 | if (r < 0) |
552 | goto out; | 593 | goto out; |
553 | vcpu->arch.vm_tr_slot = r; | 594 | vcpu->arch.vm_tr_slot = r; |
595 | |||
596 | #if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC) | ||
597 | if (kvm->arch.is_sn2) { | ||
598 | r = kvm_sn2_setup_mappings(vcpu); | ||
599 | if (r < 0) | ||
600 | goto out; | ||
601 | } | ||
602 | #endif | ||
603 | |||
554 | r = 0; | 604 | r = 0; |
555 | out: | 605 | out: |
556 | return r; | 606 | return r; |
557 | |||
558 | } | 607 | } |
559 | 608 | ||
560 | static void kvm_purge_vmm_mapping(struct kvm_vcpu *vcpu) | 609 | static void kvm_purge_vmm_mapping(struct kvm_vcpu *vcpu) |
561 | { | 610 | { |
562 | 611 | struct kvm *kvm = vcpu->kvm; | |
563 | ia64_ptr_entry(0x3, vcpu->arch.vmm_tr_slot); | 612 | ia64_ptr_entry(0x3, vcpu->arch.vmm_tr_slot); |
564 | ia64_ptr_entry(0x3, vcpu->arch.vm_tr_slot); | 613 | ia64_ptr_entry(0x3, vcpu->arch.vm_tr_slot); |
565 | 614 | #if defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC) | |
615 | if (kvm->arch.is_sn2) | ||
616 | ia64_ptr_entry(0x3, vcpu->arch.sn_rtc_tr_slot); | ||
617 | #endif | ||
566 | } | 618 | } |
567 | 619 | ||
568 | static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu) | 620 | static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu) |
569 | { | 621 | { |
622 | unsigned long psr; | ||
623 | int r; | ||
570 | int cpu = smp_processor_id(); | 624 | int cpu = smp_processor_id(); |
571 | 625 | ||
572 | if (vcpu->arch.last_run_cpu != cpu || | 626 | if (vcpu->arch.last_run_cpu != cpu || |
@@ -578,36 +632,27 @@ static int kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu) | |||
578 | 632 | ||
579 | vcpu->arch.host_rr6 = ia64_get_rr(RR6); | 633 | vcpu->arch.host_rr6 = ia64_get_rr(RR6); |
580 | vti_set_rr6(vcpu->arch.vmm_rr); | 634 | vti_set_rr6(vcpu->arch.vmm_rr); |
581 | return kvm_insert_vmm_mapping(vcpu); | 635 | local_irq_save(psr); |
636 | r = kvm_insert_vmm_mapping(vcpu); | ||
637 | local_irq_restore(psr); | ||
638 | return r; | ||
582 | } | 639 | } |
640 | |||
583 | static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu) | 641 | static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu) |
584 | { | 642 | { |
585 | kvm_purge_vmm_mapping(vcpu); | 643 | kvm_purge_vmm_mapping(vcpu); |
586 | vti_set_rr6(vcpu->arch.host_rr6); | 644 | vti_set_rr6(vcpu->arch.host_rr6); |
587 | } | 645 | } |
588 | 646 | ||
589 | static int vti_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 647 | static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
590 | { | 648 | { |
591 | union context *host_ctx, *guest_ctx; | 649 | union context *host_ctx, *guest_ctx; |
592 | int r; | 650 | int r; |
593 | 651 | ||
594 | /*Get host and guest context with guest address space.*/ | 652 | /* |
595 | host_ctx = kvm_get_host_context(vcpu); | 653 | * down_read() may sleep and return with interrupts enabled |
596 | guest_ctx = kvm_get_guest_context(vcpu); | 654 | */ |
597 | 655 | down_read(&vcpu->kvm->slots_lock); | |
598 | r = kvm_vcpu_pre_transition(vcpu); | ||
599 | if (r < 0) | ||
600 | goto out; | ||
601 | kvm_vmm_info->tramp_entry(host_ctx, guest_ctx); | ||
602 | kvm_vcpu_post_transition(vcpu); | ||
603 | r = 0; | ||
604 | out: | ||
605 | return r; | ||
606 | } | ||
607 | |||
608 | static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
609 | { | ||
610 | int r; | ||
611 | 656 | ||
612 | again: | 657 | again: |
613 | if (signal_pending(current)) { | 658 | if (signal_pending(current)) { |
@@ -616,26 +661,31 @@ again: | |||
616 | goto out; | 661 | goto out; |
617 | } | 662 | } |
618 | 663 | ||
619 | /* | ||
620 | * down_read() may sleep and return with interrupts enabled | ||
621 | */ | ||
622 | down_read(&vcpu->kvm->slots_lock); | ||
623 | |||
624 | preempt_disable(); | 664 | preempt_disable(); |
625 | local_irq_disable(); | 665 | local_irq_disable(); |
626 | 666 | ||
627 | vcpu->guest_mode = 1; | 667 | /*Get host and guest context with guest address space.*/ |
668 | host_ctx = kvm_get_host_context(vcpu); | ||
669 | guest_ctx = kvm_get_guest_context(vcpu); | ||
670 | |||
671 | clear_bit(KVM_REQ_KICK, &vcpu->requests); | ||
672 | |||
673 | r = kvm_vcpu_pre_transition(vcpu); | ||
674 | if (r < 0) | ||
675 | goto vcpu_run_fail; | ||
676 | |||
677 | up_read(&vcpu->kvm->slots_lock); | ||
628 | kvm_guest_enter(); | 678 | kvm_guest_enter(); |
629 | r = vti_vcpu_run(vcpu, kvm_run); | 679 | |
630 | if (r < 0) { | 680 | /* |
631 | local_irq_enable(); | 681 | * Transition to the guest |
632 | preempt_enable(); | 682 | */ |
633 | kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY; | 683 | kvm_vmm_info->tramp_entry(host_ctx, guest_ctx); |
634 | goto out; | 684 | |
635 | } | 685 | kvm_vcpu_post_transition(vcpu); |
636 | 686 | ||
637 | vcpu->arch.launched = 1; | 687 | vcpu->arch.launched = 1; |
638 | vcpu->guest_mode = 0; | 688 | set_bit(KVM_REQ_KICK, &vcpu->requests); |
639 | local_irq_enable(); | 689 | local_irq_enable(); |
640 | 690 | ||
641 | /* | 691 | /* |
@@ -646,9 +696,10 @@ again: | |||
646 | */ | 696 | */ |
647 | barrier(); | 697 | barrier(); |
648 | kvm_guest_exit(); | 698 | kvm_guest_exit(); |
649 | up_read(&vcpu->kvm->slots_lock); | ||
650 | preempt_enable(); | 699 | preempt_enable(); |
651 | 700 | ||
701 | down_read(&vcpu->kvm->slots_lock); | ||
702 | |||
652 | r = kvm_handle_exit(kvm_run, vcpu); | 703 | r = kvm_handle_exit(kvm_run, vcpu); |
653 | 704 | ||
654 | if (r > 0) { | 705 | if (r > 0) { |
@@ -657,12 +708,20 @@ again: | |||
657 | } | 708 | } |
658 | 709 | ||
659 | out: | 710 | out: |
711 | up_read(&vcpu->kvm->slots_lock); | ||
660 | if (r > 0) { | 712 | if (r > 0) { |
661 | kvm_resched(vcpu); | 713 | kvm_resched(vcpu); |
714 | down_read(&vcpu->kvm->slots_lock); | ||
662 | goto again; | 715 | goto again; |
663 | } | 716 | } |
664 | 717 | ||
665 | return r; | 718 | return r; |
719 | |||
720 | vcpu_run_fail: | ||
721 | local_irq_enable(); | ||
722 | preempt_enable(); | ||
723 | kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY; | ||
724 | goto out; | ||
666 | } | 725 | } |
667 | 726 | ||
668 | static void kvm_set_mmio_data(struct kvm_vcpu *vcpu) | 727 | static void kvm_set_mmio_data(struct kvm_vcpu *vcpu) |
@@ -788,6 +847,9 @@ struct kvm *kvm_arch_create_vm(void) | |||
788 | 847 | ||
789 | if (IS_ERR(kvm)) | 848 | if (IS_ERR(kvm)) |
790 | return ERR_PTR(-ENOMEM); | 849 | return ERR_PTR(-ENOMEM); |
850 | |||
851 | kvm->arch.is_sn2 = ia64_platform_is("sn2"); | ||
852 | |||
791 | kvm_init_vm(kvm); | 853 | kvm_init_vm(kvm); |
792 | 854 | ||
793 | kvm->arch.online_vcpus = 0; | 855 | kvm->arch.online_vcpus = 0; |
@@ -884,7 +946,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
884 | RESTORE_REGS(saved_gp); | 946 | RESTORE_REGS(saved_gp); |
885 | 947 | ||
886 | vcpu->arch.irq_new_pending = 1; | 948 | vcpu->arch.irq_new_pending = 1; |
887 | vcpu->arch.itc_offset = regs->saved_itc - ia64_getreg(_IA64_REG_AR_ITC); | 949 | vcpu->arch.itc_offset = regs->saved_itc - kvm_get_itc(vcpu); |
888 | set_bit(KVM_REQ_RESUME, &vcpu->requests); | 950 | set_bit(KVM_REQ_RESUME, &vcpu->requests); |
889 | 951 | ||
890 | vcpu_put(vcpu); | 952 | vcpu_put(vcpu); |
@@ -1043,10 +1105,6 @@ static void kvm_free_vmm_area(void) | |||
1043 | } | 1105 | } |
1044 | } | 1106 | } |
1045 | 1107 | ||
1046 | static void vti_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | ||
1047 | { | ||
1048 | } | ||
1049 | |||
1050 | static int vti_init_vpd(struct kvm_vcpu *vcpu) | 1108 | static int vti_init_vpd(struct kvm_vcpu *vcpu) |
1051 | { | 1109 | { |
1052 | int i; | 1110 | int i; |
@@ -1165,7 +1223,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | |||
1165 | regs->cr_iip = PALE_RESET_ENTRY; | 1223 | regs->cr_iip = PALE_RESET_ENTRY; |
1166 | 1224 | ||
1167 | /*Initialize itc offset for vcpus*/ | 1225 | /*Initialize itc offset for vcpus*/ |
1168 | itc_offset = 0UL - ia64_getreg(_IA64_REG_AR_ITC); | 1226 | itc_offset = 0UL - kvm_get_itc(vcpu); |
1169 | for (i = 0; i < kvm->arch.online_vcpus; i++) { | 1227 | for (i = 0; i < kvm->arch.online_vcpus; i++) { |
1170 | v = (struct kvm_vcpu *)((char *)vcpu + | 1228 | v = (struct kvm_vcpu *)((char *)vcpu + |
1171 | sizeof(struct kvm_vcpu_data) * i); | 1229 | sizeof(struct kvm_vcpu_data) * i); |
@@ -1237,6 +1295,7 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id) | |||
1237 | 1295 | ||
1238 | local_irq_save(psr); | 1296 | local_irq_save(psr); |
1239 | r = kvm_insert_vmm_mapping(vcpu); | 1297 | r = kvm_insert_vmm_mapping(vcpu); |
1298 | local_irq_restore(psr); | ||
1240 | if (r) | 1299 | if (r) |
1241 | goto fail; | 1300 | goto fail; |
1242 | r = kvm_vcpu_init(vcpu, vcpu->kvm, id); | 1301 | r = kvm_vcpu_init(vcpu, vcpu->kvm, id); |
@@ -1254,13 +1313,11 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id) | |||
1254 | goto uninit; | 1313 | goto uninit; |
1255 | 1314 | ||
1256 | kvm_purge_vmm_mapping(vcpu); | 1315 | kvm_purge_vmm_mapping(vcpu); |
1257 | local_irq_restore(psr); | ||
1258 | 1316 | ||
1259 | return 0; | 1317 | return 0; |
1260 | uninit: | 1318 | uninit: |
1261 | kvm_vcpu_uninit(vcpu); | 1319 | kvm_vcpu_uninit(vcpu); |
1262 | fail: | 1320 | fail: |
1263 | local_irq_restore(psr); | ||
1264 | return r; | 1321 | return r; |
1265 | } | 1322 | } |
1266 | 1323 | ||
@@ -1291,7 +1348,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | |||
1291 | vcpu->kvm = kvm; | 1348 | vcpu->kvm = kvm; |
1292 | 1349 | ||
1293 | cpu = get_cpu(); | 1350 | cpu = get_cpu(); |
1294 | vti_vcpu_load(vcpu, cpu); | ||
1295 | r = vti_vcpu_setup(vcpu, id); | 1351 | r = vti_vcpu_setup(vcpu, id); |
1296 | put_cpu(); | 1352 | put_cpu(); |
1297 | 1353 | ||
@@ -1427,7 +1483,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
1427 | } | 1483 | } |
1428 | for (i = 0; i < 4; i++) | 1484 | for (i = 0; i < 4; i++) |
1429 | regs->insvc[i] = vcpu->arch.insvc[i]; | 1485 | regs->insvc[i] = vcpu->arch.insvc[i]; |
1430 | regs->saved_itc = vcpu->arch.itc_offset + ia64_getreg(_IA64_REG_AR_ITC); | 1486 | regs->saved_itc = vcpu->arch.itc_offset + kvm_get_itc(vcpu); |
1431 | SAVE_REGS(xtp); | 1487 | SAVE_REGS(xtp); |
1432 | SAVE_REGS(metaphysical_rr0); | 1488 | SAVE_REGS(metaphysical_rr0); |
1433 | SAVE_REGS(metaphysical_rr4); | 1489 | SAVE_REGS(metaphysical_rr4); |
@@ -1574,6 +1630,7 @@ int kvm_arch_set_memory_region(struct kvm *kvm, | |||
1574 | 1630 | ||
1575 | void kvm_arch_flush_shadow(struct kvm *kvm) | 1631 | void kvm_arch_flush_shadow(struct kvm *kvm) |
1576 | { | 1632 | { |
1633 | kvm_flush_remote_tlbs(kvm); | ||
1577 | } | 1634 | } |
1578 | 1635 | ||
1579 | long kvm_arch_dev_ioctl(struct file *filp, | 1636 | long kvm_arch_dev_ioctl(struct file *filp, |
@@ -1616,8 +1673,37 @@ out: | |||
1616 | return 0; | 1673 | return 0; |
1617 | } | 1674 | } |
1618 | 1675 | ||
1676 | |||
1677 | /* | ||
1678 | * On SN2, the ITC isn't stable, so copy in fast path code to use the | ||
1679 | * SN2 RTC, replacing the ITC based default verion. | ||
1680 | */ | ||
1681 | static void kvm_patch_vmm(struct kvm_vmm_info *vmm_info, | ||
1682 | struct module *module) | ||
1683 | { | ||
1684 | unsigned long new_ar, new_ar_sn2; | ||
1685 | unsigned long module_base; | ||
1686 | |||
1687 | if (!ia64_platform_is("sn2")) | ||
1688 | return; | ||
1689 | |||
1690 | module_base = (unsigned long)module->module_core; | ||
1691 | |||
1692 | new_ar = kvm_vmm_base + vmm_info->patch_mov_ar - module_base; | ||
1693 | new_ar_sn2 = kvm_vmm_base + vmm_info->patch_mov_ar_sn2 - module_base; | ||
1694 | |||
1695 | printk(KERN_INFO "kvm: Patching ITC emulation to use SGI SN2 RTC " | ||
1696 | "as source\n"); | ||
1697 | |||
1698 | /* | ||
1699 | * Copy the SN2 version of mov_ar into place. They are both | ||
1700 | * the same size, so 6 bundles is sufficient (6 * 0x10). | ||
1701 | */ | ||
1702 | memcpy((void *)new_ar, (void *)new_ar_sn2, 0x60); | ||
1703 | } | ||
1704 | |||
1619 | static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info, | 1705 | static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info, |
1620 | struct module *module) | 1706 | struct module *module) |
1621 | { | 1707 | { |
1622 | unsigned long module_base; | 1708 | unsigned long module_base; |
1623 | unsigned long vmm_size; | 1709 | unsigned long vmm_size; |
@@ -1639,6 +1725,7 @@ static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info, | |||
1639 | return -EFAULT; | 1725 | return -EFAULT; |
1640 | 1726 | ||
1641 | memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size); | 1727 | memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size); |
1728 | kvm_patch_vmm(vmm_info, module); | ||
1642 | kvm_flush_icache(kvm_vmm_base, vmm_size); | 1729 | kvm_flush_icache(kvm_vmm_base, vmm_size); |
1643 | 1730 | ||
1644 | /*Recalculate kvm_vmm_info based on new VMM*/ | 1731 | /*Recalculate kvm_vmm_info based on new VMM*/ |
@@ -1792,38 +1879,24 @@ void kvm_arch_hardware_unsetup(void) | |||
1792 | { | 1879 | { |
1793 | } | 1880 | } |
1794 | 1881 | ||
1795 | static void vcpu_kick_intr(void *info) | ||
1796 | { | ||
1797 | #ifdef DEBUG | ||
1798 | struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info; | ||
1799 | printk(KERN_DEBUG"vcpu_kick_intr %p \n", vcpu); | ||
1800 | #endif | ||
1801 | } | ||
1802 | |||
1803 | void kvm_vcpu_kick(struct kvm_vcpu *vcpu) | 1882 | void kvm_vcpu_kick(struct kvm_vcpu *vcpu) |
1804 | { | 1883 | { |
1805 | int ipi_pcpu = vcpu->cpu; | 1884 | int me; |
1806 | int cpu = get_cpu(); | 1885 | int cpu = vcpu->cpu; |
1807 | 1886 | ||
1808 | if (waitqueue_active(&vcpu->wq)) | 1887 | if (waitqueue_active(&vcpu->wq)) |
1809 | wake_up_interruptible(&vcpu->wq); | 1888 | wake_up_interruptible(&vcpu->wq); |
1810 | 1889 | ||
1811 | if (vcpu->guest_mode && cpu != ipi_pcpu) | 1890 | me = get_cpu(); |
1812 | smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0); | 1891 | if (cpu != me && (unsigned) cpu < nr_cpu_ids && cpu_online(cpu)) |
1892 | if (!test_and_set_bit(KVM_REQ_KICK, &vcpu->requests)) | ||
1893 | smp_send_reschedule(cpu); | ||
1813 | put_cpu(); | 1894 | put_cpu(); |
1814 | } | 1895 | } |
1815 | 1896 | ||
1816 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) | 1897 | int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq) |
1817 | { | 1898 | { |
1818 | 1899 | return __apic_accept_irq(vcpu, irq->vector); | |
1819 | struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); | ||
1820 | |||
1821 | if (!test_and_set_bit(vec, &vpd->irr[0])) { | ||
1822 | vcpu->arch.irq_new_pending = 1; | ||
1823 | kvm_vcpu_kick(vcpu); | ||
1824 | return 1; | ||
1825 | } | ||
1826 | return 0; | ||
1827 | } | 1900 | } |
1828 | 1901 | ||
1829 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest) | 1902 | int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest) |
@@ -1836,20 +1909,18 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda) | |||
1836 | return 0; | 1909 | return 0; |
1837 | } | 1910 | } |
1838 | 1911 | ||
1839 | struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, | 1912 | int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2) |
1840 | unsigned long bitmap) | ||
1841 | { | 1913 | { |
1842 | struct kvm_vcpu *lvcpu = kvm->vcpus[0]; | 1914 | return vcpu1->arch.xtp - vcpu2->arch.xtp; |
1843 | int i; | 1915 | } |
1844 | |||
1845 | for (i = 1; i < kvm->arch.online_vcpus; i++) { | ||
1846 | if (!kvm->vcpus[i]) | ||
1847 | continue; | ||
1848 | if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp) | ||
1849 | lvcpu = kvm->vcpus[i]; | ||
1850 | } | ||
1851 | 1916 | ||
1852 | return lvcpu; | 1917 | int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, |
1918 | int short_hand, int dest, int dest_mode) | ||
1919 | { | ||
1920 | struct kvm_lapic *target = vcpu->arch.apic; | ||
1921 | return (dest_mode == 0) ? | ||
1922 | kvm_apic_match_physical_addr(target, dest) : | ||
1923 | kvm_apic_match_logical_addr(target, dest); | ||
1853 | } | 1924 | } |
1854 | 1925 | ||
1855 | static int find_highest_bits(int *dat) | 1926 | static int find_highest_bits(int *dat) |
@@ -1888,6 +1959,12 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) | |||
1888 | return 0; | 1959 | return 0; |
1889 | } | 1960 | } |
1890 | 1961 | ||
1962 | int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu) | ||
1963 | { | ||
1964 | /* do real check here */ | ||
1965 | return 1; | ||
1966 | } | ||
1967 | |||
1891 | int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) | 1968 | int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) |
1892 | { | 1969 | { |
1893 | return vcpu->arch.timer_fired; | 1970 | return vcpu->arch.timer_fired; |
@@ -1918,6 +1995,7 @@ static int vcpu_reset(struct kvm_vcpu *vcpu) | |||
1918 | long psr; | 1995 | long psr; |
1919 | local_irq_save(psr); | 1996 | local_irq_save(psr); |
1920 | r = kvm_insert_vmm_mapping(vcpu); | 1997 | r = kvm_insert_vmm_mapping(vcpu); |
1998 | local_irq_restore(psr); | ||
1921 | if (r) | 1999 | if (r) |
1922 | goto fail; | 2000 | goto fail; |
1923 | 2001 | ||
@@ -1930,7 +2008,6 @@ static int vcpu_reset(struct kvm_vcpu *vcpu) | |||
1930 | kvm_purge_vmm_mapping(vcpu); | 2008 | kvm_purge_vmm_mapping(vcpu); |
1931 | r = 0; | 2009 | r = 0; |
1932 | fail: | 2010 | fail: |
1933 | local_irq_restore(psr); | ||
1934 | return r; | 2011 | return r; |
1935 | } | 2012 | } |
1936 | 2013 | ||