[PATCH 2/3] lib: sbi: Zicfilp/Zicfiss detection and elp cfi state reflect back in status

Samuel Holland samuel.holland at sifive.com
Wed Aug 21 17:32:35 PDT 2024


Hi Deepak,

On 2024-08-21 6:55 PM, Deepak Gupta wrote:
> This patch adds support for zicfilp / zicfiss detection in sbi_hart.c
> If zicfilp and zicfiss are detected, this patch turns on menvcfg.LPE and
> menvcfg.SSE
> 
> Zicfilp records status of hart's ELP state in *status csr. Missing landing pad
> sets MPELP in mstatus. When SBI is redirecting back to S/VS/HS, SPELP is
> set in sstatus/vsstatus.
> 
> Signed-off-by: Deepak Gupta <debug at rivosinc.com>
> ---
>  lib/sbi/sbi_hart.c | 28 ++++++++++++++++++++++++++++
>  lib/sbi/sbi_trap.c | 16 ++++++++++++++++
>  2 files changed, 44 insertions(+)
> 
> diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> index c366701..67a2e42 100644
> --- a/lib/sbi/sbi_hart.c
> +++ b/lib/sbi/sbi_hart.c
> @@ -148,6 +148,16 @@ static void mstatus_init(struct sbi_scratch *scratch)
>  		if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SVADE))
>  			menvcfg_val &= ~ENVCFG_ADUE;
>  
> +		/*
> +		 * By default allow shadow stack opreations in S/HS mode
> +		 * don't enable landing pad because supervisor may keep faulting
> +		 * due to missing landing pad. Open up a SBI interface to enable
> +		 * landing pad
> +		 */
> +		if (sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICFISS)) {
> +			menvcfg_val |= ENVCFG_SSE;
> +		}

This violates the default value provided for the SHADOW_STACK feature in the SBI
FWFT extension specification[1].

[1]:
https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/src/ext-firmware-features.adoc#user-content-table_fw_features_attribute_values

> +
>  		csr_write(CSR_MENVCFG, menvcfg_val);
>  #if __riscv_xlen == 32
>  		csr_write(CSR_MENVCFGH, menvcfg_val >> 32);
> @@ -680,6 +690,8 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
>  	__SBI_HART_EXT_DATA(ssccfg, SBI_HART_EXT_SSCCFG),
>  	__SBI_HART_EXT_DATA(svade, SBI_HART_EXT_SVADE),
>  	__SBI_HART_EXT_DATA(svadu, SBI_HART_EXT_SVADU),
> +	__SBI_HART_EXT_DATA(zicfilp, SBI_HART_EXT_ZICFILP),
> +	__SBI_HART_EXT_DATA(zicfiss, SBI_HART_EXT_ZICFISS),
>  };
>  
>  _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),
> @@ -776,6 +788,7 @@ static int hart_detect_features(struct sbi_scratch *scratch)
>  	unsigned long val, oldval;
>  	bool has_zicntr = false;
>  	int rc;
> +	bool ssp_exist, elp_exist;
>  
>  	/* If hart features already detected then do nothing */
>  	if (hfeatures->detected)
> @@ -933,6 +946,21 @@ __pmp_skip:
>  	/* Save trap based detection of Zicntr */
>  	has_zicntr = sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICNTR);
>  
> +	if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) {
> +		val = csr_read_allowed(CSR_SSP, (unsigned long)&trap);
> +		ssp_exist = trap.cause == 0;

Would it be simpler to try setting menvcfg.SSE here, since that would never
cause a trap?

> +		if (ssp_exist)
> +			__sbi_hart_update_extension(hfeatures,
> +					SBI_HART_EXT_ZICFISS, true);
> +
> +		csr_set(CSR_MSTATUS, MSTATUS_MPELP);
> +		val = csr_read_clear(CSR_MSTATUS, MSTATUS_MPELP);
> +		elp_exist = val & MSTATUS_MPELP;
> +		if (elp_exist)
> +			__sbi_hart_update_extension(hfeatures,
> +					SBI_HART_EXT_ZICFILP, true);
> +	}
> +
>  	/* Let platform populate extensions */
>  	rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(),
>  					  hfeatures);
> diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> index b4f3a17..2273b3a 100644
> --- a/lib/sbi/sbi_trap.c
> +++ b/lib/sbi/sbi_trap.c
> @@ -103,6 +103,7 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
>  		      const struct sbi_trap_info *trap)
>  {
>  	ulong hstatus, vsstatus, prev_mode;
> +	bool elp = false;
>  #if __riscv_xlen == 32
>  	bool prev_virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false;
>  #else
> @@ -116,6 +117,13 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
>  	if (prev_mode != PRV_S && prev_mode != PRV_U)
>  		return SBI_ENOTSUPP;
>  
> +	/* If extension has support for CFI, clear MPELP because redirecting to VS or (H)S */
> +	if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(), SBI_HART_EXT_ZICFILP)) {
> +		elp = (regs->mstatus & MSTATUS_MPELP)? true: false;

The ternary expression here is unnecessary. The left side is already truthy/falsy.

Regards,
Samuel

> +		/* Since redirecting, clear mpelp unconditionally */
> +		regs->mstatus &= ~MSTATUS_MPELP;
> +	}
> +
>  	/* If exceptions came from VS/VU-mode, redirect to VS-mode if
>  	 * delegated in hedeleg
>  	 */
> @@ -169,6 +177,10 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
>  		/* Get VS-mode SSTATUS CSR */
>  		vsstatus = csr_read(CSR_VSSTATUS);
>  
> +		/*if elp was set, set it back in vsstatus */
> +		if (elp)
> +			vsstatus |= MSTATUS_SPELP;
> +
>  		/* Set SPP for VS-mode */
>  		vsstatus &= ~SSTATUS_SPP;
>  		if (prev_mode == PRV_S)
> @@ -209,6 +221,10 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
>  
>  		/* Clear SIE for S-mode */
>  		regs->mstatus &= ~MSTATUS_SIE;
> +
> +		/* if elp was set, set it back in mstatus */
> +		if (elp)
> +			regs->mstatus |= MSTATUS_SPELP;
>  	}
>  
>  	return 0;




More information about the opensbi mailing list