/** Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.* All rights reserved. Distributed under the terms of the MIT License.** Copyright 2003, Travis Geiselbrecht. All rights reserved.* Distributed under the terms of the NewOS License.*/#include <asm_defs.h>#include "asm_offsets.h"/* General exception handling concept:Starting with 68020 the vector offset (=vector number * 4) is partof the all exception frame types, so we can easily have a commonasm stub for all of them, which calls m68k_exception_entry inarch_int.cpp.Also, m68k doesn't disable the mmu on interrupt as ppc does,which makes things simpler.----ppcThe PPC architecture specifies entry point offsets for the variousexceptions in the first two physical pages. We put a short piece of code(VEC_ENTRY()) into each exception vector. It calls exception_vector_common,which is defined in the unused space at the beginning of the first physicalpage. It re-enables address translation and calls ppc_exception_tail whichlies in the kernel. It dumps an iframe and invokes ppc_exception_entry()(arch_int.cpp), which handles the exception and returns eventually.The registers are restored from the iframe and we return from theinterrupt.algorithm overview:* VEC_ENTRY* exception_vector_common* ppc_exception_tail- dump iframe- ppc_exception_entry()- restore registers and return from interruptHere we use the following SPRG registers, which are at the disposal of theoperating system:* SPRG0: Physical address pointer to a struct cpu_exception_contextfor the current CPU. The structure contains helpful pointersas well as some scratch memory for temporarily saving registers.* SPRG1: Scratch.struct cpu_exception_context (defined in arch_int.h):offset 0: virtual address of the exception handler routine in the kerneloffset 4: virtual address of the exception contextoffset 8: kernel stack for the current threadoffset 12: start of scratch memory for saving registers etc.algorithm in detail:* VEC_ENTRY- save r1 in SPRG1 and load cpu_exception_context into r1- save r0, save LR in r0* exception_vector_common- params:. r0: old LR. r1: exception context (physical address). SPRG1: original r1- save r0-3- load virtual exception context address to r1- turn on BAT for exception vector code- turn on address translation- get exception vector offset from LR* ppc_exception_tail- params:. r1: exception context (virtual address). r3: exception vector offset. SPRG1: original r1- turn off BAT- get kernel stack pointer- dump iframe- ppc_exception_entry()- restore registers and return from interrupt*//* exception vector definitions *//* this one just returns */FUNCTION(__m68k_exception_noop):rteFUNCTION_END(__m68k_exception_noop)/* see arch_asm.S for ctx switch */FUNCTION(__m68k_exception_common):/* save regs */movem.l %d0-%d7/%a0-%a6,-(%sp) /* push the iframe address *//* save fp */sub.l #FPU_STATE_sizeof,%spfsave (%sp)tst.b (%sp) /* check for a null state */beq null_sav_1 /* yes */fmovem %fpcr/%fpsr/%fpiar,-(%sp)fmovem %fp0-%fp7,-(%sp)bra null_sav_2null_sav_1:sub.l #IFRAME_fpu-IFRAME_fp,%spnull_sav_2:move.l %sp,%fp /* have stack_trace() find the iframe */move.l %sp,-(%sp) /* push address of iframe */bsr m68k_exception_entry /* call C entry */add.l #4,%sp/* restore fp */tst.b IFRAME_fpu-IFRAME_fp(%sp) /* check for a null state */beq null_res_1 /* yes */fmovem (%sp)+,%fp0-%fp7fmovem (%sp)+,%fpcr/%fpsr/%fpiarbra null_res_2null_res_1:add.l #IFRAME_fpu-IFRAME_fp,%spnull_res_2:/* restore fp */frestore (%sp)add.l #FPU_STATE_sizeof,%sp/* restore regs */movem.l (%sp)+,%d0-%d7/%a0-%a6rteFUNCTION_END(__m68k_exception_common)