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#include <sys/asm_linkage.h> 28 29/* 30 * Kernel function call invocation 31 */ 32 33#if defined(__lint) 34/*ARGSUSED*/ 35uintptr_t 36kaif_invoke(uintptr_t funcva, uint_t argc, const uintptr_t argv[]) 37{ 38 return (0); 39} 40#else 41 /* 42 * A jump table containing the addresses for register argument copy 43 * code. 44 */ 45copyargs: 46 .quad cp0arg 47 .quad cp1arg 48 .quad cp2arg 49 .quad cp3arg 50 .quad cp4arg 51 .quad cp5arg 52 .quad cp6arg 53 54 /* 55 * This is going to be fun. We were called with the function pointer 56 * in in %rsi, argc in %rdx, and a pointer to an array of uintptr_t's 57 * (the arguments to be passed) in %rcx. In the worst case, we need 58 * to move the first six arguments from the array to %rdi, %rsi, %rdx, 59 * %rcx, %r8, and %r9. The remaining arguments need to be copied from 60 * the array to 0(%rsp), 8(%rsp), and so on. Then we can call the 61 * function. 62 */ 63 64 ENTRY_NP(kaif_invoke) 65 66 pushq %rbp 67 movq %rsp, %rbp 68 pushq %r12 /* our extra stack space */ 69 clrq %r12 70 71 movq %rdi, %rax /* function pointer */ 72 movq %rdx, %rdi /* argv */ 73 74 cmpq $6, %rsi 75 jle stackdone 76 77 /* 78 * More than six arguments. Reserve space for the seventh and beyond on 79 * the stack, and copy them in. To make the copy easier, we're going to 80 * pretend to reserve space on the stack for all of the arguments, thus 81 * allowing us to use the same scaling for the store as we do for the 82 * load. When we're done copying the excess arguments, we'll move %rsp 83 * back, reclaiming the extra space we reserved. 84 */ 85 movq %rsi, %r12 86 subq $6, %r12 87 shlq $3, %r12 88 subq %r12, %rsp 89 subq $0x30, %rsp /* reserve 6 arg space for scaling */ 90 911: decq %rsi 92 movq (%rdx, %rsi, 8), %r9 93 movq %r9, (%rsp, %rsi, 8) 94 cmpq $6, %rsi 95 jg 1b 96 97 addq $0x30, %rsp /* restore scaling arg space */ 98 99stackdone: 100 /* 101 * Excess arguments have been copied and stripped from argc (or there 102 * weren't any to begin with). Copy the first five to their ABI- 103 * designated registers. We have to do this somewhat carefully, as 104 * argc (%rdx) and argv (%rsi) are in to-be-trampled registers. 105 */ 106 leaq copyargs(%rip), %r9 107 shlq $3, %rsi 108 addq %rsi, %r9 109 jmp *(%r9) 110 111cp6arg: movq 0x28(%rdi), %r9 112cp5arg: movq 0x20(%rdi), %r8 113cp4arg: movq 0x18(%rdi), %rcx 114cp3arg: movq 0x10(%rdi), %rdx 115cp2arg: movq 0x08(%rdi), %rsi 116cp1arg: movq 0x00(%rdi), %rdi 117cp0arg: 118 119 /* Arguments are copied. Time to call the function */ 120 call *%rax 121 122 /* 123 * Deallocate the stack-based arguments, if any, and return to the 124 * caller. 125 */ 126 127 addq %r12, %rsp 128 popq %r12 129 leave 130 ret 131 132 SET_SIZE(kaif_invoke) 133 134#endif 135