📄 entry.s
字号:
/* * Linux/PA-RISC Project (http://www.parisc-linux.org/) * * kernel entry points (interruptions, system call wrappers) * Copyright (C) 1999,2000 Philipp Rumpf * Copyright (C) 1999 SuSE GmbH Nuernberg * Copyright (C) 2000 Hewlett-Packard (John Marvin) * Copyright (C) 1999 Hewlett-Packard (Frank Rowand) * * 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, 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/config.h>#include <asm/offset.h>/* we have the following possibilities to act on an interruption: * - handle in assembly and use shadowed registers only * - save registers to kernel stack and handle in assembly or C */#include <asm/assembly.h> /* for LDREG/STREG defines */#include <asm/pgtable.h>#include <asm/psw.h>#include <asm/signal.h>#include <asm/unistd.h>#ifdef __LP64__#define FRAME_SIZE 128#define CMPIB cmpib,*#define CMPB cmpb,* .level 2.0w#else#define FRAME_SIZE 64#define CMPIB cmpib,#define CMPB cmpb, .level 2.0#endif .import pa_dbit_lock,data /* space_to_prot macro creates a prot id from a space id */#if (SPACEID_SHIFT) == 0 .macro space_to_prot spc prot depd,z \spc,62,31,\prot .endm#else .macro space_to_prot spc prot extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot .endm#endif /* Switch to virtual mapping, trashing only %r1 */ .macro virt_map rsm PSW_SM_Q,%r0 tovirt_r1 %r29 mfsp %sr7, %r1 or,= %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */ mtsp %r1, %sr3 mtsp %r0, %sr4 mtsp %r0, %sr5 mtsp %r0, %sr6 mtsp %r0, %sr7 ldil L%KERNEL_PSW, %r1 ldo R%KERNEL_PSW(%r1), %r1 mtctl %r1, %cr22 mtctl %r0, %cr17 mtctl %r0, %cr17 ldil L%4f, %r1 ldo R%4f(%r1), %r1 mtctl %r1, %cr18 ldo 4(%r1), %r1 mtctl %r1, %cr18 rfir nop4: .endm /* * The "get_stack" macros are responsible for determining the * kernel stack value. * * For Faults: * If sr7 == 0 * Already using a kernel stack, so call the * get_stack_use_r30 macro to push a pt_regs structure * on the stack, and store registers there. * else * Need to set up a kernel stack, so call the * get_stack_use_cr30 macro to set up a pointer * to the pt_regs structure contained within the * task pointer pointed to by cr30. Set the stack * pointer to point to the end of the task structure. * * For Interrupts: * If sr7 == 0 * Already using a kernel stack, check to see if r30 * is already pointing to the per processor interrupt * stack. If it is, call the get_stack_use_r30 macro * to push a pt_regs structure on the stack, and store * registers there. Otherwise, call get_stack_use_cr31 * to get a pointer to the base of the interrupt stack * and push a pt_regs structure on that stack. * else * Need to set up a kernel stack, so call the * get_stack_use_cr30 macro to set up a pointer * to the pt_regs structure contained within the * task pointer pointed to by cr30. Set the stack * pointer to point to the end of the task structure. * N.B: We don't use the interrupt stack for the * first interrupt from userland, because signals/ * resched's are processed when returning to userland, * and we can sleep in those cases. * * Note that we use shadowed registers for temps until * we can save %r26 and %r29. %r26 is used to preserve * %r8 (a shadowed register) which temporarily contained * either the fault type ("code") or the eirr. We need * to use a non-shadowed register to carry the value over * the rfir in virt_map. We use %r26 since this value winds * up being passed as the argument to either do_cpu_irq_mask * or handle_interruption. %r29 is used to hold a pointer * the register save area, and once again, it needs to * be a non-shadowed register so that it survives the rfir. * * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame. */ .macro get_stack_use_cr30 /* we save the registers in the task struct */ mfctl %cr30, %r1 tophys %r1,%r9 ldo TASK_REGS(%r9),%r9 STREG %r30, PT_GR30(%r9) ldo TASK_SZ_ALGN(%r1), %r30 STREG %r29,PT_GR29(%r9) STREG %r26,PT_GR26(%r9) copy %r9,%r29 .endm .macro get_stack_use_r30 /* we put a struct pt_regs on the stack and save the registers there */ tophys %r30,%r9 STREG %r30,PT_GR30(%r9) ldo PT_SZ_ALGN(%r30),%r30 STREG %r29,PT_GR29(%r9) STREG %r26,PT_GR26(%r9) copy %r9,%r29 .endm .macro rest_stack LDREG PT_GR1(%r29), %r1 LDREG PT_GR30(%r29),%r30 LDREG PT_GR29(%r29),%r29 .endm /* default interruption handler * (calls traps.c:handle_interruption) */ .macro def code b intr_save ldi \code, %r8 .align 32 .endm /* Interrupt interruption handler * (calls irq.c:do_cpu_irq_mask) */ .macro extint code b intr_extint mfsp %sr7,%r16 .align 32 .endm .import os_hpmc, code /* HPMC handler */ .macro hpmc code nop /* must be a NOP, will be patched later */ ldil L%PA(os_hpmc), %r3 ldo R%PA(os_hpmc)(%r3), %r3 bv,n 0(%r3) nop .word 0 /* checksum (will be patched) */ .word PA(os_hpmc) /* address of handler */ .word 0 /* length of handler */ .endm /* * Performance Note: Instructions will be moved up into * this part of the code later on, once we are sure * that the tlb miss handlers are close to final form. */ /* Register definitions for tlb miss handler macros */ va = r8 /* virtual address for which the trap occured */ spc = r24 /* space for which the trap occured */#ifndef __LP64__ /* * itlb miss interruption handler (parisc 1.1 - 32 bit) */ .macro itlb_11 code mfctl %pcsq, spc b itlb_miss_11 mfctl %pcoq, va .align 32 .endm#endif /* * itlb miss interruption handler (parisc 2.0) */ .macro itlb_20 code mfctl %pcsq, spc#ifdef __LP64__ b itlb_miss_20w#else b itlb_miss_20#endif mfctl %pcoq, va .align 32 .endm #ifndef __LP64__ /* * naitlb miss interruption handler (parisc 1.1 - 32 bit) * * Note: naitlb misses will be treated * as an ordinary itlb miss for now. * However, note that naitlb misses * have the faulting address in the * IOR/ISR. */ .macro naitlb_11 code mfctl %isr,spc b itlb_miss_11 mfctl %ior,va /* FIXME: If user causes a naitlb miss, the priv level may not be in * lower bits of va, where the itlb miss handler is expecting them */ .align 32 .endm#endif /* * naitlb miss interruption handler (parisc 2.0) * * Note: naitlb misses will be treated * as an ordinary itlb miss for now. * However, note that naitlb misses * have the faulting address in the * IOR/ISR. */ .macro naitlb_20 code mfctl %isr,spc#ifdef __LP64__ b itlb_miss_20w#else b itlb_miss_20#endif mfctl %ior,va /* FIXME: If user causes a naitlb miss, the priv level may not be in * lower bits of va, where the itlb miss handler is expecting them */ .align 32 .endm #ifndef __LP64__ /* * dtlb miss interruption handler (parisc 1.1 - 32 bit) */ .macro dtlb_11 code mfctl %isr, spc b dtlb_miss_11 mfctl %ior, va .align 32 .endm#endif /* * dtlb miss interruption handler (parisc 2.0) */ .macro dtlb_20 code mfctl %isr, spc#ifdef __LP64__ b dtlb_miss_20w#else b dtlb_miss_20#endif mfctl %ior, va .align 32 .endm #ifndef __LP64__ /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */ .macro nadtlb_11 code mfctl %isr,spc b nadtlb_miss_11 mfctl %ior,va .align 32 .endm#endif /* nadtlb miss interruption handler (parisc 2.0) */ .macro nadtlb_20 code mfctl %isr,spc#ifdef __LP64__ b nadtlb_miss_20w#else b nadtlb_miss_20#endif mfctl %ior,va .align 32 .endm #ifndef __LP64__ /* * dirty bit trap interruption handler (parisc 1.1 - 32 bit) */ .macro dbit_11 code mfctl %isr,spc b dbit_trap_11 mfctl %ior,va .align 32 .endm#endif /* * dirty bit trap interruption handler (parisc 2.0) */ .macro dbit_20 code mfctl %isr,spc#ifdef __LP64__ b dbit_trap_20w#else b dbit_trap_20#endif mfctl %ior,va .align 32 .endm /* * Align fault_vector_20 on 4K boundary so that both * fault_vector_11 and fault_vector_20 are on the * same page. This is only necessary as long as we * write protect the kernel text, which we may stop * doing once we use large page translations to cover * the static part of the kernel address space. */ .export fault_vector_20 .text .align 4096fault_vector_20: /* First vector is invalid (0) */ .ascii "cows can fly" .byte 0 .align 32 hpmc 1 def 2 def 3 extint 4 def 5 itlb_20 6 def 7 def 8 def 9 def 10 def 11 def 12 def 13 def 14 dtlb_20 15#if 0 naitlb_20 16#else def 16#endif nadtlb_20 17 def 18 def 19 dbit_20 20 def 21 def 22 def 23 def 24 def 25 def 26 def 27 def 28 def 29 def 30 def 31#ifndef __LP64__ .export fault_vector_11 .align 2048fault_vector_11: /* First vector is invalid (0) */ .ascii "cows can fly" .byte 0 .align 32 hpmc 1 def 2 def 3 extint 4 def 5 itlb_11 6 def 7 def 8 def 9 def 10 def 11 def 12 def 13 def 14 dtlb_11 15#if 0 naitlb_11 16#else def 16#endif nadtlb_11 17 def 18 def 19 dbit_11 20 def 21 def 22 def 23 def 24 def 25 def 26 def 27 def 28 def 29 def 30 def 31#endif .import handle_interruption,code .import handle_real_interruption,code .import do_cpu_irq_mask,code .import parisc_stopkernel,code /* * r26 = function to be called * r25 = argument to pass in * r24 = flags for do_fork() * * Kernel threads don't ever return, so they don't need * a true register context. We just save away the arguments * for copy_thread/ret_ to properly set up the child. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -