From 6b995c8cb722d10aaacba52999f5c43e43daeb85 Mon Sep 17 00:00:00 2001 From: Lunaixsky Date: Wed, 2 Oct 2024 17:38:42 +0100 Subject: [PATCH] adjust exec_param to keep track of sp_el0, fix incorrect use sys regs * rename BITS to BITFIELD for better clarity * allow architecturally optimisation to override the default BITS ops * implement the trace utility for arm64 --- lunaix-os/arch/aarch64/LBuild | 5 ++ lunaix-os/arch/aarch64/exception/context.S | 12 ++- lunaix-os/arch/aarch64/exception/handler.c | 40 ++++++++++ lunaix-os/arch/aarch64/fault.c | 9 +++ .../aarch64/includes/asm/aa64_exception.h | 12 ++- .../arch/aarch64/includes/asm/aa64_spsr.h | 2 +- lunaix-os/arch/aarch64/includes/asm/abi.h | 2 +- lunaix-os/arch/aarch64/includes/asm/bits.h | 31 ++++++++ lunaix-os/arch/aarch64/includes/asm/hart.h | 2 +- lunaix-os/arch/aarch64/trace.c | 76 +++++++++++++++++++ .../arch/generic/includes/asm-generic/bits.h | 13 ++++ lunaix-os/includes/lunaix/bits.h | 13 ++-- 12 files changed, 200 insertions(+), 17 deletions(-) create mode 100644 lunaix-os/arch/aarch64/fault.c create mode 100644 lunaix-os/arch/aarch64/includes/asm/bits.h create mode 100644 lunaix-os/arch/aarch64/trace.c create mode 100644 lunaix-os/arch/generic/includes/asm-generic/bits.h diff --git a/lunaix-os/arch/aarch64/LBuild b/lunaix-os/arch/aarch64/LBuild index 7526610..52b3479 100644 --- a/lunaix-os/arch/aarch64/LBuild +++ b/lunaix-os/arch/aarch64/LBuild @@ -11,6 +11,11 @@ sources([ "exception/handler.c" ]) +sources([ + "fault.c", + "trace.c" +]) + compile_opts([ "-mlittle-endian", "-mgeneral-regs-only", diff --git a/lunaix-os/arch/aarch64/exception/context.S b/lunaix-os/arch/aarch64/exception/context.S index cbb7cf4..fd85849 100644 --- a/lunaix-os/arch/aarch64/exception/context.S +++ b/lunaix-os/arch/aarch64/exception/context.S @@ -8,8 +8,10 @@ .globl _aa64_switch_task _aa64_evec_prehandle: - stp xzr, elr, [sp, #-16]! # push {xzr , elr} - stp spsr, xzr, [sp, #-16]! # push {spsr, xzr} + # reservation for struct exec_param + sub sp, sp, #8 # push sp_el1 + sub sp, sp, #16 # push {sp_el0, link} + sub sp, sp, #16 # push {spsr, parent_hart} stp lr, fp, [sp, #-16]! # push {x31-x1} stp x28, x27, [sp, #-16]! @@ -32,6 +34,12 @@ mrs x0, SP_EL0 str x0, [x1, #execp_spel0_saved] + + mrs x0, ELR_E1 + str x0, [x1, #execp_link] + + mrs x0, SPSR_EL1 + str x0, [x1, #execp_spsr] sub x0, sp, #hart_end str x0, [x1, #execp_spel1_saved] diff --git a/lunaix-os/arch/aarch64/exception/handler.c b/lunaix-os/arch/aarch64/exception/handler.c index ab2b806..0c861bb 100644 --- a/lunaix-os/arch/aarch64/exception/handler.c +++ b/lunaix-os/arch/aarch64/exception/handler.c @@ -1,5 +1,7 @@ #include #include +#include + static inline void update_thread_context(struct hart_state* state) @@ -10,18 +12,56 @@ update_thread_context(struct hart_state* state) struct hart_state* parent = current_thread->hstate; hart_push_state(parent, state); + current_thread->hstate = state; + current_thread->ustack_top = state->execp.sp_el0; if (parent) { state->depth = parent->depth + 1; } } +extern void +handle_mm_abort(struct hart_state* state); + +static void +handle_sync_exception(struct hart_state* hstate) +{ + unsigned int ec; + + ec = esr_ec(hstate->execp.syndrome); + + switch (ec) + { + case EC_I_ABORT: + case EC_D_ABORT: + case EC_I_ABORT_EL: + case EC_D_ABORT_EL: + handle_mm_abort(hstate); + break; + + default: + fail("unhandled exception (synced)"); + break; + } +} + +static void +handle_async_exception(struct hart_state* hstate) +{ + +} struct hart_state* handle_exception(struct hart_state* hstate) { update_thread_context(hstate); + if (hart_vector_stamp(hstate) == EXCEPTION_SYNC) { + handle_sync_exception(hstate); + } else { + handle_async_exception(hstate); + } + return hstate; } \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/fault.c b/lunaix-os/arch/aarch64/fault.c new file mode 100644 index 0000000..e551d68 --- /dev/null +++ b/lunaix-os/arch/aarch64/fault.c @@ -0,0 +1,9 @@ +#include +#include +#include + +void +handle_mm_abort(struct hart_state* state) +{ + // TODO +} \ No newline at end of file diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h b/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h index 5ed8104..db74b88 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_exception.h @@ -1,22 +1,20 @@ #ifndef __LUNAIX_AA64_ESR_H #define __LUNAIX_AA64_ESR_H -#ifdef __ASM__ - #define EXCEPTION_SYNC 0 -#define EXCEPTION_IFQ 1 +#define EXCEPTION_FIQ 1 #define EXCEPTION_IRQ 2 #define EXCEPTION_SERR 3 -#else +#ifndef __ASM__ #include #include -#define ESR_ISS2 BITS(55, 32) -#define ESR_EC BITS(31, 26) +#define ESR_ISS2 BITFIELD(55, 32) +#define ESR_EC BITFIELD(31, 26) #define ESR_IL BIT(25) -#define ESR_ISS BITS(24, 0) +#define ESR_ISS BITFIELD(24, 0) #define EC_UNKNOWN 0b000000 #define EC_WF 0b000001 diff --git a/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h b/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h index 07a807a..8b5b46f 100644 --- a/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h +++ b/lunaix-os/arch/aarch64/includes/asm/aa64_spsr.h @@ -4,7 +4,7 @@ #include #include -#define SPSR_EL BITS(3, 2) +#define SPSR_EL BITFIELD(3, 2) #define SPSR_SP BIT(0) static inline bool diff --git a/lunaix-os/arch/aarch64/includes/asm/abi.h b/lunaix-os/arch/aarch64/includes/asm/abi.h index c5dc081..7f8d83d 100644 --- a/lunaix-os/arch/aarch64/includes/asm/abi.h +++ b/lunaix-os/arch/aarch64/includes/asm/abi.h @@ -4,7 +4,7 @@ #include #ifndef __ASM__ -#define align_stack(ptr) ((ptr) & stack_alignment) +#define align_stack(ptr) ((ptr) & ~15) static inline void must_inline noret switch_context() { diff --git a/lunaix-os/arch/aarch64/includes/asm/bits.h b/lunaix-os/arch/aarch64/includes/asm/bits.h new file mode 100644 index 0000000..a30f254 --- /dev/null +++ b/lunaix-os/arch/aarch64/includes/asm/bits.h @@ -0,0 +1,31 @@ +#ifndef __LUNAIX_ARCH_BITS_H +#define __LUNAIX_ARCH_BITS_H + +#include + +#undef _BITS_EXTRACT +#undef _BITS_INSERT + +#define _BITS_EXTRACT(from, h, l) \ + ({ \ + unsigned long _r; \ + asm ("ubfm %0, %1, %2, %3" \ + : "=r"(_r) \ + : "r"(from) \ + "i"(l) "i"(h)); \ + _r; \ + }) + +#define _BITS_INSERT(to, from, h, l) \ + ({ \ + unsigned long _r = to; \ + asm ("bfi %0, %1, %2, %3" \ + : "=r"(_r) \ + : "r"(from) \ + "i"(l) \ + "i"(h - l + 1)); \ + _r; \ + }) + + +#endif /* __LUNAIX_ARCH_BITS_H */ diff --git a/lunaix-os/arch/aarch64/includes/asm/hart.h b/lunaix-os/arch/aarch64/includes/asm/hart.h index 89a2e9a..ae84ddd 100644 --- a/lunaix-os/arch/aarch64/includes/asm/hart.h +++ b/lunaix-os/arch/aarch64/includes/asm/hart.h @@ -6,7 +6,7 @@ #include #include -#define SYNDROME_ETYPE BITS(63, 56) +#define SYNDROME_ETYPE BITFIELD(63, 56) struct hart_state; diff --git a/lunaix-os/arch/aarch64/trace.c b/lunaix-os/arch/aarch64/trace.c new file mode 100644 index 0000000..1930003 --- /dev/null +++ b/lunaix-os/arch/aarch64/trace.c @@ -0,0 +1,76 @@ +#include +#include +#include + +static inline char* +__type_name(reg_t syndrome) +{ + switch (hart_vector_stamp(syndrome)) + { + case EXCEPTION_SYNC: + return "sync"; + case EXCEPTION_IRQ: + return "async (irq)"; + case EXCEPTION_FIQ: + return "async (fiq)"; + case EXCEPTION_SERR: + return "async (serr)"; + } + + return "unknwon"; +} + +void +trace_print_transistion_short(struct hart_state* hstate) +{ + struct exec_param* execp; + reg_t syndrome; + + execp = &hstate->execp; + syndrome = execp->syndrome; + + trace_log("%s from EL%d: ec=%04x, iss=%08lx, il=%d", + __type_name(syndrome), !spsr_from_el0(execp->syndrome), + esr_ec(syndrome), esr_iss(syndrome), esr_inst32(syndrome)); +} + +void +trace_print_transition_full(struct hart_state* hstate) +{ + struct exec_param* execp; + reg_t syndrome; + + execp = &hstate->execp; + syndrome = execp->syndrome; + + trace_log("exception %s from EL%d", + __type_name(syndrome), !spsr_from_el0(execp->syndrome)); + trace_log(" ec=0x%08lx, iss=0x%08lx, il=%d", + esr_ec(syndrome), esr_iss(syndrome), esr_inst32(syndrome)); + trace_log(" esr=0x%016lx, spsr=0x%016lx", + syndrome, execp->spsr); + trace_log(" sp_el0=0x%016lx, sp_el1=0x%016lx", + execp->sp_el0, execp->sp_el1); + trace_log(" pc=0x%016lx", execp->link); +} + +void +trace_dump_state(struct hart_state* hstate) +{ + struct regcontext* r; + + r = &hstate->registers; + + trace_log("hart state dump (depth=%d)", hstate->depth); + + for (int i = 0; i < 30; i+=3) + { + trace_log(" x%02d=0x%016lx x%02d=0x%016lx x%02d=0x%016lx", + i, r->x[i], + i + 1, r->x[i + 1], + i + 2, r->x[i + 2]); + } + + trace_log(" x30=0x%016lx x31=0x%016lx (sp)", + r->x[30], hart_sp(hstate)); +} \ No newline at end of file diff --git a/lunaix-os/arch/generic/includes/asm-generic/bits.h b/lunaix-os/arch/generic/includes/asm-generic/bits.h new file mode 100644 index 0000000..430e395 --- /dev/null +++ b/lunaix-os/arch/generic/includes/asm-generic/bits.h @@ -0,0 +1,13 @@ +#ifndef __LUNAIX_ARCH_GENERIC_BITS_H +#define __LUNAIX_ARCH_GENERIC_BITS_H + +#define _BITS_GENMASK(h, l) \ + (((1UL << ((h) + 1)) - 1) ^ ((1UL << (l)) - 1)) + +#define _BITS_EXTRACT(from, h, l) \ + (((from) & (((1UL << (h + 1)) - 1) ^ ((1UL << l) - 1))) >> l) + +#define _BITS_INSERT(to, from, h, l) \ + (((to) & ~_BITS_GENMASK(h, l)) | (((from) << l) & _BITS_GENMASK(h, l))) + +#endif /* __LUNAIX_ARCH_BITS_H */ diff --git a/lunaix-os/includes/lunaix/bits.h b/lunaix-os/includes/lunaix/bits.h index 1029bb0..ddc2800 100644 --- a/lunaix-os/includes/lunaix/bits.h +++ b/lunaix-os/includes/lunaix/bits.h @@ -2,13 +2,16 @@ #define __LUNAIX_BITS_H #include +#include -#define BITS(h, l) (((1UL << ((h) + 1)) - 1) ^ ((1UL << (l)) - 1)) -#define BIT(p) BITS(p, p) +#define BITFIELD(h, l) (h), (l) -#define BITS_GET(from, bits) (((from) & (bits)) >> ctzl(bits)) +#define BIT(p) BITFIELD(p, p) -#define BITS_SET(to, bits, val) \ - (((to) & ~(bits)) | (((val) << ctzl(bits)) & (bits))) +#define BITS_GENMASK(bits) _BITS_GENMASK(bits) + +#define BITS_GET(from, bits) _BITS_EXTRACT(from, bits) + +#define BITS_SET(to, bits, val) _BITS_INSERT(to, val, bits) #endif /* __LUNAIX_BITS_H */ -- 2.27.0