1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29#include <sys/asm_linkage.h> 30 31/* 32 * Kernel function call invocation 33 */ 34 35#if defined(__lint) 36/*ARGSUSED*/ 37uintptr_t 38kaif_invoke(uintptr_t funcva, uint_t argc, const uintptr_t argv[]) 39{ 40 return (0); 41} 42#else 43 /* 44 * A jump table containing the addresses for register argument copy 45 * code. 46 */ 47copyargs: 48 .quad cp0arg 49 .quad cp1arg 50 .quad cp2arg 51 .quad cp3arg 52 .quad cp4arg 53 .quad cp5arg 54 .quad cp6arg 55 56 /* 57 * This is going to be fun. We were called with the function pointer 58 * in in %rsi, argc in %rdx, and a pointer to an array of uintptr_t's 59 * (the arguments to be passed) in %rcx. In the worst case, we need 60 * to move the first six arguments from the array to %rdi, %rsi, %rdx, 61 * %rcx, %r8, and %r9. The remaining arguments need to be copied from 62 * the array to 0(%rsp), 8(%rsp), and so on. Then we can call the 63 * function. 64 */ 65 66 ENTRY_NP(kaif_invoke) 67 68 pushq %rbp 69 movq %rsp, %rbp 70 pushq %r12 /* our extra stack space */ 71 clrq %r12 72 73 movq %rdi, %rax /* function pointer */ 74 movq %rdx, %rdi /* argv */ 75 76 cmpq $6, %rsi 77 jle stackdone 78 79 /* 80 * More than six arguments. Reserve space for the seventh and beyond on 81 * the stack, and copy them in. To make the copy easier, we're going to 82 * pretend to reserve space on the stack for all of the arguments, thus 83 * allowing us to use the same scaling for the store as we do for the 84 * load. When we're done copying the excess arguments, we'll move %rsp 85 * back, reclaiming the extra space we reserved. 86 */ 87 movq %rsi, %r12 88 subq $6, %r12 89 shlq $3, %r12 90 subq %r12, %rsp 91 subq $0x30, %rsp /* reserve 6 arg space for scaling */ 92 931: decq %rsi 94 movq (%rdx, %rsi, 8), %r9 95 movq %r9, (%rsp, %rsi, 8) 96 cmpq $6, %rsi 97 jg 1b 98 99 addq $0x30, %rsp /* restore scaling arg space */ 100 101stackdone: 102 /* 103 * Excess arguments have been copied and stripped from argc (or there 104 * weren't any to begin with). Copy the first five to their ABI- 105 * designated registers. We have to do this somewhat carefully, as 106 * argc (%rdx) and argv (%rsi) are in to-be-trampled registers. 107 */ 108 leaq copyargs(%rip), %r9 109 shlq $3, %rsi 110 addq %rsi, %r9 111 jmp *(%r9) 112 113cp6arg: movq 0x28(%rdi), %r9 114cp5arg: movq 0x20(%rdi), %r8 115cp4arg: movq 0x18(%rdi), %rcx 116cp3arg: movq 0x10(%rdi), %rdx 117cp2arg: movq 0x08(%rdi), %rsi 118cp1arg: movq 0x00(%rdi), %rdi 119cp0arg: 120 121 /* Arguments are copied. Time to call the function */ 122 call *%rax 123 124 /* 125 * Deallocate the stack-based arguments, if any, and return to the 126 * caller. 127 */ 128 129 addq %r12, %rsp 130 popq %r12 131 leave 132 ret 133 134 SET_SIZE(kaif_invoke) 135 136#endif 137