summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb/intel/amd64/kmdb/kaif_invoke.s
blob: f4fef9fa940f1023e19d6a109e524fb1fcf94aeb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * 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 <sys/asm_linkage.h>

/*
 * Kernel function call invocation
 */

#if defined(__lint)
/*ARGSUSED*/
uintptr_t
kaif_invoke(uintptr_t funcva, uint_t argc, const uintptr_t argv[])
{
	return (0);
}
#else
	/*
	 * A jump table containing the addresses for register argument copy
	 * code.
	 */
copyargs:
	.quad	cp0arg
	.quad	cp1arg
	.quad	cp2arg
	.quad	cp3arg
	.quad	cp4arg
	.quad	cp5arg
	.quad	cp6arg

	/*
	 * This is going to be fun.  We were called with the function pointer
	 * in in %rsi, argc in %rdx, and a pointer to an array of uintptr_t's
	 * (the arguments to be passed) in %rcx.  In the worst case, we need
	 * to move the first six arguments from the array to %rdi, %rsi, %rdx,
	 * %rcx, %r8, and %r9.  The remaining arguments need to be copied from
	 * the array to 0(%rsp), 8(%rsp), and so on.  Then we can call the
	 * function.
	 */

	ENTRY_NP(kaif_invoke)

	pushq	%rbp
	movq	%rsp, %rbp
	pushq	%r12			/* our extra stack space */
	clrq	%r12

	movq	%rdi, %rax		/* function pointer */
	movq	%rdx, %rdi		/* argv */

	cmpq	$6, %rsi
	jle	stackdone

	/*
	 * More than six arguments.  Reserve space for the seventh and beyond on
	 * the stack, and copy them in.  To make the copy easier, we're going to
	 * pretend to reserve space on the stack for all of the arguments, thus
	 * allowing us to use the same scaling for the store as we do for the
	 * load.  When we're done copying the excess arguments, we'll move %rsp
	 * back, reclaiming the extra space we reserved.
	 */
	movq	%rsi, %r12
	subq	$6, %r12
	shlq	$3, %r12
	subq	%r12, %rsp
	subq	$0x30, %rsp		/* reserve 6 arg space for scaling */

1:	decq	%rsi
	movq	(%rdx, %rsi, 8), %r9
	movq	%r9, (%rsp, %rsi, 8)
	cmpq	$6, %rsi
	jg	1b

	addq	$0x30, %rsp		/* restore scaling arg space */

stackdone:
	/*
	 * Excess arguments have been copied and stripped from argc (or there
	 * weren't any to begin with).  Copy the first five to their ABI-
	 * designated registers.  We have to do this somewhat carefully, as
	 * argc (%rdx) and argv (%rsi) are in to-be-trampled registers.
	 */
	leaq	copyargs(%rip), %r9
	shlq	$3, %rsi
	addq	%rsi, %r9
	jmp	*(%r9)

cp6arg:	movq	0x28(%rdi), %r9
cp5arg:	movq	0x20(%rdi), %r8
cp4arg:	movq	0x18(%rdi), %rcx
cp3arg:	movq	0x10(%rdi), %rdx
cp2arg:	movq	0x08(%rdi), %rsi
cp1arg: movq	0x00(%rdi), %rdi
cp0arg:

	/* Arguments are copied.  Time to call the function */
	call	*%rax

	/*
	 * Deallocate the stack-based arguments, if any, and return to the
	 * caller.
	 */

	addq	%r12, %rsp
	popq	%r12
	leave
	ret

	SET_SIZE(kaif_invoke)

#endif