opensbi/include/sbi/sbi_sse.h
Clément Léger c8cdf01d8f lib: sbi: Add support for Supervisor Software Events extension
This extension [1] allows to deliver events from SBI to supervisor via
a software mechanism. This extension defines events (either local or
global) which are signaled by the SBI on specific signal sources (IRQ,
exceptions, etc) and are injected to be executed in supervisor mode.

[1] https://lists.riscv.org/g/tech-prs/message/798

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-04-05 15:47:30 +05:30

93 lines
2.7 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023 Rivos Systems.
*/
#ifndef __SBI_SSE_H__
#define __SBI_SSE_H__
#include <sbi/sbi_types.h>
#include <sbi/sbi_list.h>
#include <sbi/riscv_locks.h>
struct sbi_scratch;
struct sbi_trap_regs;
struct sbi_ecall_return;
#define EXC_MODE_PP_SHIFT 0
#define EXC_MODE_PP BIT(EXC_MODE_PP_SHIFT)
#define EXC_MODE_PV_SHIFT 1
#define EXC_MODE_PV BIT(EXC_MODE_PV_SHIFT)
#define EXC_MODE_SSTATUS_SPIE_SHIFT 2
#define EXC_MODE_SSTATUS_SPIE BIT(EXC_MODE_SSTATUS_SPIE_SHIFT)
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);
/**
* 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);
/**
* Called when the SBI_EXT_SSE_ENABLE is invoked on the event.
*/
void (*enable_cb)(uint32_t event_id);
/**
* Called when the SBI_EXT_SSE_DISABLE is invoked on the event.
*/
void (*disable_cb)(uint32_t event_id);
};
/* Set the callback operations for an event
* @param event_id Event identifier (SBI_SSE_EVENT_*)
* @param cb_ops Callback operations
* @return 0 on success, error otherwise
*/
int sbi_sse_set_cb_ops(uint32_t event_id, const struct sbi_sse_cb_ops *cb_ops);
/* Inject an event to the current hard
* @param event_id Event identifier (SBI_SSE_EVENT_*)
* @param regs Registers that were used on SBI entry
* @return 0 on success, error otherwise
*/
int sbi_sse_inject_event(uint32_t event_id);
void sbi_sse_process_pending_events(struct sbi_trap_regs *regs);
int sbi_sse_init(struct sbi_scratch *scratch, bool cold_boot);
void sbi_sse_exit(struct sbi_scratch *scratch);
/* Interface called from sbi_ecall_sse.c */
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_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);
int sbi_sse_inject_from_ecall(uint32_t event_id, unsigned long hart_id,
struct sbi_ecall_return *out);
int sbi_sse_read_attrs(uint32_t event_id, uint32_t base_attr_id,
uint32_t attr_count, unsigned long output_phys_lo,
unsigned long output_phys_hi);
int sbi_sse_write_attrs(uint32_t event_id, uint32_t base_attr_id,
uint32_t attr_count, unsigned long input_phys_lo,
unsigned long input_phys_hi);
#endif