1 /** 2 * @file oprofile_stubs.S 3 * Assembly language system call interceptor stubs 4 * 5 * @remark Copyright 2001-2002 Hewlett-Packard Company 6 * @remark Read the file COPYING 7 * 8 * @author Bob Montgomery <bob_montgomery (at) hp.com> 9 */ 10 11 /* 12 * This interceptor for execve was stolen from ia64/kernel/entry.S 13 * 14 * Kernel entry points. 15 * 16 * Copyright (C) 1998-2001 Hewlett-Packard Co 17 * David Mosberger-Tang <davidm (at) hpl.hp.com> 18 * Copyright (C) 1999 VA Linux Systems 19 * Copyright (C) 1999 Walt Drummond <drummond (at) valinux.com> 20 * Copyright (C) 1999 Asit Mallick <Asit.K.Mallick (at) intel.com> 21 * Copyright (C) 1999 Don Dugger <Don.Dugger (at) intel.com> 22 */ 23 /* 24 * ia64_switch_to now places correct virtual mapping in in TR2 for 25 * kernel stack. This allows us to handle interrupts without changing 26 * to physical mode. 27 * 28 * Jonathan Nicklin <nicklin (at) missioncriticallinux.com> 29 * Patrick O'Rourke <orourke (at) missioncriticallinux.com> 30 * 11/07/2000 31 */ 32 /* 33 * Global (preserved) predicate usage on syscall entry/exit path: 34 * 35 * pKern: See entry.h. 36 * pUser: See entry.h. 37 * pSys: See entry.h. 38 * pNonSys: !pSys 39 */ 40 41 #include <linux/config.h> 42 43 #include <asm/cache.h> 44 #include <asm/errno.h> 45 #include <asm/kregs.h> 46 #include <asm/offsets.h> 47 #include <asm/processor.h> 48 #include <asm/unistd.h> 49 #include <asm/asmmacro.h> 50 #include <asm/pgtable.h> 51 52 #include "IA64minstate.h" 53 54 /* 55 * execve() is special because in case of success, we need to 56 * setup a null register window frame. 57 */ 58 GLOBAL_ENTRY(my_ia64_execve) 59 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3) 60 alloc loc1=ar.pfs, 3, 3, 4, 0 61 mov loc0=rp 62 mov loc2=gp 63 .body 64 mov out0=in0 // filename 65 ;; // stop bit between alloc and call 66 mov out1=in1 // argv 67 mov out2=in2 // envp 68 add out3=16, sp // regs 69 /* 70 * We are here with the kernel's gp register value but we need 71 * to find the module's gp value before we can call our own 72 * routine. That's why we can't just use: 73 * br.call.sptk.many rp=my_sys_execve 74 * Use ip-relative addressing to get to the fptr since I can't 75 * use gp-relative anything without the module's gp. 76 */ 77 .L1_execve: 78 mov r3 = ip 79 ;; 80 addl r14 = .fptr_execve - .L1_execve, r3 81 ;; 82 ld8 r14=[r14] 83 ;; 84 ld8 r15=[r14], 8 85 ;; 86 ld8 gp=[r14] 87 ;; 88 mov b6=r15 89 br.call.sptk.many b0=b6 90 ;; 91 .ret0: cmp4.ge p6, p7=r8, r0 92 mov ar.pfs=loc1 // restore ar.pfs 93 sxt4 r8=r8 // return 64-bit result 94 ;; 95 stf.spill [sp]=f0 96 (p6) cmp.ne pKern, pUser=r0, r0 // a successful execve() lands us in user-mode... 97 mov gp=loc2 98 mov rp=loc0 99 (p6) mov ar.pfs=r0 // clear ar.pfs on success 100 (p7) br.ret.sptk.many rp 101 102 /* 103 * In theory, we'd have to zap this state only to prevent leaking of 104 * security sensitive state (e.g., if current->mm->dumpable is zero). However, 105 * this executes in less than 20 cycles even on Itanium, so it's not worth 106 * optimizing for...). 107 */ 108 mov r4=0; mov f2=f0; mov b1=r0 109 mov r5=0; mov f3=f0; mov b2=r0 110 mov r6=0; mov f4=f0; mov b3=r0 111 mov r7=0; mov f5=f0; mov b4=r0 112 mov ar.unat=0; mov f10=f0; mov b5=r0 113 ldf.fill f11=[sp]; ldf.fill f12=[sp]; mov f13=f0 114 ldf.fill f14=[sp]; ldf.fill f15=[sp]; mov f16=f0 115 ldf.fill f17=[sp]; ldf.fill f18=[sp]; mov f19=f0 116 ldf.fill f20=[sp]; ldf.fill f21=[sp]; mov f22=f0 117 ldf.fill f23=[sp]; ldf.fill f24=[sp]; mov f25=f0 118 ldf.fill f26=[sp]; ldf.fill f27=[sp]; mov f28=f0 119 ldf.fill f29=[sp]; ldf.fill f30=[sp]; mov f31=f0 120 mov ar.lc=0 121 br.ret.sptk.many rp 122 .align 16 123 .fptr_execve: 124 data8 @fptr(my_sys_execve) 125 END(my_ia64_execve) 126 127 /* These interceptors are from IA64syscallstub.h macros */ 128 #include "IA64syscallstub.h" 129 130 SYSCALLSTUB_POST(clone) 131 132 SYSCALLSTUB_POST(clone2) 133 134 SYSCALLSTUB_POST(mmap) 135 136 SYSCALLSTUB_POST(mmap2) 137 138 SYSCALLSTUB_POST(init_module) 139 140 SYSCALLSTUB_PRE(exit) 141