diff options
author | Alexander Graf <agraf@suse.de> | 2012-08-10 06:28:50 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2012-10-05 17:38:42 -0400 |
commit | 03d25c5bd5c3125055bd36f4813ddb817def19dd (patch) | |
tree | ed1135f8862466b9fc9373049f30ce087fb668a8 | |
parent | 2d8185d4ee22f425001d28d1817fc8d478e6fa02 (diff) |
KVM: PPC: Use same kvmppc_prepare_to_enter code for booke and book3s_pr
We need to do the same things when preparing to enter a guest for booke and
book3s_pr cores. Fold the generic code into a generic function that both call.
Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 22 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 58 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 57 |
4 files changed, 67 insertions, 73 deletions
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 88de3146838..59b7c87e47f 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -112,6 +112,7 @@ extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, | |||
112 | ulong val); | 112 | ulong val); |
113 | extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, | 113 | extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, |
114 | ulong *val); | 114 | ulong *val); |
115 | extern void kvmppc_core_check_requests(struct kvm_vcpu *vcpu); | ||
115 | 116 | ||
116 | extern int kvmppc_booke_init(void); | 117 | extern int kvmppc_booke_init(void); |
117 | extern void kvmppc_booke_exit(void); | 118 | extern void kvmppc_booke_exit(void); |
@@ -150,6 +151,8 @@ extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, | |||
150 | extern int kvmppc_bookehv_init(void); | 151 | extern int kvmppc_bookehv_init(void); |
151 | extern void kvmppc_bookehv_exit(void); | 152 | extern void kvmppc_bookehv_exit(void); |
152 | 153 | ||
154 | extern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu); | ||
155 | |||
153 | /* | 156 | /* |
154 | * Cuts out inst bits with ordering according to spec. | 157 | * Cuts out inst bits with ordering according to spec. |
155 | * That means the leftmost bit is zero. All given bits are included. | 158 | * That means the leftmost bit is zero. All given bits are included. |
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 7f0fe6f9e29..cae2defd146 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -88,6 +88,10 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | |||
88 | kvmppc_giveup_ext(vcpu, MSR_VSX); | 88 | kvmppc_giveup_ext(vcpu, MSR_VSX); |
89 | } | 89 | } |
90 | 90 | ||
91 | void kvmppc_core_check_requests(struct kvm_vcpu *vcpu) | ||
92 | { | ||
93 | } | ||
94 | |||
91 | static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) | 95 | static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) |
92 | { | 96 | { |
93 | ulong smsr = vcpu->arch.shared->msr; | 97 | ulong smsr = vcpu->arch.shared->msr; |
@@ -815,19 +819,9 @@ program_interrupt: | |||
815 | * again due to a host external interrupt. | 819 | * again due to a host external interrupt. |
816 | */ | 820 | */ |
817 | __hard_irq_disable(); | 821 | __hard_irq_disable(); |
818 | if (signal_pending(current)) { | 822 | if (kvmppc_prepare_to_enter(vcpu)) { |
819 | __hard_irq_enable(); | ||
820 | #ifdef EXIT_DEBUG | ||
821 | printk(KERN_EMERG "KVM: Going back to host\n"); | ||
822 | #endif | ||
823 | vcpu->stat.signal_exits++; | ||
824 | run->exit_reason = KVM_EXIT_INTR; | 823 | run->exit_reason = KVM_EXIT_INTR; |
825 | r = -EINTR; | 824 | r = -EINTR; |
826 | } else { | ||
827 | /* In case an interrupt came in that was triggered | ||
828 | * from userspace (like DEC), we need to check what | ||
829 | * to inject now! */ | ||
830 | kvmppc_core_prepare_to_enter(vcpu); | ||
831 | } | 825 | } |
832 | } | 826 | } |
833 | 827 | ||
@@ -1029,8 +1023,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1029 | goto out; | 1023 | goto out; |
1030 | } | 1024 | } |
1031 | 1025 | ||
1032 | kvmppc_core_prepare_to_enter(vcpu); | ||
1033 | |||
1034 | /* | 1026 | /* |
1035 | * Interrupts could be timers for the guest which we have to inject | 1027 | * Interrupts could be timers for the guest which we have to inject |
1036 | * again, so let's postpone them until we're in the guest and if we | 1028 | * again, so let's postpone them until we're in the guest and if we |
@@ -1038,9 +1030,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1038 | * a host external interrupt. | 1030 | * a host external interrupt. |
1039 | */ | 1031 | */ |
1040 | __hard_irq_disable(); | 1032 | __hard_irq_disable(); |
1041 | 1033 | if (kvmppc_prepare_to_enter(vcpu)) { | |
1042 | /* No need to go into the guest when all we do is going out */ | ||
1043 | if (signal_pending(current)) { | ||
1044 | __hard_irq_enable(); | 1034 | __hard_irq_enable(); |
1045 | kvm_run->exit_reason = KVM_EXIT_INTR; | 1035 | kvm_run->exit_reason = KVM_EXIT_INTR; |
1046 | ret = -EINTR; | 1036 | ret = -EINTR; |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 683cbd686d0..4652e0bfa78 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -455,10 +455,8 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu) | |||
455 | return r; | 455 | return r; |
456 | } | 456 | } |
457 | 457 | ||
458 | static void kvmppc_check_requests(struct kvm_vcpu *vcpu) | 458 | void kvmppc_core_check_requests(struct kvm_vcpu *vcpu) |
459 | { | 459 | { |
460 | trace_kvm_check_requests(vcpu); | ||
461 | |||
462 | if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) | 460 | if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) |
463 | update_timer_ints(vcpu); | 461 | update_timer_ints(vcpu); |
464 | #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC) | 462 | #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC) |
@@ -467,60 +465,6 @@ static void kvmppc_check_requests(struct kvm_vcpu *vcpu) | |||
467 | #endif | 465 | #endif |
468 | } | 466 | } |
469 | 467 | ||
470 | /* | ||
471 | * Common checks before entering the guest world. Call with interrupts | ||
472 | * disabled. | ||
473 | * | ||
474 | * returns !0 if a signal is pending and check_signal is true | ||
475 | */ | ||
476 | static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu) | ||
477 | { | ||
478 | int r = 0; | ||
479 | |||
480 | WARN_ON_ONCE(!irqs_disabled()); | ||
481 | while (true) { | ||
482 | if (need_resched()) { | ||
483 | local_irq_enable(); | ||
484 | cond_resched(); | ||
485 | local_irq_disable(); | ||
486 | continue; | ||
487 | } | ||
488 | |||
489 | if (signal_pending(current)) { | ||
490 | r = 1; | ||
491 | break; | ||
492 | } | ||
493 | |||
494 | smp_mb(); | ||
495 | if (vcpu->requests) { | ||
496 | /* Make sure we process requests preemptable */ | ||
497 | local_irq_enable(); | ||
498 | kvmppc_check_requests(vcpu); | ||
499 | local_irq_disable(); | ||
500 | continue; | ||
501 | } | ||
502 | |||
503 | if (kvmppc_core_prepare_to_enter(vcpu)) { | ||
504 | /* interrupts got enabled in between, so we | ||
505 | are back at square 1 */ | ||
506 | continue; | ||
507 | } | ||
508 | |||
509 | if (vcpu->mode == EXITING_GUEST_MODE) { | ||
510 | r = 1; | ||
511 | break; | ||
512 | } | ||
513 | |||
514 | /* Going into guest context! Yay! */ | ||
515 | vcpu->mode = IN_GUEST_MODE; | ||
516 | smp_wmb(); | ||
517 | |||
518 | break; | ||
519 | } | ||
520 | |||
521 | return r; | ||
522 | } | ||
523 | |||
524 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | 468 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) |
525 | { | 469 | { |
526 | int ret; | 470 | int ret; |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 45fe433316e..153a26abc91 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -47,6 +47,63 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) | |||
47 | return 1; | 47 | return 1; |
48 | } | 48 | } |
49 | 49 | ||
50 | #ifndef CONFIG_KVM_BOOK3S_64_HV | ||
51 | /* | ||
52 | * Common checks before entering the guest world. Call with interrupts | ||
53 | * disabled. | ||
54 | * | ||
55 | * returns !0 if a signal is pending and check_signal is true | ||
56 | */ | ||
57 | int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu) | ||
58 | { | ||
59 | int r = 0; | ||
60 | |||
61 | WARN_ON_ONCE(!irqs_disabled()); | ||
62 | while (true) { | ||
63 | if (need_resched()) { | ||
64 | local_irq_enable(); | ||
65 | cond_resched(); | ||
66 | local_irq_disable(); | ||
67 | continue; | ||
68 | } | ||
69 | |||
70 | if (signal_pending(current)) { | ||
71 | r = 1; | ||
72 | break; | ||
73 | } | ||
74 | |||
75 | smp_mb(); | ||
76 | if (vcpu->requests) { | ||
77 | /* Make sure we process requests preemptable */ | ||
78 | local_irq_enable(); | ||
79 | trace_kvm_check_requests(vcpu); | ||
80 | kvmppc_core_check_requests(vcpu); | ||
81 | local_irq_disable(); | ||
82 | continue; | ||
83 | } | ||
84 | |||
85 | if (kvmppc_core_prepare_to_enter(vcpu)) { | ||
86 | /* interrupts got enabled in between, so we | ||
87 | are back at square 1 */ | ||
88 | continue; | ||
89 | } | ||
90 | |||
91 | if (vcpu->mode == EXITING_GUEST_MODE) { | ||
92 | r = 1; | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | /* Going into guest context! Yay! */ | ||
97 | vcpu->mode = IN_GUEST_MODE; | ||
98 | smp_wmb(); | ||
99 | |||
100 | break; | ||
101 | } | ||
102 | |||
103 | return r; | ||
104 | } | ||
105 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | ||
106 | |||
50 | int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) | 107 | int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) |
51 | { | 108 | { |
52 | int nr = kvmppc_get_gpr(vcpu, 11); | 109 | int nr = kvmppc_get_gpr(vcpu, 11); |