diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h index 4f12c03..04502e1 100644 --- a/include/sbi/riscv_asm.h +++ b/include/sbi/riscv_asm.h @@ -159,22 +159,18 @@ void csr_write_num(int csr_num, unsigned long val); __asm__ __volatile__("wfi" ::: "memory"); \ } while (0) -static inline int misa_extension(char ext) -{ - return csr_read(CSR_MISA) & (1 << (ext - 'A')); -} +/* Determine CPU extension, return non-zero support */ +int misa_extension(char ext); -static inline int misa_xlen(void) -{ - return ((long)csr_read(CSR_MISA) < 0) ? 64 : 32; -} +/* Get MXL field of misa, return -1 on error */ +int misa_xlen(void); static inline void misa_string(char *out, unsigned int out_sz) { - unsigned long i, val = csr_read(CSR_MISA); + unsigned long i; for (i = 0; i < 26; i++) { - if (val & (1 << i)) { + if (misa_extension('A' + i)) { *out = 'A' + i; out++; } diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h index 01d4a85..beb2f23 100644 --- a/include/sbi/sbi_platform.h +++ b/include/sbi/sbi_platform.h @@ -76,6 +76,16 @@ struct sbi_platform_operations { /** Platform final initialization */ int (*final_init)(bool cold_boot); + /** For platforms that do not implement misa, non-standard + * methods are needed to determine cpu extension. + */ + int (*misa_check_extension)(char ext); + + /** For platforms that do not implement misa, non-standard + * methods are needed to get MXL field of misa. + */ + int (*misa_get_xlen)(void); + /** Get number of PMP regions for given HART */ u32 (*pmp_region_count)(u32 hartid); /** @@ -291,6 +301,36 @@ static inline int sbi_platform_final_init(const struct sbi_platform *plat, return 0; } +/** + * Check CPU extension in MISA + * + * @param plat pointer to struct sbi_platform + * @param ext shorthand letter for CPU extensions + * + * @return zero for not-supported and non-zero for supported + */ +static inline int sbi_platform_misa_extension(const struct sbi_platform *plat, + char ext) +{ + if (plat && sbi_platform_ops(plat)->misa_check_extension) + return sbi_platform_ops(plat)->misa_check_extension(ext); + return 0; +} + +/** + * Get MXL field of MISA + * + * @param plat pointer to struct sbi_platform + * + * @return 1/2/3 on success and error code on failure + */ +static inline int sbi_platform_misa_xlen(const struct sbi_platform *plat) +{ + if (plat && sbi_platform_ops(plat)->misa_get_xlen) + return sbi_platform_ops(plat)->misa_get_xlen(); + return -1; +} + /** * Get the number of PMP regions of a HART * diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c index e0c8889..d16e32a 100644 --- a/lib/sbi/riscv_asm.c +++ b/lib/sbi/riscv_asm.c @@ -10,6 +10,38 @@ #include #include #include +#include + +int misa_extension(char ext) +{ + unsigned long misa = csr_read(CSR_MISA); + + if (misa) + return misa & (1 << (ext - 'A')); + + return sbi_platform_misa_extension(sbi_platform_thishart_ptr(), ext); +} + +int misa_xlen(void) +{ + long r; + + if (csr_read(CSR_MISA) == 0) + return sbi_platform_misa_xlen(sbi_platform_thishart_ptr()); + + __asm__ __volatile__( + "csrr t0, misa\n\t" + "slti t1, t0, 0\n\t" + "slli t1, t1, 1\n\t" + "slli t0, t0, 1\n\t" + "slti t0, t0, 0\n\t" + "add %0, t0, t1" + : "=r"(r) + : + : "t0", "t1"); + + return r ? r : -1; +} unsigned long csr_read_num(int csr_num) { diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c index 265bb02..51ce3a0 100644 --- a/lib/sbi/sbi_init.c +++ b/lib/sbi/sbi_init.c @@ -30,10 +30,10 @@ static void sbi_boot_prints(struct sbi_scratch *scratch, u32 hartid) { + int xlen; char str[64]; const struct sbi_platform *plat = sbi_platform_ptr(scratch); - misa_string(str, sizeof(str)); #ifdef OPENSBI_VERSION_GIT sbi_printf("\nOpenSBI %s\n", OPENSBI_VERSION_GIT); #else @@ -43,9 +43,18 @@ static void sbi_boot_prints(struct sbi_scratch *scratch, u32 hartid) sbi_printf(BANNER); + /* Determine MISA XLEN and MISA string */ + xlen = misa_xlen(); + if (xlen < 1) { + sbi_printf("Error %d getting MISA XLEN\n", xlen); + sbi_hart_hang(); + } + xlen = 16 * (1 << xlen); + misa_string(str, sizeof(str)); + /* Platform details */ sbi_printf("Platform Name : %s\n", sbi_platform_name(plat)); - sbi_printf("Platform HART Features : RV%d%s\n", misa_xlen(), str); + sbi_printf("Platform HART Features : RV%d%s\n", xlen, str); sbi_printf("Platform Max HARTs : %d\n", sbi_platform_hart_count(plat)); sbi_printf("Current Hart : %u\n", hartid);