forked from Mirrors/opensbi
		
	lib: sbi: Add support to mask/unmask SSE events
Add functions to globally mask/unmask supervisor software events on the calling hart. Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com> Reviewed-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
		
				
					committed by
					
						
						Anup Patel
					
				
			
			
				
	
			
			
			
						parent
						
							ebbd276146
						
					
				
				
					commit
					b919daf495
				
			@@ -342,6 +342,8 @@ enum sbi_cppc_reg_id {
 | 
				
			|||||||
#define SBI_EXT_SSE_DISABLE		0x00000005
 | 
					#define SBI_EXT_SSE_DISABLE		0x00000005
 | 
				
			||||||
#define SBI_EXT_SSE_COMPLETE		0x00000006
 | 
					#define SBI_EXT_SSE_COMPLETE		0x00000006
 | 
				
			||||||
#define SBI_EXT_SSE_INJECT		0x00000007
 | 
					#define SBI_EXT_SSE_INJECT		0x00000007
 | 
				
			||||||
 | 
					#define SBI_EXT_SSE_HART_UNMASK		0x00000008
 | 
				
			||||||
 | 
					#define SBI_EXT_SSE_HART_MASK		0x00000009
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SBI SSE Event Attributes. */
 | 
					/* SBI SSE Event Attributes. */
 | 
				
			||||||
enum sbi_sse_attr_id {
 | 
					enum sbi_sse_attr_id {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
					int sbi_sse_register(uint32_t event_id, unsigned long handler_entry_pc,
 | 
				
			||||||
		     unsigned long handler_entry_arg);
 | 
							     unsigned long handler_entry_arg);
 | 
				
			||||||
int sbi_sse_unregister(uint32_t event_id);
 | 
					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_enable(uint32_t event_id);
 | 
				
			||||||
int sbi_sse_disable(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_complete(struct sbi_trap_regs *regs, struct sbi_ecall_return *out);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,12 @@ static int sbi_ecall_sse_handler(unsigned long extid, unsigned long funcid,
 | 
				
			|||||||
	case SBI_EXT_SSE_INJECT:
 | 
						case SBI_EXT_SSE_INJECT:
 | 
				
			||||||
		ret = sbi_sse_inject_from_ecall(regs->a0, regs->a1, out);
 | 
							ret = sbi_sse_inject_from_ecall(regs->a0, regs->a1, out);
 | 
				
			||||||
		break;
 | 
							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:
 | 
						default:
 | 
				
			||||||
		ret = SBI_ENOTSUPP;
 | 
							ret = SBI_ENOTSUPP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,6 +142,12 @@ struct sse_hart_state {
 | 
				
			|||||||
	 * List of local events allocated at boot time.
 | 
						 * List of local events allocated at boot time.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	struct sbi_sse_event *local_events;
 | 
						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 masked;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -610,6 +616,10 @@ void sbi_sse_process_pending_events(struct sbi_trap_regs *regs)
 | 
				
			|||||||
	struct sbi_sse_event *e;
 | 
						struct sbi_sse_event *e;
 | 
				
			||||||
	struct sse_hart_state *state = sse_thishart_state_ptr();
 | 
						struct sse_hart_state *state = sse_thishart_state_ptr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* if sse is masked on this hart, do nothing */
 | 
				
			||||||
 | 
						if (state->masked)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(&state->enabled_event_lock);
 | 
						spin_lock(&state->enabled_event_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sbi_list_for_each_entry(e, &state->enabled_event_list, node) {
 | 
						sbi_list_for_each_entry(e, &state->enabled_event_list, node) {
 | 
				
			||||||
@@ -807,6 +817,36 @@ int sbi_sse_disable(uint32_t event_id)
 | 
				
			|||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sbi_sse_hart_mask(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sse_hart_state *state = sse_thishart_state_ptr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!state)
 | 
				
			||||||
 | 
							return SBI_EFAIL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state->masked)
 | 
				
			||||||
 | 
							return SBI_EALREADY_STARTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state->masked = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SBI_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sbi_sse_hart_unmask(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sse_hart_state *state = sse_thishart_state_ptr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!state)
 | 
				
			||||||
 | 
							return SBI_EFAIL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!state->masked)
 | 
				
			||||||
 | 
							return SBI_EALREADY_STOPPED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state->masked = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SBI_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sbi_sse_inject_from_ecall(uint32_t event_id, unsigned long hartid,
 | 
					int sbi_sse_inject_from_ecall(uint32_t event_id, unsigned long hartid,
 | 
				
			||||||
			      struct sbi_ecall_return *out)
 | 
								      struct sbi_ecall_return *out)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -1127,6 +1167,9 @@ int sbi_sse_init(struct sbi_scratch *scratch, bool cold_boot)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		shs->local_events = (struct sbi_sse_event *)(shs + 1);
 | 
							shs->local_events = (struct sbi_sse_event *)(shs + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* SSE events are masked until hart unmasks them */
 | 
				
			||||||
 | 
							shs->masked = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sse_set_hart_state_ptr(scratch, shs);
 | 
							sse_set_hart_state_ptr(scratch, shs);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user