mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
arm64: sdei: move uaccess logic to arch/arm64/
The SDEI support code is split across arch/arm64/ and drivers/firmware/, largley this is split so that the arch-specific portions are under arch/arm64, and the management logic is under drivers/firmware/. However, exception entry fixups are currently under drivers/firmware. Let's move the exception entry fixups under arch/arm64/. This de-clutters the management logic, and puts all the arch-specific portions in one place. Doing this also allows the fixups to be applied earlier, so things like PAN and UAO will be in a known good state before we run other logic. This will also make subsequent refactoring easier. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: James Morse <james.morse@arm.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20201202131558.39270-2-mark.rutland@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
committed by
Catalin Marinas
parent
d87a8e65b5
commit
a0ccf2ba68
@@ -178,12 +178,6 @@ static __kprobes unsigned long _sdei_handler(struct pt_regs *regs,
|
|||||||
sdei_api_event_context(i, ®s->regs[i]);
|
sdei_api_event_context(i, ®s->regs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We didn't take an exception to get here, set PAN. UAO will be cleared
|
|
||||||
* by sdei_event_handler()s force_uaccess_begin() call.
|
|
||||||
*/
|
|
||||||
__uaccess_enable_hw_pan();
|
|
||||||
|
|
||||||
err = sdei_event_handler(regs, arg);
|
err = sdei_event_handler(regs, arg);
|
||||||
if (err)
|
if (err)
|
||||||
return SDEI_EV_FAILED;
|
return SDEI_EV_FAILED;
|
||||||
@@ -227,6 +221,16 @@ asmlinkage __kprobes notrace unsigned long
|
|||||||
__sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
|
__sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
|
||||||
{
|
{
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
|
mm_segment_t orig_addr_limit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We didn't take an exception to get here, so the HW hasn't set PAN or
|
||||||
|
* cleared UAO, and the exception entry code hasn't reset addr_limit.
|
||||||
|
* Set PAN, then use force_uaccess_begin() to clear UAO and reset
|
||||||
|
* addr_limit.
|
||||||
|
*/
|
||||||
|
__uaccess_enable_hw_pan();
|
||||||
|
orig_addr_limit = force_uaccess_begin();
|
||||||
|
|
||||||
nmi_enter();
|
nmi_enter();
|
||||||
|
|
||||||
@@ -234,5 +238,7 @@ __sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg)
|
|||||||
|
|
||||||
nmi_exit();
|
nmi_exit();
|
||||||
|
|
||||||
|
force_uaccess_end(orig_addr_limit);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,6 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/uaccess.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The call to use to reach the firmware.
|
* The call to use to reach the firmware.
|
||||||
@@ -1092,26 +1091,13 @@ int sdei_event_handler(struct pt_regs *regs,
|
|||||||
struct sdei_registered_event *arg)
|
struct sdei_registered_event *arg)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
mm_segment_t orig_addr_limit;
|
|
||||||
u32 event_num = arg->event_num;
|
u32 event_num = arg->event_num;
|
||||||
|
|
||||||
/*
|
|
||||||
* Save restore 'fs'.
|
|
||||||
* The architecture's entry code save/restores 'fs' when taking an
|
|
||||||
* exception from the kernel. This ensures addr_limit isn't inherited
|
|
||||||
* if you interrupted something that allowed the uaccess routines to
|
|
||||||
* access kernel memory.
|
|
||||||
* Do the same here because this doesn't come via the same entry code.
|
|
||||||
*/
|
|
||||||
orig_addr_limit = force_uaccess_begin();
|
|
||||||
|
|
||||||
err = arg->callback(event_num, regs, arg->callback_arg);
|
err = arg->callback(event_num, regs, arg->callback_arg);
|
||||||
if (err)
|
if (err)
|
||||||
pr_err_ratelimited("event %u on CPU %u failed with error: %d\n",
|
pr_err_ratelimited("event %u on CPU %u failed with error: %d\n",
|
||||||
event_num, smp_processor_id(), err);
|
event_num, smp_processor_id(), err);
|
||||||
|
|
||||||
force_uaccess_end(orig_addr_limit);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
NOKPROBE_SYMBOL(sdei_event_handler);
|
NOKPROBE_SYMBOL(sdei_event_handler);
|
||||||
|
Reference in New Issue
Block a user