From e855a262fd872171156894e9045814cb0f346dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Mon, 18 Feb 2019 00:00:00 +0000 Subject: [PATCH] aarch64 baremetal svc factored out for C and asm --- README.adoc | 22 +- baremetal/add.c | 4 +- baremetal/arch/aarch64/add.S | 2 +- baremetal/arch/aarch64/common_aarch64.h | 29 --- baremetal/arch/aarch64/fadd.S | 6 +- baremetal/arch/aarch64/svc.c | 37 ++-- baremetal/arch/aarch64/svc_asm.S | 217 +------------------- baremetal/arch/aarch64/timer.c | 39 +--- baremetal/arch/arm/add.S | 2 +- baremetal/interactive/assert_fail.c | 4 +- baremetal/lib/aarch64.S | 21 ++ build-baremetal | 2 +- common.c | 7 - common.h | 8 - lkmc.c | 28 +++ lkmc.h | 259 ++++++++++++++++++++++++ userland/Makefile | 2 +- 17 files changed, 355 insertions(+), 334 deletions(-) delete mode 100644 baremetal/arch/aarch64/common_aarch64.h delete mode 100644 common.c delete mode 100644 common.h create mode 100644 lkmc.c create mode 100644 lkmc.h diff --git a/README.adoc b/README.adoc index d7a52a2..88158b9 100644 --- a/README.adoc +++ b/README.adoc @@ -11293,21 +11293,19 @@ output: ==== ARM exception handling -Setup a handler for `svc`, do an `svc`, and observe that the handler got called and returned: - -.... -./run --arch aarch64 --baremetal arch/aarch64/svc_asm -.... - -Source: link:baremetal/arch/aarch64/svc_asm.S[] - -TODO: factor out the above, and make it also work on C: +Setup a handler for `svc`, do an `svc`, and observe that the handler got called and returned from C and assembly: .... ./run --arch aarch64 --baremetal arch/aarch64/svc +./run --arch aarch64 --baremetal arch/aarch64/svc_asm .... -Output: +Sources: + +* link:baremetal/arch/aarch64/svc_asm.S[] +* link:baremetal/arch/aarch64/svc.c[] + +Output for the C one: .... daif 0x3c0 @@ -11315,8 +11313,6 @@ spsel 0x1 vbar_el1 0x0 .... -Source: link:baremetal/arch/aarch64/svc.c[] - The vector table format is described on <> Table D1-7 "Vector offsets from vector table base address". A good representation of the format of the vector table can also be found at <> Table 10-2 "Vector table offsets from vector table base address". @@ -13034,7 +13030,7 @@ to the terminal, then our run scripts detect that and exit with status `1`. This magic output string is notably used by: -* the `common_assert_fail()` function, which is used by <> +* the `lkmc_assert_fail()` function, which is used by <> * link:rootfs_overlay/test_fail.sh[], which is used by <> ==== Non-automated tests diff --git a/baremetal/add.c b/baremetal/add.c index 3ec6671..b363317 100644 --- a/baremetal/add.c +++ b/baremetal/add.c @@ -1,4 +1,4 @@ -#include +#include int main(void) { int i, j, k; @@ -9,5 +9,5 @@ int main(void) { k = i + j; /* test-gdb-result */ if (k != 3) - common_assert_fail(); + lkmc_assert_fail(); } diff --git a/baremetal/arch/aarch64/add.S b/baremetal/arch/aarch64/add.S index 6abad47..6c08fe8 100644 --- a/baremetal/arch/aarch64/add.S +++ b/baremetal/arch/aarch64/add.S @@ -7,6 +7,6 @@ main: /* test-gdb-result */ cmp x1, #3 beq 1f - bl common_assert_fail + bl lkmc_assert_fail 1: ret diff --git a/baremetal/arch/aarch64/common_aarch64.h b/baremetal/arch/aarch64/common_aarch64.h deleted file mode 100644 index 8c8db6e..0000000 --- a/baremetal/arch/aarch64/common_aarch64.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef COMMON_AARCH64_H -#define COMMON_AARCH64_H - -#include - -#define SYSREG_READ(type, name) \ - type sysreg_ ## name ## _read(void) { \ - type name; \ - __asm__ __volatile__("mrs %0, " #name : "=r" (name) : : ); \ - return name; \ - } - -#define SYSREG_WRITE(type, name) \ - void sysreg_ ## name ## _write(type name) { \ - __asm__ __volatile__("msr " #name ", %0" : : "r" (name) : ); \ - } - -#define SYSREG_READ_WRITE(name, type) \ - SYSREG_READ(name, type) \ - SYSREG_WRITE(name, type) - -SYSREG_READ_WRITE(uint32_t, daif) -SYSREG_READ_WRITE(uint32_t, spsel) -SYSREG_READ_WRITE(uint64_t, sp_el1) -SYSREG_READ_WRITE(uint64_t, vbar_el1) - -#define SVC(immediate) __asm__ __volatile__("svc " #immediate : : : ) - -#endif diff --git a/baremetal/arch/aarch64/fadd.S b/baremetal/arch/aarch64/fadd.S index e706a13..f9259f7 100644 --- a/baremetal/arch/aarch64/fadd.S +++ b/baremetal/arch/aarch64/fadd.S @@ -12,7 +12,7 @@ main: fmov d3, #4.0 fcmp d2, d3 beq 1f - bl common_assert_fail + bl lkmc_assert_fail 1: /* Now in 32-bit. */ @@ -26,7 +26,7 @@ main: fmov s3, #4.0 fcmp s2, s3 beq 1f - bl common_assert_fail + bl lkmc_assert_fail 1: /* Higher registers. */ @@ -40,6 +40,6 @@ main: /* test-gdb-d31 */ fcmp d30, d31 beq 1f - bl common_assert_fail + bl lkmc_assert_fail 1: ret diff --git a/baremetal/arch/aarch64/svc.c b/baremetal/arch/aarch64/svc.c index e1d9c81..11b15d7 100644 --- a/baremetal/arch/aarch64/svc.c +++ b/baremetal/arch/aarch64/svc.c @@ -2,33 +2,22 @@ #include #include -#include -#include "common_aarch64.h" +#include -void handle_svc() { - exit(0); +int myvar = 0; + +void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception) { + puts("trap handler"); + myvar = 1; } int main(void) { - /* View initial register values. */ - printf("daif 0x%" PRIx32 "\n", sysreg_daif_read()); - printf("spsel 0x%" PRIx32 "\n", sysreg_spsel_read()); - printf("vbar_el1 0x%" PRIx64 "\n", sysreg_vbar_el1_read()); - - /* Set registers to the values that we need. */ - sysreg_daif_write(0); - sysreg_vbar_el1_write(0); - printf("daif 0x%" PRIx32 "\n", sysreg_daif_read()); - printf("spsel 0x%" PRIx32 "\n", sysreg_spsel_read()); - printf("vbar_el1 0x%" PRIx64 "\n", sysreg_vbar_el1_read()); - - /* TODO this breaks execution because reading system registers that end - * in ELx "trap", leading into an exception on the upper EL. - */ - /*printf("sp_el1 0x%" PRIx64 "\n", sysreg_sp_el1_read());*/ - /*SVC(0);*/ - - /* Should never be reached. */ - /*common_assert_fail();*/ + /* View initial relevant register values. */ + printf("daif 0x%" PRIx32 "\n", lkmc_sysreg_daif_read()); + printf("spsel 0x%" PRIx32 "\n", lkmc_sysreg_spsel_read()); + printf("vbar_el1 0x%" PRIx64 "\n", lkmc_sysreg_vbar_el1_read()); + lkmc_assert(myvar == 0); + LKMC_SVC(0); + lkmc_assert(myvar == 1); return 0; } diff --git a/baremetal/arch/aarch64/svc_asm.S b/baremetal/arch/aarch64/svc_asm.S index 0feb7da..e92ad25 100644 --- a/baremetal/arch/aarch64/svc_asm.S +++ b/baremetal/arch/aarch64/svc_asm.S @@ -1,11 +1,7 @@ -/* TODO factor it out to make reusable. */ +#include .global main main: - /* Load the vector table. */ - ldr x0, =vector_table - msr vbar_el1, x0 - /* Do the svc. */ svc 0 @@ -14,13 +10,13 @@ main: ldr x1, mynewvar cmp x0, x1 beq 1f - bl common_assert_fail + bl lkmc_assert_fail 1: /* Go home. */ ret -common_trap_handler: +LKMC_GLOBAL(lkmc_vector_trap_handler) /* Modify myvar as a visible side effect. */ ldr x0, mynewvar ldr x1, =myvar @@ -31,210 +27,3 @@ myvar: .quad 0x0 mynewvar: .quad 0x12346789ABCDEF0 - -/* .h - * - * Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S - */ - -#define AARCH64_EXC_SYNC_SP0 (0x1) -#define AARCH64_EXC_IRQ_SP0 (0x2) -#define AARCH64_EXC_FIQ_SP0 (0x3) -#define AARCH64_EXC_SERR_SP0 (0x4) - -#define AARCH64_EXC_SYNC_SPX (0x11) -#define AARCH64_EXC_IRQ_SPX (0x12) -#define AARCH64_EXC_FIQ_SPX (0x13) -#define AARCH64_EXC_SERR_SPX (0x14) - -#define AARCH64_EXC_SYNC_AARCH64 (0x21) -#define AARCH64_EXC_IRQ_AARCH64 (0x22) -#define AARCH64_EXC_FIQ_AARCH64 (0x23) -#define AARCH64_EXC_SERR_AARCH64 (0x24) - -#define AARCH64_EXC_SYNC_AARCH32 (0x31) -#define AARCH64_EXC_IRQ_AARCH32 (0x32) -#define AARCH64_EXC_FIQ_AARCH32 (0x33) -#define AARCH64_EXC_SERR_AARCH32 (0x34) - -#if !defined(__ASSEMBLER__) -#include -typedef struct _exception_frame{ - uint64_t exc_type; - uint64_t exc_esr; - uint64_t exc_sp; - uint64_t exc_elr; - uint64_t exc_spsr; - uint64_t x0; - uint64_t x1; - uint64_t x2; - uint64_t x3; - uint64_t x4; - uint64_t x5; - uint64_t x6; - uint64_t x7; - uint64_t x8; - uint64_t x9; - uint64_t x10; - uint64_t x11; - uint64_t x12; - uint64_t x13; - uint64_t x14; - uint64_t x15; - uint64_t x16; - uint64_t x17; - uint64_t x18; - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - uint64_t x23; - uint64_t x24; - uint64_t x25; - uint64_t x26; - uint64_t x27; - uint64_t x28; - uint64_t x29; - uint64_t x30; -} exception_frame; -void common_trap_handler(exception_frame *exception); -#endif - -/* .S */ - -#define EXC_FRAME_SIZE (288) /* sizeof(exception_frame) */ -#define EXC_EXC_TYPE_OFFSET (0) /* offsetof(exception_frame, exc_type) */ -#define EXC_EXC_ESR_OFFSET (8) /* offsetof(exception_frame, exc_esr) */ -#define EXC_EXC_SP_OFFSET (16) /* offsetof(exception_frame, exc_sp) */ -#define EXC_EXC_ELR_OFFSET (24) /* offsetof(exception_frame, exc_elr) */ -#define EXC_EXC_SPSR_OFFSET (32) /* offsetof(exception_frame, exc_spsr) */ - -#define BUILD_TRAPFRAME(exc_type) \ - stp x29, x30, [sp, -16]!; \ - stp x27, x28, [sp, -16]!; \ - stp x25, x26, [sp, -16]!; \ - stp x23, x24, [sp, -16]!; \ - stp x21, x22, [sp, -16]!; \ - stp x19, x20, [sp, -16]!; \ - stp x17, x18, [sp, -16]!; \ - stp x15, x16, [sp, -16]!; \ - stp x13, x14, [sp, -16]!; \ - stp x11, x12, [sp, -16]!; \ - stp x9, x10, [sp, -16]!; \ - stp x7, x8, [sp, -16]!; \ - stp x5, x6, [sp, -16]!; \ - stp x3, x4, [sp, -16]!; \ - stp x1, x2, [sp, -16]!; \ - mrs x21, spsr_el1; \ - stp x21, x0, [sp, -16]!; \ - mrs x21, elr_el1; \ - stp xzr, x21, [sp, -16]!; \ - mov x21, (exc_type); \ - mrs x22, esr_el1; \ - stp x21, x22, [sp, -16]! - -#define STORE_TRAPED_SP \ - mrs x21, sp_el0; \ - str x21, [sp, EXC_EXC_SP_OFFSET] - -#define CALL_COMMON_TRAP_HANDLER \ - mov x0, sp; \ - bl common_trap_handler - -#define STORE_NESTED_SP \ - mov x21, sp; \ - add x21, x21, EXC_FRAME_SIZE; \ - str x21, [sp, EXC_EXC_SP_OFFSET] - -#define RESTORE_TRAPED_SP \ - ldr x21, [sp, EXC_EXC_SP_OFFSET]; \ - msr sp_el0, x21 - -#define RESTORE_TRAPFRAME \ - add sp, sp, 16; \ - ldp x21, x22, [sp], 16; \ - msr elr_el1, x22; \ - ldp x21, x0, [sp], 16; \ - msr spsr_el1, x21; \ - ldp x1, x2, [sp], 16; \ - ldp x3, x4, [sp], 16; \ - ldp x5, x6, [sp], 16; \ - ldp x7, x8, [sp], 16; \ - ldp x9, x10, [sp], 16; \ - ldp x11, x12, [sp], 16; \ - ldp x13, x14, [sp], 16; \ - ldp x15, x16, [sp], 16; \ - ldp x17, x18, [sp], 16; \ - ldp x19, x20, [sp], 16; \ - ldp x21, x22, [sp], 16; \ - ldp x23, x24, [sp], 16; \ - ldp x25, x26, [sp], 16; \ - ldp x27, x28, [sp], 16; \ - ldp x29, x30, [sp], 16; \ - eret - -#define VECTOR_ENTRY(func_name) \ - .align 7; \ - b func_name - -#define VECTOR_FUNC_ALIGN .align 2 - -#define VECTOR_FUNC(func_name, func_id) \ - VECTOR_FUNC_ALIGN; \ -func_name:; \ - BUILD_TRAPFRAME(func_id); \ - STORE_TRAPED_SP; \ - CALL_COMMON_TRAP_HANDLER; \ - RESTORE_TRAPED_SP; \ - RESTORE_TRAPFRAME - -#define VECTOR_FUNC_NESTED(func_name, func_id) \ - VECTOR_FUNC_ALIGN; \ -func_name:; \ - BUILD_TRAPFRAME(func_id); \ - STORE_NESTED_SP; \ - CALL_COMMON_TRAP_HANDLER; \ - RESTORE_TRAPFRAME - - .align 11 - .global vector_table -vector_table: - VECTOR_ENTRY(_curr_el_sp0_sync) - VECTOR_ENTRY(_curr_el_sp0_irq) - VECTOR_ENTRY(_curr_el_sp0_fiq) - VECTOR_ENTRY(_curr_el_sp0_serror) - - VECTOR_ENTRY(_curr_el_spx_sync) - VECTOR_ENTRY(_curr_el_spx_irq) - VECTOR_ENTRY(_curr_el_spx_fiq) - VECTOR_ENTRY(_curr_el_spx_serror) - - VECTOR_ENTRY(_lower_el_aarch64_sync) - VECTOR_ENTRY(_lower_el_aarch64_irq) - VECTOR_ENTRY(_lower_el_aarch64_fiq) - VECTOR_ENTRY(_lower_el_aarch64_serror) - - VECTOR_ENTRY(_lower_el_aarch32_sync) - VECTOR_ENTRY(_lower_el_aarch32_irq) - VECTOR_ENTRY(_lower_el_aarch32_fiq) - VECTOR_ENTRY(_lower_el_aarch32_serror) - - VECTOR_FUNC(_curr_el_sp0_sync, AARCH64_EXC_SYNC_SP0) - VECTOR_FUNC(_curr_el_sp0_irq, AARCH64_EXC_IRQ_SP0) - VECTOR_FUNC(_curr_el_sp0_fiq, AARCH64_EXC_FIQ_SP0) - VECTOR_FUNC(_curr_el_sp0_serror, AARCH64_EXC_SERR_SP0) - - VECTOR_FUNC_NESTED(_curr_el_spx_sync, AARCH64_EXC_SYNC_SPX) - VECTOR_FUNC_NESTED(_curr_el_spx_irq, AARCH64_EXC_IRQ_SPX) - VECTOR_FUNC_NESTED(_curr_el_spx_fiq, AARCH64_EXC_FIQ_SPX) - VECTOR_FUNC_NESTED(_curr_el_spx_serror, AARCH64_EXC_SERR_SPX) - - VECTOR_FUNC(_lower_el_aarch64_sync, AARCH64_EXC_SYNC_AARCH64) - VECTOR_FUNC(_lower_el_aarch64_irq, AARCH64_EXC_IRQ_AARCH64) - VECTOR_FUNC(_lower_el_aarch64_fiq, AARCH64_EXC_FIQ_AARCH64) - VECTOR_FUNC(_lower_el_aarch64_serror, AARCH64_EXC_SERR_AARCH64) - - VECTOR_FUNC(_lower_el_aarch32_sync, AARCH64_EXC_SYNC_AARCH32) - VECTOR_FUNC(_lower_el_aarch32_irq, AARCH64_EXC_IRQ_AARCH32) - VECTOR_FUNC(_lower_el_aarch32_fiq, AARCH64_EXC_FIQ_AARCH32) - VECTOR_FUNC(_lower_el_aarch32_serror, AARCH64_EXC_SERR_AARCH32) diff --git a/baremetal/arch/aarch64/timer.c b/baremetal/arch/aarch64/timer.c index b42d369..ec0a8db 100644 --- a/baremetal/arch/aarch64/timer.c +++ b/baremetal/arch/aarch64/timer.c @@ -1,31 +1,14 @@ #include #include -#include "common_aarch64.h" +#include #define CNTV_CTL_ENABLE (1 << 0) #define CNTV_CTL_IMASK (1 << 1) #define CNTV_CTL_ISTATUS (1 << 2) -/* Frequency in Hz. ? */ -SYSREG_READ_WRITE(uint64_t, cntfrq_el0) - -/* Current virtual counter value. */ -SYSREG_READ(uint64_t, cntvct_el0) - -/* Compare value. See: cntv_ctl_el0_enable. */ -SYSREG_READ_WRITE(uint64_t, cntv_cval_el0) - -/* On write, set cntv_cval_el0 = (cntvct_el0 + cntv_tval_el0). - * This means that the next interrupt will happen in cntv_tval_el0 cycles. - */ -SYSREG_READ_WRITE(uint64_t, cntv_tval_el0) - -/* Control register. */ -SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0) - void cntv_ctl_el0_disable(void) { - sysreg_cntv_ctl_el0_write(sysreg_cntv_ctl_el0_read() & ~CNTV_CTL_ENABLE); + lkmc_sysreg_cntv_ctl_el0_write(lkmc_sysreg_cntv_ctl_el0_read() & ~CNTV_CTL_ENABLE); } /* If enabled, when: cntv_ctl > cntv_cval then: @@ -34,25 +17,25 @@ void cntv_ctl_el0_disable(void) { * * set CNTV_CTL_ISTATUS */ void cntv_ctl_el0_enable(void) { - sysreg_cntv_ctl_el0_write(sysreg_cntv_ctl_el0_read() | CNTV_CTL_ENABLE); + lkmc_sysreg_cntv_ctl_el0_write(lkmc_sysreg_cntv_ctl_el0_read() | CNTV_CTL_ENABLE); } int main(void) { /* Initial state. */ - printf("cntv_ctl_el0 0x%" PRIx32 "\n", sysreg_cntv_ctl_el0_read()); - printf("cntfrq_el0 0x%" PRIx64 "\n", sysreg_cntfrq_el0_read()); - printf("cntv_cval_el0 0x%" PRIx64 "\n", sysreg_cntv_cval_el0_read()); + printf("cntv_ctl_el0 0x%" PRIx32 "\n", lkmc_sysreg_cntv_ctl_el0_read()); + printf("cntfrq_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_el0_read()); + printf("cntv_cval_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntv_cval_el0_read()); /* Get the counter value many times to watch the time pass. */ - printf("cntvct_el0 0x%" PRIx64 "\n", sysreg_cntvct_el0_read()); - printf("cntvct_el0 0x%" PRIx64 "\n", sysreg_cntvct_el0_read()); - printf("cntvct_el0 0x%" PRIx64 "\n", sysreg_cntvct_el0_read()); + printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); + printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); + printf("cntvct_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntvct_el0_read()); #if 0 /* TODO crashes gem5. */ puts("cntfrq_el0 = 1"); - sysreg_cntfrq_el0_write(1); - printf("cntfrq_el0 0x%" PRIx64 "\n", sysreg_cntfrq_el0_read()); + lkmc_sysreg_cntfrq_el0_write(1); + printf("cntfrq_el0 0x%" PRIx64 "\n", lkmc_sysreg_cntfrq_el0_read()); #endif return 0; diff --git a/baremetal/arch/arm/add.S b/baremetal/arch/arm/add.S index 97e5c5b..bb9eb0f 100644 --- a/baremetal/arch/arm/add.S +++ b/baremetal/arch/arm/add.S @@ -7,6 +7,6 @@ main: /* test-gdb-result */ cmp r1, #3 beq 1f - bl common_assert_fail + bl lkmc_assert_fail 1: bx lr diff --git a/baremetal/interactive/assert_fail.c b/baremetal/interactive/assert_fail.c index 419a3c0..a08a498 100644 --- a/baremetal/interactive/assert_fail.c +++ b/baremetal/interactive/assert_fail.c @@ -1,6 +1,6 @@ -#include +#include int main(void) { - common_assert_fail(); + lkmc_assert_fail(); } diff --git a/baremetal/lib/aarch64.S b/baremetal/lib/aarch64.S index 8834c86..65916ea 100644 --- a/baremetal/lib/aarch64.S +++ b/baremetal/lib/aarch64.S @@ -1,3 +1,5 @@ +#include + .global mystart mystart: /* = NEON setup */ @@ -5,7 +7,26 @@ mystart: msr cpacr_el1, x1 isb + /* Load the vector table. */ + ldr x0, =vector_table + msr vbar_el1, x0 + + /* Prepare the stack for main, mandatory for C code. */ ldr x0, =stack_top mov sp, x0 bl main + + /* If main returns, exit. */ bl exit + +LKMC_VECTOR_TABLE + +/* Default trap handler that does nothing. + * + * Weak means that if any other file deinfes it as a non-weak global, + * that one will take precedence. + * + * We need this one to not get undefined references. + */ +LKMC_WEAK(lkmc_vector_trap_handler) + ret diff --git a/build-baremetal b/build-baremetal index cd3f270..b76e211 100755 --- a/build-baremetal +++ b/build-baremetal @@ -19,7 +19,7 @@ Build the baremetal examples with crosstool-NG. def build(self): build_dir = self.get_build_dir() bootloader_obj = os.path.join(self.env['baremetal_build_lib_dir'], 'bootloader{}'.format(self.env['obj_ext'])) - common_basename_noext = 'common' + common_basename_noext = 'lkmc' common_src = os.path.join(self.env['root_dir'], common_basename_noext + self.env['c_ext']) common_obj = os.path.join(self.env['baremetal_build_lib_dir'], common_basename_noext + self.env['obj_ext']) syscalls_basename_noext = 'syscalls' diff --git a/common.c b/common.c deleted file mode 100644 index f51ccd0..0000000 --- a/common.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -void common_assert_fail() { - puts("lkmc_test_fail"); - exit(1); -} diff --git a/common.h b/common.h deleted file mode 100644 index 138fa4a..0000000 --- a/common.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -/* Common baremetal and userland functionality. */ - -void common_assert_fail(); - -#endif diff --git a/lkmc.c b/lkmc.c new file mode 100644 index 0000000..deb6261 --- /dev/null +++ b/lkmc.c @@ -0,0 +1,28 @@ +#include +#include + +#include + +void lkmc_assert(bool condition) { + if (!condition) + lkmc_assert_fail(); +} + +void lkmc_assert_fail() { + puts("lkmc_test_fail"); + exit(1); +} + +#if defined(__aarch64__) +#define LKMC_SYSREG_READ_WRITE(type, name) \ + type CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read(void)) { \ + type name; \ + __asm__ __volatile__("mrs %0, " #name : "=r" (name) : : ); \ + return name; \ + } \ + void CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write(type name)) { \ + __asm__ __volatile__("msr " #name ", %0" : : "r" (name) : ); \ + } +LKMC_SYSREG_OPS +#undef LKMC_SYSREG_READ_WRITE +#endif diff --git a/lkmc.h b/lkmc.h new file mode 100644 index 0000000..db515a3 --- /dev/null +++ b/lkmc.h @@ -0,0 +1,259 @@ +#ifndef LKMC_H +#define LKMC_H + +/* Common C definitions. */ +#if !defined(__ASSEMBLER__) +#include +#include + +void lkmc_assert(bool); +void lkmc_assert_fail(); +#endif + +/* https://stackoverflow.com/questions/1489932/how-to-concatenate-twice-with-the-c-preprocessor-and-expand-a-macro-as-in-arg */ +#define CONCAT_EVAL(a,b) a ## b +#define CONCAT(a,b) CONCAT_EVAL(a, b) + +#define LKMC_GLOBAL(name) \ + .global name; \ + name: + +#define LKMC_WEAK(name) \ + .weak name; \ + name: + +/* aarch64 specifics. */ +#if defined(__aarch64__) + +/* LKMC_VECTOR_TABLE + * + * Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S + */ + +#define LKMC_VECTOR_SYNC_SP0 (0x1) +#define LKMC_VECTOR_IRQ_SP0 (0x2) +#define LKMC_VECTOR_FIQ_SP0 (0x3) +#define LKMC_VECTOR_SERR_SP0 (0x4) + +#define LKMC_VECTOR_SYNC_SPX (0x11) +#define LKMC_VECTOR_IRQ_SPX (0x12) +#define LKMC_VECTOR_FIQ_SPX (0x13) +#define LKMC_VECTOR_SERR_SPX (0x14) + +#define LKMC_VECTOR_SYNC_AARCH64 (0x21) +#define LKMC_VECTOR_IRQ_AARCH64 (0x22) +#define LKMC_VECTOR_FIQ_AARCH64 (0x23) +#define LKMC_VECTOR_SERR_AARCH64 (0x24) + +#define LKMC_VECTOR_SYNC_AARCH32 (0x31) +#define LKMC_VECTOR_IRQ_AARCH32 (0x32) +#define LKMC_VECTOR_FIQ_AARCH32 (0x33) +#define LKMC_VECTOR_SERR_AARCH32 (0x34) + +#define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */ +#define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */ +#define LKMC_VECTOR_EXC_EXC_ESR_OFFSE (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */ +#define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */ +#define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */ +#define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */ + +#define LKMC_VECTOR_FUNC_ALIGN .align 2 +#define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_ + +#define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \ + stp x29, x30, [sp, -16]!; \ + stp x27, x28, [sp, -16]!; \ + stp x25, x26, [sp, -16]!; \ + stp x23, x24, [sp, -16]!; \ + stp x21, x22, [sp, -16]!; \ + stp x19, x20, [sp, -16]!; \ + stp x17, x18, [sp, -16]!; \ + stp x15, x16, [sp, -16]!; \ + stp x13, x14, [sp, -16]!; \ + stp x11, x12, [sp, -16]!; \ + stp x9, x10, [sp, -16]!; \ + stp x7, x8, [sp, -16]!; \ + stp x5, x6, [sp, -16]!; \ + stp x3, x4, [sp, -16]!; \ + stp x1, x2, [sp, -16]!; \ + mrs x21, spsr_el1; \ + stp x21, x0, [sp, -16]!; \ + mrs x21, elr_el1; \ + stp xzr, x21, [sp, -16]!; \ + mov x21, (exc_type); \ + mrs x22, esr_el1; \ + stp x21, x22, [sp, -16]! + +#define LKMC_VECTOR_STORE_TRAPED_SP \ + mrs x21, sp_el0; \ + str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET] + +#define LKMC_VECTOR_CALL_TRAP_HANDLER \ + mov x0, sp; \ + bl lkmc_vector_trap_handler + +#define LKMC_VECTOR_STORE_NESTED_SP \ + mov x21, sp; \ + add x21, x21, LKMC_VECTOR_EXC_FRAME_SIZE; \ + str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET] + +#define LKMC_VECTOR_RESTORE_TRAPED_SP \ + ldr x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]; \ + msr sp_el0, x21 + +#define LKMC_VECTOR_RESTORE_TRAPFRAME \ + add sp, sp, 16; \ + ldp x21, x22, [sp], 16; \ + msr elr_el1, x22; \ + ldp x21, x0, [sp], 16; \ + msr spsr_el1, x21; \ + ldp x1, x2, [sp], 16; \ + ldp x3, x4, [sp], 16; \ + ldp x5, x6, [sp], 16; \ + ldp x7, x8, [sp], 16; \ + ldp x9, x10, [sp], 16; \ + ldp x11, x12, [sp], 16; \ + ldp x13, x14, [sp], 16; \ + ldp x15, x16, [sp], 16; \ + ldp x17, x18, [sp], 16; \ + ldp x19, x20, [sp], 16; \ + ldp x21, x22, [sp], 16; \ + ldp x23, x24, [sp], 16; \ + ldp x25, x26, [sp], 16; \ + ldp x27, x28, [sp], 16; \ + ldp x29, x30, [sp], 16; \ + eret + +#define LKMC_VECTOR_ENTRY(func_name) \ + .align 7; \ + b LKMC_VECTOR_SYMBOL_PREFIX ## func_name + +#define LKMC_VECTOR_FUNC(func_name, func_id) \ + LKMC_VECTOR_FUNC_ALIGN; \ +LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \ + LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \ + LKMC_VECTOR_STORE_TRAPED_SP; \ + LKMC_VECTOR_CALL_TRAP_HANDLER; \ + LKMC_VECTOR_RESTORE_TRAPED_SP; \ + LKMC_VECTOR_RESTORE_TRAPFRAME + +#define LKMC_VECTOR_FUNC_NESTED(func_name, func_id) \ + LKMC_VECTOR_FUNC_ALIGN; \ +LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \ + LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \ + LKMC_VECTOR_STORE_NESTED_SP; \ + LKMC_VECTOR_CALL_TRAP_HANDLER; \ + LKMC_VECTOR_RESTORE_TRAPFRAME + +/* Define the actual vector table. */ +#define LKMC_VECTOR_TABLE \ + .align 11; \ + .global vector_table; \ +vector_table:; \ + LKMC_VECTOR_ENTRY(curr_el_sp0_sync); \ + LKMC_VECTOR_ENTRY(curr_el_sp0_irq); \ + LKMC_VECTOR_ENTRY(curr_el_sp0_fiq); \ + LKMC_VECTOR_ENTRY(curr_el_sp0_serror); \ + ; \ + LKMC_VECTOR_ENTRY(curr_el_spx_sync); \ + LKMC_VECTOR_ENTRY(curr_el_spx_irq); \ + LKMC_VECTOR_ENTRY(curr_el_spx_fiq); \ + LKMC_VECTOR_ENTRY(curr_el_spx_serror); \ + ; \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_sync); \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_irq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_fiq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_serror); \ + ; \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_sync); \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_irq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_fiq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_serror); \ + ; \ + LKMC_VECTOR_FUNC(curr_el_sp0_sync, LKMC_VECTOR_SYNC_SP0); \ + LKMC_VECTOR_FUNC(curr_el_sp0_irq, LKMC_VECTOR_IRQ_SP0); \ + LKMC_VECTOR_FUNC(curr_el_sp0_fiq, LKMC_VECTOR_FIQ_SP0); \ + LKMC_VECTOR_FUNC(curr_el_sp0_serror, LKMC_VECTOR_SERR_SP0); \ + ; \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_sync, LKMC_VECTOR_SYNC_SPX); \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_irq, LKMC_VECTOR_IRQ_SPX); \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_fiq, LKMC_VECTOR_FIQ_SPX); \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_serror, LKMC_VECTOR_SERR_SPX); \ + ; \ + LKMC_VECTOR_FUNC(lower_el_aarch64_sync, LKMC_VECTOR_SYNC_AARCH64); \ + LKMC_VECTOR_FUNC(lower_el_aarch64_irq, LKMC_VECTOR_IRQ_AARCH64); \ + LKMC_VECTOR_FUNC(lower_el_aarch64_fiq, LKMC_VECTOR_FIQ_AARCH64); \ + LKMC_VECTOR_FUNC(lower_el_aarch64_serror, LKMC_VECTOR_SERR_AARCH64); \ + ; \ + LKMC_VECTOR_FUNC(lower_el_aarch32_sync, LKMC_VECTOR_SYNC_AARCH32); \ + LKMC_VECTOR_FUNC(lower_el_aarch32_irq, LKMC_VECTOR_IRQ_AARCH32); \ + LKMC_VECTOR_FUNC(lower_el_aarch32_fiq, LKMC_VECTOR_FIQ_AARCH32); \ + LKMC_VECTOR_FUNC(lower_el_aarch32_serror, LKMC_VECTOR_SERR_AARCH32) + +/* aarch64 C definitions. */ +#if !defined(__ASSEMBLER__) +#include + +typedef struct { + uint64_t exc_type; + uint64_t exc_esr; + uint64_t exc_sp; + uint64_t exc_elr; + uint64_t exc_spsr; + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; + uint64_t x30; +} LkmcVectorExceptionFrame; + +void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception); + +#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : ) + +#define LKMC_SYSREG_SYMBOL_PREFIX lkmc_sysreg_ +#define LKMC_SYSREG_READ_WRITE(type, name) \ + type CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read)(void); \ + void CONCAT(CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write)(type name) +#define LKMC_SYSREG_OPS \ + LKMC_SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0); \ + LKMC_SYSREG_READ_WRITE(uint32_t, daif); \ + LKMC_SYSREG_READ_WRITE(uint32_t, spsel); \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntfrq_el0); \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntv_cval_el0); \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntv_tval_el0); \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntvct_el0); \ + LKMC_SYSREG_READ_WRITE(uint64_t, sp_el1); \ + LKMC_SYSREG_READ_WRITE(uint64_t, vbar_el1); +LKMC_SYSREG_OPS +#undef LKMC_SYSREG_READ_WRITE + +#endif +#endif +#endif diff --git a/userland/Makefile b/userland/Makefile index bb0bee3..c8510af 100644 --- a/userland/Makefile +++ b/userland/Makefile @@ -7,7 +7,7 @@ CXXFLAGS = -std=c++17 $(CCFLAGS) $(CXXFLAGS_EXTRA) # -Wno-unused-function for function definitions on headers, # because we are lazy to make a shared object. TODO. COMMON_DIR = $(CURDIR)/.. -COMMON_BASENAME = common +COMMON_BASENAME = lkmc COMMON_OBJ = $(OUT_DIR)/$(COMMON_BASENAME)$(OBJ_EXT) IN_EXT_ASM = .S IN_EXT_C = .c