diff options
author | Mihai Caraman <mihai.caraman@freescale.com> | 2014-07-23 12:06:20 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-07-28 09:23:13 -0400 |
commit | 9a26af64d6bba72c9dfd62cc0cab0e79f8a66d7b (patch) | |
tree | c5f5d37390630b55f6a9b234a56fc6c76b887792 /arch | |
parent | 9c0d4e0dcf69b1ab3a9f8debebd119f53964cb57 (diff) |
KVM: PPC: Book3s: Remove kvmppc_read_inst() function
In the context of replacing kvmppc_ld() function calls with a version of
kvmppc_get_last_inst() which allow to fail, Alex Graf suggested this:
"If we get EMULATE_AGAIN, we just have to make sure we go back into the guest.
No need to inject an ISI into the guest - it'll do that all by itself.
With an error returning kvmppc_get_last_inst we can just use completely
get rid of kvmppc_read_inst() and only use kvmppc_get_last_inst() instead."
As a intermediate step get rid of kvmppc_read_inst() and only use kvmppc_ld()
instead.
Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 85 |
1 files changed, 34 insertions, 51 deletions
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index e40765f8cbad..e76aec38ec21 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -710,42 +710,6 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac) | |||
710 | #endif | 710 | #endif |
711 | } | 711 | } |
712 | 712 | ||
713 | static int kvmppc_read_inst(struct kvm_vcpu *vcpu) | ||
714 | { | ||
715 | ulong srr0 = kvmppc_get_pc(vcpu); | ||
716 | u32 last_inst = kvmppc_get_last_inst(vcpu); | ||
717 | int ret; | ||
718 | |||
719 | ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false); | ||
720 | if (ret == -ENOENT) { | ||
721 | ulong msr = kvmppc_get_msr(vcpu); | ||
722 | |||
723 | msr = kvmppc_set_field(msr, 33, 33, 1); | ||
724 | msr = kvmppc_set_field(msr, 34, 36, 0); | ||
725 | msr = kvmppc_set_field(msr, 42, 47, 0); | ||
726 | kvmppc_set_msr_fast(vcpu, msr); | ||
727 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE); | ||
728 | return EMULATE_AGAIN; | ||
729 | } | ||
730 | |||
731 | return EMULATE_DONE; | ||
732 | } | ||
733 | |||
734 | static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr) | ||
735 | { | ||
736 | |||
737 | /* Need to do paired single emulation? */ | ||
738 | if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)) | ||
739 | return EMULATE_DONE; | ||
740 | |||
741 | /* Read out the instruction */ | ||
742 | if (kvmppc_read_inst(vcpu) == EMULATE_DONE) | ||
743 | /* Need to emulate */ | ||
744 | return EMULATE_FAIL; | ||
745 | |||
746 | return EMULATE_AGAIN; | ||
747 | } | ||
748 | |||
749 | /* Handle external providers (FPU, Altivec, VSX) */ | 713 | /* Handle external providers (FPU, Altivec, VSX) */ |
750 | static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | 714 | static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, |
751 | ulong msr) | 715 | ulong msr) |
@@ -1149,31 +1113,49 @@ program_interrupt: | |||
1149 | case BOOK3S_INTERRUPT_VSX: | 1113 | case BOOK3S_INTERRUPT_VSX: |
1150 | { | 1114 | { |
1151 | int ext_msr = 0; | 1115 | int ext_msr = 0; |
1116 | int emul; | ||
1117 | ulong pc; | ||
1118 | u32 last_inst; | ||
1119 | |||
1120 | if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) { | ||
1121 | /* Do paired single instruction emulation */ | ||
1122 | pc = kvmppc_get_pc(vcpu); | ||
1123 | last_inst = kvmppc_get_last_inst(vcpu); | ||
1124 | emul = kvmppc_ld(vcpu, &pc, sizeof(u32), &last_inst, | ||
1125 | false); | ||
1126 | if (emul == EMULATE_DONE) | ||
1127 | goto program_interrupt; | ||
1128 | else | ||
1129 | r = RESUME_GUEST; | ||
1152 | 1130 | ||
1153 | switch (exit_nr) { | 1131 | break; |
1154 | case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP; break; | ||
1155 | case BOOK3S_INTERRUPT_ALTIVEC: ext_msr = MSR_VEC; break; | ||
1156 | case BOOK3S_INTERRUPT_VSX: ext_msr = MSR_VSX; break; | ||
1157 | } | 1132 | } |
1158 | 1133 | ||
1159 | switch (kvmppc_check_ext(vcpu, exit_nr)) { | 1134 | /* Enable external provider */ |
1160 | case EMULATE_DONE: | 1135 | switch (exit_nr) { |
1161 | /* everything ok - let's enable the ext */ | 1136 | case BOOK3S_INTERRUPT_FP_UNAVAIL: |
1162 | r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr); | 1137 | ext_msr = MSR_FP; |
1163 | break; | 1138 | break; |
1164 | case EMULATE_FAIL: | 1139 | |
1165 | /* we need to emulate this instruction */ | 1140 | case BOOK3S_INTERRUPT_ALTIVEC: |
1166 | goto program_interrupt; | 1141 | ext_msr = MSR_VEC; |
1167 | break; | 1142 | break; |
1168 | default: | 1143 | |
1169 | /* nothing to worry about - go again */ | 1144 | case BOOK3S_INTERRUPT_VSX: |
1145 | ext_msr = MSR_VSX; | ||
1170 | break; | 1146 | break; |
1171 | } | 1147 | } |
1148 | |||
1149 | r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr); | ||
1172 | break; | 1150 | break; |
1173 | } | 1151 | } |
1174 | case BOOK3S_INTERRUPT_ALIGNMENT: | 1152 | case BOOK3S_INTERRUPT_ALIGNMENT: |
1175 | if (kvmppc_read_inst(vcpu) == EMULATE_DONE) { | 1153 | { |
1176 | u32 last_inst = kvmppc_get_last_inst(vcpu); | 1154 | ulong pc = kvmppc_get_pc(vcpu); |
1155 | u32 last_inst = kvmppc_get_last_inst(vcpu); | ||
1156 | int emul = kvmppc_ld(vcpu, &pc, sizeof(u32), &last_inst, false); | ||
1157 | |||
1158 | if (emul == EMULATE_DONE) { | ||
1177 | u32 dsisr; | 1159 | u32 dsisr; |
1178 | u64 dar; | 1160 | u64 dar; |
1179 | 1161 | ||
@@ -1187,6 +1169,7 @@ program_interrupt: | |||
1187 | } | 1169 | } |
1188 | r = RESUME_GUEST; | 1170 | r = RESUME_GUEST; |
1189 | break; | 1171 | break; |
1172 | } | ||
1190 | #ifdef CONFIG_PPC_BOOK3S_64 | 1173 | #ifdef CONFIG_PPC_BOOK3S_64 |
1191 | case BOOK3S_INTERRUPT_FAC_UNAVAIL: | 1174 | case BOOK3S_INTERRUPT_FAC_UNAVAIL: |
1192 | kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56); | 1175 | kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56); |