/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include /* * Kernel function call invocation */ #if !defined(__lint) .section RODATA .align 8 /* * A jump table containing the addresses for register argument copy * code. */ copyargs: .xword cp0arg .xword cp1arg .xword cp2arg .xword cp3arg .xword cp4arg .xword cp5arg copyargsend: .xword cp6arg #endif /* __lint */ #if defined(__lint) /*ARGSUSED*/ uintptr_t kaif_invoke(uintptr_t funcva, uint_t argc, const uintptr_t *argv, kreg_t g6, kreg_t g7) { return (0); } #else ENTRY_NP(kaif_invoke) save %sp, -SA(MINFRAME), %sp /* * Will registers suffice, or do we need to put excess args (>6) on the * stack? */ sub %i1, 6, %i1 ! %i1 is now num regs over 6 (if any) brgz,pn %i1, savestackargs sllx %i1, 3, %i1 ! (argc - 6) * 8 /* * We have fewer than six arguments. Below, starting at the cp6arg * label, we've got code that'll copy these arguments to the out * registers in descending order (%o5 is copied, then %o4, and so on). * We only want to move valid arguments, so we'll jump into this copy * code just before it copies our highest arg. If we have four args, * for example, we'll jump to cp4arg. * * %i6 is now a negative word-scaled offset, which we can use to * retrieve the appropriate address from the jump table. We start at * bottom of the table, and let the negative offset jump back to the * correct location. If we have four arguments, %i1 will be -16. * Starting from copyargs+48 (the address of the last slot), we get * copyargs+32, which contains the address (cp4arg) to be used to copy * four arguments. */ setx copyargsend, %l1, %l0 ldx [%l0 + %i1], %l0 jmp %l0 nop savestackargs: /* * We have more than six arguments, and will thus need to allocate space * for the seventh and beyond on the stack. %i1 is the number of bytes * needed to hold the seventh and higher arguments. */ /* Allocate swap space - %i1 rounded up to STACK_ALIGN */ add %i1, STACK_ALIGN/2, %g1 and %g1, -STACK_ALIGN, %g1 sub %sp, %g1, %sp add %i2, 6*8, %l0 ! %l0 is &argv[6] add %sp, STACK_BIAS+MINFRAME, %l1 ! %l1 is base of stack reg save /* * Copy arguments to the stack. %i1 is the offset from the seventh arg * in argv and the offset from the base of the stack save area. */ sub %i1, 8, %i1 1: ldx [%l0 + %i1], %l2 stx %l2, [%l1 + %i1] brnz,pt %i1, 1b sub %i1, 8, %i1 /* * Copy the register arguments. The argc <= 6 case will be jumping to * one of these labels. */ cp6arg: ldx [%i2 + 5*8], %o5 cp5arg: ldx [%i2 + 4*8], %o4 cp4arg: ldx [%i2 + 3*8], %o3 cp3arg: ldx [%i2 + 2*8], %o2 cp2arg: ldx [%i2 + 1*8], %o1 cp1arg: ldx [%i2 + 0*8], %o0 cp0arg: mov %g6, %l0 mov %i3, %g6 ! Restore PROC_REG for kernel call mov %g7, %l1 mov %i4, %g7 ! Restore THREAD_REG for kernel call jmpl %i0, %o7 ! Make call nop mov %l0, %g6 mov %l1, %g7 ret restore %g0, %o0, %o0 SET_SIZE(kaif_invoke) #endif