@@ -214,3 +214,110 @@ int kvm_emu_idle(struct kvm_vcpu *vcpu)
214214
215215 return EMULATE_DONE ;
216216}
217+
218+ static int kvm_trap_handle_gspr (struct kvm_vcpu * vcpu )
219+ {
220+ int rd , rj ;
221+ unsigned int index ;
222+ unsigned long curr_pc ;
223+ larch_inst inst ;
224+ enum emulation_result er = EMULATE_DONE ;
225+ struct kvm_run * run = vcpu -> run ;
226+
227+ /* Fetch the instruction */
228+ inst .word = vcpu -> arch .badi ;
229+ curr_pc = vcpu -> arch .pc ;
230+ update_pc (& vcpu -> arch );
231+
232+ trace_kvm_exit_gspr (vcpu , inst .word );
233+ er = EMULATE_FAIL ;
234+ switch (((inst .word >> 24 ) & 0xff )) {
235+ case 0x0 : /* CPUCFG GSPR */
236+ if (inst .reg2_format .opcode == 0x1B ) {
237+ rd = inst .reg2_format .rd ;
238+ rj = inst .reg2_format .rj ;
239+ ++ vcpu -> stat .cpucfg_exits ;
240+ index = vcpu -> arch .gprs [rj ];
241+ er = EMULATE_DONE ;
242+ /*
243+ * By LoongArch Reference Manual 2.2.10.5
244+ * return value is 0 for undefined cpucfg index
245+ */
246+ if (index < KVM_MAX_CPUCFG_REGS )
247+ vcpu -> arch .gprs [rd ] = vcpu -> arch .cpucfg [index ];
248+ else
249+ vcpu -> arch .gprs [rd ] = 0 ;
250+ }
251+ break ;
252+ case 0x4 : /* CSR{RD,WR,XCHG} GSPR */
253+ er = kvm_handle_csr (vcpu , inst );
254+ break ;
255+ case 0x6 : /* Cache, Idle and IOCSR GSPR */
256+ switch (((inst .word >> 22 ) & 0x3ff )) {
257+ case 0x18 : /* Cache GSPR */
258+ er = EMULATE_DONE ;
259+ trace_kvm_exit_cache (vcpu , KVM_TRACE_EXIT_CACHE );
260+ break ;
261+ case 0x19 : /* Idle/IOCSR GSPR */
262+ switch (((inst .word >> 15 ) & 0x1ffff )) {
263+ case 0xc90 : /* IOCSR GSPR */
264+ er = kvm_emu_iocsr (inst , run , vcpu );
265+ break ;
266+ case 0xc91 : /* Idle GSPR */
267+ er = kvm_emu_idle (vcpu );
268+ break ;
269+ default :
270+ er = EMULATE_FAIL ;
271+ break ;
272+ }
273+ break ;
274+ default :
275+ er = EMULATE_FAIL ;
276+ break ;
277+ }
278+ break ;
279+ default :
280+ er = EMULATE_FAIL ;
281+ break ;
282+ }
283+
284+ /* Rollback PC only if emulation was unsuccessful */
285+ if (er == EMULATE_FAIL ) {
286+ kvm_err ("[%#lx]%s: unsupported gspr instruction 0x%08x\n" ,
287+ curr_pc , __func__ , inst .word );
288+
289+ kvm_arch_vcpu_dump_regs (vcpu );
290+ vcpu -> arch .pc = curr_pc ;
291+ }
292+
293+ return er ;
294+ }
295+
296+ /*
297+ * Trigger GSPR:
298+ * 1) Execute CPUCFG instruction;
299+ * 2) Execute CACOP/IDLE instructions;
300+ * 3) Access to unimplemented CSRs/IOCSRs.
301+ */
302+ static int kvm_handle_gspr (struct kvm_vcpu * vcpu )
303+ {
304+ int ret = RESUME_GUEST ;
305+ enum emulation_result er = EMULATE_DONE ;
306+
307+ er = kvm_trap_handle_gspr (vcpu );
308+
309+ if (er == EMULATE_DONE ) {
310+ ret = RESUME_GUEST ;
311+ } else if (er == EMULATE_DO_MMIO ) {
312+ vcpu -> run -> exit_reason = KVM_EXIT_MMIO ;
313+ ret = RESUME_HOST ;
314+ } else if (er == EMULATE_DO_IOCSR ) {
315+ vcpu -> run -> exit_reason = KVM_EXIT_LOONGARCH_IOCSR ;
316+ ret = RESUME_HOST ;
317+ } else {
318+ kvm_queue_exception (vcpu , EXCCODE_INE , 0 );
319+ ret = RESUME_GUEST ;
320+ }
321+
322+ return ret ;
323+ }
0 commit comments