+sources([
+ "boot/init.c",
+ "boot/kremap.c",
+ "boot/start.S"
+])
+
+sources([
+ "exception/entries.S",
+ "exception/context.S",
+ "exception/handler.c"
+])
+
compile_opts([
"-mlittle-endian",
"-mgeneral-regs-only",
#include <lunaix/boot_generic.h>
-#include <asm/aa64_msrs.h>
+#include <asm/aa64.h>
#include "init.h"
set_sysreg(SPSel, 1);
}
+extern void aa64_vbase();
+
static inline void
setup_evbar()
{
- // TODO install exception vectors, setup VBAR
+ set_sysreg(VBAR_EL1, aa64_vbase);
}
static inline void
--- /dev/null
+#define __ASM__
+#include <asm/aa64_msrs.h>
+#include "hart_field.inc"
+
+.section .text
+
+ .globl _aa64_evec_prehandle
+ .globl _aa64_switch_task
+
+ _aa64_evec_prehandle:
+ stp xzr, elr, [sp, #-16]! # push {xzr , elr}
+ stp spsr, xzr, [sp, #-16]! # push {spsr, xzr}
+
+ stp lr, fp, [sp, #-16]! # push {x31-x1}
+ stp x28, x27, [sp, #-16]!
+ stp x26, x25, [sp, #-16]!
+ stp x24, x23, [sp, #-16]!
+ stp x22, x21, [sp, #-16]!
+ stp x20, x19, [sp, #-16]!
+ stp x18, x17, [sp, #-16]!
+ stp x16, x15, [sp, #-16]!
+ stp x14, x13, [sp, #-16]!
+ stp x12, x11, [sp, #-16]!
+ stp x10, x9, [sp, #-16]!
+ stp x8, x7, [sp, #-16]!
+ stp x6, x5, [sp, #-16]!
+ stp x4, x3, [sp, #-16]!
+ stp x2, x1, [sp, #-16]!
+ stp x0, xzr, [sp, #-16]! # push {x0, xzr}
+
+ add x1, sp, #hart_execp
+
+ mrs x0, SP_EL0
+ str x0, [x1, #execp_spel0_saved]
+
+ sub x0, sp, #hart_end
+ str x0, [x1, #execp_spel1_saved]
+
+ mov x0, sp
+ bl handle_exception
+
+ do_eret:
+ mov sp, x0
+
+ add x1, x0, #hart_execp
+
+ ldr x0, [x1, #execp_spsr]
+ msr SPSR_EL1, x0
+
+ ldr x0, [x1, #execp_link]
+ msr ELR_E1, x0
+
+ ldr x0, [x1, #execp_spel0_saved]
+ msr SP_EL0, x0
+
+ add sp, sp, #hart_regs
+
+ ldr x0, [sp, #8 ]!
+ 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 fp, lr, [sp, #16]!
+
+ # sp now point to the start of exec_param
+
+ ldr sp, [sp, #execp_spel1_saved]
+
+ eret
+
+ _aa64_switch_task:
+ # TODO
+ b do_eret
\ No newline at end of file
--- /dev/null
+#define __ASM__
+#include <asm/aa64_exception.h>
+#include <asm/aa64_msrs.h>
+
+.macro aa64_exception_entry type
+ .align 128
+ .type _exception_entry_t\type, @function
+
+ # each handler has at most 128 bytes (32 insts)
+ _exception_entry_t\type:
+ stp x1, x0, [sp, #-16]
+
+ # re-purpose the [63, 56] of ESR to exception
+ # type identifier
+
+ mov x0, =\type
+ lsl x0, x0, #56
+ mrs x1, ESR_EL1
+ orr x0, x0, x1
+
+ ldr x1, [sp, #-8]
+ str x0, [sp, #-8]!
+ ldr x0, [sp, #-8]
+
+ b _aa64_evec_prehandle
+.endm
+
+.section .text
+
+ .globl aa64_vbase
+ .align 128
+
+ aa64_vbase:
+ aa64_exception_entry EXCEPTION_SYNC
+ aa64_exception_entry EXCEPTION_IRQ
+ aa64_exception_entry EXCEPTION_FIQ
+ aa64_exception_entry EXCEPTION_SERR
--- /dev/null
+#include <lunaix/process.h>
+#include <asm/hart.h>
+
+static inline void
+update_thread_context(struct hart_state* state)
+{
+ if (!current_thread) {
+ return;
+ }
+
+ struct hart_state* parent = current_thread->hstate;
+ hart_push_state(parent, state);
+ current_thread->hstate = state;
+
+ if (parent) {
+ state->depth = parent->depth + 1;
+ }
+}
+
+
+struct hart_state*
+handle_exception(struct hart_state* hstate)
+{
+ update_thread_context(hstate);
+
+ return hstate;
+}
\ No newline at end of file
--- /dev/null
+ .struct 0
+reg_xn:
+ .struct reg_xn + 8 * 29
+reg_fp:
+ .struct reg_fp + 8
+reg_lr:
+ .struct reg_lr + 8
+reg_end:
+
+ .struct 0
+execp_parent:
+ .struct execp_parent + 8
+execp_spsr:
+ .struct execp_spsr + 8
+execp_link:
+ .struct execp_link + 8
+execp_spel0_saved:
+ .struct execp_spel0_saved + 8
+execp_spel1_saved:
+ .struct execp_spel1_saved + 8
+execp_syndrome:
+ .struct execp_syndrome + 8
+execp_end:
+
+ .struct 0
+hart_depth:
+ .struct hart_depth + 8
+hart_regs:
+ .struct hart_regs + reg_end
+hart_execp:
+ .struct hart_execp + execp_end
+hart_end:
#ifndef __LUNAIX_AA64_ASM_H
#define __LUNAIX_AA64_ASM_H
-#include <lunaix/compiler.h>
-
#define __sr_encode(op0, op1, crn, crm, op2) \
s##op0##_##op1##_c##crn##_c##crm##_##op2
+#ifndef __ASM__
+
+#include <lunaix/compiler.h>
+
+#else
+#endif
#endif /* __LUNAIX_AA64_ASM_H */
--- /dev/null
+#ifndef __LUNAIX_AA64_ESR_H
+#define __LUNAIX_AA64_ESR_H
+
+#ifdef __ASM__
+
+#define EXCEPTION_SYNC 0
+#define EXCEPTION_IFQ 1
+#define EXCEPTION_IRQ 2
+#define EXCEPTION_SERR 3
+
+#else
+
+#include <lunaix/bits.h>
+#include <lunaix/types.h>
+
+#define ESR_ISS2 BITS(55, 32)
+#define ESR_EC BITS(31, 26)
+#define ESR_IL BIT(25)
+#define ESR_ISS BITS(24, 0)
+
+#define EC_UNKNOWN 0b000000
+#define EC_WF 0b000001
+#define EC_SIMD 0b000111
+#define EC_LS64 0b001010
+#define EC_BTI 0b001101
+#define EC_EXEC_STATE 0b001110
+#define EC_SYS_INST 0b011000
+
+#define EC_I_ABORT 0b100000
+#define EC_I_ABORT_EL 0b100001
+
+#define EC_D_ABORT 0b100100
+#define EC_D_ABORT_EL 0b100101
+
+#define EC_PC_ALIGN 0b100010
+#define EC_SP_ALIGN 0b100110
+
+#define EC_SERROR 0b101111
+
+static inline bool
+esr_inst32(reg_t esr)
+{
+ return !!BITS_GET(esr, ESR_IL);
+}
+
+static inline unsigned int
+esr_ec(reg_t esr)
+{
+ return (unsigned int)BITS_GET(esr, ESR_EC);
+}
+
+static inline reg_t
+esr_iss(reg_t esr)
+{
+ return (reg_t)BITS_GET(esr, ESR_ISS);
+}
+
+#endif /* !__ASM__ */
+#endif /* __LUNAIX_AA64_ESR_H */
#define SP_EL0 __sr_encode(3, 0, 4, 1, 0)
#define SP_EL1 __sr_encode(3, 4, 4, 1, 0)
+#ifndef __ASM__
#define read_sysreg(reg) \
({ unsigned long _x; \
asm ("mrs %0, " stringify(reg):"=r"(_x)); \
#define SCTRL_A (1UL << 1)
#define SCTRL_M (1UL << 0)
-
+#endif
#endif /* __LUNAIX_AA64_MSRS_H */
--- /dev/null
+#ifndef __LUNAIX_AA64_SPSR_H
+#define __LUNAIX_AA64_SPSR_H
+
+#include <lunaix/types.h>
+#include <lunaix/bits.h>
+
+#define SPSR_EL BITS(3, 2)
+#define SPSR_SP BIT(0)
+
+static inline bool
+spsr_from_el0(reg_t spsr)
+{
+ return BITS_GET(spsr, SPSR_EL) == 0;
+}
+
+#endif /* __LUNAIX_AA64_SPSR_H */
static inline void must_inline noret
switch_context() {
// TODO
+ asm ("b _aa64_switch_task");
unreachable;
}
#ifndef __ASM__
#include <lunaix/types.h>
+#include <lunaix/bits.h>
+#include <asm/aa64_spsr.h>
+
+#define SYNDROME_ETYPE BITS(63, 56)
struct hart_state;
struct regcontext
{
union {
- reg_t x[32];
+ reg_t x[31];
struct {
reg_t x[29];
reg_t fp;
reg_t lr;
- reg_t sp;
};
};
-} compact;
+} compact align(8);
struct exec_param
{
struct hart_state* parent_state;
- reg_t vector;
+ reg_t spsr;
+ reg_t link;
+ struct {
+ reg_t sp_el0;
+ reg_t sp_el1;
+ };
+
reg_t syndrome;
- reg_t elink;
- reg_t sp;
-} compact;
+} compact align(8);
struct hart_state
{
reg_t depth;
struct regcontext registers;
- union
- {
- reg_t sp;
- volatile struct exec_param* execp;
- };
-} compact;
+ struct exec_param execp;
+} compact align(16);
static inline int
hart_vector_stamp(struct hart_state* hstate) {
- return hstate->execp->vector;
+ return BITS_GET(hstate->execp.syndrome, SYNDROME_ETYPE);
}
static inline unsigned int
hart_ecause(struct hart_state* hstate) {
- return hstate->execp->syndrome;
+ return hstate->execp.syndrome;
}
static inline struct hart_state*
hart_parent_state(struct hart_state* hstate)
{
- return hstate->execp->parent_state;
+ return hstate->execp.parent_state;
}
static inline void
hart_push_state(struct hart_state* p_hstate, struct hart_state* hstate)
{
- hstate->execp->parent_state = p_hstate;
+ hstate->execp.parent_state = p_hstate;
}
static inline ptr_t
hart_pc(struct hart_state* hstate)
{
- return hstate->execp->elink;
+ return hstate->execp.link;
}
static inline ptr_t
hart_sp(struct hart_state* hstate)
{
- return hstate->execp->sp;
+ if (spsr_from_el0(hstate->execp.spsr)) {
+ return hstate->execp.sp_el0;
+ }
+ return hstate->execp.sp_el1;
}
static inline bool
--- /dev/null
+#ifndef __LUNAIX_BITS_H
+#define __LUNAIX_BITS_H
+
+#include <lunaix/compiler.h>
+
+#define BITS(h, l) (((1UL << ((h) + 1)) - 1) ^ ((1UL << (l)) - 1))
+#define BIT(p) BITS(p, p)
+
+#define BITS_GET(from, bits) (((from) & (bits)) >> ctzl(bits))
+
+#define BITS_SET(to, bits, val) \
+ (((to) & ~(bits)) | (((val) << ctzl(bits)) & (bits)))
+
+#endif /* __LUNAIX_BITS_H */
#define msbiti (sizeof(int) * 8 - 1)
#define clz(bits) __builtin_clz(bits)
+#define ctz(bits) __builtin_ctz(bits)
#ifdef CONFIG_ARCH_BITS_64
#define msbitl (sizeof(long) * 8 - 1)
#define clzl(bits) __builtin_clzl(bits)
+#define ctzl(bits) __builtin_ctzl(bits)
#else
#define msbitl msbiti
#define clzl(bits) clz(bits)
+#define ctzl(bits) ctz(bits)
#endif
#define sadd_of(a, b, of) __builtin_sadd_overflow(a, b, of)
#define reclaimable_start __section_mark(bssreclaim, start)
#define reclaimable_end __section_mark(bssreclaim, end)
+#define boot_start __section_mark(kboot, start)
+#define boot_end __section_mark(kboot, end)
+
#define kernel_start __section_mark(kexec, start)
#define kernel_load_end __section_mark(kexec, end)
#define kernel_end __section_mark(kimg, end)