aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);