|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v1 1/4] xen/riscv: add exception table support
On 3/24/26 3:04 PM, Jan Beulich wrote: On 13.03.2026 17:44, Oleksii Kurochko wrote:Introduce exception table handling for RISC-V so faults from selected instructions can be recovered via fixup handlers instead of being treated as fatal. Add the RISC-V exception table format, sorting at boot to allow binary search used furthuer, and lookup from the trap handler. Update the linker script to emit the .ex_table section using introduced common EX_TABLE macro shared with other architectures. Also, the __start___ext_table is aligned now by POINTER_ALIGN instead of just using hard-coded 8 as there is no too much sense to align __start___ext_table by 8 for 32-bit systems.Nit: The identifier named here twice isn't correct (extra 't'). No, I'll use singular form.I called it tables as potentially I will need a different types of exception table, so I counted different types as different exception tables. --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -3,6 +3,7 @@ obj-y += cpufeature.o obj-y += domain.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += entry.o +obj-$(CONFIG_HAS_EX_TABLE) += extables.oSimply obj-y please as long as the select is unconditional. I see your point and at the moment there is no also other options howto handle case(s) for which exception table is introduced now. But if potentially another mechanism will be introduced what will be the point to have extable.o code in the final binary?
It makes sense. Lets switch to "long".
I will introduce then void init_or_livepatch sort_exception_table(...) and re-use it inside sort_extable() with renaming it to sort_exception_tables() to take into account live-patching which requires sort_exception_table().
The stuff is easier with such implementation.We could really drop cmp_ex_search() if to pass struct exception_table_entry instead of (unsigned long *) so the following will allow to drop cmp_ex_search():
@@ -78,12 +78,15 @@ bool fixup_exception(struct cpu_user_regs *regs)
unsigned long pc = regs->sepc;
const struct virtual_region *region = find_text_region(pc);
const struct exception_table_entry *ex;
+ struct exception_table_entry key;
if ( !region || !region->ex )
return false;
- ex = bsearch(&pc, region->ex, region->ex_end - region->ex,
- sizeof(struct exception_table_entry), cmp_ex_search);
+ key.insn = pc - (unsigned long)&key.insn;
+
+ ex = bsearch(&key, region->ex, region->ex_end - region->ex,
+ sizeof(struct exception_table_entry), cmp_ex_sort
/*cmp_ex_search*/);
Also, then I will rename l and r variable inside cmp_ex_sort() to insn_a and insn_b. + const unsigned long insn = ex_insn(elt); + + /* avoid overflow */ + return (k > insn) - (k < insn); +} + +static bool ex_handler_fixup(const struct exception_table_entry *ex, + struct cpu_user_regs *regs)Nit: Bad indentation. As potentially we could have other handlers which might return not only true, so it will be easier to handle return type inside fixup_exception(). But if you think there is no any sense to have for handlers the same signature then I am also return void instead of bool for ex_handler_fixup(). --- /dev/null +++ b/xen/arch/riscv/include/asm/extables.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef ASM__RISCV__ASM_EXTABLES_H +#define ASM__RISCV__ASM_EXTABLES_H + +#ifdef __ASSEMBLER__ + +#define ASM_EXTABLE(insn, fixup) \ + .pushsection .ex_table, "a"; \ + .balign 4; \ + .long ((insn) - .); \ + .long ((fixup) - .); \Nit: More uses of hard tabs. Maybe that alone is the reason for the mis-aligned trailing backslashes.+ .popsection; +.endmI can't spot the corresponding .macro. What's going on here?
Good question... It was:
.macro asm_extable, insn, fixup
ASM_EXTABLE(\insn, \fixup)
.endm
It is. "No register" meant no general purpose register. I will reprase this part to:+ +/* + * The exception table consists of pairs of relative offsets: the first + * is the relative offset to an instruction that is allowed to fault, + * and the second is the relative offset at which the program should + * continue. No registers are modified, so it is entirely up to the + * continuation code to figure out what to do.And the program counter is not a register? No general-purpose registers are modified by the exception handling mechanism itself, so it is up to the fixup code to handle any necessary state cleanup. Or it could be just dropped. + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries.What is this paragraph about? There's nothing "below" which I can associate this with. It is orphaned from Linux (generally it is about that some functions from uaccess.h are using ASM_EXTABLE, the similar for Xen has in x86/uaccess.h). I'll rephrase it to: * The exception table and fixup code live out of line with the main * instruction path. This means when everything is well, we don't even * have to jump over them. Further, they do not intrude on our cache or * tlb entries.
To handle the potential in future case that CONFIG_HAS_EX_TABLE will become conditional. I thought that it makes sense to be in sync with common/virtual_region.c also uses ifdef around exception table related information. --- a/xen/include/xen/xen.lds.h +++ b/xen/include/xen/xen.lds.h @@ -219,4 +219,14 @@ #define VPCI_ARRAY #endif+#ifdef CONFIG_HAS_EX_TABLENo real need for this? Here I can agree that there is not reason as if CONFIG_HAS_EX_TABLE is nthen no one is expected to use exception table so the section is empty and don't occupy any extra space in binary (except potentially some space because of alignment). +#define EX_TABLE \ + . = ALIGN(POINTER_ALIGN); \Strictly speaking the original 8 (in x86 code) as much as this is more than we need - each element is a struct of 2 4-byte entities, after all. For the current struct - yes, we can do . = ALIGN(4) but if the architecture will add uint64_t inside (or unsigned long) shouldn't we then have ALIGN(POINTER_ALIGN)? Thanks. ~ Oleksii
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |