Index: sys/riscv/include/sbi.h =================================================================== --- sys/riscv/include/sbi.h +++ sys/riscv/include/sbi.h @@ -67,6 +67,24 @@ #define SBI_BASE_GET_MARCHID 5 #define SBI_BASE_GET_MIMPID 6 +/* Timer (TIME) Extension */ +#define SBI_EXT_ID_TIME 0x54494D45 +#define SBI_TIME_SET_TIMER 0 + +/* IPI (IPI) Extension */ +#define SBI_EXT_ID_IPI 0x735049 +#define SBI_IPI_SEND_IPI 0 + +/* RFENCE (RFNC) Extension */ +#define SBI_EXT_ID_RFNC 0x52464E43 +#define SBI_RFNC_REMOTE_FENCE_I 0 +#define SBI_RFNC_REMOTE_SFENCE_VMA 1 +#define SBI_RFNC_REMOTE_SFENCE_VMA_ASID 2 +#define SBI_RFNC_REMOTE_HFENCE_GVMA_VMID 3 +#define SBI_RFNC_REMOTE_HFENCE_GVMA 4 +#define SBI_RFNC_REMOTE_HFENCE_VVMA_ASID 5 +#define SBI_RFNC_REMOTE_HFENCE_VVMA 6 + /* Hart State Management (HSM) Extension */ #define SBI_EXT_ID_HSM 0x48534D #define SBI_HSM_HART_START 0 @@ -88,11 +106,12 @@ #define SBI_REMOTE_SFENCE_VMA_ASID 7 #define SBI_SHUTDOWN 8 -#define SBI_CALL0(e, f) SBI_CALL4(e, f, 0, 0, 0, 0) -#define SBI_CALL1(e, f, p1) SBI_CALL4(e, f, p1, 0, 0, 0) -#define SBI_CALL2(e, f, p1, p2) SBI_CALL4(e, f, p1, p2, 0, 0) -#define SBI_CALL3(e, f, p1, p2, p3) SBI_CALL4(e, f, p1, p2, p3, 0) -#define SBI_CALL4(e, f, p1, p2, p3, p4) sbi_call(e, f, p1, p2, p3, p4) +#define SBI_CALL0(e, f) SBI_CALL5(e, f, 0, 0, 0, 0, 0) +#define SBI_CALL1(e, f, p1) SBI_CALL5(e, f, p1, 0, 0, 0, 0) +#define SBI_CALL2(e, f, p1, p2) SBI_CALL5(e, f, p1, p2, 0, 0, 0) +#define SBI_CALL3(e, f, p1, p2, p3) SBI_CALL5(e, f, p1, p2, p3, 0, 0) +#define SBI_CALL4(e, f, p1, p2, p3, p4) SBI_CALL5(e, f, p1, p2, p3, p4, 0) +#define SBI_CALL5(e, f, p1, p2, p3, p4, p5) sbi_call(e, f, p1, p2, p3, p4, p5) /* * Documentation available at @@ -106,7 +125,7 @@ static __inline struct sbi_ret sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1, - uint64_t arg2, uint64_t arg3) + uint64_t arg2, uint64_t arg3, uint64_t arg4) { struct sbi_ret ret; @@ -114,13 +133,14 @@ register uintptr_t a1 __asm ("a1") = (uintptr_t)(arg1); register uintptr_t a2 __asm ("a2") = (uintptr_t)(arg2); register uintptr_t a3 __asm ("a3") = (uintptr_t)(arg3); + register uintptr_t a4 __asm ("a4") = (uintptr_t)(arg4); register uintptr_t a6 __asm ("a6") = (uintptr_t)(arg6); register uintptr_t a7 __asm ("a7") = (uintptr_t)(arg7); __asm __volatile( \ "ecall" \ :"+r"(a0), "+r"(a1) \ - :"r"(a2), "r"(a3), "r"(a6), "r"(a7) \ + :"r"(a2), "r"(a3), "r"(a4), "r"(a6), "r"(a7) \ :"memory"); ret.error = a0; @@ -139,6 +159,18 @@ return (SBI_CALL1(SBI_EXT_ID_BASE, SBI_BASE_PROBE_EXTENSION, id).value); } +/* TIME extension functions. */ +void sbi_set_timer(uint64_t val); + +/* IPI extension functions. */ +void sbi_send_ipi(const u_long *hart_mask); + +/* RFENCE extension functions. */ +void sbi_remote_fence_i(const u_long *hart_mask); +void sbi_remote_sfence_vma(const u_long *hart_mask, u_long start, u_long size); +void sbi_remote_sfence_vma_asid(const u_long *hart_mask, u_long start, + u_long size, u_long asid); + /* Hart State Management extension functions. */ /* @@ -182,13 +214,6 @@ return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).error); } -static __inline void -sbi_set_timer(uint64_t val) -{ - - (void)SBI_CALL1(SBI_SET_TIMER, 0, val); -} - static __inline void sbi_shutdown(void) { @@ -196,39 +221,6 @@ (void)SBI_CALL0(SBI_SHUTDOWN, 0); } -static __inline void -sbi_send_ipi(const unsigned long *hart_mask) -{ - - (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask); -} - -static __inline void -sbi_remote_fence_i(const unsigned long *hart_mask) -{ - - (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask); -} - -static __inline void -sbi_remote_sfence_vma(const unsigned long *hart_mask, - unsigned long start, unsigned long size) -{ - - (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, start, - size); -} - -static __inline void -sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, - unsigned long start, unsigned long size, - unsigned long asid) -{ - - (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, (uint64_t)hart_mask, - start, size, asid); -} - void sbi_print_version(void); void sbi_init(void); Index: sys/riscv/riscv/sbi.c =================================================================== --- sys/riscv/riscv/sbi.c +++ sys/riscv/riscv/sbi.c @@ -46,6 +46,10 @@ u_long sbi_impl_id; u_long sbi_impl_version; +static bool has_time_extension = false; +static bool has_ipi_extension = false; +static bool has_rfnc_extension = false; + static struct sbi_ret sbi_get_spec_version(void) { @@ -122,6 +126,71 @@ printf("SBI Specification Version: %u.%u\n", major, minor); } +void +sbi_set_timer(uint64_t val) +{ + /* Use the TIME legacy replacement extension, if available. */ + if (has_time_extension) + (void)SBI_CALL1(SBI_EXT_ID_TIME, SBI_TIME_SET_TIMER, val); + else + (void)SBI_CALL1(SBI_SET_TIMER, 0, val); +} + +void +sbi_send_ipi(const u_long *hart_mask) +{ + /* Use the IPI legacy replacement extension, if available. */ + if (has_ipi_extension) + (void)SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI, + *hart_mask, 0); + else + (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask); +} + +void +sbi_remote_fence_i(const u_long *hart_mask) +{ + /* Use the RFENCE legacy replacement extension, if available. */ + if (has_rfnc_extension) + (void)SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I, + *hart_mask, 0); + else + (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask); +} + +void +sbi_remote_sfence_vma(const u_long *hart_mask, u_long start, u_long size) +{ + struct sbi_ret ret; + + /* Use the RFENCE legacy replacement extension, if available. */ + if (has_rfnc_extension) { + ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA, + *hart_mask, 0, start, size); + MPASS(ret.error == 0); + } else { + (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, + start, size); + } +} + +void +sbi_remote_sfence_vma_asid(const u_long *hart_mask, u_long start, u_long size, + u_long asid) +{ + struct sbi_ret ret; + + /* Use the RFENCE legacy replacement extension, if available. */ + if (has_rfnc_extension) { + ret = SBI_CALL5(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA_ASID, + *hart_mask, 0, start, size, asid); + MPASS(ret.error == 0); + } else { + (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, + (uint64_t)hart_mask, start, size, asid); + } +} + int sbi_hsm_hart_start(u_long hart, u_long start_addr, u_long priv) { @@ -173,23 +242,34 @@ marchid = sbi_get_marchid().value; mimpid = sbi_get_mimpid().value; + /* Probe for legacy replacement extensions. */ + if (sbi_probe_extension(SBI_EXT_ID_TIME) != 0) + has_time_extension = true; + if (sbi_probe_extension(SBI_EXT_ID_IPI) != 0) + has_ipi_extension = true; + if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0) + has_rfnc_extension = true; + /* - * Probe for legacy extensions. Currently we rely on all of them - * to be implemented, but this is not guaranteed by the spec. + * Probe for legacy extensions. We still rely on many of to be + * implemented, but this is not guaranteed by the spec. */ - KASSERT(sbi_probe_extension(SBI_SET_TIMER) != 0, + KASSERT(has_time_extension || sbi_probe_extension(SBI_SET_TIMER) != 0, ("SBI doesn't implement sbi_set_timer()")); KASSERT(sbi_probe_extension(SBI_CONSOLE_PUTCHAR) != 0, ("SBI doesn't implement sbi_console_putchar()")); KASSERT(sbi_probe_extension(SBI_CONSOLE_GETCHAR) != 0, ("SBI doesn't implement sbi_console_getchar()")); - KASSERT(sbi_probe_extension(SBI_SEND_IPI) != 0, + KASSERT(has_ipi_extension || sbi_probe_extension(SBI_SEND_IPI) != 0, ("SBI doesn't implement sbi_send_ipi()")); - KASSERT(sbi_probe_extension(SBI_REMOTE_FENCE_I) != 0, + KASSERT(has_rfnc_extension || + sbi_probe_extension(SBI_REMOTE_FENCE_I) != 0, ("SBI doesn't implement sbi_remote_fence_i()")); - KASSERT(sbi_probe_extension(SBI_REMOTE_SFENCE_VMA) != 0, + KASSERT(has_rfnc_extension || + sbi_probe_extension(SBI_REMOTE_SFENCE_VMA) != 0, ("SBI doesn't implement sbi_remote_sfence_vma()")); - KASSERT(sbi_probe_extension(SBI_REMOTE_SFENCE_VMA_ASID) != 0, + KASSERT(has_rfnc_extension || + sbi_probe_extension(SBI_REMOTE_SFENCE_VMA_ASID) != 0, ("SBI doesn't implement sbi_remote_sfence_vma_asid()")); KASSERT(sbi_probe_extension(SBI_SHUTDOWN) != 0, ("SBI doesn't implement sbi_shutdown()"));