mirror of
				https://github.com/riscv-software-src/opensbi
				synced 2025-11-03 21:48:45 +00:00 
			
		
		
		
	lib: Fix CPU capabilities detection function
On some platforms, misa may not be implemented. On such a platform, reading misa will get 0. At this time, platform is required to implement a non-standard function to detect the CPU's capabilities. Therefore, this modification add interfaces for non-standard function. The MXL field of misa is always at the highest two bits, whether it is a 32-bit 64-bit or a 128-bit machine. Therefore, this modification fixes the use of a fixed offset to detect the machine length. Signed-off-by: Xiang Wang <merle@hardenedlinux.org> Signed-off-by: Anup Patel <anup.patel@wdc.com>
This commit is contained in:
		
							parent
							
								
									75f903dd78
								
							
						
					
					
						commit
						c96cc03fcc
					
				@ -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++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 *
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,38 @@
 | 
			
		||||
#include <sbi/riscv_asm.h>
 | 
			
		||||
#include <sbi/riscv_encoding.h>
 | 
			
		||||
#include <sbi/sbi_error.h>
 | 
			
		||||
#include <sbi/sbi_platform.h>
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user