/* * TOPPERS/SSP Kernel * Smallest Set Profile Kernel * * Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory * Graduate School of Information Science, Nagoya Univ., JAPAN * Copyright (C) 2018,2019 by Naoki Saito * Nagoya Municipal Industrial Research Institute, JAPAN * * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー * スコード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 * の無保証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ * と. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 * 作権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに * 報告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを * 免責すること. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * */ /* * プロセッサ依存モジュール アセンブリ言語部(ARM64用) */ #define TOPPERS_MACRO_ONLY #define UINT_C(val) (val) /* uint_t型の定数を作るマクロ */ #define ULONG_C(val) (val) /* ulong_t型の定数を作るマクロ */ #define UINT64_C(val) (val) /* uint64_t型の定数を作るマクロ */ #define CAST(type, val) (val) /* 型キャストを行うマクロ */ #include "kernel_impl.h" /* * ディスパッチャの動作開始 */ .text .align 2 .globl start_dispatch .type start_dispatch, function start_dispatch: /* * このルーチンは,カーネル起動時に,以下の状態で呼び出される. * ・すべての割込みを禁止した状態割込みロック状態と同等) * ・割込み優先度マスク全解除状態 * * ここでは dispatcher を呼び出す前の初期設定を行う. * (1) システム状態の初期化.以下の状態へ移行する. * ・全割込みロック解除状態(カーネル管理外の割込み許可) * ・CPUロック状態(カーネル管理の割込み禁止) * ・割込み優先度マスク全解除状態 * ・ディスパッチ許可状態 * * (1-1) 割込み優先度マスクは前提よりすでに * モデル上の)割込み優先度マスク全解除状態になっている. * (1-2) ディスパッチ禁止フラグは task_initialize で disdsp を false に * 初期化しているため,すでにディスパッチ許可状態になっている. * (1-3) ここでは割込みロック状態を解除し,CPUロック状態の設定を行う. * * (2) スタックポインタの初期化 * start_dispatch が呼び出されると,今後ここに戻ってくることはないため * スタックポインタをここで初期化する. */ ldr x0, =_kernel_istkpt // setup stack ldr x0, [x0] mov sp, x0 // F フラグをクリア(割込みロック解除,CPUロック相当) msr daifclr, #AARCH64_DAIF_FIQ // dispatcher呼び出し b dispatcher /* * カーネルの終了処理の呼出し * * スタックを非タスクコンテキスト用に切り替え. * */ .text .align 2 .globl call_exit_kernel .type call_exit_kernel, function call_exit_kernel: /* * スタックポインタの初期化 */ ldr x0, =_kernel_istkpt ldr x0, [x0] mov sp, x0 // 全ての例外をマスク(全割込みロック相当) msr daifset, #(AARCH64_DAIF_ALL) b exit_kernel /* カーネルの終了処理を呼ぶ */ /* * 割込み/例外コンテキスト保存処理 */ .macro __save_context /* * x0 - x29 の保存(x0,x1ペアからx28, x29まで) */ stp x1, x0, [sp, #-16]! stp x3, x2, [sp, #-16]! stp x5, x4, [sp, #-16]! stp x7, x6, [sp, #-16]! stp x9, x8, [sp, #-16]! stp x11, x10, [sp, #-16]! stp x13, x12, [sp, #-16]! stp x15, x14, [sp, #-16]! stp x17, x16, [sp, #-16]! stp x19, x18, [sp, #-16]! stp x21, x20, [sp, #-16]! stp x23, x22, [sp, #-16]! stp x25, x24, [sp, #-16]! stp x27, x26, [sp, #-16]! stp x29, x28, [sp, #-16]! /* * spsr_el1, x30をペアで保存 */ mrs x21, spsr_el1 stp x21, x30, [sp, #-16]! /* * esr_el1, elr_el1 をペアで保存 */ mrs x21, esr_el1 mrs x22, elr_el1 stp x21, x22, [sp, #-16]! /* * 追加の格納領域を確保するため,SPを減算しておく */ sub sp, sp, #16 .endm /* * コンテキスト復帰処理 */ .macro __restore_context /* * スタックに保存した一部データの破棄 */ mov x1, #16 add sp, sp, x1 /* * ELR の復元(ESRは破棄) */ ldp x21, x22, [sp], #16 msr elr_el1, x22 /* * SPSR/x30 の復元 */ ldp x21, x30, [sp], #16 msr spsr_el1, x21 /* * x0 - x29 の復元 */ ldp x29, x28, [sp], #16 ldp x27, x26, [sp], #16 ldp x25, x24, [sp], #16 ldp x23, x22, [sp], #16 ldp x21, x20, [sp], #16 ldp x19, x18, [sp], #16 ldp x17, x16, [sp], #16 ldp x15, x14, [sp], #16 ldp x13, x12, [sp], #16 ldp x11, x10, [sp], #16 ldp x9, x8, [sp], #16 ldp x7, x6, [sp], #16 ldp x5, x4, [sp], #16 ldp x3, x2, [sp], #16 ldp x1, x0, [sp], #16 .endm /* * (カーネル管理外の)CPU例外/FIQの出口処理 */ .text .align 2 .global ret_exc .global ret_fiq ret_exc: ret_fiq: __restore_context // レジスタ復帰 eret /* * 割込み/(カーネル管理の)CPU例外の出口処理 * 前提:CPUロック状態, ネストカウンタデクリメント済み */ .text .align 2 .global ret_int ret_int: // 戻り先のコンテキストを確認し,多段割込みならリターン ldr x1, =_kernel_intnest ldrb w3, [x1] cbnz w3, int_return ret_int_2: // 初段の割込みの場合 // reqflg が false なら呼び出し元へ戻る ldr x0, =reqflg ldr w1, [x0] cbz w1, int_return ret_int_3: // reqflg が true の場合 mov w1, #0 // reqflg = false str w1, [x0] // ディスパッチ禁止なら呼び出し元へ戻る ldr x0, =disdsp ldr w1, [x0] cbnz w1, int_return /* * 遅延ディスパッチ * search_schedtsk の返値(x0)を引数として run_task を呼び出す */ bl search_schedtsk bl run_task /* * 呼び出し元へリターン */ int_return: __restore_context // レジスタ復帰 eret /* * 割込みベクタ * 最初に割込み発生前のスタックに戻してからレジスタを保存する * ハードウェアによってPSTATE.{I,F} がセット済であることを前提とする */ .text .global vectors .align 11 vectors: /* * From EL1t */ // Sync EL1 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context mov x22, #0 // 例外番号をx22にセット b chip_exc_entry // IRQ EL1 .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context b chip_int_entry // FIQ EL1 .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)へ戻す __save_context b chip_fiq_entry // SError EL1 .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)へ戻す __save_context mov x22, #1 // 例外番号をx22にセット b chip_exc_entry /* * From EL1h */ // Sync EL1 .align 7 __save_context mov x22, #2 // 例外番号をx22にセット b chip_exc_entry // IRQ EL1 .align 7 __save_context b chip_int_entry // FIQ EL1 .align 7 __save_context b chip_fiq_entry // Error EL1 .align 7 __save_context mov x22, #3 // 例外番号をx22にセット b chip_exc_entry /* * From EL0t */ // Sync EL0 .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context mov x22, #4 // 例外番号をx22にセット b chip_exc_entry // IRQ EL0 .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context b chip_int_entry // FIQ EL0 .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context b chip_fiq_entry // Error EL0 .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context mov x22, #5 // 例外番号をx22にセット b chip_exc_entry /* * From EL0 using AArch32 */ // AArch32 sync .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context mov x22, #6 // 例外番号をx22にセット b chip_exc_entry // AArch32 IRQ .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context b chip_int_entry // AArch32 FIQ .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context b chip_fiq_entry // AArch32 Error .align 7 msr spsel, #0 // 例外発生前のスタック(SP_EL0)に戻す __save_context mov x22, #7 // 例外番号をx22にセット b chip_exc_entry