/* * TOPPERS/SSP Kernel * Smallest Set Profile Kernel * * 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プロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * */ /* * チップ依存モジュール アセンブリ言語部(BCM2837) */ #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" /* * 例外入口の操作 * x22: excno(0..7) */ .text .align 2 .global chip_exc_entry chip_exc_entry: mov x0, sp str x22, [x0, #8] // save excno in stack adrp x1, current_intpri // save int priority in stack add x1, x1, :lo12:current_intpri ldr w2, [x1] str w2, [x0] mov x1, x22 // arg: excno bl call_exc_handler // 例外発生直前のIフラグまたはFフラグが1ならカーネル管理外のCPU例外とみなす ldr x3, [x0, #32] // SPSR --> x1 tst x3, #(3 << 6) b.ne ret_exc // カーネル管理のCPU例外の場合は割込みの出口処理と共通 msr daifclr, #AARCH64_DAIF_FIQ b ret_int /* * FIQの入口処理 */ .text .align 2 .global chip_fiq_entry chip_fiq_entry: ldr x30, =ret_fiq // return to ret_fiq b call_fiq_handler /* * 割込み入口の操作 */ .text .align 2 .global chip_int_entry chip_int_entry: mov x0, sp /* * 割込み要因の特定と保存 */ find_int_src_core: // find a interrupt source from core(core 0) movz x1,#:abs_g1_nc:CORE0_IRQ_SRC movk x1,#:abs_g0_nc:CORE0_IRQ_SRC ldr w2, [x1] mov x9, xzr 1: tst w2, #0x1 b.ne 2f lsr w2, w2, #1 add w9, w9, #1 cmp w9, #32 b.ne 1b 2: cmp w9, #8 // pending interrupt is GPU interrupt b.eq find_int_src_basic cmp w9, #32 // pending interrupt is not found b.eq find_int_src_basic b find_int_src_exit find_int_src_basic: // basic pending register mov w9, #32 movz x1,#:abs_g1_nc:IRQ_PEND_B movk x1,#:abs_g0_nc:IRQ_PEND_B ldr w2, [x1] 1: tst w2, #0x1 b.ne 2f lsr w2, w2, #1 add w9, w9, #1 cmp w9, #64 b.ne 1b 2: cmp w9, #(32+8) // GPU pending register 1 b.eq find_int_src_gpu1 cmp w9, #(32+9) // GPU pending register 2 b.eq find_int_src_gpu2 cmp w9, #(32+10) // GPU irq 7 b.eq gpu_irq_7 cmp w9, #(32+11) // GPU irq 9 b.eq gpu_irq_9 cmp w9, #(32+12) // GPU irq 10 b.eq gpu_irq_10 cmp w9, #(32+13) // GPU irq 18 b.eq gpu_irq_18 cmp w9, #(32+14) // GPU irq 19 b.eq gpu_irq_19 cmp w9, #(32+15) // GPU irq 53 b.eq gpu_irq_53 cmp w9, #(32+16) // GPU irq 54 b.eq gpu_irq_54 cmp w9, #(32+17) // GPU irq 55 b.eq gpu_irq_55 cmp w9, #(32+18) // GPU irq 56 b.eq gpu_irq_56 cmp w9, #(32+19) // GPU irq 57 b.eq gpu_irq_57 cmp w9, #(32+20) // GPU irq 62 b.eq gpu_irq_62 cmp w9, #64 // pending interrupt is not found b.eq find_int_src_gpu1 b find_int_src_exit // others gpu_irq_7: mov w9, #(64+7) b find_int_src_exit gpu_irq_9: mov w9, #(64+9) b find_int_src_exit gpu_irq_10: mov w9, #(64+10) b find_int_src_exit gpu_irq_18: mov w9, #(64+18) b find_int_src_exit gpu_irq_19: mov w9, #(64+19) b find_int_src_exit gpu_irq_53: mov w9, #(64+53) b find_int_src_exit gpu_irq_54: mov w9, #(64+54) b find_int_src_exit gpu_irq_55: mov w9, #(64+55) b find_int_src_exit gpu_irq_56: mov w9, #(64+56) b find_int_src_exit gpu_irq_57: mov w9, #(64+57) b find_int_src_exit gpu_irq_62: mov w9, #(64+62) b find_int_src_exit find_int_src_gpu1: // GPU pending register 1 mov w9, #64 movz x1,#:abs_g1_nc:IRQ_PEND_1 movk x1,#:abs_g0_nc:IRQ_PEND_1 ldr w2, [x1] 1: tst w2, #0x1 b.ne 2f lsr w2, w2, #1 add w9, w9, #1 cmp w9, #96 b.ne 1b 2: cmp w9, #96 // pending interrupt is not found b.eq find_int_src_gpu2 b find_int_src_exit find_int_src_gpu2: // GPU pending register 2 mov w9, #96 movz x1,#:abs_g1_nc:IRQ_PEND_2 movk x1,#:abs_g0_nc:IRQ_PEND_2 ldr w2, [x1] 1: tst w2, #0x1 b.ne find_int_src_exit lsr w2, w2, #1 add w9, w9, #1 cmp w9, #128 // pending interrupt is not found (and interrupt source is unknown) b.ne 1b find_int_src_exit: cmp w9, #128 b.eq ret_int str w9, [x0, #8] // save intno to (sp+8) /* * 割込み発生直前の割込み優先度(内部表現)を保存 */ adrp x1, current_intpri add x1, x1, :lo12:current_intpri ldr w2, [x1] str w2, [x0] /* * 割込み要因の優先度を取得 */ adrp x3, _kernel_intpri_table add x3, x3, #:lo12:_kernel_intpri_table ldr w4, [x3, x9, lsl #2] // 発生した割込みの優先度をもとに割込みをマスク mov w0, w4 // arg: intpri bl chip_mask_interrupt // D,A,F フラグをクリアしておく(CPUロック相当にする) msr daifclr, #(AARCH64_DAIF_DBG | AARCH64_DAIF_SERR | AARCH64_DAIF_FIQ) // ハンドラ呼び出し mov x0, sp ldr w9, [x0, #8] mov w0, w9 // arg: intno bl call_int_handler /* そのまま chip_ret_int へ */ /* * 割込み出口のGIC操作 */ chip_ret_int: // 割込み発生前の優先度に戻す mov x0, sp adrp x1, current_intpri add x1, x1, :lo12:current_intpri ldr w2, [x0] // previous int priority str w2, [x1] // 優先度を元に割込みのマスクを戻す mov w0, w2 bl chip_unmask_interrupt b ret_int