diff --git a/arch/x86/link.ld b/arch/x86/link.ld index fe5e93dd..aac61e12 100644 --- a/arch/x86/link.ld +++ b/arch/x86/link.ld @@ -170,6 +170,14 @@ SECTIONS __end_data = .; } :kernel + .extables BLOCK(4K) : ALIGN(4K) + { + __start_extables = .; + *(.extables) + . = ALIGN(4K); + __end_extables = .; + } :kernel + .bss BLOCK(4K) : ALIGN(4K) { . = ALIGN(4K); diff --git a/arch/x86/traps.c b/arch/x86/traps.c index 20843690..8c8a5bff 100644 --- a/arch/x86/traps.c +++ b/arch/x86/traps.c @@ -28,8 +28,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -289,6 +291,22 @@ void print_callstack(const void *sp, const void *ip) { void do_exception(struct cpu_regs *regs) { static char ec_str[32], panic_str[128]; + for (extable_entry_t *cur = __start_extables; cur < __end_extables; ++cur) { + if (regs->_ASM_IP == cur->fault_addr) { + if (cur->fixup) { + regs->_ASM_IP = cur->fixup; + } + if (cur->cb) { + cur->cb(regs); + } + if (cur->fixup || cur->cb) { + return; + } + else { + panic("fixup or cb must be set in the extable_entry\n"); + } + } + } dump_regs(regs); print_callstack(_ptr(regs->_ASM_SP), _ptr(regs->_ASM_IP)); diff --git a/include/extables.h b/include/extables.h new file mode 100644 index 00000000..9e387e39 --- /dev/null +++ b/include/extables.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2021 Amazon.com, Inc. or its affiliates. + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef KTF_EXTABLES_H +#define KTF_EXTABLES_H + +#include + +typedef void(extable_entry_callback_t)(cpu_regs_t *regs); + +struct extable_entry { + uint64_t fault_addr; + + uint64_t fixup; + extable_entry_callback_t *cb; +}; +typedef struct extable_entry extable_entry_t; + +#define ASM_EXTABLE_HANDLER(fault_address, fixup, handler) \ + ".pushsection .extables;\n" \ + ".quad " STR(fault_address) ", " STR(fixup) ", " STR(handler) ";\n" \ + ".popsection;\n" + +#endif diff --git a/include/mm/regions.h b/include/mm/regions.h index 3111927d..ba8c5821 100644 --- a/include/mm/regions.h +++ b/include/mm/regions.h @@ -38,6 +38,7 @@ #ifndef __ASSEMBLY__ #include +#include #include #include @@ -56,6 +57,7 @@ extern unsigned long __start_bss_init[], __end_bss_init[]; extern unsigned long __start_text_rmode[], __end_text_rmode[]; extern unsigned long __start_data_rmode[], __end_data_rmode[]; +extern struct extable_entry __start_extables[], __end_extables[]; extern unsigned long __start_bss_rmode[], __end_bss_rmode[]; extern struct ktf_param __start_cmdline[], __end_cmdline[]; diff --git a/mm/regions.c b/mm/regions.c index bdafd433..d53408da 100644 --- a/mm/regions.c +++ b/mm/regions.c @@ -60,6 +60,7 @@ addr_range_t addr_ranges[] = { KERNEL_RANGE( ".text", L1_PROT_RO, __start_text, __end_text ), KERNEL_RANGE( ".data", L1_PROT, __start_data, __end_data ), + KERNEL_RANGE( ".extables", L1_PROT_RO, __start_extables, __end_extables ), KERNEL_RANGE( ".bss", L1_PROT, __start_bss, __end_bss ), KERNEL_RANGE( ".rodata", L1_PROT_RO, __start_rodata, __end_rodata ), KERNEL_RANGE( ".symbols", L1_PROT_RO, __start_symbols, __end_symbols ),