Files
opensbi/include/sbi/sbi_hart.h
Rajnesh Kanwal aa40c53ce4 lib: sbi: Enable Control Transfer Records (CTR) Ext using xstateen.
The Control Transfer Records (CTR) extension provides a method to
record a limited branch history in register-accessible internal chip
storage.

This extension is similar to Arch LBR in x86 and BRBE in ARM.
The Extension has been stable and the latest release can be found here
https://github.com/riscv/riscv-control-transfer-records/release

Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250307124451.122828-1-rkanwal@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-04-13 06:11:43 +05:30

160 lines
4.8 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
*
* Authors:
* Anup Patel <anup.patel@wdc.com>
*/
#ifndef __SBI_HART_H__
#define __SBI_HART_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_bitops.h>
/** Possible privileged specification versions of a hart */
enum sbi_hart_priv_versions {
/** Unknown privileged specification */
SBI_HART_PRIV_VER_UNKNOWN = 0,
/** Privileged specification v1.10 */
SBI_HART_PRIV_VER_1_10 = 1,
/** Privileged specification v1.11 */
SBI_HART_PRIV_VER_1_11 = 2,
/** Privileged specification v1.12 */
SBI_HART_PRIV_VER_1_12 = 3,
};
/** Possible ISA extensions of a hart */
enum sbi_hart_extensions {
/** HART has AIA M-mode CSRs */
SBI_HART_EXT_SMAIA = 0,
/** HART has Smepmp */
SBI_HART_EXT_SMEPMP,
/** HART has Smstateen CSR **/
SBI_HART_EXT_SMSTATEEN,
/** Hart has Sscofpmt extension */
SBI_HART_EXT_SSCOFPMF,
/** HART has Sstc extension */
SBI_HART_EXT_SSTC,
/** HART has Zicntr extension (i.e. HW cycle, time & instret CSRs) */
SBI_HART_EXT_ZICNTR,
/** HART has Zihpm extension */
SBI_HART_EXT_ZIHPM,
/** HART has Zkr extension */
SBI_HART_EXT_ZKR,
/** Hart has Smcntrpmf extension */
SBI_HART_EXT_SMCNTRPMF,
/** Hart has Xandespmu extension */
SBI_HART_EXT_XANDESPMU,
/** Hart has Zicboz extension */
SBI_HART_EXT_ZICBOZ,
/** Hart has Zicbom extension */
SBI_HART_EXT_ZICBOM,
/** Hart has Svpbmt extension */
SBI_HART_EXT_SVPBMT,
/** Hart has debug trigger extension */
SBI_HART_EXT_SDTRIG,
/** Hart has Smcsrind extension */
SBI_HART_EXT_SMCSRIND,
/** Hart has Smcdeleg extension */
SBI_HART_EXT_SMCDELEG,
/** Hart has Sscsrind extension */
SBI_HART_EXT_SSCSRIND,
/** Hart has Ssccfg extension */
SBI_HART_EXT_SSCCFG,
/** Hart has Svade extension */
SBI_HART_EXT_SVADE,
/** Hart has Svadu extension */
SBI_HART_EXT_SVADU,
/** Hart has Smnpm extension */
SBI_HART_EXT_SMNPM,
/** HART has zicfilp extension */
SBI_HART_EXT_ZICFILP,
/** HART has zicfiss extension */
SBI_HART_EXT_ZICFISS,
/** Hart has Ssdbltrp extension */
SBI_HART_EXT_SSDBLTRP,
/** HART has CTR M-mode CSRs */
SBI_HART_EXT_SMCTR,
/** HART has CTR S-mode CSRs */
SBI_HART_EXT_SSCTR,
/** Maximum index of Hart extension */
SBI_HART_EXT_MAX,
};
struct sbi_hart_ext_data {
const unsigned int id;
const char *name;
};
extern const struct sbi_hart_ext_data sbi_hart_ext[];
/*
* Smepmp enforces access boundaries between M-mode and
* S/U-mode. When it is enabled, the PMPs are programmed
* such that M-mode doesn't have access to S/U-mode memory.
*
* To give M-mode R/W access to the shared memory between M and
* S/U-mode, first entry is reserved. It is disabled at boot.
* When shared memory access is required, the physical address
* should be programmed into the first PMP entry with R/W
* permissions to the M-mode. Once the work is done, it should be
* unmapped. sbi_hart_map_saddr/sbi_hart_unmap_saddr function
* pair should be used to map/unmap the shared memory.
*/
#define SBI_SMEPMP_RESV_ENTRY 0
struct sbi_hart_features {
bool detected;
int priv_version;
unsigned long extensions[BITS_TO_LONGS(SBI_HART_EXT_MAX)];
unsigned int pmp_count;
unsigned int pmp_addr_bits;
unsigned int pmp_log2gran;
unsigned int mhpm_mask;
unsigned int mhpm_bits;
};
struct sbi_scratch;
int sbi_hart_reinit(struct sbi_scratch *scratch);
int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
extern void (*sbi_hart_expected_trap)(void);
static inline ulong sbi_hart_expected_trap_addr(void)
{
return (ulong)sbi_hart_expected_trap;
}
unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
const char *prefix, const char *suffix);
unsigned int sbi_hart_pmp_count(struct sbi_scratch *scratch);
unsigned int sbi_hart_pmp_log2gran(struct sbi_scratch *scratch);
unsigned int sbi_hart_pmp_addrbits(struct sbi_scratch *scratch);
unsigned int sbi_hart_mhpm_bits(struct sbi_scratch *scratch);
int sbi_hart_pmp_configure(struct sbi_scratch *scratch);
int sbi_hart_map_saddr(unsigned long base, unsigned long size);
int sbi_hart_unmap_saddr(void);
int sbi_hart_priv_version(struct sbi_scratch *scratch);
void sbi_hart_get_priv_version_str(struct sbi_scratch *scratch,
char *version_str, int nvstr);
void sbi_hart_update_extension(struct sbi_scratch *scratch,
enum sbi_hart_extensions ext,
bool enable);
bool sbi_hart_has_extension(struct sbi_scratch *scratch,
enum sbi_hart_extensions ext);
void sbi_hart_get_extensions_str(struct sbi_scratch *scratch,
char *extension_str, int nestr);
void __attribute__((noreturn)) sbi_hart_hang(void);
void __attribute__((noreturn))
sbi_hart_switch_mode(unsigned long arg0, unsigned long arg1,
unsigned long next_addr, unsigned long next_mode,
bool next_virt);
#endif