1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2019 Western Digital Corporation or its affiliates. 4 * Copyright (c) 2022 Ventana Micro Systems Inc. 5 */ 6 7 #include <linux/bitops.h> 8 #include <linux/kvm_host.h> 9 10 #include <asm/cpufeature.h> 11 #include <asm/insn.h> 12 #include "trace.h" 13 14 struct insn_func { 15 unsigned long mask; 16 unsigned long match; 17 /* 18 * Possible return values are as follows: 19 * 1) Returns < 0 for error case 20 * 2) Returns 0 for exit to user-space 21 * 3) Returns 1 to continue with next sepc 22 * 4) Returns 2 to continue with same sepc 23 * 5) Returns 3 to inject illegal instruction trap and continue 24 * 6) Returns 4 to inject virtual instruction trap and continue 25 * 26 * Use enum kvm_insn_return for return values 27 */ 28 int (*func)(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn); 29 }; 30 31 static int truly_illegal_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, 32 ulong insn) 33 { 34 struct kvm_cpu_trap utrap = { 0 }; 35 36 /* Redirect trap to Guest VCPU */ 37 utrap.sepc = vcpu->arch.guest_context.sepc; 38 utrap.scause = EXC_INST_ILLEGAL; 39 utrap.stval = insn; 40 utrap.htval = 0; 41 utrap.htinst = 0; 42 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); 43 44 return 1; 45 } 46 47 static int truly_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, 48 ulong insn) 49 { 50 struct kvm_cpu_trap utrap = { 0 }; 51 52 /* Redirect trap to Guest VCPU */ 53 utrap.sepc = vcpu->arch.guest_context.sepc; 54 utrap.scause = EXC_VIRTUAL_INST_FAULT; 55 utrap.stval = insn; 56 utrap.htval = 0; 57 utrap.htinst = 0; 58 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); 59 60 return 1; 61 } 62 63 /** 64 * kvm_riscv_vcpu_wfi -- Emulate wait for interrupt (WFI) behaviour 65 * 66 * @vcpu: The VCPU pointer 67 */ 68 void kvm_riscv_vcpu_wfi(struct kvm_vcpu *vcpu) 69 { 70 if (!kvm_arch_vcpu_runnable(vcpu)) { 71 kvm_vcpu_srcu_read_unlock(vcpu); 72 kvm_vcpu_halt(vcpu); 73 kvm_vcpu_srcu_read_lock(vcpu); 74 } 75 } 76 77 static int wfi_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn) 78 { 79 vcpu->stat.wfi_exit_stat++; 80 kvm_riscv_vcpu_wfi(vcpu); 81 return KVM_INSN_CONTINUE_NEXT_SEPC; 82 } 83 84 static int wrs_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn) 85 { 86 vcpu->stat.wrs_exit_stat++; 87 kvm_vcpu_on_spin(vcpu, vcpu->arch.guest_context.sstatus & SR_SPP); 88 return KVM_INSN_CONTINUE_NEXT_SEPC; 89 } 90 91 struct csr_func { 92 unsigned int base; 93 unsigned int count; 94 /* 95 * Possible return values are as same as "func" callback in 96 * "struct insn_func". 97 */ 98 int (*func)(struct kvm_vcpu *vcpu, unsigned int csr_num, 99 unsigned long *val, unsigned long new_val, 100 unsigned long wr_mask); 101 }; 102 103 static int seed_csr_rmw(struct kvm_vcpu *vcpu, unsigned int csr_num, 104 unsigned long *val, unsigned long new_val, 105 unsigned long wr_mask) 106 { 107 if (!riscv_isa_extension_available(vcpu->arch.isa, ZKR)) 108 return KVM_INSN_ILLEGAL_TRAP; 109 110 return KVM_INSN_EXIT_TO_USER_SPACE; 111 } 112 113 static const struct csr_func csr_funcs[] = { 114 KVM_RISCV_VCPU_AIA_CSR_FUNCS 115 KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS 116 { .base = CSR_SEED, .count = 1, .func = seed_csr_rmw }, 117 }; 118 119 /** 120 * kvm_riscv_vcpu_csr_return -- Handle CSR read/write after user space 121 * emulation or in-kernel emulation 122 * 123 * @vcpu: The VCPU pointer 124 * @run: The VCPU run struct containing the CSR data 125 * 126 * Returns > 0 upon failure and 0 upon success 127 */ 128 int kvm_riscv_vcpu_csr_return(struct kvm_vcpu *vcpu, struct kvm_run *run) 129 { 130 ulong insn; 131 132 if (vcpu->arch.csr_decode.return_handled) 133 return 0; 134 vcpu->arch.csr_decode.return_handled = 1; 135 136 /* Update destination register for CSR reads */ 137 insn = vcpu->arch.csr_decode.insn; 138 if ((insn >> SH_RD) & MASK_RX) 139 SET_RD(insn, &vcpu->arch.guest_context, 140 run->riscv_csr.ret_value); 141 142 /* Move to next instruction */ 143 vcpu->arch.guest_context.sepc += INSN_LEN(insn); 144 145 return 0; 146 } 147 148 static int csr_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn) 149 { 150 int i, rc = KVM_INSN_ILLEGAL_TRAP; 151 unsigned int csr_num = insn >> SH_RS2; 152 unsigned int rs1_num = (insn >> SH_RS1) & MASK_RX; 153 ulong rs1_val = GET_RS1(insn, &vcpu->arch.guest_context); 154 const struct csr_func *tcfn, *cfn = NULL; 155 ulong val = 0, wr_mask = 0, new_val = 0; 156 157 /* Decode the CSR instruction */ 158 switch (GET_FUNCT3(insn)) { 159 case GET_FUNCT3(INSN_MATCH_CSRRW): 160 wr_mask = -1UL; 161 new_val = rs1_val; 162 break; 163 case GET_FUNCT3(INSN_MATCH_CSRRS): 164 wr_mask = rs1_val; 165 new_val = -1UL; 166 break; 167 case GET_FUNCT3(INSN_MATCH_CSRRC): 168 wr_mask = rs1_val; 169 new_val = 0; 170 break; 171 case GET_FUNCT3(INSN_MATCH_CSRRWI): 172 wr_mask = -1UL; 173 new_val = rs1_num; 174 break; 175 case GET_FUNCT3(INSN_MATCH_CSRRSI): 176 wr_mask = rs1_num; 177 new_val = -1UL; 178 break; 179 case GET_FUNCT3(INSN_MATCH_CSRRCI): 180 wr_mask = rs1_num; 181 new_val = 0; 182 break; 183 default: 184 return rc; 185 } 186 187 /* Save instruction decode info */ 188 vcpu->arch.csr_decode.insn = insn; 189 vcpu->arch.csr_decode.return_handled = 0; 190 191 /* Update CSR details in kvm_run struct */ 192 run->riscv_csr.csr_num = csr_num; 193 run->riscv_csr.new_value = new_val; 194 run->riscv_csr.write_mask = wr_mask; 195 run->riscv_csr.ret_value = 0; 196 197 /* Find in-kernel CSR function */ 198 for (i = 0; i < ARRAY_SIZE(csr_funcs); i++) { 199 tcfn = &csr_funcs[i]; 200 if ((tcfn->base <= csr_num) && 201 (csr_num < (tcfn->base + tcfn->count))) { 202 cfn = tcfn; 203 break; 204 } 205 } 206 207 /* First try in-kernel CSR emulation */ 208 if (cfn && cfn->func) { 209 rc = cfn->func(vcpu, csr_num, &val, new_val, wr_mask); 210 if (rc > KVM_INSN_EXIT_TO_USER_SPACE) { 211 if (rc == KVM_INSN_CONTINUE_NEXT_SEPC) { 212 run->riscv_csr.ret_value = val; 213 vcpu->stat.csr_exit_kernel++; 214 kvm_riscv_vcpu_csr_return(vcpu, run); 215 rc = KVM_INSN_CONTINUE_SAME_SEPC; 216 } 217 return rc; 218 } 219 } 220 221 /* Exit to user-space for CSR emulation */ 222 if (rc <= KVM_INSN_EXIT_TO_USER_SPACE) { 223 vcpu->stat.csr_exit_user++; 224 run->exit_reason = KVM_EXIT_RISCV_CSR; 225 } 226 227 return rc; 228 } 229 230 static const struct insn_func system_opcode_funcs[] = { 231 { 232 .mask = INSN_MASK_CSRRW, 233 .match = INSN_MATCH_CSRRW, 234 .func = csr_insn, 235 }, 236 { 237 .mask = INSN_MASK_CSRRS, 238 .match = INSN_MATCH_CSRRS, 239 .func = csr_insn, 240 }, 241 { 242 .mask = INSN_MASK_CSRRC, 243 .match = INSN_MATCH_CSRRC, 244 .func = csr_insn, 245 }, 246 { 247 .mask = INSN_MASK_CSRRWI, 248 .match = INSN_MATCH_CSRRWI, 249 .func = csr_insn, 250 }, 251 { 252 .mask = INSN_MASK_CSRRSI, 253 .match = INSN_MATCH_CSRRSI, 254 .func = csr_insn, 255 }, 256 { 257 .mask = INSN_MASK_CSRRCI, 258 .match = INSN_MATCH_CSRRCI, 259 .func = csr_insn, 260 }, 261 { 262 .mask = INSN_MASK_WFI, 263 .match = INSN_MATCH_WFI, 264 .func = wfi_insn, 265 }, 266 { 267 .mask = INSN_MASK_WRS, 268 .match = INSN_MATCH_WRS, 269 .func = wrs_insn, 270 }, 271 }; 272 273 static int system_opcode_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, 274 ulong insn) 275 { 276 int i, rc = KVM_INSN_ILLEGAL_TRAP; 277 const struct insn_func *ifn; 278 279 for (i = 0; i < ARRAY_SIZE(system_opcode_funcs); i++) { 280 ifn = &system_opcode_funcs[i]; 281 if ((insn & ifn->mask) == ifn->match) { 282 rc = ifn->func(vcpu, run, insn); 283 break; 284 } 285 } 286 287 switch (rc) { 288 case KVM_INSN_ILLEGAL_TRAP: 289 return truly_illegal_insn(vcpu, run, insn); 290 case KVM_INSN_VIRTUAL_TRAP: 291 return truly_virtual_insn(vcpu, run, insn); 292 case KVM_INSN_CONTINUE_NEXT_SEPC: 293 vcpu->arch.guest_context.sepc += INSN_LEN(insn); 294 break; 295 default: 296 break; 297 } 298 299 return (rc <= 0) ? rc : 1; 300 } 301 302 static bool is_load_guest_page_fault(unsigned long scause) 303 { 304 /** 305 * If a g-stage page fault occurs, the direct approach 306 * is to let the g-stage page fault handler handle it 307 * naturally, however, calling the g-stage page fault 308 * handler here seems rather strange. 309 * Considering this is a corner case, we can directly 310 * return to the guest and re-execute the same PC, this 311 * will trigger a g-stage page fault again and then the 312 * regular g-stage page fault handler will populate 313 * g-stage page table. 314 */ 315 return (scause == EXC_LOAD_GUEST_PAGE_FAULT); 316 } 317 318 /** 319 * kvm_riscv_vcpu_virtual_insn -- Handle virtual instruction trap 320 * 321 * @vcpu: The VCPU pointer 322 * @run: The VCPU run struct containing the mmio data 323 * @trap: Trap details 324 * 325 * Returns > 0 to continue run-loop 326 * Returns 0 to exit run-loop and handle in user-space. 327 * Returns < 0 to report failure and exit run-loop 328 */ 329 int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, 330 struct kvm_cpu_trap *trap) 331 { 332 unsigned long insn = trap->stval; 333 struct kvm_cpu_trap utrap = { 0 }; 334 struct kvm_cpu_context *ct; 335 336 if (unlikely(INSN_IS_16BIT(insn))) { 337 if (insn == 0) { 338 ct = &vcpu->arch.guest_context; 339 insn = kvm_riscv_vcpu_unpriv_read(vcpu, true, 340 ct->sepc, 341 &utrap); 342 if (utrap.scause) { 343 if (is_load_guest_page_fault(utrap.scause)) 344 return 1; 345 utrap.sepc = ct->sepc; 346 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); 347 return 1; 348 } 349 } 350 if (INSN_IS_16BIT(insn)) 351 return truly_illegal_insn(vcpu, run, insn); 352 } 353 354 switch ((insn & INSN_OPCODE_MASK) >> INSN_OPCODE_SHIFT) { 355 case INSN_OPCODE_SYSTEM: 356 return system_opcode_insn(vcpu, run, insn); 357 default: 358 return truly_illegal_insn(vcpu, run, insn); 359 } 360 } 361 362 /** 363 * kvm_riscv_vcpu_mmio_load -- Emulate MMIO load instruction 364 * 365 * @vcpu: The VCPU pointer 366 * @run: The VCPU run struct containing the mmio data 367 * @fault_addr: Guest physical address to load 368 * @htinst: Transformed encoding of the load instruction 369 * 370 * Returns > 0 to continue run-loop 371 * Returns 0 to exit run-loop and handle in user-space. 372 * Returns < 0 to report failure and exit run-loop 373 */ 374 int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run, 375 gpa_t fault_addr, 376 unsigned long htinst) 377 { 378 u8 data_buf[8]; 379 unsigned long insn, raw_insn; 380 int shift = 0, len = 0, insn_len = 0; 381 struct kvm_cpu_trap utrap = { 0 }; 382 struct kvm_cpu_context *ct = &vcpu->arch.guest_context; 383 384 /* Determine trapped instruction */ 385 if (htinst & 0x1) { 386 /* 387 * Bit[0] == 1 implies trapped instruction value is 388 * transformed instruction or custom instruction. 389 */ 390 insn = htinst | INSN_16BIT_MASK; 391 insn_len = (htinst & BIT(1)) ? INSN_LEN(insn) : 2; 392 } else { 393 /* 394 * Bit[0] == 0 implies trapped instruction value is 395 * zero or special value. 396 */ 397 insn = kvm_riscv_vcpu_unpriv_read(vcpu, true, ct->sepc, 398 &utrap); 399 if (utrap.scause) { 400 if (is_load_guest_page_fault(utrap.scause)) 401 return 1; 402 /* Redirect trap if we failed to read instruction */ 403 utrap.sepc = ct->sepc; 404 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); 405 return 1; 406 } 407 insn_len = INSN_LEN(insn); 408 } 409 raw_insn = insn; 410 411 /* Decode length of MMIO and shift */ 412 if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) { 413 len = 4; 414 shift = 8 * (sizeof(ulong) - len); 415 } else if ((insn & INSN_MASK_LB) == INSN_MATCH_LB) { 416 len = 1; 417 shift = 8 * (sizeof(ulong) - len); 418 } else if ((insn & INSN_MASK_LBU) == INSN_MATCH_LBU) { 419 len = 1; 420 #ifdef CONFIG_64BIT 421 } else if ((insn & INSN_MASK_LD) == INSN_MATCH_LD) { 422 len = 8; 423 shift = 8 * (sizeof(ulong) - len); 424 } else if ((insn & INSN_MASK_LWU) == INSN_MATCH_LWU) { 425 len = 4; 426 #endif 427 } else if ((insn & INSN_MASK_LH) == INSN_MATCH_LH) { 428 len = 2; 429 shift = 8 * (sizeof(ulong) - len); 430 } else if ((insn & INSN_MASK_LHU) == INSN_MATCH_LHU) { 431 len = 2; 432 #ifdef CONFIG_64BIT 433 } else if ((insn & INSN_MASK_C_LD) == INSN_MATCH_C_LD) { 434 len = 8; 435 shift = 8 * (sizeof(ulong) - len); 436 insn = RVC_RS2S(insn) << SH_RD; 437 } else if ((insn & INSN_MASK_C_LDSP) == INSN_MATCH_C_LDSP && 438 ((insn >> SH_RD) & 0x1f)) { 439 len = 8; 440 shift = 8 * (sizeof(ulong) - len); 441 #endif 442 } else if ((insn & INSN_MASK_C_LW) == INSN_MATCH_C_LW) { 443 len = 4; 444 shift = 8 * (sizeof(ulong) - len); 445 insn = RVC_RS2S(insn) << SH_RD; 446 } else if ((insn & INSN_MASK_C_LWSP) == INSN_MATCH_C_LWSP && 447 ((insn >> SH_RD) & 0x1f)) { 448 len = 4; 449 shift = 8 * (sizeof(ulong) - len); 450 } else { 451 return -EOPNOTSUPP; 452 } 453 454 /* Fault address should be aligned to length of MMIO */ 455 if (fault_addr & (len - 1)) 456 return -EIO; 457 458 trace_kvm_mmio_emulate(vcpu->vcpu_id, ct->sepc, raw_insn, fault_addr, 459 false, len); 460 461 /* Save instruction decode info */ 462 vcpu->arch.mmio_decode.insn = insn; 463 vcpu->arch.mmio_decode.insn_len = insn_len; 464 vcpu->arch.mmio_decode.shift = shift; 465 vcpu->arch.mmio_decode.len = len; 466 vcpu->arch.mmio_decode.return_handled = 0; 467 468 /* Update MMIO details in kvm_run struct */ 469 run->mmio.is_write = false; 470 run->mmio.phys_addr = fault_addr; 471 run->mmio.len = len; 472 473 /* Try to handle MMIO access in the kernel */ 474 if (!kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_addr, len, data_buf)) { 475 /* Successfully handled MMIO access in the kernel so resume */ 476 memcpy(run->mmio.data, data_buf, len); 477 vcpu->stat.mmio_exit_kernel++; 478 kvm_riscv_vcpu_mmio_return(vcpu, run); 479 return 1; 480 } 481 482 /* Exit to userspace for MMIO emulation */ 483 vcpu->stat.mmio_exit_user++; 484 run->exit_reason = KVM_EXIT_MMIO; 485 486 return 0; 487 } 488 489 /** 490 * kvm_riscv_vcpu_mmio_store -- Emulate MMIO store instruction 491 * 492 * @vcpu: The VCPU pointer 493 * @run: The VCPU run struct containing the mmio data 494 * @fault_addr: Guest physical address to store 495 * @htinst: Transformed encoding of the store instruction 496 * 497 * Returns > 0 to continue run-loop 498 * Returns 0 to exit run-loop and handle in user-space. 499 * Returns < 0 to report failure and exit run-loop 500 */ 501 int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run, 502 gpa_t fault_addr, 503 unsigned long htinst) 504 { 505 u8 data8; 506 u16 data16; 507 u32 data32; 508 u64 data64; 509 ulong data; 510 unsigned long insn, raw_insn; 511 int len = 0, insn_len = 0; 512 struct kvm_cpu_trap utrap = { 0 }; 513 struct kvm_cpu_context *ct = &vcpu->arch.guest_context; 514 515 /* Determine trapped instruction */ 516 if (htinst & 0x1) { 517 /* 518 * Bit[0] == 1 implies trapped instruction value is 519 * transformed instruction or custom instruction. 520 */ 521 insn = htinst | INSN_16BIT_MASK; 522 insn_len = (htinst & BIT(1)) ? INSN_LEN(insn) : 2; 523 } else { 524 /* 525 * Bit[0] == 0 implies trapped instruction value is 526 * zero or special value. 527 */ 528 insn = kvm_riscv_vcpu_unpriv_read(vcpu, true, ct->sepc, 529 &utrap); 530 if (utrap.scause) { 531 if (is_load_guest_page_fault(utrap.scause)) 532 return 1; 533 /* Redirect trap if we failed to read instruction */ 534 utrap.sepc = ct->sepc; 535 kvm_riscv_vcpu_trap_redirect(vcpu, &utrap); 536 return 1; 537 } 538 insn_len = INSN_LEN(insn); 539 } 540 raw_insn = insn; 541 542 data = GET_RS2(insn, &vcpu->arch.guest_context); 543 data8 = data16 = data32 = data64 = data; 544 545 if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) { 546 len = 4; 547 } else if ((insn & INSN_MASK_SB) == INSN_MATCH_SB) { 548 len = 1; 549 #ifdef CONFIG_64BIT 550 } else if ((insn & INSN_MASK_SD) == INSN_MATCH_SD) { 551 len = 8; 552 #endif 553 } else if ((insn & INSN_MASK_SH) == INSN_MATCH_SH) { 554 len = 2; 555 #ifdef CONFIG_64BIT 556 } else if ((insn & INSN_MASK_C_SD) == INSN_MATCH_C_SD) { 557 len = 8; 558 data64 = GET_RS2S(insn, &vcpu->arch.guest_context); 559 } else if ((insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP && 560 ((insn >> SH_RD) & 0x1f)) { 561 len = 8; 562 data64 = GET_RS2C(insn, &vcpu->arch.guest_context); 563 #endif 564 } else if ((insn & INSN_MASK_C_SW) == INSN_MATCH_C_SW) { 565 len = 4; 566 data32 = GET_RS2S(insn, &vcpu->arch.guest_context); 567 } else if ((insn & INSN_MASK_C_SWSP) == INSN_MATCH_C_SWSP && 568 ((insn >> SH_RD) & 0x1f)) { 569 len = 4; 570 data32 = GET_RS2C(insn, &vcpu->arch.guest_context); 571 } else { 572 return -EOPNOTSUPP; 573 } 574 575 /* Fault address should be aligned to length of MMIO */ 576 if (fault_addr & (len - 1)) 577 return -EIO; 578 579 trace_kvm_mmio_emulate(vcpu->vcpu_id, ct->sepc, raw_insn, fault_addr, 580 true, len); 581 582 /* Save instruction decode info */ 583 vcpu->arch.mmio_decode.insn = insn; 584 vcpu->arch.mmio_decode.insn_len = insn_len; 585 vcpu->arch.mmio_decode.shift = 0; 586 vcpu->arch.mmio_decode.len = len; 587 vcpu->arch.mmio_decode.return_handled = 0; 588 589 /* Copy data to kvm_run instance */ 590 switch (len) { 591 case 1: 592 *((u8 *)run->mmio.data) = data8; 593 break; 594 case 2: 595 *((u16 *)run->mmio.data) = data16; 596 break; 597 case 4: 598 *((u32 *)run->mmio.data) = data32; 599 break; 600 case 8: 601 *((u64 *)run->mmio.data) = data64; 602 break; 603 default: 604 return -EOPNOTSUPP; 605 } 606 607 /* Update MMIO details in kvm_run struct */ 608 run->mmio.is_write = true; 609 run->mmio.phys_addr = fault_addr; 610 run->mmio.len = len; 611 612 /* Try to handle MMIO access in the kernel */ 613 if (!kvm_io_bus_write(vcpu, KVM_MMIO_BUS, 614 fault_addr, len, run->mmio.data)) { 615 /* Successfully handled MMIO access in the kernel so resume */ 616 vcpu->stat.mmio_exit_kernel++; 617 kvm_riscv_vcpu_mmio_return(vcpu, run); 618 return 1; 619 } 620 621 /* Exit to userspace for MMIO emulation */ 622 vcpu->stat.mmio_exit_user++; 623 run->exit_reason = KVM_EXIT_MMIO; 624 625 return 0; 626 } 627 628 /** 629 * kvm_riscv_vcpu_mmio_return -- Handle MMIO loads after user space emulation 630 * or in-kernel IO emulation 631 * 632 * @vcpu: The VCPU pointer 633 * @run: The VCPU run struct containing the mmio data 634 */ 635 int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) 636 { 637 u8 data8; 638 u16 data16; 639 u32 data32; 640 u64 data64; 641 ulong insn; 642 int len, shift; 643 644 if (vcpu->arch.mmio_decode.return_handled) 645 return 0; 646 647 vcpu->arch.mmio_decode.return_handled = 1; 648 insn = vcpu->arch.mmio_decode.insn; 649 650 if (run->mmio.is_write) 651 goto done; 652 653 len = vcpu->arch.mmio_decode.len; 654 shift = vcpu->arch.mmio_decode.shift; 655 656 switch (len) { 657 case 1: 658 data8 = *((u8 *)run->mmio.data); 659 SET_RD(insn, &vcpu->arch.guest_context, 660 (long)((ulong)data8 << shift) >> shift); 661 break; 662 case 2: 663 data16 = *((u16 *)run->mmio.data); 664 SET_RD(insn, &vcpu->arch.guest_context, 665 (long)((ulong)data16 << shift) >> shift); 666 break; 667 case 4: 668 data32 = *((u32 *)run->mmio.data); 669 SET_RD(insn, &vcpu->arch.guest_context, 670 (long)((ulong)data32 << shift) >> shift); 671 break; 672 case 8: 673 data64 = *((u64 *)run->mmio.data); 674 SET_RD(insn, &vcpu->arch.guest_context, 675 (long)((ulong)data64 << shift) >> shift); 676 break; 677 default: 678 return -EOPNOTSUPP; 679 } 680 681 done: 682 /* Move to next instruction */ 683 vcpu->arch.guest_context.sepc += vcpu->arch.mmio_decode.insn_len; 684 685 return 0; 686 } 687