[PATCH v4 09/13] arm64: kernel: Add arch-specific SDEI entry code and CPU masking

Catalin Marinas catalin.marinas at arm.com
Wed Oct 18 04:18:02 PDT 2017


On Tue, Oct 17, 2017 at 06:44:28PM +0100, James Morse wrote:
> The Software Delegated Exception Interface (SDEI) is an ARM standard
> for registering callbacks from the platform firmware into the OS.
> This is typically used to implement RAS notifications.
> 
> Such notifications enter the kernel at the registered entry-point
> with the register values of the interrupted CPU context. Because this
> is not a CPU exception, it cannot reuse the existing entry code.
> (crucially we don't implicitly know which exception level we interrupted),
> 
> Add an sdei-entry.S asm file to set us up for calling into C code. If
> the event interrupted code that had interrupts masked, we always return
> to that location. Otherwise we pretend this was an IRQ, and use SDEI's
> complete_and_resume call to return to vbar_el1 + offset.
> 
> This allows the kernel to deliver signals to user space processes. For
> KVM this triggers the world switch, a quick spin round vcpu_run, then
> back into the guest, unless there are pending signals.
> 
> Add sdei_mask_local_cpu() calls to the smp_send_stop() code, this covers
> the panic() code-path, which doesn't invoke cpuhotplug notifiers.
> 
> Because we can interrupt entry-from/exit-to another EL, we can't trust the
> value in sp_el0 or x29, even if we interrupted the kernel, in this case
> the code in entry.S will save/restore sp_el0 and use the value in
> __entry_task.
> 
> When we have VMAP stacks we can interrupt the stack-overflow test, which
> stirs x0 into sp, meaning we have to have our own VMAP stack.
> 
> Signed-off-by: James Morse <james.morse at arm.com>

Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>

> +static __kprobes unsigned long _sdei_handler(struct pt_regs *regs,
> +					     struct sdei_registered_event *arg)
> +{
> +	u32 mode;
> +	int i, err = 0;
> +	const int clobbered_registers = 4;
> +	u64 elr = read_sysreg(elr_el1);
> +	u32 kernel_mode = read_sysreg(CurrentEL) | 1;	/* +SPSel */
> +	unsigned long vbar = read_sysreg(vbar_el1);
> +
> +	/* Retrieve the missing registers values */
> +	for (i = 0; i < clobbered_registers; i++) {
> +		/* from within the handler, this call always succeeds */
> +		sdei_api_event_context(i, &regs->regs[i]);
> +	}
> +
> +	/*
> +	 * We didn't take an exception to get here, set PAN. UAO will be cleared
> +	 * by sdei_event_handler()s set_fs(USER_DS) call.
> +	 */
> +	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,
> +			CONFIG_ARM64_PAN));

We have a similar asm in __cpu_suspend_exit(), so there's precedent. As
a separate patch (not part of this series), we should move them into
a macro, e.g. __uaccess_disable_hw_pan() (enabling as well for
consistency).

-- 
Catalin



More information about the linux-arm-kernel mailing list