mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-27 16:01:27 +00:00
riscv: allow resume after exception
If CSRs like seed are readable by S-mode, may not be determinable by S-mode. For safe driver probing allow to resume via a longjmp after an exception. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>
This commit is contained in:
parent
b8a902b814
commit
9757cae991
4 changed files with 65 additions and 0 deletions
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <efi_loader.h>
|
#include <efi_loader.h>
|
||||||
#include <hang.h>
|
#include <hang.h>
|
||||||
|
#include <interrupt.h>
|
||||||
#include <irq_func.h>
|
#include <irq_func.h>
|
||||||
#include <asm/global_data.h>
|
#include <asm/global_data.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
@ -21,6 +22,13 @@
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
static struct resume_data *resume;
|
||||||
|
|
||||||
|
void set_resume(struct resume_data *data)
|
||||||
|
{
|
||||||
|
resume = data;
|
||||||
|
}
|
||||||
|
|
||||||
static void show_efi_loaded_images(uintptr_t epc)
|
static void show_efi_loaded_images(uintptr_t epc)
|
||||||
{
|
{
|
||||||
efi_print_image_infos((void *)epc);
|
efi_print_image_infos((void *)epc);
|
||||||
|
@ -105,6 +113,11 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs)
|
||||||
"Store/AMO page fault",
|
"Store/AMO page fault",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (resume) {
|
||||||
|
resume->code = code;
|
||||||
|
longjmp(resume->jump, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (code < ARRAY_SIZE(exception_code))
|
if (code < ARRAY_SIZE(exception_code))
|
||||||
printf("Unhandled exception: %s\n", exception_code[code]);
|
printf("Unhandled exception: %s\n", exception_code[code]);
|
||||||
else
|
else
|
||||||
|
|
|
@ -12,6 +12,7 @@ U-Boot API documentation
|
||||||
efi
|
efi
|
||||||
event
|
event
|
||||||
getopt
|
getopt
|
||||||
|
interrupt
|
||||||
linker_lists
|
linker_lists
|
||||||
lmb
|
lmb
|
||||||
logging
|
logging
|
||||||
|
|
6
doc/api/interrupt.rst
Normal file
6
doc/api/interrupt.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
.. SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
Interrupt API
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. kernel-doc:: include/interrupt.h
|
45
include/interrupt.h
Normal file
45
include/interrupt.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include <asm/setjmp.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct resume_data - data for resume after interrupt
|
||||||
|
*/
|
||||||
|
struct resume_data {
|
||||||
|
/** @jump: longjmp buffer */
|
||||||
|
jmp_buf jump;
|
||||||
|
/** @code: exception code */
|
||||||
|
ulong code;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set_resume() - set longjmp buffer for resuming after exception
|
||||||
|
*
|
||||||
|
* By calling this function it is possible to use a long jump to catch an
|
||||||
|
* exception. The caller sets the long jump buffer with set_resume() and then
|
||||||
|
* executes setjmp(). If an exception occurs, the code will return to the
|
||||||
|
* setjmp caller(). The exception code will be returned in @data->code.
|
||||||
|
*
|
||||||
|
* After the critical operation call set_resume(NULL) so that an exception in
|
||||||
|
* another part of the code will not accidently invoke the long jump.
|
||||||
|
*
|
||||||
|
* .. code-block:: c
|
||||||
|
*
|
||||||
|
* // This example shows how to use set_resume().
|
||||||
|
*
|
||||||
|
* struct resume_data resume;
|
||||||
|
* int ret;
|
||||||
|
*
|
||||||
|
* set_resume(&resume);
|
||||||
|
* ret = setjmp(resume.jump);
|
||||||
|
* if (ret) {
|
||||||
|
* printf("An exception %ld occurred\n", resume.code);
|
||||||
|
* } else {
|
||||||
|
* // Do what might raise an exception here.
|
||||||
|
* }
|
||||||
|
* set_resume(NULL);
|
||||||
|
*
|
||||||
|
* @data: pointer to structure with longjmp address
|
||||||
|
* Return: 0 before an exception, 1 after an exception occurred
|
||||||
|
*/
|
||||||
|
void set_resume(struct resume_data *data);
|
Loading…
Add table
Reference in a new issue