aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2015-02-06 18:01:00 -0500
committerJames Hogan <james.hogan@imgtec.com>2015-03-27 17:25:19 -0400
commit2b6009d646887cac8888f1ce8694af0beefce88b (patch)
treef19289e342e1c42959dfa51ca7b6b278550dad89
parent539cb89fbdfe082d00be6f83d0f2140b7802151c (diff)
MIPS: KVM: Emulate MSA bits in COP0 interface
Emulate MSA related parts of COP0 interface so that the guest will be able to enable/disable MSA (Config5.MSAEn) once the MSA capability has been wired up. As with the FPU (Status.CU1) setting Config5.MSAEn has no immediate effect if the MSA state isn't live, as MSA state is restored lazily on first use. Changes after the MSA state has been restored take immediate effect, so that the guest can start getting MSA disabled exceptions right away for guest MSA operations. The MSA state is saved lazily too, as MSA may get re-enabled in the near future anyway. A special case is also added for when Status.CU1 is set while FR=0 and the MSA state is live. In this case we are at risk of getting reserved instruction exceptions if we try and save the MSA state, so we lose the MSA state sooner while MSA is still usable. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Gleb Natapov <gleb@kernel.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org
-rw-r--r--arch/mips/kvm/emulate.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index fbf169fb63df..07f554c72cb8 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -912,7 +912,13 @@ unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu)
912unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu) 912unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu)
913{ 913{
914 /* Config4 is optional */ 914 /* Config4 is optional */
915 return MIPS_CONF_M; 915 unsigned int mask = MIPS_CONF_M;
916
917 /* Permit MSA to be present if MSA is supported */
918 if (kvm_mips_guest_can_have_msa(&vcpu->arch))
919 mask |= MIPS_CONF3_MSA;
920
921 return mask;
916} 922}
917 923
918/** 924/**
@@ -939,6 +945,10 @@ unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu)
939{ 945{
940 unsigned int mask = 0; 946 unsigned int mask = 0;
941 947
948 /* Permit MSAEn changes if MSA supported and enabled */
949 if (kvm_mips_guest_has_msa(&vcpu->arch))
950 mask |= MIPS_CONF5_MSAEN;
951
942 /* 952 /*
943 * Permit guest FPU mode changes if FPU is enabled and the relevant 953 * Permit guest FPU mode changes if FPU is enabled and the relevant
944 * feature exists according to FIR register. 954 * feature exists according to FIR register.
@@ -1126,6 +1136,18 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
1126 kvm_drop_fpu(vcpu); 1136 kvm_drop_fpu(vcpu);
1127 1137
1128 /* 1138 /*
1139 * If MSA state is already live, it is undefined
1140 * how it interacts with FR=0 FPU state, and we
1141 * don't want to hit reserved instruction
1142 * exceptions trying to save the MSA state later
1143 * when CU=1 && FR=1, so play it safe and save
1144 * it first.
1145 */
1146 if (change & ST0_CU1 && !(val & ST0_FR) &&
1147 vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA)
1148 kvm_lose_fpu(vcpu);
1149
1150 /*
1129 * Propagate CU1 (FPU enable) changes 1151 * Propagate CU1 (FPU enable) changes
1130 * immediately if the FPU context is already 1152 * immediately if the FPU context is already
1131 * loaded. When disabling we leave the context 1153 * loaded. When disabling we leave the context
@@ -1160,7 +1182,7 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
1160 val = old_val ^ change; 1182 val = old_val ^ change;
1161 1183
1162 1184
1163 /* Handle changes in FPU modes */ 1185 /* Handle changes in FPU/MSA modes */
1164 preempt_disable(); 1186 preempt_disable();
1165 1187
1166 /* 1188 /*
@@ -1171,6 +1193,17 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
1171 vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) 1193 vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU)
1172 change_c0_config5(MIPS_CONF5_FRE, val); 1194 change_c0_config5(MIPS_CONF5_FRE, val);
1173 1195
1196 /*
1197 * Propagate MSAEn changes immediately if the
1198 * MSA context is already loaded. When disabling
1199 * we leave the context loaded so it can be
1200 * quickly enabled again in the near future.
1201 */
1202 if (change & MIPS_CONF5_MSAEN &&
1203 vcpu->arch.fpu_inuse & KVM_MIPS_FPU_MSA)
1204 change_c0_config5(MIPS_CONF5_MSAEN,
1205 val);
1206
1174 preempt_enable(); 1207 preempt_enable();
1175 1208
1176 kvm_write_c0_guest_config5(cop0, val); 1209 kvm_write_c0_guest_config5(cop0, val);