[PATCH] lib: sbi: Add support to mask/unmask SSE events
Samuel Holland
samuel.holland at sifive.com
Thu Sep 12 18:42:58 PDT 2024
Hi Himanshu,
On 2024-09-10 8:24 AM, Himanshu Chauhan wrote:
> A hart in non-retentive suspend state can't handle software events
> until the hart has come out of the non-retentive suspend and restored
> the hart state.
>
> To support this, define separate hart mask/unmask functions for the
> SSE extension which allow supervisor software to globally mask/unmask
> software event delivery on the calling hart.
>
> Signed-off-by: Himanshu Chauhan <hchauhan at ventanamicro.com>
> ---
> include/sbi/sbi_ecall_interface.h | 2 ++
> include/sbi/sbi_sse.h | 2 ++
> lib/sbi/sbi_ecall_sse.c | 6 ++++++
> lib/sbi/sbi_sse.c | 31 +++++++++++++++++++++++++++++++
> 4 files changed, 41 insertions(+)
>
> diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
> index 085b33e7..3bf8f1da 100644
> --- a/include/sbi/sbi_ecall_interface.h
> +++ b/include/sbi/sbi_ecall_interface.h
> @@ -342,6 +342,8 @@ enum sbi_cppc_reg_id {
> #define SBI_EXT_SSE_DISABLE 0x00000005
> #define SBI_EXT_SSE_COMPLETE 0x00000006
> #define SBI_EXT_SSE_INJECT 0x00000007
> +#define SBI_EXT_SSE_HART_MASK 0x00000008
> +#define SBI_EXT_SSE_HART_UNMASK 0x00000009
These function IDs are swapped compared to the proposed spec.
>
> /* SBI SSE Event Attributes. */
> enum sbi_sse_attr_id {
> diff --git a/include/sbi/sbi_sse.h b/include/sbi/sbi_sse.h
> index e5b0ad69..7419698a 100644
> --- a/include/sbi/sbi_sse.h
> +++ b/include/sbi/sbi_sse.h
> @@ -78,6 +78,8 @@ void sbi_sse_exit(struct sbi_scratch *scratch);
> int sbi_sse_register(uint32_t event_id, unsigned long handler_entry_pc,
> unsigned long handler_entry_arg);
> int sbi_sse_unregister(uint32_t event_id);
> +int sbi_sse_hart_mask(void);
> +int sbi_sse_hart_unmask(void);
> int sbi_sse_enable(uint32_t event_id);
> int sbi_sse_disable(uint32_t event_id);
> int sbi_sse_complete(struct sbi_trap_regs *regs, struct sbi_ecall_return *out);
> diff --git a/lib/sbi/sbi_ecall_sse.c b/lib/sbi/sbi_ecall_sse.c
> index a28a033e..beddc2cd 100644
> --- a/lib/sbi/sbi_ecall_sse.c
> +++ b/lib/sbi/sbi_ecall_sse.c
> @@ -36,6 +36,12 @@ static int sbi_ecall_sse_handler(unsigned long extid, unsigned long funcid,
> case SBI_EXT_SSE_INJECT:
> ret = sbi_sse_inject_from_ecall(regs->a0, regs->a1, out);
> break;
> + case SBI_EXT_SSE_HART_MASK:
> + ret = sbi_sse_hart_mask();
> + break;
> + case SBI_EXT_SSE_HART_UNMASK:
> + ret = sbi_sse_hart_unmask();
> + break;
> default:
> ret = SBI_ENOTSUPP;
> }
> diff --git a/lib/sbi/sbi_sse.c b/lib/sbi/sbi_sse.c
> index 52172fcd..e9085324 100644
> --- a/lib/sbi/sbi_sse.c
> +++ b/lib/sbi/sbi_sse.c
> @@ -141,6 +141,12 @@ struct sse_hart_state {
> * List of local events allocated at boot time.
> */
> struct sbi_sse_event *local_events;
> +
> + /**
> + * State to track if the hart is ready to take sse events.
> + * One hart cannot modify this state of another hart.
> + */
> + bool sse_masked;
"sse_" is a bit redundant here, since this whole structure is SSE state.
> };
>
> /**
> @@ -608,6 +614,11 @@ void sbi_sse_process_pending_events(struct sbi_trap_regs *regs)
> struct sbi_sse_event *e;
> struct sse_hart_state *state = sse_thishart_state_ptr();
>
> + /* if sse is masked on this hart, do nothing */
> + if (state->sse_masked) {
> + return;
> + }
This will block global events if the preferred hart has events masked.
sse_event_is_ready() needs to ignore the preferred hartid in that case, so the
event can be injected on another hart.
Regards,
Samuel
> +
> spin_lock(&state->enabled_event_lock);
>
> sbi_list_for_each_entry(e, &state->enabled_event_list, node) {
> @@ -805,6 +816,24 @@ int sbi_sse_disable(uint32_t event_id)
> return ret;
> }
>
> +int sbi_sse_hart_mask(void)
> +{
> + struct sse_hart_state *state = sse_thishart_state_ptr();
> +
> + state->sse_masked = true;
> +
> + return SBI_SUCCESS;
> +}
> +
> +int sbi_sse_hart_unmask(void)
> +{
> + struct sse_hart_state *state = sse_thishart_state_ptr();
> +
> + state->sse_masked = false;
> +
> + return SBI_SUCCESS;
> +}
> +
> int sbi_sse_inject_from_ecall(uint32_t event_id, unsigned long hartid,
> struct sbi_ecall_return *out)
> {
> @@ -1123,6 +1152,8 @@ int sbi_sse_init(struct sbi_scratch *scratch, bool cold_boot)
>
> shs->local_events = (struct sbi_sse_event *)(shs + 1);
>
> + /* SSE events are masked until hart unmasks them */
> + shs->sse_masked = true;
> sse_set_hart_state_ptr(scratch, shs);
> }
>
More information about the opensbi
mailing list