1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Western Digital Corporation or its affiliates. 4 * 5 * Authors: 6 * Atish Patra <atish.patra@wdc.com> 7 */ 8 9 #include <linux/errno.h> 10 #include <linux/err.h> 11 #include <linux/kvm_host.h> 12 #include <asm/sbi.h> 13 #include <asm/kvm_vcpu_sbi.h> 14 15 #ifndef CONFIG_RISCV_SBI_V01 16 static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01 = { 17 .extid_start = -1UL, 18 .extid_end = -1UL, 19 .handler = NULL, 20 }; 21 #endif 22 23 #ifndef CONFIG_RISCV_PMU_SBI 24 static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_pmu = { 25 .extid_start = -1UL, 26 .extid_end = -1UL, 27 .handler = NULL, 28 }; 29 #endif 30 31 struct kvm_riscv_sbi_extension_entry { 32 enum KVM_RISCV_SBI_EXT_ID ext_idx; 33 const struct kvm_vcpu_sbi_extension *ext_ptr; 34 }; 35 36 static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = { 37 { 38 .ext_idx = KVM_RISCV_SBI_EXT_V01, 39 .ext_ptr = &vcpu_sbi_ext_v01, 40 }, 41 { 42 .ext_idx = KVM_RISCV_SBI_EXT_MAX, /* Can't be disabled */ 43 .ext_ptr = &vcpu_sbi_ext_base, 44 }, 45 { 46 .ext_idx = KVM_RISCV_SBI_EXT_TIME, 47 .ext_ptr = &vcpu_sbi_ext_time, 48 }, 49 { 50 .ext_idx = KVM_RISCV_SBI_EXT_IPI, 51 .ext_ptr = &vcpu_sbi_ext_ipi, 52 }, 53 { 54 .ext_idx = KVM_RISCV_SBI_EXT_RFENCE, 55 .ext_ptr = &vcpu_sbi_ext_rfence, 56 }, 57 { 58 .ext_idx = KVM_RISCV_SBI_EXT_SRST, 59 .ext_ptr = &vcpu_sbi_ext_srst, 60 }, 61 { 62 .ext_idx = KVM_RISCV_SBI_EXT_HSM, 63 .ext_ptr = &vcpu_sbi_ext_hsm, 64 }, 65 { 66 .ext_idx = KVM_RISCV_SBI_EXT_PMU, 67 .ext_ptr = &vcpu_sbi_ext_pmu, 68 }, 69 { 70 .ext_idx = KVM_RISCV_SBI_EXT_DBCN, 71 .ext_ptr = &vcpu_sbi_ext_dbcn, 72 }, 73 { 74 .ext_idx = KVM_RISCV_SBI_EXT_SUSP, 75 .ext_ptr = &vcpu_sbi_ext_susp, 76 }, 77 { 78 .ext_idx = KVM_RISCV_SBI_EXT_STA, 79 .ext_ptr = &vcpu_sbi_ext_sta, 80 }, 81 { 82 .ext_idx = KVM_RISCV_SBI_EXT_FWFT, 83 .ext_ptr = &vcpu_sbi_ext_fwft, 84 }, 85 { 86 .ext_idx = KVM_RISCV_SBI_EXT_MPXY, 87 .ext_ptr = &vcpu_sbi_ext_mpxy, 88 }, 89 { 90 .ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL, 91 .ext_ptr = &vcpu_sbi_ext_experimental, 92 }, 93 { 94 .ext_idx = KVM_RISCV_SBI_EXT_VENDOR, 95 .ext_ptr = &vcpu_sbi_ext_vendor, 96 }, 97 }; 98 99 static const struct kvm_riscv_sbi_extension_entry * 100 riscv_vcpu_get_sbi_ext(struct kvm_vcpu *vcpu, unsigned long idx) 101 { 102 const struct kvm_riscv_sbi_extension_entry *sext = NULL; 103 104 if (idx >= KVM_RISCV_SBI_EXT_MAX) 105 return NULL; 106 107 for (int i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 108 if (sbi_ext[i].ext_idx == idx) { 109 sext = &sbi_ext[i]; 110 break; 111 } 112 } 113 114 return sext; 115 } 116 117 static bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx) 118 { 119 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 120 const struct kvm_riscv_sbi_extension_entry *sext; 121 122 sext = riscv_vcpu_get_sbi_ext(vcpu, idx); 123 124 return sext && scontext->ext_status[sext->ext_idx] != KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE; 125 } 126 127 int kvm_riscv_vcpu_sbi_forward_handler(struct kvm_vcpu *vcpu, 128 struct kvm_run *run, 129 struct kvm_vcpu_sbi_return *retdata) 130 { 131 struct kvm_cpu_context *cp = &vcpu->arch.guest_context; 132 133 vcpu->arch.sbi_context.return_handled = 0; 134 vcpu->stat.ecall_exit_stat++; 135 run->exit_reason = KVM_EXIT_RISCV_SBI; 136 run->riscv_sbi.extension_id = cp->a7; 137 run->riscv_sbi.function_id = cp->a6; 138 run->riscv_sbi.args[0] = cp->a0; 139 run->riscv_sbi.args[1] = cp->a1; 140 run->riscv_sbi.args[2] = cp->a2; 141 run->riscv_sbi.args[3] = cp->a3; 142 run->riscv_sbi.args[4] = cp->a4; 143 run->riscv_sbi.args[5] = cp->a5; 144 run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED; 145 run->riscv_sbi.ret[1] = 0; 146 retdata->uexit = true; 147 return 0; 148 } 149 150 void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu, 151 struct kvm_run *run, 152 u32 type, u64 reason) 153 { 154 unsigned long i; 155 struct kvm_vcpu *tmp; 156 157 kvm_for_each_vcpu(i, tmp, vcpu->kvm) { 158 spin_lock(&tmp->arch.mp_state_lock); 159 WRITE_ONCE(tmp->arch.mp_state.mp_state, KVM_MP_STATE_STOPPED); 160 spin_unlock(&tmp->arch.mp_state_lock); 161 } 162 kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP); 163 164 memset(&run->system_event, 0, sizeof(run->system_event)); 165 run->system_event.type = type; 166 run->system_event.ndata = 1; 167 run->system_event.data[0] = reason; 168 run->exit_reason = KVM_EXIT_SYSTEM_EVENT; 169 } 170 171 void kvm_riscv_vcpu_sbi_request_reset(struct kvm_vcpu *vcpu, 172 unsigned long pc, unsigned long a1) 173 { 174 spin_lock(&vcpu->arch.reset_state.lock); 175 vcpu->arch.reset_state.pc = pc; 176 vcpu->arch.reset_state.a1 = a1; 177 spin_unlock(&vcpu->arch.reset_state.lock); 178 179 kvm_make_request(KVM_REQ_VCPU_RESET, vcpu); 180 } 181 182 void kvm_riscv_vcpu_sbi_load_reset_state(struct kvm_vcpu *vcpu) 183 { 184 struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; 185 struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; 186 struct kvm_vcpu_reset_state *reset_state = &vcpu->arch.reset_state; 187 188 cntx->a0 = vcpu->vcpu_id; 189 190 spin_lock(&vcpu->arch.reset_state.lock); 191 cntx->sepc = reset_state->pc; 192 cntx->a1 = reset_state->a1; 193 spin_unlock(&vcpu->arch.reset_state.lock); 194 195 cntx->sstatus &= ~SR_SIE; 196 csr->vsatp = 0; 197 } 198 199 int kvm_riscv_vcpu_sbi_return(struct kvm_vcpu *vcpu, struct kvm_run *run) 200 { 201 struct kvm_cpu_context *cp = &vcpu->arch.guest_context; 202 203 /* Handle SBI return only once */ 204 if (vcpu->arch.sbi_context.return_handled) 205 return 0; 206 vcpu->arch.sbi_context.return_handled = 1; 207 208 /* Update return values */ 209 cp->a0 = run->riscv_sbi.ret[0]; 210 cp->a1 = run->riscv_sbi.ret[1]; 211 212 /* Move to next instruction */ 213 vcpu->arch.guest_context.sepc += 4; 214 215 return 0; 216 } 217 218 static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu, 219 unsigned long reg_num, 220 unsigned long reg_val) 221 { 222 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 223 const struct kvm_riscv_sbi_extension_entry *sext; 224 const struct kvm_vcpu_sbi_extension *ext; 225 226 if (reg_val != 1 && reg_val != 0) 227 return -EINVAL; 228 229 sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num); 230 if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE) 231 return -ENOENT; 232 233 ext = sext->ext_ptr; 234 235 if (!reg_val && scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_ENABLED && 236 ext->reset) 237 ext->reset(vcpu); 238 239 scontext->ext_status[sext->ext_idx] = (reg_val) ? 240 KVM_RISCV_SBI_EXT_STATUS_ENABLED : 241 KVM_RISCV_SBI_EXT_STATUS_DISABLED; 242 243 return 0; 244 } 245 246 static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu, 247 unsigned long reg_num, 248 unsigned long *reg_val) 249 { 250 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 251 const struct kvm_riscv_sbi_extension_entry *sext; 252 253 sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num); 254 if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE) 255 return -ENOENT; 256 257 *reg_val = scontext->ext_status[sext->ext_idx] == 258 KVM_RISCV_SBI_EXT_STATUS_ENABLED; 259 260 return 0; 261 } 262 263 static int riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu *vcpu, 264 unsigned long reg_num, 265 unsigned long reg_val, bool enable) 266 { 267 unsigned long i, ext_id; 268 269 if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST) 270 return -ENOENT; 271 272 for_each_set_bit(i, ®_val, BITS_PER_LONG) { 273 ext_id = i + reg_num * BITS_PER_LONG; 274 if (ext_id >= KVM_RISCV_SBI_EXT_MAX) 275 break; 276 277 riscv_vcpu_set_sbi_ext_single(vcpu, ext_id, enable); 278 } 279 280 return 0; 281 } 282 283 static int riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu *vcpu, 284 unsigned long reg_num, 285 unsigned long *reg_val) 286 { 287 unsigned long i, ext_id, ext_val; 288 289 if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST) 290 return -ENOENT; 291 292 for (i = 0; i < BITS_PER_LONG; i++) { 293 ext_id = i + reg_num * BITS_PER_LONG; 294 if (ext_id >= KVM_RISCV_SBI_EXT_MAX) 295 break; 296 297 ext_val = 0; 298 riscv_vcpu_get_sbi_ext_single(vcpu, ext_id, &ext_val); 299 if (ext_val) 300 *reg_val |= KVM_REG_RISCV_SBI_MULTI_MASK(ext_id); 301 } 302 303 return 0; 304 } 305 306 int kvm_riscv_vcpu_reg_indices_sbi_ext(struct kvm_vcpu *vcpu, u64 __user *uindices) 307 { 308 unsigned int n = 0; 309 310 for (int i = 0; i < KVM_RISCV_SBI_EXT_MAX; i++) { 311 u64 size = IS_ENABLED(CONFIG_32BIT) ? 312 KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64; 313 u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_SBI_EXT | 314 KVM_REG_RISCV_SBI_SINGLE | i; 315 316 if (!riscv_vcpu_supports_sbi_ext(vcpu, i)) 317 continue; 318 319 if (uindices) { 320 if (put_user(reg, uindices)) 321 return -EFAULT; 322 uindices++; 323 } 324 325 n++; 326 } 327 328 return n; 329 } 330 331 int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu, 332 const struct kvm_one_reg *reg) 333 { 334 unsigned long __user *uaddr = 335 (unsigned long __user *)(unsigned long)reg->addr; 336 unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 337 KVM_REG_SIZE_MASK | 338 KVM_REG_RISCV_SBI_EXT); 339 unsigned long reg_val, reg_subtype; 340 341 if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 342 return -EINVAL; 343 344 if (vcpu->arch.ran_atleast_once) 345 return -EBUSY; 346 347 reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK; 348 reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK; 349 350 if (copy_from_user(®_val, uaddr, KVM_REG_SIZE(reg->id))) 351 return -EFAULT; 352 353 switch (reg_subtype) { 354 case KVM_REG_RISCV_SBI_SINGLE: 355 return riscv_vcpu_set_sbi_ext_single(vcpu, reg_num, reg_val); 356 case KVM_REG_RISCV_SBI_MULTI_EN: 357 return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, true); 358 case KVM_REG_RISCV_SBI_MULTI_DIS: 359 return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, false); 360 default: 361 return -ENOENT; 362 } 363 364 return 0; 365 } 366 367 int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu, 368 const struct kvm_one_reg *reg) 369 { 370 int rc; 371 unsigned long __user *uaddr = 372 (unsigned long __user *)(unsigned long)reg->addr; 373 unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 374 KVM_REG_SIZE_MASK | 375 KVM_REG_RISCV_SBI_EXT); 376 unsigned long reg_val, reg_subtype; 377 378 if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) 379 return -EINVAL; 380 381 reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK; 382 reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK; 383 384 reg_val = 0; 385 switch (reg_subtype) { 386 case KVM_REG_RISCV_SBI_SINGLE: 387 rc = riscv_vcpu_get_sbi_ext_single(vcpu, reg_num, ®_val); 388 break; 389 case KVM_REG_RISCV_SBI_MULTI_EN: 390 case KVM_REG_RISCV_SBI_MULTI_DIS: 391 rc = riscv_vcpu_get_sbi_ext_multi(vcpu, reg_num, ®_val); 392 if (!rc && reg_subtype == KVM_REG_RISCV_SBI_MULTI_DIS) 393 reg_val = ~reg_val; 394 break; 395 default: 396 rc = -ENOENT; 397 } 398 if (rc) 399 return rc; 400 401 if (copy_to_user(uaddr, ®_val, KVM_REG_SIZE(reg->id))) 402 return -EFAULT; 403 404 return 0; 405 } 406 407 int kvm_riscv_vcpu_reg_indices_sbi(struct kvm_vcpu *vcpu, u64 __user *uindices) 408 { 409 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 410 const struct kvm_riscv_sbi_extension_entry *entry; 411 const struct kvm_vcpu_sbi_extension *ext; 412 unsigned long state_reg_count; 413 int i, j, rc, count = 0; 414 u64 reg; 415 416 for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 417 entry = &sbi_ext[i]; 418 ext = entry->ext_ptr; 419 420 if (!ext->get_state_reg_count || 421 scontext->ext_status[entry->ext_idx] != KVM_RISCV_SBI_EXT_STATUS_ENABLED) 422 continue; 423 424 state_reg_count = ext->get_state_reg_count(vcpu); 425 if (!uindices) 426 goto skip_put_user; 427 428 for (j = 0; j < state_reg_count; j++) { 429 if (ext->get_state_reg_id) { 430 rc = ext->get_state_reg_id(vcpu, j, ®); 431 if (rc) 432 return rc; 433 } else { 434 reg = KVM_REG_RISCV | 435 (IS_ENABLED(CONFIG_32BIT) ? 436 KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64) | 437 KVM_REG_RISCV_SBI_STATE | 438 ext->state_reg_subtype | j; 439 } 440 441 if (put_user(reg, uindices)) 442 return -EFAULT; 443 uindices++; 444 } 445 446 skip_put_user: 447 count += state_reg_count; 448 } 449 450 return count; 451 } 452 453 static const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext_withstate(struct kvm_vcpu *vcpu, 454 unsigned long subtype) 455 { 456 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 457 const struct kvm_riscv_sbi_extension_entry *entry; 458 const struct kvm_vcpu_sbi_extension *ext; 459 int i; 460 461 for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 462 entry = &sbi_ext[i]; 463 ext = entry->ext_ptr; 464 465 if (ext->get_state_reg_count && 466 ext->state_reg_subtype == subtype && 467 scontext->ext_status[entry->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_ENABLED) 468 return ext; 469 } 470 471 return NULL; 472 } 473 474 int kvm_riscv_vcpu_set_reg_sbi(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 475 { 476 unsigned long __user *uaddr = 477 (unsigned long __user *)(unsigned long)reg->addr; 478 unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 479 KVM_REG_SIZE_MASK | 480 KVM_REG_RISCV_SBI_STATE); 481 const struct kvm_vcpu_sbi_extension *ext; 482 unsigned long reg_subtype; 483 void *reg_val; 484 u64 data64; 485 u32 data32; 486 u16 data16; 487 u8 data8; 488 489 switch (KVM_REG_SIZE(reg->id)) { 490 case 1: 491 reg_val = &data8; 492 break; 493 case 2: 494 reg_val = &data16; 495 break; 496 case 4: 497 reg_val = &data32; 498 break; 499 case 8: 500 reg_val = &data64; 501 break; 502 default: 503 return -EINVAL; 504 } 505 506 if (copy_from_user(reg_val, uaddr, KVM_REG_SIZE(reg->id))) 507 return -EFAULT; 508 509 reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK; 510 reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK; 511 512 ext = kvm_vcpu_sbi_find_ext_withstate(vcpu, reg_subtype); 513 if (!ext || !ext->set_state_reg) 514 return -EINVAL; 515 516 return ext->set_state_reg(vcpu, reg_num, KVM_REG_SIZE(reg->id), reg_val); 517 } 518 519 int kvm_riscv_vcpu_get_reg_sbi(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 520 { 521 unsigned long __user *uaddr = 522 (unsigned long __user *)(unsigned long)reg->addr; 523 unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | 524 KVM_REG_SIZE_MASK | 525 KVM_REG_RISCV_SBI_STATE); 526 const struct kvm_vcpu_sbi_extension *ext; 527 unsigned long reg_subtype; 528 void *reg_val; 529 u64 data64; 530 u32 data32; 531 u16 data16; 532 u8 data8; 533 int ret; 534 535 switch (KVM_REG_SIZE(reg->id)) { 536 case 1: 537 reg_val = &data8; 538 break; 539 case 2: 540 reg_val = &data16; 541 break; 542 case 4: 543 reg_val = &data32; 544 break; 545 case 8: 546 reg_val = &data64; 547 break; 548 default: 549 return -EINVAL; 550 } 551 552 reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK; 553 reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK; 554 555 ext = kvm_vcpu_sbi_find_ext_withstate(vcpu, reg_subtype); 556 if (!ext || !ext->get_state_reg) 557 return -EINVAL; 558 559 ret = ext->get_state_reg(vcpu, reg_num, KVM_REG_SIZE(reg->id), reg_val); 560 if (ret) 561 return ret; 562 563 if (copy_to_user(uaddr, reg_val, KVM_REG_SIZE(reg->id))) 564 return -EFAULT; 565 566 return 0; 567 } 568 569 const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext( 570 struct kvm_vcpu *vcpu, unsigned long extid) 571 { 572 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 573 const struct kvm_riscv_sbi_extension_entry *entry; 574 const struct kvm_vcpu_sbi_extension *ext; 575 int i; 576 577 for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 578 entry = &sbi_ext[i]; 579 ext = entry->ext_ptr; 580 581 if (ext->extid_start <= extid && ext->extid_end >= extid) { 582 if (entry->ext_idx >= KVM_RISCV_SBI_EXT_MAX || 583 scontext->ext_status[entry->ext_idx] == 584 KVM_RISCV_SBI_EXT_STATUS_ENABLED) 585 return ext; 586 587 return NULL; 588 } 589 } 590 591 return NULL; 592 } 593 594 int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run) 595 { 596 int ret = 1; 597 bool next_sepc = true; 598 struct kvm_cpu_context *cp = &vcpu->arch.guest_context; 599 const struct kvm_vcpu_sbi_extension *sbi_ext; 600 struct kvm_cpu_trap utrap = {0}; 601 struct kvm_vcpu_sbi_return sbi_ret = { 602 .out_val = 0, 603 .err_val = 0, 604 .utrap = &utrap, 605 }; 606 bool ext_is_v01 = false; 607 608 sbi_ext = kvm_vcpu_sbi_find_ext(vcpu, cp->a7); 609 if (sbi_ext && sbi_ext->handler) { 610 #ifdef CONFIG_RISCV_SBI_V01 611 if (cp->a7 >= SBI_EXT_0_1_SET_TIMER && 612 cp->a7 <= SBI_EXT_0_1_SHUTDOWN) 613 ext_is_v01 = true; 614 #endif 615 ret = sbi_ext->handler(vcpu, run, &sbi_ret); 616 } else { 617 /* Return error for unsupported SBI calls */ 618 cp->a0 = SBI_ERR_NOT_SUPPORTED; 619 goto ecall_done; 620 } 621 622 /* 623 * When the SBI extension returns a Linux error code, it exits the ioctl 624 * loop and forwards the error to userspace. 625 */ 626 if (ret < 0) { 627 next_sepc = false; 628 goto ecall_done; 629 } 630 631 /* Handle special error cases i.e trap, exit or userspace forward */ 632 if (sbi_ret.utrap->scause) { 633 /* No need to increment sepc or exit ioctl loop */ 634 ret = 1; 635 sbi_ret.utrap->sepc = cp->sepc; 636 kvm_riscv_vcpu_trap_redirect(vcpu, sbi_ret.utrap); 637 next_sepc = false; 638 goto ecall_done; 639 } 640 641 /* Exit ioctl loop or Propagate the error code the guest */ 642 if (sbi_ret.uexit) { 643 next_sepc = false; 644 ret = 0; 645 } else { 646 cp->a0 = sbi_ret.err_val; 647 ret = 1; 648 } 649 ecall_done: 650 if (next_sepc) 651 cp->sepc += 4; 652 /* a1 should only be updated when we continue the ioctl loop */ 653 if (!ext_is_v01 && ret == 1) 654 cp->a1 = sbi_ret.out_val; 655 656 return ret; 657 } 658 659 void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu) 660 { 661 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 662 const struct kvm_riscv_sbi_extension_entry *entry; 663 const struct kvm_vcpu_sbi_extension *ext; 664 int idx, i; 665 666 for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 667 entry = &sbi_ext[i]; 668 ext = entry->ext_ptr; 669 idx = entry->ext_idx; 670 671 if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status)) 672 continue; 673 674 if (ext->probe && !ext->probe(vcpu)) { 675 scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE; 676 continue; 677 } 678 679 scontext->ext_status[idx] = ext->default_disabled ? 680 KVM_RISCV_SBI_EXT_STATUS_DISABLED : 681 KVM_RISCV_SBI_EXT_STATUS_ENABLED; 682 683 if (ext->init && ext->init(vcpu) != 0) 684 scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE; 685 } 686 } 687 688 void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu) 689 { 690 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 691 const struct kvm_riscv_sbi_extension_entry *entry; 692 const struct kvm_vcpu_sbi_extension *ext; 693 int idx, i; 694 695 for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 696 entry = &sbi_ext[i]; 697 ext = entry->ext_ptr; 698 idx = entry->ext_idx; 699 700 if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status)) 701 continue; 702 703 if (scontext->ext_status[idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE || 704 !ext->deinit) 705 continue; 706 707 ext->deinit(vcpu); 708 } 709 } 710 711 void kvm_riscv_vcpu_sbi_reset(struct kvm_vcpu *vcpu) 712 { 713 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 714 const struct kvm_riscv_sbi_extension_entry *entry; 715 const struct kvm_vcpu_sbi_extension *ext; 716 int idx, i; 717 718 for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 719 entry = &sbi_ext[i]; 720 ext = entry->ext_ptr; 721 idx = entry->ext_idx; 722 723 if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status)) 724 continue; 725 726 if (scontext->ext_status[idx] != KVM_RISCV_SBI_EXT_STATUS_ENABLED || 727 !ext->reset) 728 continue; 729 730 ext->reset(vcpu); 731 } 732 } 733 734 void kvm_riscv_vcpu_sbi_validate(struct kvm_vcpu *vcpu) 735 { 736 struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; 737 const struct kvm_riscv_sbi_extension_entry *entry; 738 const struct kvm_vcpu_sbi_extension *ext; 739 int idx, i; 740 741 for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { 742 entry = &sbi_ext[i]; 743 ext = entry->ext_ptr; 744 idx = entry->ext_idx; 745 746 if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status)) 747 continue; 748 749 if (scontext->ext_status[idx] != KVM_RISCV_SBI_EXT_STATUS_ENABLED || 750 !ext->validate) 751 continue; 752 753 ext->validate(vcpu); 754 } 755 } 756