1e71ca95cSGerald Jelinek/* 2e71ca95cSGerald Jelinek * CDDL HEADER START 3e71ca95cSGerald Jelinek * 4e71ca95cSGerald Jelinek * The contents of this file are subject to the terms of the 5e71ca95cSGerald Jelinek * Common Development and Distribution License (the "License"). 6e71ca95cSGerald Jelinek * You may not use this file except in compliance with the License. 7e71ca95cSGerald Jelinek * 8e71ca95cSGerald Jelinek * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9e71ca95cSGerald Jelinek * or http://www.opensolaris.org/os/licensing. 10e71ca95cSGerald Jelinek * See the License for the specific language governing permissions 11e71ca95cSGerald Jelinek * and limitations under the License. 12e71ca95cSGerald Jelinek * 13e71ca95cSGerald Jelinek * When distributing Covered Code, include this CDDL HEADER in each 14e71ca95cSGerald Jelinek * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15e71ca95cSGerald Jelinek * If applicable, add the following below this CDDL HEADER, with the 16e71ca95cSGerald Jelinek * fields enclosed by brackets "[]" replaced with your own identifying 17e71ca95cSGerald Jelinek * information: Portions Copyright [yyyy] [name of copyright owner] 18e71ca95cSGerald Jelinek * 19e71ca95cSGerald Jelinek * CDDL HEADER END 20e71ca95cSGerald Jelinek */ 21e71ca95cSGerald Jelinek/* 2280e2ca85S * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23e71ca95cSGerald Jelinek */ 24e71ca95cSGerald Jelinek 2580e2ca85S#include <brand_misc.h> 26e71ca95cSGerald Jelinek 27e71ca95cSGerald Jelinek#if defined(lint) 28e71ca95cSGerald Jelinek 29e71ca95cSGerald Jelinekvoid 3080e2ca85Sbrand_handler(void) 31e71ca95cSGerald Jelinek{ 32e71ca95cSGerald Jelinek} 33e71ca95cSGerald Jelinek 34e71ca95cSGerald Jelinek#else /* !lint */ 35e71ca95cSGerald Jelinek 36e71ca95cSGerald Jelinek#define PIC_SETUP(r) \ 37e71ca95cSGerald Jelinek mov %o7, %g1; \ 38e71ca95cSGerald Jelinek9: call 8f; \ 39e71ca95cSGerald Jelinek sethi %hi(_GLOBAL_OFFSET_TABLE_ - (9b - .)), r; \ 40e71ca95cSGerald Jelinek8: or r, %lo(_GLOBAL_OFFSET_TABLE_ - (9b - .)), r; \ 41e71ca95cSGerald Jelinek add r, %o7, r; \ 42e71ca95cSGerald Jelinek mov %g1, %o7 43e71ca95cSGerald Jelinek 44e71ca95cSGerald Jelinek/* 45e71ca95cSGerald Jelinek * Translate a global symbol into an address. The resulting address 46e71ca95cSGerald Jelinek * is returned in the first register parameter. The second register 47e71ca95cSGerald Jelinek * is just for scratch space. 48e71ca95cSGerald Jelinek */ 49e71ca95cSGerald Jelinek#if defined(__sparcv9) 50e71ca95cSGerald Jelinek#define GET_SYM_ADDR(r1, r2, name) \ 51e71ca95cSGerald Jelinek PIC_SETUP(r1) ;\ 52e71ca95cSGerald Jelinek sethi %hi(name), r2 ;\ 53e71ca95cSGerald Jelinek or r2, %lo(name), r2 ;\ 54e71ca95cSGerald Jelinek ldn [r2 + r1], r1 55e71ca95cSGerald Jelinek#else /* !__sparcv9 */ 56e71ca95cSGerald Jelinek#define GET_SYM_ADDR(r1, r2, name) \ 57e71ca95cSGerald Jelinek PIC_SETUP(r1); \ 58e71ca95cSGerald Jelinek ld [r1 + name], r1 59e71ca95cSGerald Jelinek#endif /* !__sparcv9 */ 60e71ca95cSGerald Jelinek 61e71ca95cSGerald Jelinek .section ".text" 62e71ca95cSGerald Jelinek 63e71ca95cSGerald Jelinek /* 64e71ca95cSGerald Jelinek * When we get here, %g1 should contain the system call and 65e71ca95cSGerald Jelinek * %g5 should contain the address immediately after the trap 66e71ca95cSGerald Jelinek * instruction. 67e71ca95cSGerald Jelinek */ 6880e2ca85S ENTRY_NP(brand_handler) 69e71ca95cSGerald Jelinek 70e71ca95cSGerald Jelinek /* 71e71ca95cSGerald Jelinek * 64-bit sparc may need to save 3 parameters on the stack. 72e71ca95cSGerald Jelinek * 32-bit sparc may need to save 4 parameters on the stack. 73e71ca95cSGerald Jelinek * 7480e2ca85S * Our stack frame format is documented in brand_misc.h. 75e71ca95cSGerald Jelinek */ 76e71ca95cSGerald Jelinek save %sp, -SA(MINFRAME + EH_LOCALS_SIZE), %sp 77e71ca95cSGerald Jelinek 78e71ca95cSGerald Jelinek /* 79e71ca95cSGerald Jelinek * Save the current caller state into gregs and gwins. 80e71ca95cSGerald Jelinek * Note that this state isn't exact, %g1 and %g5 have been 81e71ca95cSGerald Jelinek * already been lost. Also, we've pushed a stack frame so 82e71ca95cSGerald Jelinek * the callers output registers are our input registers. 83e71ca95cSGerald Jelinek */ 84e71ca95cSGerald Jelinek stn %g0, [%sp + EH_LOCALS_GREG(REG_G1)] /* %g1 is lost */ 85e71ca95cSGerald Jelinek stn %g2, [%sp + EH_LOCALS_GREG(REG_G2)] 86e71ca95cSGerald Jelinek stn %g3, [%sp + EH_LOCALS_GREG(REG_G3)] 87e71ca95cSGerald Jelinek stn %g4, [%sp + EH_LOCALS_GREG(REG_G4)] 88e71ca95cSGerald Jelinek stn %g0, [%sp + EH_LOCALS_GREG(REG_G5)] /* %g5 is lost */ 89e71ca95cSGerald Jelinek stn %g6, [%sp + EH_LOCALS_GREG(REG_G6)] 90e71ca95cSGerald Jelinek stn %g7, [%sp + EH_LOCALS_GREG(REG_G7)] 91e71ca95cSGerald Jelinek stn %i0, [%sp + EH_LOCALS_GREG(REG_O0)] 92e71ca95cSGerald Jelinek stn %i1, [%sp + EH_LOCALS_GREG(REG_O1)] 93e71ca95cSGerald Jelinek stn %i2, [%sp + EH_LOCALS_GREG(REG_O2)] 94e71ca95cSGerald Jelinek stn %i3, [%sp + EH_LOCALS_GREG(REG_O3)] 95e71ca95cSGerald Jelinek stn %i4, [%sp + EH_LOCALS_GREG(REG_O4)] 96e71ca95cSGerald Jelinek stn %i5, [%sp + EH_LOCALS_GREG(REG_O5)] 97e71ca95cSGerald Jelinek stn %i6, [%sp + EH_LOCALS_GREG(REG_O6)] 98e71ca95cSGerald Jelinek stn %i7, [%sp + EH_LOCALS_GREG(REG_O7)] 99e71ca95cSGerald Jelinek sub %g5, 4, %o0 100e71ca95cSGerald Jelinek stn %o0, [%sp + EH_LOCALS_GREG(REG_PC)] 101e71ca95cSGerald Jelinek stn %g5, [%sp + EH_LOCALS_GREG(REG_nPC)] 102e71ca95cSGerald Jelinek rd %y, %o0 103e71ca95cSGerald Jelinek stn %o0, [%sp + EH_LOCALS_GREG(REG_Y)] 104e71ca95cSGerald Jelinek#if defined(__sparcv9) 105e71ca95cSGerald Jelinek stn %g0, [%sp + EH_LOCALS_GREG(REG_ASI)] 106e71ca95cSGerald Jelinek rd %fprs, %o0 107e71ca95cSGerald Jelinek stn %o0, [%sp + EH_LOCALS_GREG(REG_FPRS)] 108e71ca95cSGerald Jelinek#endif /* __sparcv9 */ 109e71ca95cSGerald Jelinek 110e71ca95cSGerald Jelinek /* 111e71ca95cSGerald Jelinek * Look up the system call's entry in the sysent table 112e71ca95cSGerald Jelinek * and obtain the address of the proper emulation routine (%l2). 113e71ca95cSGerald Jelinek */ 114e71ca95cSGerald Jelinek mov %g1, %l5 /* save syscall number */ 11580e2ca85S GET_SYM_ADDR(%l1, %l2, brand_sysent_table) 116e71ca95cSGerald Jelinek mov %l5, %g1 /* restore syscall number */ 117e71ca95cSGerald Jelinek sll %g1, (1 + CLONGSHIFT), %l2 /* Each entry has 2 longs */ 118e71ca95cSGerald Jelinek add %l2, %l1, %l2 /* index to proper entry */ 119e71ca95cSGerald Jelinek ldn [%l2], %l2 /* emulation func address */ 120e71ca95cSGerald Jelinek 121e71ca95cSGerald Jelinek /* 122e71ca95cSGerald Jelinek * Look up the system call's entry in the sysent table, 123e71ca95cSGerald Jelinek * taking into account the posibility of indirect system calls, and 124e71ca95cSGerald Jelinek * obtain the number of arguments (%l4) and return value flag (%l3). 125e71ca95cSGerald Jelinek */ 126e71ca95cSGerald Jelinek#if defined(__sparcv9) 127e71ca95cSGerald Jelinek mov %g1, %l3 /* %g1 == syscall number */ 128e71ca95cSGerald Jelinek#else /* !__sparcv9 */ 129e71ca95cSGerald Jelinek /* 130e71ca95cSGerald Jelinek * Check for indirect system calls, in which case the real syscall 131e71ca95cSGerald Jelinek * number is the first parameter to the indirect system call. 132e71ca95cSGerald Jelinek */ 133e71ca95cSGerald Jelinek cmp %g1, %g0 /* saved syscall number */ 134e71ca95cSGerald Jelinek bne,a,pt %icc, no_indir /* indirect syscall? */ 135e71ca95cSGerald Jelinek mov %g1, %l3 /* %g1 == syscall number */ 136e71ca95cSGerald Jelinek mov %i0, %l3 /* %i0 == syscall number */ 137e71ca95cSGerald Jelinekno_indir: 138e71ca95cSGerald Jelinek#endif /* !__sparcv9 */ 139e71ca95cSGerald Jelinek sll %l3, (1 + CLONGSHIFT), %l3 /* Each entry has 2 longs */ 140e71ca95cSGerald Jelinek add %l3, %l1, %l3 /* index to proper entry */ 141e71ca95cSGerald Jelinek ldn [%l3 + CPTRSIZE], %l4 /* number of args + rv flag */ 142e71ca95cSGerald Jelinek sethi %hi(RV_MASK), %l5 143e71ca95cSGerald Jelinek or %l5, %lo(RV_MASK), %l5 144e71ca95cSGerald Jelinek andcc %l4, %l5, %l3 /* strip out number of args*/ 145e71ca95cSGerald Jelinek andcc %l4, NARGS_MASK, %l4 /* strip out rv flag */ 146e71ca95cSGerald Jelinek 147e71ca95cSGerald Jelinek /* 148e71ca95cSGerald Jelinek * Setup arguments for our emulation call. Our input arguments, 149e71ca95cSGerald Jelinek * 0 to N, will become emulation call arguments 1 to N+1. 150e71ca95cSGerald Jelinek * %l4 == number of arguments. 151e71ca95cSGerald Jelinek */ 152e71ca95cSGerald Jelinek mov %i0, %o1 153e71ca95cSGerald Jelinek mov %i1, %o2 154e71ca95cSGerald Jelinek mov %i2, %o3 155e71ca95cSGerald Jelinek mov %i3, %o4 156e71ca95cSGerald Jelinek mov %i4, %o5 157e71ca95cSGerald Jelinek 158e71ca95cSGerald Jelinek /* 7th argument and above get passed on the stack */ 159e71ca95cSGerald Jelinek cmp %l4, 0x6 160e71ca95cSGerald Jelinek bl,pt %ncc, args_copied 161e71ca95cSGerald Jelinek nop 162e71ca95cSGerald Jelinek stn %i5, [%sp + EH_ARGS_OFFSET(0)] /* copy 6th syscall arg */ 163e71ca95cSGerald Jelinek cmp %l4, 0x7 164e71ca95cSGerald Jelinek bl,pt %ncc, args_copied 165e71ca95cSGerald Jelinek nop 166e71ca95cSGerald Jelinek ldn [%fp + EH_ARGS_OFFSET(0)], %l5 /* copy 7th syscall arg */ 167e71ca95cSGerald Jelinek stn %l5, [%sp + EH_ARGS_OFFSET(1)] 168e71ca95cSGerald Jelinek cmp %l4, 0x8 169e71ca95cSGerald Jelinek bl,pt %ncc, args_copied 170e71ca95cSGerald Jelinek nop 171e71ca95cSGerald Jelinek ldn [%fp + EH_ARGS_OFFSET(1)], %l5 172e71ca95cSGerald Jelinek stn %l5, [%sp + EH_ARGS_OFFSET(2)] /* copy 8th syscall arg */ 173e71ca95cSGerald Jelinek#if !defined(__sparcv9) 174e71ca95cSGerald Jelinek cmp %l4, 0x9 175e71ca95cSGerald Jelinek bl,pt %ncc, args_copied 176e71ca95cSGerald Jelinek nop 177e71ca95cSGerald Jelinek ldn [%fp + EH_ARGS_OFFSET(2)], %l5 178e71ca95cSGerald Jelinek stn %l5, [%sp + EH_ARGS_OFFSET(3)] /* copy 9th syscall arg */ 179e71ca95cSGerald Jelinek#endif /* !__sparcv9 */ 180e71ca95cSGerald Jelinek 181e71ca95cSGerald Jelinekargs_copied: 182e71ca95cSGerald Jelinek /* 183e71ca95cSGerald Jelinek * The first parameter to the emulation callback function is a 184e71ca95cSGerald Jelinek * pointer to a sysret_t structure. 185e71ca95cSGerald Jelinek * 186e71ca95cSGerald Jelinek * invoke the emulation routine. 187e71ca95cSGerald Jelinek */ 18880e2ca85S ALTENTRY(brand_handler_savepc) 189e71ca95cSGerald Jelinek call %l2 190e71ca95cSGerald Jelinek add %sp, EH_LOCALS_SYSRET, %o0 /* arg0 == sysret_t ptr */ 191e71ca95cSGerald Jelinek 192e71ca95cSGerald Jelinek /* Check for syscall emulation success or failure */ 193e71ca95cSGerald Jelinek cmp %g0, %o0 194e71ca95cSGerald Jelinek be success 195e71ca95cSGerald Jelinek nop 196e71ca95cSGerald Jelinek subcc %g0, 1, %g0 /* failure, set carry flag */ 197e71ca95cSGerald Jelinek ba return 198e71ca95cSGerald Jelinek mov %o0, %i0 /* return, %o0 == errno */ 199e71ca95cSGerald Jelinek 200e71ca95cSGerald Jelineksuccess: 201e71ca95cSGerald Jelinek /* There is always at least one return value. */ 202e71ca95cSGerald Jelinek ldn [%sp + EH_LOCALS_SYSRET1], %i0 /* %i0 == sys_rval1 */ 203e71ca95cSGerald Jelinek cmp %l3, RV_DEFAULT /* check rv flag */ 204e71ca95cSGerald Jelinek be,a clear_carry 205e71ca95cSGerald Jelinek mov %g0, %i1 /* clear second rval */ 206e71ca95cSGerald Jelinek ldn [%sp + EH_LOCALS_SYSRET2], %i1 /* %i1 == sys_rval2 */ 207e71ca95cSGerald Jelinekclear_carry: 208e71ca95cSGerald Jelinek addcc %g0, %g0, %g0 /* success, clear carry flag */ 209e71ca95cSGerald Jelinek 210e71ca95cSGerald Jelinekreturn: 211e71ca95cSGerald Jelinek /* 212e71ca95cSGerald Jelinek * Our syscall emulation is complete. Return to the caller that 213e71ca95cSGerald Jelinek * originally invoked a system which needed emulation. Note that 214e71ca95cSGerald Jelinek * we have to load the return address that we saved earlier because 215e71ca95cSGerald Jelinek * it's possible that %g5 was overwritten by a nested call into 216e71ca95cSGerald Jelinek * this emulation library. 217e71ca95cSGerald Jelinek */ 218e71ca95cSGerald Jelinek ldn [%sp + EH_LOCALS_GREG(REG_nPC)], %g5 219e71ca95cSGerald Jelinek jmp %g5 220e71ca95cSGerald Jelinek restore /* delay slot */ 22180e2ca85S SET_SIZE(brand_handler) 222e71ca95cSGerald Jelinek 223e71ca95cSGerald Jelinek 224e71ca95cSGerald Jelinek#endif /* !lint */ 225