@@ -214,3 +214,110 @@ int kvm_emu_idle(struct kvm_vcpu *vcpu)
214
214
215
215
return EMULATE_DONE ;
216
216
}
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