diff options
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r-- | arch/powerpc/kvm/booke.c | 150 |
1 files changed, 106 insertions, 44 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index bb6c988f010a..ee9e1ee9c858 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -124,12 +124,6 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) | |||
124 | vcpu->arch.shared->msr = new_msr; | 124 | vcpu->arch.shared->msr = new_msr; |
125 | 125 | ||
126 | kvmppc_mmu_msr_notify(vcpu, old_msr); | 126 | kvmppc_mmu_msr_notify(vcpu, old_msr); |
127 | |||
128 | if (vcpu->arch.shared->msr & MSR_WE) { | ||
129 | kvm_vcpu_block(vcpu); | ||
130 | kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS); | ||
131 | }; | ||
132 | |||
133 | kvmppc_vcpu_sync_spe(vcpu); | 127 | kvmppc_vcpu_sync_spe(vcpu); |
134 | } | 128 | } |
135 | 129 | ||
@@ -258,9 +252,11 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
258 | allowed = vcpu->arch.shared->msr & MSR_ME; | 252 | allowed = vcpu->arch.shared->msr & MSR_ME; |
259 | msr_mask = 0; | 253 | msr_mask = 0; |
260 | break; | 254 | break; |
261 | case BOOKE_IRQPRIO_EXTERNAL: | ||
262 | case BOOKE_IRQPRIO_DECREMENTER: | 255 | case BOOKE_IRQPRIO_DECREMENTER: |
263 | case BOOKE_IRQPRIO_FIT: | 256 | case BOOKE_IRQPRIO_FIT: |
257 | keep_irq = true; | ||
258 | /* fall through */ | ||
259 | case BOOKE_IRQPRIO_EXTERNAL: | ||
264 | allowed = vcpu->arch.shared->msr & MSR_EE; | 260 | allowed = vcpu->arch.shared->msr & MSR_EE; |
265 | allowed = allowed && !crit; | 261 | allowed = allowed && !crit; |
266 | msr_mask = MSR_CE|MSR_ME|MSR_DE; | 262 | msr_mask = MSR_CE|MSR_ME|MSR_DE; |
@@ -276,7 +272,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
276 | vcpu->arch.shared->srr1 = vcpu->arch.shared->msr; | 272 | vcpu->arch.shared->srr1 = vcpu->arch.shared->msr; |
277 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority]; | 273 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority]; |
278 | if (update_esr == true) | 274 | if (update_esr == true) |
279 | vcpu->arch.esr = vcpu->arch.queued_esr; | 275 | vcpu->arch.shared->esr = vcpu->arch.queued_esr; |
280 | if (update_dear == true) | 276 | if (update_dear == true) |
281 | vcpu->arch.shared->dar = vcpu->arch.queued_dear; | 277 | vcpu->arch.shared->dar = vcpu->arch.queued_dear; |
282 | kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask); | 278 | kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask); |
@@ -288,13 +284,26 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
288 | return allowed; | 284 | return allowed; |
289 | } | 285 | } |
290 | 286 | ||
291 | /* Check pending exceptions and deliver one, if possible. */ | 287 | static void update_timer_ints(struct kvm_vcpu *vcpu) |
292 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | 288 | { |
289 | if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS)) | ||
290 | kvmppc_core_queue_dec(vcpu); | ||
291 | else | ||
292 | kvmppc_core_dequeue_dec(vcpu); | ||
293 | } | ||
294 | |||
295 | static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu) | ||
293 | { | 296 | { |
294 | unsigned long *pending = &vcpu->arch.pending_exceptions; | 297 | unsigned long *pending = &vcpu->arch.pending_exceptions; |
295 | unsigned long old_pending = vcpu->arch.pending_exceptions; | ||
296 | unsigned int priority; | 298 | unsigned int priority; |
297 | 299 | ||
300 | if (vcpu->requests) { | ||
301 | if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) { | ||
302 | smp_mb(); | ||
303 | update_timer_ints(vcpu); | ||
304 | } | ||
305 | } | ||
306 | |||
298 | priority = __ffs(*pending); | 307 | priority = __ffs(*pending); |
299 | while (priority <= BOOKE_IRQPRIO_MAX) { | 308 | while (priority <= BOOKE_IRQPRIO_MAX) { |
300 | if (kvmppc_booke_irqprio_deliver(vcpu, priority)) | 309 | if (kvmppc_booke_irqprio_deliver(vcpu, priority)) |
@@ -306,10 +315,24 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | |||
306 | } | 315 | } |
307 | 316 | ||
308 | /* Tell the guest about our interrupt status */ | 317 | /* Tell the guest about our interrupt status */ |
309 | if (*pending) | 318 | vcpu->arch.shared->int_pending = !!*pending; |
310 | vcpu->arch.shared->int_pending = 1; | 319 | } |
311 | else if (old_pending) | 320 | |
312 | vcpu->arch.shared->int_pending = 0; | 321 | /* Check pending exceptions and deliver one, if possible. */ |
322 | void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu) | ||
323 | { | ||
324 | WARN_ON_ONCE(!irqs_disabled()); | ||
325 | |||
326 | kvmppc_core_check_exceptions(vcpu); | ||
327 | |||
328 | if (vcpu->arch.shared->msr & MSR_WE) { | ||
329 | local_irq_enable(); | ||
330 | kvm_vcpu_block(vcpu); | ||
331 | local_irq_disable(); | ||
332 | |||
333 | kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS); | ||
334 | kvmppc_core_check_exceptions(vcpu); | ||
335 | }; | ||
313 | } | 336 | } |
314 | 337 | ||
315 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | 338 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) |
@@ -322,11 +345,21 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
322 | } | 345 | } |
323 | 346 | ||
324 | local_irq_disable(); | 347 | local_irq_disable(); |
348 | |||
349 | kvmppc_core_prepare_to_enter(vcpu); | ||
350 | |||
351 | if (signal_pending(current)) { | ||
352 | kvm_run->exit_reason = KVM_EXIT_INTR; | ||
353 | ret = -EINTR; | ||
354 | goto out; | ||
355 | } | ||
356 | |||
325 | kvm_guest_enter(); | 357 | kvm_guest_enter(); |
326 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); | 358 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); |
327 | kvm_guest_exit(); | 359 | kvm_guest_exit(); |
328 | local_irq_enable(); | ||
329 | 360 | ||
361 | out: | ||
362 | local_irq_enable(); | ||
330 | return ret; | 363 | return ret; |
331 | } | 364 | } |
332 | 365 | ||
@@ -603,7 +636,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
603 | 636 | ||
604 | local_irq_disable(); | 637 | local_irq_disable(); |
605 | 638 | ||
606 | kvmppc_core_deliver_interrupts(vcpu); | 639 | kvmppc_core_prepare_to_enter(vcpu); |
607 | 640 | ||
608 | if (!(r & RESUME_HOST)) { | 641 | if (!(r & RESUME_HOST)) { |
609 | /* To avoid clobbering exit_reason, only check for signals if | 642 | /* To avoid clobbering exit_reason, only check for signals if |
@@ -628,6 +661,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
628 | vcpu->arch.pc = 0; | 661 | vcpu->arch.pc = 0; |
629 | vcpu->arch.shared->msr = 0; | 662 | vcpu->arch.shared->msr = 0; |
630 | vcpu->arch.shadow_msr = MSR_USER | MSR_DE | MSR_IS | MSR_DS; | 663 | vcpu->arch.shadow_msr = MSR_USER | MSR_DE | MSR_IS | MSR_DS; |
664 | vcpu->arch.shared->pir = vcpu->vcpu_id; | ||
631 | kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */ | 665 | kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */ |
632 | 666 | ||
633 | vcpu->arch.shadow_pid = 1; | 667 | vcpu->arch.shadow_pid = 1; |
@@ -662,10 +696,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
662 | regs->sprg1 = vcpu->arch.shared->sprg1; | 696 | regs->sprg1 = vcpu->arch.shared->sprg1; |
663 | regs->sprg2 = vcpu->arch.shared->sprg2; | 697 | regs->sprg2 = vcpu->arch.shared->sprg2; |
664 | regs->sprg3 = vcpu->arch.shared->sprg3; | 698 | regs->sprg3 = vcpu->arch.shared->sprg3; |
665 | regs->sprg4 = vcpu->arch.sprg4; | 699 | regs->sprg4 = vcpu->arch.shared->sprg4; |
666 | regs->sprg5 = vcpu->arch.sprg5; | 700 | regs->sprg5 = vcpu->arch.shared->sprg5; |
667 | regs->sprg6 = vcpu->arch.sprg6; | 701 | regs->sprg6 = vcpu->arch.shared->sprg6; |
668 | regs->sprg7 = vcpu->arch.sprg7; | 702 | regs->sprg7 = vcpu->arch.shared->sprg7; |
669 | 703 | ||
670 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) | 704 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) |
671 | regs->gpr[i] = kvmppc_get_gpr(vcpu, i); | 705 | regs->gpr[i] = kvmppc_get_gpr(vcpu, i); |
@@ -690,10 +724,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
690 | vcpu->arch.shared->sprg1 = regs->sprg1; | 724 | vcpu->arch.shared->sprg1 = regs->sprg1; |
691 | vcpu->arch.shared->sprg2 = regs->sprg2; | 725 | vcpu->arch.shared->sprg2 = regs->sprg2; |
692 | vcpu->arch.shared->sprg3 = regs->sprg3; | 726 | vcpu->arch.shared->sprg3 = regs->sprg3; |
693 | vcpu->arch.sprg4 = regs->sprg4; | 727 | vcpu->arch.shared->sprg4 = regs->sprg4; |
694 | vcpu->arch.sprg5 = regs->sprg5; | 728 | vcpu->arch.shared->sprg5 = regs->sprg5; |
695 | vcpu->arch.sprg6 = regs->sprg6; | 729 | vcpu->arch.shared->sprg6 = regs->sprg6; |
696 | vcpu->arch.sprg7 = regs->sprg7; | 730 | vcpu->arch.shared->sprg7 = regs->sprg7; |
697 | 731 | ||
698 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) | 732 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) |
699 | kvmppc_set_gpr(vcpu, i, regs->gpr[i]); | 733 | kvmppc_set_gpr(vcpu, i, regs->gpr[i]); |
@@ -711,7 +745,7 @@ static void get_sregs_base(struct kvm_vcpu *vcpu, | |||
711 | sregs->u.e.csrr0 = vcpu->arch.csrr0; | 745 | sregs->u.e.csrr0 = vcpu->arch.csrr0; |
712 | sregs->u.e.csrr1 = vcpu->arch.csrr1; | 746 | sregs->u.e.csrr1 = vcpu->arch.csrr1; |
713 | sregs->u.e.mcsr = vcpu->arch.mcsr; | 747 | sregs->u.e.mcsr = vcpu->arch.mcsr; |
714 | sregs->u.e.esr = vcpu->arch.esr; | 748 | sregs->u.e.esr = vcpu->arch.shared->esr; |
715 | sregs->u.e.dear = vcpu->arch.shared->dar; | 749 | sregs->u.e.dear = vcpu->arch.shared->dar; |
716 | sregs->u.e.tsr = vcpu->arch.tsr; | 750 | sregs->u.e.tsr = vcpu->arch.tsr; |
717 | sregs->u.e.tcr = vcpu->arch.tcr; | 751 | sregs->u.e.tcr = vcpu->arch.tcr; |
@@ -729,28 +763,19 @@ static int set_sregs_base(struct kvm_vcpu *vcpu, | |||
729 | vcpu->arch.csrr0 = sregs->u.e.csrr0; | 763 | vcpu->arch.csrr0 = sregs->u.e.csrr0; |
730 | vcpu->arch.csrr1 = sregs->u.e.csrr1; | 764 | vcpu->arch.csrr1 = sregs->u.e.csrr1; |
731 | vcpu->arch.mcsr = sregs->u.e.mcsr; | 765 | vcpu->arch.mcsr = sregs->u.e.mcsr; |
732 | vcpu->arch.esr = sregs->u.e.esr; | 766 | vcpu->arch.shared->esr = sregs->u.e.esr; |
733 | vcpu->arch.shared->dar = sregs->u.e.dear; | 767 | vcpu->arch.shared->dar = sregs->u.e.dear; |
734 | vcpu->arch.vrsave = sregs->u.e.vrsave; | 768 | vcpu->arch.vrsave = sregs->u.e.vrsave; |
735 | vcpu->arch.tcr = sregs->u.e.tcr; | 769 | kvmppc_set_tcr(vcpu, sregs->u.e.tcr); |
736 | 770 | ||
737 | if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC) | 771 | if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC) { |
738 | vcpu->arch.dec = sregs->u.e.dec; | 772 | vcpu->arch.dec = sregs->u.e.dec; |
739 | 773 | kvmppc_emulate_dec(vcpu); | |
740 | kvmppc_emulate_dec(vcpu); | 774 | } |
741 | 775 | ||
742 | if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) { | 776 | if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) { |
743 | /* | 777 | vcpu->arch.tsr = sregs->u.e.tsr; |
744 | * FIXME: existing KVM timer handling is incomplete. | 778 | update_timer_ints(vcpu); |
745 | * TSR cannot be read by the guest, and its value in | ||
746 | * vcpu->arch is always zero. For now, just handle | ||
747 | * the case where the caller is trying to inject a | ||
748 | * decrementer interrupt. | ||
749 | */ | ||
750 | |||
751 | if ((sregs->u.e.tsr & TSR_DIS) && | ||
752 | (vcpu->arch.tcr & TCR_DIE)) | ||
753 | kvmppc_core_queue_dec(vcpu); | ||
754 | } | 779 | } |
755 | 780 | ||
756 | return 0; | 781 | return 0; |
@@ -761,7 +786,7 @@ static void get_sregs_arch206(struct kvm_vcpu *vcpu, | |||
761 | { | 786 | { |
762 | sregs->u.e.features |= KVM_SREGS_E_ARCH206; | 787 | sregs->u.e.features |= KVM_SREGS_E_ARCH206; |
763 | 788 | ||
764 | sregs->u.e.pir = 0; | 789 | sregs->u.e.pir = vcpu->vcpu_id; |
765 | sregs->u.e.mcsrr0 = vcpu->arch.mcsrr0; | 790 | sregs->u.e.mcsrr0 = vcpu->arch.mcsrr0; |
766 | sregs->u.e.mcsrr1 = vcpu->arch.mcsrr1; | 791 | sregs->u.e.mcsrr1 = vcpu->arch.mcsrr1; |
767 | sregs->u.e.decar = vcpu->arch.decar; | 792 | sregs->u.e.decar = vcpu->arch.decar; |
@@ -774,7 +799,7 @@ static int set_sregs_arch206(struct kvm_vcpu *vcpu, | |||
774 | if (!(sregs->u.e.features & KVM_SREGS_E_ARCH206)) | 799 | if (!(sregs->u.e.features & KVM_SREGS_E_ARCH206)) |
775 | return 0; | 800 | return 0; |
776 | 801 | ||
777 | if (sregs->u.e.pir != 0) | 802 | if (sregs->u.e.pir != vcpu->vcpu_id) |
778 | return -EINVAL; | 803 | return -EINVAL; |
779 | 804 | ||
780 | vcpu->arch.mcsrr0 = sregs->u.e.mcsrr0; | 805 | vcpu->arch.mcsrr0 = sregs->u.e.mcsrr0; |
@@ -862,6 +887,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
862 | return kvmppc_core_set_sregs(vcpu, sregs); | 887 | return kvmppc_core_set_sregs(vcpu, sregs); |
863 | } | 888 | } |
864 | 889 | ||
890 | int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | ||
891 | { | ||
892 | return -EINVAL; | ||
893 | } | ||
894 | |||
895 | int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | ||
896 | { | ||
897 | return -EINVAL; | ||
898 | } | ||
899 | |||
865 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | 900 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) |
866 | { | 901 | { |
867 | return -ENOTSUPP; | 902 | return -ENOTSUPP; |
@@ -906,6 +941,33 @@ void kvmppc_core_destroy_vm(struct kvm *kvm) | |||
906 | { | 941 | { |
907 | } | 942 | } |
908 | 943 | ||
944 | void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr) | ||
945 | { | ||
946 | vcpu->arch.tcr = new_tcr; | ||
947 | update_timer_ints(vcpu); | ||
948 | } | ||
949 | |||
950 | void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits) | ||
951 | { | ||
952 | set_bits(tsr_bits, &vcpu->arch.tsr); | ||
953 | smp_wmb(); | ||
954 | kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu); | ||
955 | kvm_vcpu_kick(vcpu); | ||
956 | } | ||
957 | |||
958 | void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits) | ||
959 | { | ||
960 | clear_bits(tsr_bits, &vcpu->arch.tsr); | ||
961 | update_timer_ints(vcpu); | ||
962 | } | ||
963 | |||
964 | void kvmppc_decrementer_func(unsigned long data) | ||
965 | { | ||
966 | struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; | ||
967 | |||
968 | kvmppc_set_tsr_bits(vcpu, TSR_DIS); | ||
969 | } | ||
970 | |||
909 | int __init kvmppc_booke_init(void) | 971 | int __init kvmppc_booke_init(void) |
910 | { | 972 | { |
911 | unsigned long ivor[16]; | 973 | unsigned long ivor[16]; |