[RFC PATCH 2/2] lib: sbi: add support for Supervisor Software Events extension
Xiang W
wxjstz at 126.com
Mon Dec 4 21:19:16 PST 2023
在 2023-11-30星期四的 10:13 +0100,Clément Léger写道:
> This extension [1] allows to deliver events from SBI to supervisor via a
> software mecanism. This extensions defines events (either local or
> global) which are signaled by the SBI on specific signal sources (IRQ,
> traps, etc) and are injected to be executed in supervisor mode.
>
> [1] https://lists.riscv.org/g/tech-prs/message/515
>
> Signed-off-by: Clément Léger <cleger at rivosinc.com>
> ---
>
> +struct sbi_sse_cb_ops {
> + /**
> + * Called when hart_id is changed on the event.
> + */
> + void (*set_hartid_cb)(uint32_t event_id, unsigned long hart_id);
> +
Maybe should add a callback before running. This callback can be used to
access sensitive resources, such as keys.
> + /**
> + * Called when the SBI_EXT_SSE_COMPLETE is invoked on the event.
> + */
> + void (*complete_cb)(uint32_t event_id);
> +
> + /**
> + * Called when the SBI_EXT_SSE_REGISTER is invoked on the event.
> + */
> + void (*register_cb)(uint32_t event_id);
> +
> + /**
> + * Called when the SBI_EXT_SSE_UNREGISTER is invoked on the event.
> + */
> + void (*unregister_cb)(uint32_t event_id);
> +};
> +
>
> +static void sse_event_set_state(struct sbi_sse_event *e,
> + enum sbi_sse_state new_state)
> +{
> + enum sbi_sse_state prev_state = e->state;
> +
> + e->state = new_state;
Do not change before checking.
> + switch (new_state) {
> + case SSE_STATE_UNUSED:
> + if (prev_state == SSE_STATE_REGISTERED)
> + return;
> + break;
> + case SSE_STATE_REGISTERED:
> + if (prev_state == SSE_STATE_UNUSED ||
> + prev_state == SSE_STATE_ENABLED) {
> + return;
> + }
> + break;
> + case SSE_STATE_ENABLED:
> + if (prev_state == SSE_STATE_REGISTERED ||
> + prev_state == SSE_STATE_RUNNING)
> + return;
> + break;
> + case SSE_STATE_RUNNING:
> + if (prev_state == SSE_STATE_ENABLED)
> + return;
> + break;
> + }
This state machine is characterized by the difference between the old and new
states being 1. So the code can be simplified as follows:
if ((new_state - prev_state == 1) || (prev_state - new_state == 1)) {
e->state = new_state;
return;
}
> +
> + sbi_panic("Invalid SSE state transition: %d -> %d\n", prev_state,
> + new_state);
> +}
> +
>
> +
> +static int sse_event_set_hart_id(struct sbi_sse_event *e, uint32_t event_id,
> + unsigned long new_hartid)
> +{
> + int hstate;
> + unsigned int hartid = (uint32_t) new_hartid;
> + struct sbi_domain * hd = sbi_domain_thishart_ptr();
> +
> + if (!sse_event_is_global(e))
> + return SBI_EDENIED;
> +
> + if (e->state == SSE_STATE_RUNNING)
> + return SBI_EBUSY;
> +
> + if (!sbi_domain_is_assigned_hart(hd, new_hartid))
> + return SBI_EINVAL;
> +
> + hstate = sbi_hsm_hart_get_state(hd, hartid);
> + if (hstate != SBI_HSM_STATE_STARTED)
> + return SBI_EINVAL;
> +
> + if (new_hartid == e->hartid)
> + return SBI_OK;
> +
> + if (e->state >= SSE_STATE_ENABLED)
> + sse_event_remove_from_list(e);
> +
> + e->hartid = hartid;
> +
> + if (e->cb_ops && e->cb_ops->set_hartid_cb)
> + e->cb_ops->set_hartid_cb(event_id, e->hartid);
> +
> + if (e->state >= SSE_STATE_ENABLED)
> + sse_event_add_to_list(e);
> +
> + if (e->pending)
> + sbi_ipi_send_many(BIT(e->hartid), 0, sse_ipi_inject_event, NULL);
hartid can't big then XLEN. change to:
sbi_ipi_send_many(1, e->hartid, sse_ipi_inject_event, NULL);
> +
> + return 0;
> +}
> +
>
> +
> +static int sse_ipi_inject_send(unsigned long hartid, uint32_t event_id)
> +{
> + int ret;
> + struct sbi_scratch *remote_scratch = NULL;
> + struct sse_ipi_inject_data evt = {event_id};
> + struct sbi_fifo *sse_inject_fifo_r;
> +
> + remote_scratch = sbi_hartid_to_scratch(hartid);
> + if (!remote_scratch)
> + return SBI_EINVAL;
> + sse_inject_fifo_r = sbi_scratch_offset_ptr(remote_scratch,
> + sse_inject_fifo_off);
> +
> + ret = sbi_fifo_enqueue(sse_inject_fifo_r, &evt);
> + if (ret)
> + return SBI_EFAIL;
> +
> + ret = sbi_ipi_send_many(BIT(hartid), 0, sse_ipi_inject_event, NULL);
hartid can't big then XLEN. change to:
ret = sbi_ipi_send_many(1, hartid, sse_ipi_inject_event, NULL);
> + if (ret)
> + return SBI_EFAIL;
> +
> + return SBI_OK;
> +}
> +
>
> +}
> --
> 2.42.0
>
>
Regards,
Xiang W
More information about the opensbi
mailing list