diff --git a/arch/x86/extables.c b/arch/x86/extables.c new file mode 100644 index 00000000..5f09d479 --- /dev/null +++ b/arch/x86/extables.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 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. + */ + +void init_extables(void) { /* no-op */ +} 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..f9a60c3c 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 @@ -287,9 +289,30 @@ void print_callstack(const void *sp, const void *ip) { printk("\n"); } +static inline void use_extables(struct cpu_regs *regs) { + 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"); + } + } + } +} + void do_exception(struct cpu_regs *regs) { static char ec_str[32], panic_str[128]; + use_extables(regs); + dump_regs(regs); print_callstack(_ptr(regs->_ASM_SP), _ptr(regs->_ASM_IP)); diff --git a/common/setup.c b/common/setup.c index 7c38ff27..94b9fd62 100644 --- a/common/setup.c +++ b/common/setup.c @@ -254,12 +254,12 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, if (opt_debug) dump_pagetables(); - /* TODO: Exception tables */ - init_percpu(); init_traps(get_bsp_cpu_id()); + init_extables(); + init_slab(); /* Try to initialize ACPI (and MADT) */ diff --git a/drivers/acpi/acpica/osl.c b/drivers/acpi/acpica/osl.c index 94a58925..cfa7cbef 100644 --- a/drivers/acpi/acpica/osl.c +++ b/drivers/acpi/acpica/osl.c @@ -207,11 +207,44 @@ void *AcpiOsAllocate(ACPI_SIZE Size) { return kmalloc(Size); } void AcpiOsFree(void *Memory) { kfree(Memory); } -/* FIXME: Check if pages are mapped (with exception tables) */ -BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length) { return true; } +BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length) { + volatile bool success = false; + char *mem; + + for (mfn_t mfn = virt_to_mfn(Memory); mfn <= virt_to_mfn((char *) Memory + Length); + ++mfn) { + success = false; + mem = mfn_to_virt_kern(mfn); + asm volatile("1: movq ( %[mem] ), %%rax; movq $1, %[success];" + "2:" ASM_EXTABLE(1b, 2b) + : [ success ] "=m"(success) + : [ mem ] "r"(mem) + : "rax", "memory"); + if (!success) + return false; + } + return success; +} -/* FIXME: Check if pages are mapped and writeable (with exception tables) */ -BOOLEAN AcpiOsWriteable(void *Memory, ACPI_SIZE Length) { return true; } +BOOLEAN AcpiOsWriteable(void *Memory, ACPI_SIZE Length) { + volatile bool success = false; + char *mem; + + for (mfn_t mfn = virt_to_mfn(Memory); mfn <= virt_to_mfn((char *) Memory + Length); + ++mfn) { + success = false; + mem = mfn_to_virt_kern(mfn); + asm volatile("1: orq $0, ( %[mem] ); movq $1, %[success];" + "2:" ASM_EXTABLE(1b, 2b) + : [ success ] "=m"(success), [ mem ] "=r"(mem) + : + : "memory"); + if (!success) + return false; + } + + return success; +} void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length) { unsigned offset = PhysicalAddress & ~PAGE_MASK; diff --git a/include/arch/x86/asm-macros.h b/include/arch/x86/asm-macros.h index ab5ef648..6b946d57 100644 --- a/include/arch/x86/asm-macros.h +++ b/include/arch/x86/asm-macros.h @@ -47,6 +47,9 @@ #define PT_PADDR(table, shift) (((.- (table)) / PTE_SIZE) << (shift)) +#define PUSHSECTION(name) ".pushsection " STR(name) " ;\n" +#define POPSECTION ".popsection;\n" + #ifdef __ASSEMBLY__ /* clang-format off */ diff --git a/include/extables.h b/include/extables.h new file mode 100644 index 00000000..a5d0984d --- /dev/null +++ b/include/extables.h @@ -0,0 +1,53 @@ +/* + * 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 { + x86_reg_t fault_addr; + x86_reg_t fixup; + extable_entry_callback_t cb; +} __packed; +typedef struct extable_entry extable_entry_t; + +#if defined(__x86_64__) +#define ASM_EXTABLE_HANDLER(fault_address, fixup, handler) \ + PUSHSECTION(.extables) \ + ".quad " STR(fault_address) ", " STR(fixup) ", " STR(handler) ";\n" POPSECTION +#else +#define ASM_EXTABLE_HANDLER(fault_address, fixup, handler) \ + PUSHSECTION(.extables) \ + ".long " STR(fault_address) ", " STR(fixup) ", " STR(handler) ";\n" POPSECTION +#endif + +#define ASM_EXTABLE(fault_address, fixup) ASM_EXTABLE_HANDLER(fault_address, fixup, 0) + +extern void init_extables(void); + +#endif diff --git a/include/lib.h b/include/lib.h index c3a032b7..abfe8143 100644 --- a/include/lib.h +++ b/include/lib.h @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Amazon.com, Inc. or its affiliates. + * Copyright © 2021 Amazon.com, Inc. or its affiliates. * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -434,4 +434,7 @@ extern void srand(unsigned s); extern int rand(void); +extern bool wrmsr_safe(uint32_t msr_idx, uint64_t value); +extern bool rdmsr_safe(uint32_t msr_idx, uint64_t *value); + #endif /* KTF_LIB_H */ diff --git a/include/mm/regions.h b/include/mm/regions.h index 8995baed..65ef701f 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/lib/lib.c b/lib/lib.c index 053e638d..e02179ba 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Amazon.com, Inc. or its affiliates. + * Copyright © 2021 Amazon.com, Inc. or its affiliates. * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,6 +25,8 @@ #include #include +#include + void __noreturn halt(void) { cli(); @@ -42,3 +44,33 @@ int rand(void) { seed = 6364136223846793005ULL * seed + 1; return seed >> 33; } + +/* + * read the msr_idx msr into value; the result is valid iff the returned value is true + */ +bool rdmsr_safe(uint32_t msr_idx, uint64_t *value) { + volatile bool success = false; + uint32_t low, high; + + asm volatile("1: rdmsr; movb $1, %[success];" + "2:" ASM_EXTABLE(1b, 2b) + : "=a"(low), "=d"(high), [ success ] "=m"(success) + : "c"(msr_idx) + : "memory"); + *value = (((uint64_t) high) << 32) | low; + return success; +} + +/* + * write to the msr_idx msr; the result is valid iff the returned value is true + */ +bool wrmsr_safe(uint32_t msr_idx, uint64_t value) { + volatile bool success = false; + + asm volatile("1: wrmsr; movq $1, %[success];" + "2:" ASM_EXTABLE(1b, 2b) + : [ success ] "=m"(success) + : "c"(msr_idx), "a"((uint32_t) value), "d"((uint32_t)(value >> 32)) + : "memory"); + return success; +} 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 ),