📄 exceptions.s
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright (C) IBM Corp. 2005, 2006 * * Authors: Jimi Xenidis <jimix@watson.ibm.com> * Hollis Blanchard <hollisb@us.ibm.com> */ #include <asm/config.h>#include <asm/asm-offsets.h>#include <asm/reg_defs.h>#include <asm/msr.h>#include <asm/processor.h>#include <asm/percpu.h>.macro SAVE_GPR regno uregsstd \regno, (UREGS_gprs + GPR_WIDTH * \regno)(\uregs).endm.macro SAVE_GPRS from to uregs.ifge \to-\fromSAVE_GPR \from, \uregsSAVE_GPRS "(\from+1)", \to, \uregs.endif.endm.macro LOAD_GPR regno uregsld \regno, (UREGS_gprs + GPR_WIDTH * \regno)(\uregs).endm.macro LOAD_GPRS from to uregs.ifge \to-\fromLOAD_GPR \from, \uregsLOAD_GPRS "(\from+1)", \to, \uregs.endif.endm.macro GET_STACK parea srr1 /* get processor area pointer and save off a couple registers there */ mtspr SPRN_HSPRG1, \parea mfspr \parea, SPRN_HSPRG0 std r1, PAREA_r1(\parea) mfcr r1 std r1, PAREA_cr(\parea) mfspr r1, \srr1 rldicl. r1, r1, 4, 63 /* test (H)SRR1:HV */ /* assume we interrupted the guest, in which case we start at top of this * processsor's hypervisor stack (as found in parea). */ ld r1, PAREA_stack(\parea) beq 1f /* nope, we interrupted the hypervisor. continue on that stack. */ ld r1, PAREA_r1(\parea)1:.endm/* SAVE_C_STATE: set up enough state to jump to C code * r14-r31 are non-volatile in the C ABI, so not saved here */.macro SAVE_C_STATE uregs SAVE_GPRS r2, r12, \uregs /* save r2-r12 */ mflr r0 std r0, UREGS_lr(\uregs) /* save LR */ mfxer r0 std r0, UREGS_xer(\uregs) /* save XER */.endm.macro LOAD_C_STATE uregs ld r0, UREGS_lr(\uregs) /* load LR */ mtlr r0 ld r0, UREGS_xer(\uregs) /* load XER */ mtxer r0 lwz r0, UREGS_cr(\uregs) /* load CR */ mtcr r0 LOAD_GPRS r2, r12, \uregs /* load r2-r12 */.endm.macro LOADADDR reg symbol lis \reg,\symbol@highest ori \reg,\reg,\symbol@higher rldicr \reg,\reg,32,31 oris \reg,\reg,\symbol@h ori \reg,\reg,\symbol@l.endm.macro CALL_CFUNC reg ld r2, 8(\reg) /* load function's TOC value */ ld \reg, 0(\reg) mtctr \reg bctrl nop.endm.macro PMU_SAVE_STATE scratch mfspr \scratch,SPRN_MMCR0 /* ensure MMCR0[FCH] is 1 */ ori \scratch,\scratch,MMCR0_FCH mtspr SPRN_MMCR0, \scratch.endm.macro EXCEPTION_HEAD parea continue /* make room for cpu_user_regs */ subi r1, r1, STACK_VOLATILE_AREA + UREGS_sizeof /* get all we need from the processor_area */ std r0, UREGS_r0(r1) /* get scratch register */ ld r0, PAREA_r1(\parea) std r0, UREGS_r1(r1) /* save R1 */ ld r0, PAREA_cr(\parea) stw r0, UREGS_cr(r1) /* save CR */ mfspr r0, SPRN_HSPRG1 std r0, UREGS_r13(r1) /* save R13 from HSPRG1 */ /* Only _one_ larx is allowed at a time. Any future use will be * rejected until the earlier one (if any) completes. Since we * may have interrupted a larx in the Domain, or Xen we need to * clear any larx that may currently exist. We could probably * skip which for hcalls */ ldx r0, 0, r1 stdcx. r0, 0, r1 /* save CTR and use it to jump */ mfctr r0 std r0, UREGS_ctr(r1) LOADADDR r0, \continue mtctr r0.endm/* For normal exceptions. */.macro EXCEPTION_SAVE_STATE uregs SAVE_C_STATE \uregs /* save DEC */ mfdec r0 ld r3, PAREA_vcpu(r13) stw r0, VCPU_dec(r3) /* save PC, MSR */ mfspr r0, SPRN_SRR0 std r0, UREGS_pc(\uregs) mfspr r0, SPRN_SRR1 std r0, UREGS_msr(\uregs) li r0, -1 /* we clobbered the OS's SRR0/SRR1 to get here. */ std r0, UREGS_srr0(\uregs) std r0, UREGS_srr1(\uregs) /* done with processor_area; re-enable MSR:RI */ mfmsr r0 ori r0, r0, MSR_RI@l mtmsrd r0 PMU_SAVE_STATE r0.endm/* For exceptions that use HSRR0/1 (preserving the OS's SRR0/1). */.macro H_EXCEPTION_SAVE_STATE uregs SAVE_C_STATE \uregs /* save DEC */ mfdec r0 ld r3, PAREA_vcpu(r13) stw r0, VCPU_dec(r3) /* save PC, MSR */ mfspr r0, SPRN_HSRR0 std r0, UREGS_pc(\uregs) mfspr r0, SPRN_HSRR1 std r0, UREGS_msr(\uregs) mfspr r0, SPRN_SRR0 std r0, UREGS_srr0(\uregs) mfspr r0, SPRN_SRR1 std r0, UREGS_srr1(\uregs) /* done with processor_area; re-enable MSR:RI */ mfmsr r0 ori r0, r0, MSR_RI@l mtmsrd r0 PMU_SAVE_STATE r0.endm/* Hypervisor exception handling code; copied to physical address zero. */ .align 3 .globl exception_vectorsexception_vectors: . = 0x0 # wild branch to 0zero: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x0 /* exception vector for GDB stub */ bctr /* The following byte array is where any per-CPU state flags * that can be be used across interrupts. Currently it is only used * to track Cache Inhibited Mode when a Machine Check occurs. */ /* NOTE: This array is indexed by PIR NOT CPUID */ . = MCK_CPU_STAT_BASE .space NR_CPUS . = MCK_GOOD_HID4 .quad 0 . = 0x100 # System Resetex_reset: /* XXX thread initialization */ GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x100 /* exception vector for GDB stub */ bctr . = 0x200 # Machine Checkex_machcheck: /* Restore HID4 to a known state early, we do not recover from * machine check yet, but when we do we shoul dbe able to restore * HID4 to it proper value */ mtspr SPRN_HSPRG1, r13 ld r13, MCK_GOOD_HID4(0) sync mtspr SPRN_HID4, r13 isync /* Hopefully we don't have to worry about the ERAT */ mfspr r13, SPRN_HSPRG1 /* and now back to our regularly schedualed program */ GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_machcheck_continued li r0, 0x200 /* exception vector for GDB stub */ bctr . = 0x300ex_dsi: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x300 /* exception vector for GDB stub */ bctr . = 0x380ex_data_slb: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x380 /* exception vector for GDB stub */ bctr . = 0x400ex_isi: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x400 /* exception vector for GDB stub */ bctr . = 0x480ex_inst_slb: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x480 /* exception vector for GDB stub */ bctr . = 0x500ex_external: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_external_continued bctr . = 0x600ex_alignment: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x600 /* exception vector for GDB stub */ bctr . = 0x700ex_program: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x700 /* exception vector for GDB stub */ bctr . = 0x800ex_float: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_program_continued li r0, 0x800 /* exception vector for GDB stub */ bctr . = 0x900ex_dec: /* delivered to hypervisor when MSR:EE is set... */#ifdef SLOW_TRAP GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_dec_continued bctr#else /* XXX for now just reset DEC and return */ mtspr SPRN_HSPRG1, r3 lis r3, 0x7fff mtdec r3 mfspr r3, SPRN_HSPRG1 rfid#endif . = 0x980ex_hdec: GET_STACK r13 SPRN_HSRR1 EXCEPTION_HEAD r13 ex_hdec_continued bctr . = 0xc00ex_syscall: GET_STACK r13 SPRN_SRR1 EXCEPTION_HEAD r13 ex_hcall_continued bctr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -