1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * SBI initialilization and all extension implementation. 4 * 5 * Copyright (c) 2020 Western Digital Corporation or its affiliates. 6 */ 7 8 #include <linux/init.h> 9 #include <linux/pm.h> 10 #include <linux/reboot.h> 11 #include <asm/sbi.h> 12 #include <asm/smp.h> 13 14 /* default SBI version is 0.1 */ 15 unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT; 16 EXPORT_SYMBOL(sbi_spec_version); 17 18 static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init; 19 static int (*__sbi_send_ipi)(const unsigned long *hart_mask) __ro_after_init; 20 static int (*__sbi_rfence)(int fid, const unsigned long *hart_mask, 21 unsigned long start, unsigned long size, 22 unsigned long arg4, unsigned long arg5) __ro_after_init; 23 24 struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0, 25 unsigned long arg1, unsigned long arg2, 26 unsigned long arg3, unsigned long arg4, 27 unsigned long arg5) 28 { 29 struct sbiret ret; 30 31 register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); 32 register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); 33 register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); 34 register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); 35 register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4); 36 register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5); 37 register uintptr_t a6 asm ("a6") = (uintptr_t)(fid); 38 register uintptr_t a7 asm ("a7") = (uintptr_t)(ext); 39 asm volatile ("ecall" 40 : "+r" (a0), "+r" (a1) 41 : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) 42 : "memory"); 43 ret.error = a0; 44 ret.value = a1; 45 46 return ret; 47 } 48 EXPORT_SYMBOL(sbi_ecall); 49 50 int sbi_err_map_linux_errno(int err) 51 { 52 switch (err) { 53 case SBI_SUCCESS: 54 return 0; 55 case SBI_ERR_DENIED: 56 return -EPERM; 57 case SBI_ERR_INVALID_PARAM: 58 return -EINVAL; 59 case SBI_ERR_INVALID_ADDRESS: 60 return -EFAULT; 61 case SBI_ERR_NOT_SUPPORTED: 62 case SBI_ERR_FAILURE: 63 default: 64 return -ENOTSUPP; 65 }; 66 } 67 EXPORT_SYMBOL(sbi_err_map_linux_errno); 68 69 #ifdef CONFIG_RISCV_SBI_V01 70 /** 71 * sbi_console_putchar() - Writes given character to the console device. 72 * @ch: The data to be written to the console. 73 * 74 * Return: None 75 */ 76 void sbi_console_putchar(int ch) 77 { 78 sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0); 79 } 80 EXPORT_SYMBOL(sbi_console_putchar); 81 82 /** 83 * sbi_console_getchar() - Reads a byte from console device. 84 * 85 * Returns the value read from console. 86 */ 87 int sbi_console_getchar(void) 88 { 89 struct sbiret ret; 90 91 ret = sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR, 0, 0, 0, 0, 0, 0, 0); 92 93 return ret.error; 94 } 95 EXPORT_SYMBOL(sbi_console_getchar); 96 97 /** 98 * sbi_shutdown() - Remove all the harts from executing supervisor code. 99 * 100 * Return: None 101 */ 102 void sbi_shutdown(void) 103 { 104 sbi_ecall(SBI_EXT_0_1_SHUTDOWN, 0, 0, 0, 0, 0, 0, 0); 105 } 106 EXPORT_SYMBOL(sbi_shutdown); 107 108 /** 109 * sbi_clear_ipi() - Clear any pending IPIs for the calling hart. 110 * 111 * Return: None 112 */ 113 void sbi_clear_ipi(void) 114 { 115 sbi_ecall(SBI_EXT_0_1_CLEAR_IPI, 0, 0, 0, 0, 0, 0, 0); 116 } 117 EXPORT_SYMBOL(sbi_clear_ipi); 118 119 /** 120 * __sbi_set_timer_v01() - Program the timer for next timer event. 121 * @stime_value: The value after which next timer event should fire. 122 * 123 * Return: None 124 */ 125 static void __sbi_set_timer_v01(uint64_t stime_value) 126 { 127 #if __riscv_xlen == 32 128 sbi_ecall(SBI_EXT_0_1_SET_TIMER, 0, stime_value, 129 stime_value >> 32, 0, 0, 0, 0); 130 #else 131 sbi_ecall(SBI_EXT_0_1_SET_TIMER, 0, stime_value, 0, 0, 0, 0, 0); 132 #endif 133 } 134 135 static int __sbi_send_ipi_v01(const unsigned long *hart_mask) 136 { 137 sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0, (unsigned long)hart_mask, 138 0, 0, 0, 0, 0); 139 return 0; 140 } 141 142 static int __sbi_rfence_v01(int fid, const unsigned long *hart_mask, 143 unsigned long start, unsigned long size, 144 unsigned long arg4, unsigned long arg5) 145 { 146 int result = 0; 147 148 /* v0.2 function IDs are equivalent to v0.1 extension IDs */ 149 switch (fid) { 150 case SBI_EXT_RFENCE_REMOTE_FENCE_I: 151 sbi_ecall(SBI_EXT_0_1_REMOTE_FENCE_I, 0, 152 (unsigned long)hart_mask, 0, 0, 0, 0, 0); 153 break; 154 case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: 155 sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA, 0, 156 (unsigned long)hart_mask, start, size, 157 0, 0, 0); 158 break; 159 case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: 160 sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, 0, 161 (unsigned long)hart_mask, start, size, 162 arg4, 0, 0); 163 break; 164 default: 165 pr_err("SBI call [%d]not supported in SBI v0.1\n", fid); 166 result = -EINVAL; 167 } 168 169 return result; 170 } 171 172 static void sbi_set_power_off(void) 173 { 174 pm_power_off = sbi_shutdown; 175 } 176 #else 177 static void __sbi_set_timer_v01(uint64_t stime_value) 178 { 179 pr_warn("Timer extension is not available in SBI v%lu.%lu\n", 180 sbi_major_version(), sbi_minor_version()); 181 } 182 183 static int __sbi_send_ipi_v01(const unsigned long *hart_mask) 184 { 185 pr_warn("IPI extension is not available in SBI v%lu.%lu\n", 186 sbi_major_version(), sbi_minor_version()); 187 188 return 0; 189 } 190 191 static int __sbi_rfence_v01(int fid, const unsigned long *hart_mask, 192 unsigned long start, unsigned long size, 193 unsigned long arg4, unsigned long arg5) 194 { 195 pr_warn("remote fence extension is not available in SBI v%lu.%lu\n", 196 sbi_major_version(), sbi_minor_version()); 197 198 return 0; 199 } 200 201 static void sbi_set_power_off(void) {} 202 #endif /* CONFIG_RISCV_SBI_V01 */ 203 204 static void __sbi_set_timer_v02(uint64_t stime_value) 205 { 206 #if __riscv_xlen == 32 207 sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 208 stime_value >> 32, 0, 0, 0, 0); 209 #else 210 sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0, 211 0, 0, 0, 0); 212 #endif 213 } 214 215 static int __sbi_send_ipi_v02(const unsigned long *hart_mask) 216 { 217 unsigned long hartid, hmask_val, hbase; 218 struct cpumask tmask; 219 struct sbiret ret = {0}; 220 int result; 221 222 if (!hart_mask || !(*hart_mask)) { 223 riscv_cpuid_to_hartid_mask(cpu_online_mask, &tmask); 224 hart_mask = cpumask_bits(&tmask); 225 } 226 227 hmask_val = 0; 228 hbase = 0; 229 for_each_set_bit(hartid, hart_mask, NR_CPUS) { 230 if (hmask_val && ((hbase + BITS_PER_LONG) <= hartid)) { 231 ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI, 232 hmask_val, hbase, 0, 0, 0, 0); 233 if (ret.error) 234 goto ecall_failed; 235 hmask_val = 0; 236 hbase = 0; 237 } 238 if (!hmask_val) 239 hbase = hartid; 240 hmask_val |= 1UL << (hartid - hbase); 241 } 242 243 if (hmask_val) { 244 ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI, 245 hmask_val, hbase, 0, 0, 0, 0); 246 if (ret.error) 247 goto ecall_failed; 248 } 249 250 return 0; 251 252 ecall_failed: 253 result = sbi_err_map_linux_errno(ret.error); 254 pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n", 255 __func__, hbase, hmask_val, result); 256 return result; 257 } 258 259 static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask_val, 260 unsigned long hbase, unsigned long start, 261 unsigned long size, unsigned long arg4, 262 unsigned long arg5) 263 { 264 struct sbiret ret = {0}; 265 int ext = SBI_EXT_RFENCE; 266 int result = 0; 267 268 switch (fid) { 269 case SBI_EXT_RFENCE_REMOTE_FENCE_I: 270 ret = sbi_ecall(ext, fid, hmask_val, hbase, 0, 0, 0, 0); 271 break; 272 case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: 273 ret = sbi_ecall(ext, fid, hmask_val, hbase, start, 274 size, 0, 0); 275 break; 276 case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: 277 ret = sbi_ecall(ext, fid, hmask_val, hbase, start, 278 size, arg4, 0); 279 break; 280 281 case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA: 282 ret = sbi_ecall(ext, fid, hmask_val, hbase, start, 283 size, 0, 0); 284 break; 285 case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID: 286 ret = sbi_ecall(ext, fid, hmask_val, hbase, start, 287 size, arg4, 0); 288 break; 289 case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA: 290 ret = sbi_ecall(ext, fid, hmask_val, hbase, start, 291 size, 0, 0); 292 break; 293 case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID: 294 ret = sbi_ecall(ext, fid, hmask_val, hbase, start, 295 size, arg4, 0); 296 break; 297 default: 298 pr_err("unknown function ID [%lu] for SBI extension [%d]\n", 299 fid, ext); 300 result = -EINVAL; 301 } 302 303 if (ret.error) { 304 result = sbi_err_map_linux_errno(ret.error); 305 pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n", 306 __func__, hbase, hmask_val, result); 307 } 308 309 return result; 310 } 311 312 static int __sbi_rfence_v02(int fid, const unsigned long *hart_mask, 313 unsigned long start, unsigned long size, 314 unsigned long arg4, unsigned long arg5) 315 { 316 unsigned long hmask_val, hartid, hbase; 317 struct cpumask tmask; 318 int result; 319 320 if (!hart_mask || !(*hart_mask)) { 321 riscv_cpuid_to_hartid_mask(cpu_online_mask, &tmask); 322 hart_mask = cpumask_bits(&tmask); 323 } 324 325 hmask_val = 0; 326 hbase = 0; 327 for_each_set_bit(hartid, hart_mask, NR_CPUS) { 328 if (hmask_val && ((hbase + BITS_PER_LONG) <= hartid)) { 329 result = __sbi_rfence_v02_call(fid, hmask_val, hbase, 330 start, size, arg4, arg5); 331 if (result) 332 return result; 333 hmask_val = 0; 334 hbase = 0; 335 } 336 if (!hmask_val) 337 hbase = hartid; 338 hmask_val |= 1UL << (hartid - hbase); 339 } 340 341 if (hmask_val) { 342 result = __sbi_rfence_v02_call(fid, hmask_val, hbase, 343 start, size, arg4, arg5); 344 if (result) 345 return result; 346 } 347 348 return 0; 349 } 350 351 /** 352 * sbi_set_timer() - Program the timer for next timer event. 353 * @stime_value: The value after which next timer event should fire. 354 * 355 * Return: None. 356 */ 357 void sbi_set_timer(uint64_t stime_value) 358 { 359 __sbi_set_timer(stime_value); 360 } 361 362 /** 363 * sbi_send_ipi() - Send an IPI to any hart. 364 * @hart_mask: A cpu mask containing all the target harts. 365 * 366 * Return: 0 on success, appropriate linux error code otherwise. 367 */ 368 int sbi_send_ipi(const unsigned long *hart_mask) 369 { 370 return __sbi_send_ipi(hart_mask); 371 } 372 EXPORT_SYMBOL(sbi_send_ipi); 373 374 /** 375 * sbi_remote_fence_i() - Execute FENCE.I instruction on given remote harts. 376 * @hart_mask: A cpu mask containing all the target harts. 377 * 378 * Return: 0 on success, appropriate linux error code otherwise. 379 */ 380 int sbi_remote_fence_i(const unsigned long *hart_mask) 381 { 382 return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_FENCE_I, 383 hart_mask, 0, 0, 0, 0); 384 } 385 EXPORT_SYMBOL(sbi_remote_fence_i); 386 387 /** 388 * sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote 389 * harts for the specified virtual address range. 390 * @hart_mask: A cpu mask containing all the target harts. 391 * @start: Start of the virtual address 392 * @size: Total size of the virtual address range. 393 * 394 * Return: 0 on success, appropriate linux error code otherwise. 395 */ 396 int sbi_remote_sfence_vma(const unsigned long *hart_mask, 397 unsigned long start, 398 unsigned long size) 399 { 400 return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, 401 hart_mask, start, size, 0, 0); 402 } 403 EXPORT_SYMBOL(sbi_remote_sfence_vma); 404 405 /** 406 * sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given 407 * remote harts for a virtual address range belonging to a specific ASID. 408 * 409 * @hart_mask: A cpu mask containing all the target harts. 410 * @start: Start of the virtual address 411 * @size: Total size of the virtual address range. 412 * @asid: The value of address space identifier (ASID). 413 * 414 * Return: 0 on success, appropriate linux error code otherwise. 415 */ 416 int sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, 417 unsigned long start, 418 unsigned long size, 419 unsigned long asid) 420 { 421 return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, 422 hart_mask, start, size, asid, 0); 423 } 424 EXPORT_SYMBOL(sbi_remote_sfence_vma_asid); 425 426 /** 427 * sbi_remote_hfence_gvma() - Execute HFENCE.GVMA instructions on given remote 428 * harts for the specified guest physical address range. 429 * @hart_mask: A cpu mask containing all the target harts. 430 * @start: Start of the guest physical address 431 * @size: Total size of the guest physical address range. 432 * 433 * Return: None 434 */ 435 int sbi_remote_hfence_gvma(const unsigned long *hart_mask, 436 unsigned long start, 437 unsigned long size) 438 { 439 return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA, 440 hart_mask, start, size, 0, 0); 441 } 442 EXPORT_SYMBOL_GPL(sbi_remote_hfence_gvma); 443 444 /** 445 * sbi_remote_hfence_gvma_vmid() - Execute HFENCE.GVMA instructions on given 446 * remote harts for a guest physical address range belonging to a specific VMID. 447 * 448 * @hart_mask: A cpu mask containing all the target harts. 449 * @start: Start of the guest physical address 450 * @size: Total size of the guest physical address range. 451 * @vmid: The value of guest ID (VMID). 452 * 453 * Return: 0 if success, Error otherwise. 454 */ 455 int sbi_remote_hfence_gvma_vmid(const unsigned long *hart_mask, 456 unsigned long start, 457 unsigned long size, 458 unsigned long vmid) 459 { 460 return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID, 461 hart_mask, start, size, vmid, 0); 462 } 463 EXPORT_SYMBOL(sbi_remote_hfence_gvma_vmid); 464 465 /** 466 * sbi_remote_hfence_vvma() - Execute HFENCE.VVMA instructions on given remote 467 * harts for the current guest virtual address range. 468 * @hart_mask: A cpu mask containing all the target harts. 469 * @start: Start of the current guest virtual address 470 * @size: Total size of the current guest virtual address range. 471 * 472 * Return: None 473 */ 474 int sbi_remote_hfence_vvma(const unsigned long *hart_mask, 475 unsigned long start, 476 unsigned long size) 477 { 478 return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA, 479 hart_mask, start, size, 0, 0); 480 } 481 EXPORT_SYMBOL(sbi_remote_hfence_vvma); 482 483 /** 484 * sbi_remote_hfence_vvma_asid() - Execute HFENCE.VVMA instructions on given 485 * remote harts for current guest virtual address range belonging to a specific 486 * ASID. 487 * 488 * @hart_mask: A cpu mask containing all the target harts. 489 * @start: Start of the current guest virtual address 490 * @size: Total size of the current guest virtual address range. 491 * @asid: The value of address space identifier (ASID). 492 * 493 * Return: None 494 */ 495 int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask, 496 unsigned long start, 497 unsigned long size, 498 unsigned long asid) 499 { 500 return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID, 501 hart_mask, start, size, asid, 0); 502 } 503 EXPORT_SYMBOL(sbi_remote_hfence_vvma_asid); 504 505 static void sbi_srst_reset(unsigned long type, unsigned long reason) 506 { 507 sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason, 508 0, 0, 0, 0); 509 pr_warn("%s: type=0x%lx reason=0x%lx failed\n", 510 __func__, type, reason); 511 } 512 513 static int sbi_srst_reboot(struct notifier_block *this, 514 unsigned long mode, void *cmd) 515 { 516 sbi_srst_reset((mode == REBOOT_WARM || mode == REBOOT_SOFT) ? 517 SBI_SRST_RESET_TYPE_WARM_REBOOT : 518 SBI_SRST_RESET_TYPE_COLD_REBOOT, 519 SBI_SRST_RESET_REASON_NONE); 520 return NOTIFY_DONE; 521 } 522 523 static struct notifier_block sbi_srst_reboot_nb; 524 525 static void sbi_srst_power_off(void) 526 { 527 sbi_srst_reset(SBI_SRST_RESET_TYPE_SHUTDOWN, 528 SBI_SRST_RESET_REASON_NONE); 529 } 530 531 /** 532 * sbi_probe_extension() - Check if an SBI extension ID is supported or not. 533 * @extid: The extension ID to be probed. 534 * 535 * Return: Extension specific nonzero value f yes, -ENOTSUPP otherwise. 536 */ 537 int sbi_probe_extension(int extid) 538 { 539 struct sbiret ret; 540 541 ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid, 542 0, 0, 0, 0, 0); 543 if (!ret.error) 544 if (ret.value) 545 return ret.value; 546 547 return -ENOTSUPP; 548 } 549 EXPORT_SYMBOL(sbi_probe_extension); 550 551 static long __sbi_base_ecall(int fid) 552 { 553 struct sbiret ret; 554 555 ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0); 556 if (!ret.error) 557 return ret.value; 558 else 559 return sbi_err_map_linux_errno(ret.error); 560 } 561 562 static inline long sbi_get_spec_version(void) 563 { 564 return __sbi_base_ecall(SBI_EXT_BASE_GET_SPEC_VERSION); 565 } 566 567 static inline long sbi_get_firmware_id(void) 568 { 569 return __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_ID); 570 } 571 572 static inline long sbi_get_firmware_version(void) 573 { 574 return __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_VERSION); 575 } 576 577 long sbi_get_mvendorid(void) 578 { 579 return __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID); 580 } 581 582 long sbi_get_marchid(void) 583 { 584 return __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID); 585 } 586 587 long sbi_get_mimpid(void) 588 { 589 return __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID); 590 } 591 592 static void sbi_send_cpumask_ipi(const struct cpumask *target) 593 { 594 struct cpumask hartid_mask; 595 596 riscv_cpuid_to_hartid_mask(target, &hartid_mask); 597 598 sbi_send_ipi(cpumask_bits(&hartid_mask)); 599 } 600 601 static const struct riscv_ipi_ops sbi_ipi_ops = { 602 .ipi_inject = sbi_send_cpumask_ipi 603 }; 604 605 void __init sbi_init(void) 606 { 607 int ret; 608 609 sbi_set_power_off(); 610 ret = sbi_get_spec_version(); 611 if (ret > 0) 612 sbi_spec_version = ret; 613 614 pr_info("SBI specification v%lu.%lu detected\n", 615 sbi_major_version(), sbi_minor_version()); 616 617 if (!sbi_spec_is_0_1()) { 618 pr_info("SBI implementation ID=0x%lx Version=0x%lx\n", 619 sbi_get_firmware_id(), sbi_get_firmware_version()); 620 if (sbi_probe_extension(SBI_EXT_TIME) > 0) { 621 __sbi_set_timer = __sbi_set_timer_v02; 622 pr_info("SBI TIME extension detected\n"); 623 } else { 624 __sbi_set_timer = __sbi_set_timer_v01; 625 } 626 if (sbi_probe_extension(SBI_EXT_IPI) > 0) { 627 __sbi_send_ipi = __sbi_send_ipi_v02; 628 pr_info("SBI IPI extension detected\n"); 629 } else { 630 __sbi_send_ipi = __sbi_send_ipi_v01; 631 } 632 if (sbi_probe_extension(SBI_EXT_RFENCE) > 0) { 633 __sbi_rfence = __sbi_rfence_v02; 634 pr_info("SBI RFENCE extension detected\n"); 635 } else { 636 __sbi_rfence = __sbi_rfence_v01; 637 } 638 if ((sbi_spec_version >= sbi_mk_version(0, 3)) && 639 (sbi_probe_extension(SBI_EXT_SRST) > 0)) { 640 pr_info("SBI SRST extension detected\n"); 641 pm_power_off = sbi_srst_power_off; 642 sbi_srst_reboot_nb.notifier_call = sbi_srst_reboot; 643 sbi_srst_reboot_nb.priority = 192; 644 register_restart_handler(&sbi_srst_reboot_nb); 645 } 646 } else { 647 __sbi_set_timer = __sbi_set_timer_v01; 648 __sbi_send_ipi = __sbi_send_ipi_v01; 649 __sbi_rfence = __sbi_rfence_v01; 650 } 651 652 riscv_set_ipi_ops(&sbi_ipi_ops); 653 } 654