forked from Mirrors/opensbi
		
	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>
This commit is contained in:
		
				
					committed by
					
						
						Anup Patel
					
				
			
			
				
	
			
			
			
						parent
						
							76d7e9b8ee
						
					
				
				
					commit
					c8cdf01d8f
				
			@@ -33,6 +33,7 @@
 | 
			
		||||
#define SBI_EXT_SUSP				0x53555350
 | 
			
		||||
#define SBI_EXT_CPPC				0x43505043
 | 
			
		||||
#define SBI_EXT_DBTR				0x44425452
 | 
			
		||||
#define SBI_EXT_SSE				0x535345
 | 
			
		||||
 | 
			
		||||
/* SBI function IDs for BASE extension*/
 | 
			
		||||
#define SBI_EXT_BASE_GET_SPEC_VERSION		0x0
 | 
			
		||||
@@ -304,6 +305,80 @@ enum sbi_cppc_reg_id {
 | 
			
		||||
	SBI_CPPC_NON_ACPI_LAST		= SBI_CPPC_TRANSITION_LATENCY,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* SBI Function IDs for SSE extension */
 | 
			
		||||
#define SBI_EXT_SSE_READ_ATTR		0x00000000
 | 
			
		||||
#define SBI_EXT_SSE_WRITE_ATTR		0x00000001
 | 
			
		||||
#define SBI_EXT_SSE_REGISTER		0x00000002
 | 
			
		||||
#define SBI_EXT_SSE_UNREGISTER		0x00000003
 | 
			
		||||
#define SBI_EXT_SSE_ENABLE		0x00000004
 | 
			
		||||
#define SBI_EXT_SSE_DISABLE		0x00000005
 | 
			
		||||
#define SBI_EXT_SSE_COMPLETE		0x00000006
 | 
			
		||||
#define SBI_EXT_SSE_INJECT		0x00000007
 | 
			
		||||
 | 
			
		||||
/* SBI SSE Event Attributes. */
 | 
			
		||||
enum sbi_sse_attr_id {
 | 
			
		||||
	SBI_SSE_ATTR_STATUS		= 0x00000000,
 | 
			
		||||
	SBI_SSE_ATTR_PRIO		= 0x00000001,
 | 
			
		||||
	SBI_SSE_ATTR_CONFIG		= 0x00000002,
 | 
			
		||||
	SBI_SSE_ATTR_PREFERRED_HART	= 0x00000003,
 | 
			
		||||
	SBI_SSE_ATTR_ENTRY_PC		= 0x00000004,
 | 
			
		||||
	SBI_SSE_ATTR_ENTRY_ARG		= 0x00000005,
 | 
			
		||||
	SBI_SSE_ATTR_INTERRUPTED_SEPC	= 0x00000006,
 | 
			
		||||
	SBI_SSE_ATTR_INTERRUPTED_FLAGS	= 0x00000007,
 | 
			
		||||
	SBI_SSE_ATTR_INTERRUPTED_A6	= 0x00000008,
 | 
			
		||||
	SBI_SSE_ATTR_INTERRUPTED_A7	= 0x00000009,
 | 
			
		||||
 | 
			
		||||
	SBI_SSE_ATTR_MAX		= 0x0000000A
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SBI_SSE_ATTR_STATUS_STATE_OFFSET	0
 | 
			
		||||
#define SBI_SSE_ATTR_STATUS_STATE_MASK		0x3
 | 
			
		||||
#define SBI_SSE_ATTR_STATUS_PENDING_OFFSET	2
 | 
			
		||||
#define SBI_SSE_ATTR_STATUS_INJECT_OFFSET	3
 | 
			
		||||
 | 
			
		||||
#define SBI_SSE_ATTR_CONFIG_ONESHOT	(1 << 0)
 | 
			
		||||
 | 
			
		||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_STATUS_SPP	BIT(0)
 | 
			
		||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_STATUS_SPIE	BIT(1)
 | 
			
		||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV	BIT(2)
 | 
			
		||||
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP	BIT(3)
 | 
			
		||||
 | 
			
		||||
enum sbi_sse_state {
 | 
			
		||||
	SBI_SSE_STATE_UNUSED     = 0,
 | 
			
		||||
	SBI_SSE_STATE_REGISTERED = 1,
 | 
			
		||||
	SBI_SSE_STATE_ENABLED    = 2,
 | 
			
		||||
	SBI_SSE_STATE_RUNNING    = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* SBI SSE Event IDs. */
 | 
			
		||||
#define SBI_SSE_EVENT_LOCAL_RAS			0x00000000
 | 
			
		||||
#define	SBI_SSE_EVENT_LOCAL_PLAT_0_START	0x00004000
 | 
			
		||||
#define SBI_SSE_EVENT_LOCAL_PLAT_0_END		0x00007fff
 | 
			
		||||
#define SBI_SSE_EVENT_GLOBAL_RAS		0x00008000
 | 
			
		||||
#define	SBI_SSE_EVENT_GLOBAL_PLAT_0_START	0x00004000
 | 
			
		||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_0_END		0x00007fff
 | 
			
		||||
 | 
			
		||||
#define SBI_SSE_EVENT_LOCAL_PMU			0x00010000
 | 
			
		||||
#define	SBI_SSE_EVENT_LOCAL_PLAT_1_START	0x00014000
 | 
			
		||||
#define SBI_SSE_EVENT_LOCAL_PLAT_1_END		0x00017fff
 | 
			
		||||
#define	SBI_SSE_EVENT_GLOBAL_PLAT_1_START	0x0001c000
 | 
			
		||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_1_END		0x0001ffff
 | 
			
		||||
 | 
			
		||||
#define	SBI_SSE_EVENT_LOCAL_PLAT_2_START	0x00024000
 | 
			
		||||
#define SBI_SSE_EVENT_LOCAL_PLAT_2_END		0x00027fff
 | 
			
		||||
#define	SBI_SSE_EVENT_GLOBAL_PLAT_2_START	0x0002c000
 | 
			
		||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_2_END		0x0002ffff
 | 
			
		||||
 | 
			
		||||
#define SBI_SSE_EVENT_LOCAL_SOFTWARE		0xffff0000
 | 
			
		||||
#define	SBI_SSE_EVENT_LOCAL_PLAT_3_START	0xffff4000
 | 
			
		||||
#define SBI_SSE_EVENT_LOCAL_PLAT_3_END		0xffff7fff
 | 
			
		||||
#define SBI_SSE_EVENT_GLOBAL_SOFTWARE		0xffff8000
 | 
			
		||||
#define	SBI_SSE_EVENT_GLOBAL_PLAT_3_START	0xffffc000
 | 
			
		||||
#define SBI_SSE_EVENT_GLOBAL_PLAT_3_END		0xffffffff
 | 
			
		||||
 | 
			
		||||
#define SBI_SSE_EVENT_GLOBAL_BIT		(1 << 15)
 | 
			
		||||
#define SBI_SSE_EVENT_PLATFORM_BIT		(1 << 14)
 | 
			
		||||
 | 
			
		||||
/* SBI base specification related macros */
 | 
			
		||||
#define SBI_SPEC_VERSION_MAJOR_OFFSET		24
 | 
			
		||||
#define SBI_SPEC_VERSION_MAJOR_MASK		0x7f
 | 
			
		||||
@@ -324,8 +399,10 @@ enum sbi_cppc_reg_id {
 | 
			
		||||
#define SBI_ERR_ALREADY_STARTED			-7
 | 
			
		||||
#define SBI_ERR_ALREADY_STOPPED			-8
 | 
			
		||||
#define SBI_ERR_NO_SHMEM			-9
 | 
			
		||||
#define SBI_ERR_INVALID_STATE			-10
 | 
			
		||||
#define SBI_ERR_BAD_RANGE			-11
 | 
			
		||||
 | 
			
		||||
#define SBI_LAST_ERR				SBI_ERR_NO_SHMEM
 | 
			
		||||
#define SBI_LAST_ERR				SBI_ERR_BAD_RANGE
 | 
			
		||||
 | 
			
		||||
/* clang-format on */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@
 | 
			
		||||
#define SBI_EALREADY_STARTED	SBI_ERR_ALREADY_STARTED
 | 
			
		||||
#define SBI_EALREADY_STOPPED	SBI_ERR_ALREADY_STOPPED
 | 
			
		||||
#define SBI_ENO_SHMEM		SBI_ERR_NO_SHMEM
 | 
			
		||||
#define SBI_EINVALID_STATE	SBI_ERR_INVALID_STATE
 | 
			
		||||
#define SBI_EBAD_RANGE		SBI_ERR_BAD_RANGE
 | 
			
		||||
 | 
			
		||||
#define SBI_ENODEV		-1000
 | 
			
		||||
#define SBI_ENOSYS		-1001
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										93
									
								
								include/sbi/sbi_sse.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								include/sbi/sbi_sse.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
@@ -75,6 +75,7 @@ libsbi-objs-y += sbi_platform.o
 | 
			
		||||
libsbi-objs-y += sbi_pmu.o
 | 
			
		||||
libsbi-objs-y += sbi_dbtr.o
 | 
			
		||||
libsbi-objs-y += sbi_scratch.o
 | 
			
		||||
libsbi-objs-y += sbi_sse.o
 | 
			
		||||
libsbi-objs-y += sbi_string.o
 | 
			
		||||
libsbi-objs-y += sbi_system.o
 | 
			
		||||
libsbi-objs-y += sbi_timer.o
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include <sbi/sbi_platform.h>
 | 
			
		||||
#include <sbi/sbi_pmu.h>
 | 
			
		||||
#include <sbi/sbi_dbtr.h>
 | 
			
		||||
#include <sbi/sbi_sse.h>
 | 
			
		||||
#include <sbi/sbi_system.h>
 | 
			
		||||
#include <sbi/sbi_string.h>
 | 
			
		||||
#include <sbi/sbi_timer.h>
 | 
			
		||||
@@ -319,6 +320,12 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 | 
			
		||||
	if (rc)
 | 
			
		||||
		sbi_hart_hang();
 | 
			
		||||
 | 
			
		||||
	rc = sbi_sse_init(scratch, true);
 | 
			
		||||
	if (rc) {
 | 
			
		||||
		sbi_printf("%s: sse init failed (error %d)\n", __func__, rc);
 | 
			
		||||
		sbi_hart_hang();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = sbi_pmu_init(scratch, true);
 | 
			
		||||
	if (rc) {
 | 
			
		||||
		sbi_printf("%s: pmu init failed (error %d)\n",
 | 
			
		||||
@@ -445,6 +452,10 @@ static void __noreturn init_warm_startup(struct sbi_scratch *scratch,
 | 
			
		||||
	if (rc)
 | 
			
		||||
		sbi_hart_hang();
 | 
			
		||||
 | 
			
		||||
	rc = sbi_sse_init(scratch, false);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		sbi_hart_hang();
 | 
			
		||||
 | 
			
		||||
	rc = sbi_pmu_init(scratch, false);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		sbi_hart_hang();
 | 
			
		||||
@@ -653,6 +664,8 @@ void __noreturn sbi_exit(struct sbi_scratch *scratch)
 | 
			
		||||
 | 
			
		||||
	sbi_platform_early_exit(plat);
 | 
			
		||||
 | 
			
		||||
	sbi_sse_exit(scratch);
 | 
			
		||||
 | 
			
		||||
	sbi_pmu_exit(scratch);
 | 
			
		||||
 | 
			
		||||
	sbi_timer_exit(scratch);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1130
									
								
								lib/sbi/sbi_sse.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1130
									
								
								lib/sbi/sbi_sse.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -20,6 +20,7 @@
 | 
			
		||||
#include <sbi/sbi_trap_ldst.h>
 | 
			
		||||
#include <sbi/sbi_pmu.h>
 | 
			
		||||
#include <sbi/sbi_scratch.h>
 | 
			
		||||
#include <sbi/sbi_sse.h>
 | 
			
		||||
#include <sbi/sbi_timer.h>
 | 
			
		||||
#include <sbi/sbi_trap.h>
 | 
			
		||||
 | 
			
		||||
@@ -337,6 +338,10 @@ struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx)
 | 
			
		||||
trap_done:
 | 
			
		||||
	if (rc)
 | 
			
		||||
		sbi_trap_error(msg, rc, tcntx);
 | 
			
		||||
 | 
			
		||||
	if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) != PRV_M)
 | 
			
		||||
		sbi_sse_process_pending_events(regs);
 | 
			
		||||
 | 
			
		||||
	sbi_trap_set_context(scratch, tcntx->prev_context);
 | 
			
		||||
	return tcntx;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user