syscall-ppc32-linux.S revision af839f52d74df156d655201a889954133ab01be7
1 2##--------------------------------------------------------------------## 3##--- Support for doing system calls. syscall-ppc32-linux.S ---## 4##--------------------------------------------------------------------## 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2005 Paul Mackerras <paulus@samba.org> 11 12 This program is free software; you can redistribute it and/or 13 modify it under the terms of the GNU General Public License as 14 published by the Free Software Foundation; either version 2 of the 15 License, or (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, but 18 WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 25 02111-1307, USA. 26 27 The GNU General Public License is contained in the file COPYING. 28*/ 29 30#include "pub_tool_basics_asm.h" 31#include "vki_unistd.h" 32#include "libvex_guest_offsets.h" 33 34 35/*----------------------------------------------------------------*/ 36/* 37 Perform a syscall for the client. This will run a syscall 38 with the client's specific per-thread signal mask. 39 40 The structure of this function is such that, if the syscall is 41 interrupted by a signal, we can determine exactly what 42 execution state we were in with respect to the execution of 43 the syscall by examining the value of NIP in the signal 44 handler. This means that we can always do the appropriate 45 thing to precisely emulate the kernel's signal/syscall 46 interactions. 47 48 The syscall number is taken from the argument, even though it 49 should also be in regs->m_gpr[0]. The syscall result is written 50 back to regs->m_gpr[3]/m_xer/m_result on completion. 51 52 Returns 0 if the syscall was successfully called (even if the 53 syscall itself failed), or a -ve error code if one of the 54 sigprocmasks failed (there's no way to determine which one 55 failed). 56 57 VG_(interrupted_syscall)() does the thread state fixup in the 58 case where we were interrupted by a signal. 59 60 Prototype: 61 62 Int VG_(do_syscall_for_client_WRK)( 63 Int syscallno, // r3 64 void* guest_state, // r4 65 const vki_sigset_t *sysmask, // r5 66 const vki_sigset_t *postmask, // r6 67 Int nsigwords) // r7 68*/ 69/* from vki_arch.h */ 70#define VKI_SIG_SETMASK 2 71 72.globl VG_(do_syscall_for_client_WRK) 73VG_(do_syscall_for_client_WRK): 74 /* make a stack frame */ 75 stwu 1,-32(1) 76 stw 31,28(1) 77 stw 30,24(1) 78 stw 29,20(1) 79 stw 28,16(1) 80 mr 31,3 /* syscall number */ 81 mr 30,4 /* guest_state */ 82 mr 29,6 /* postmask */ 83 mr 28,7 /* nsigwords */ 84 85 /* set the signal mask for doing the system call */ 86 /* set up for sigprocmask(SIG_SETMASK, sysmask, postmask) */ 871: li 0,__NR_sigprocmask 88 li 3,VKI_SIG_SETMASK 89 mr 4,5 90 mr 5,6 91 sc /* set the mask */ 92 bso 7f /* if the sigprocmask fails */ 93 94 /* load up syscall args from the threadstate */ 95 lwz 3,OFFSET_ppc32_GPR3(30) 96 lwz 4,OFFSET_ppc32_GPR4(30) 97 lwz 5,OFFSET_ppc32_GPR5(30) 98 lwz 6,OFFSET_ppc32_GPR6(30) 99 lwz 7,OFFSET_ppc32_GPR7(30) 100 lwz 8,OFFSET_ppc32_GPR8(30) 101 mr 0,31 /* syscall number */ 1022: sc /* do the syscall */ 103 104 /* put the result back in the threadstate */ 105 /* HACK: killing all of CR0 for simplicity (should get from gst) */ 1063: stw 3,OFFSET_ppc32_GPR3(30) /* gst->GPR3 = sc result */ 107 li 4,1 108 stw 4,OFFSET_ppc32_CC_OP(30) /* gst->CC_OP = 1 */ 109 mfcr 5 /* r5 = CR */ 110 andis. 5,5,0x1000 /* mask to only CR7.SO */ 111 oris 5,5,0x2000 /* set CR7.EQ */ 112 stw 5,OFFSET_ppc32_CC_DEP1(30) /* gst->CR7 = CR7 */ 113 114 /* block signals again */ 115 /* set up for sigprocmask(SIG_SETMASK, postmask, NULL) */ 1164: li 0,__NR_sigprocmask 117 li 3,VKI_SIG_SETMASK 118 mr 4,29 119 li 5,0 120 mr 6,28 121 sc /* set the mask */ 122 bso 7f /* if the sigprocmask fails */ 123 124 /* now safe from signals */ 125 126 /* pop off stack frame */ 1275: lwz 28,16(1) 128 lwz 29,20(1) 129 lwz 30,24(1) 130 lwz 31,28(1) 131 addi 1,1,32 132 blr 133 134 /* failure: return -ve error code */ 1357: neg 3,3 136 b 5b 137 138.section .rodata 139/* export the ranges so that 140 VG_(fixup_guest_state_after_syscall_interrupted) can do the 141 right thing */ 142 143.globl VG_(blksys_setup) 144.globl VG_(blksys_restart) 145.globl VG_(blksys_complete) 146.globl VG_(blksys_committed) 147.globl VG_(blksys_finished) 148VG_(blksys_setup): .long 1b 149VG_(blksys_restart): .long 2b 150VG_(blksys_complete): .long 3b 151VG_(blksys_committed): .long 4b 152VG_(blksys_finished): .long 5b 153 154.previous 155 156/* Let the linker know we don't need an executable stack */ 157.section .note.GNU-stack,"",@progbits 158 159##--------------------------------------------------------------------## 160##--- end ---## 161##--------------------------------------------------------------------## 162