1/*
2 * Copyright (c) 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include <i386/asm.h>
30#include <i386/asm64.h>
31
32#include <assym.s>
33
34/*
35 * Copy "count" bytes from "src" to %rsp, using
36 * "tmpindex" for a scratch counter and %rax
37 */
38#define COPY_STACK(src, count, tmpindex) \
39	mov	$0, tmpindex	/* initial scratch counter */ ; \
401: \
41	mov	0(src,tmpindex,1), %rax	 /* copy one 64-bit word from source... */ ; \
42	mov	%rax, 0(%rsp,tmpindex,1) /* ... to stack */ ; \
43	add	$8, tmpindex		 /* increment counter */ ; \
44	cmp	count, tmpindex		 /* exit it stack has been copied */ ; \
45	jne 1b
46
47/*
48	void
49	pal_efi_call_in_64bit_mode_asm(uint64_t func,
50	                           struct pal_efi_registers *efi_reg,
51	                           void *stack_contents,
52	                           size_t stack_contents_size)
53
54	* Switch from compatibility mode to long mode, and
55	* then execute the function pointer with the specified
56	* register and stack contents (based at %rsp). Afterwards,
57	* collect the return value, restore the original state,
58	* and return.
59*/
60ENTRY(_pal_efi_call_in_64bit_mode_asm)
61	FRAME
62
63	/* save non-volatile registers */
64	push	%rbx
65	push	%r12
66	push	%r13
67	push	%r14
68	push	%r15
69
70	/* save parameters that we will need later */
71	push	%rsi
72	push	%rcx
73
74	sub	$8, %rsp	/* align to 16-byte boundary */
75				/* efi_reg in %rsi */
76				/* stack_contents into %rdx */
77				/* s_c_s into %rcx */
78	sub	%rcx, %rsp	/* make room for stack contents */
79
80	COPY_STACK(%rdx, %rcx, %r8)
81
82	/* load efi_reg into real registers */
83	mov	0(%rsi),  %rcx
84	mov	8(%rsi),  %rdx
85	mov	16(%rsi), %r8
86	mov	24(%rsi), %r9
87	mov	32(%rsi), %rax
88
89					/* func pointer in %rdi */
90	call	*%rdi			/* call EFI runtime */
91
92	mov	-48(%rbp), %rsi		/* load efi_reg into %esi */
93	mov	%rax, 32(%rsi)		/* save RAX back */
94
95	mov	-56(%rbp), %rcx	/* load s_c_s into %rcx */
96	add	%rcx, %rsp	/* discard stack contents */
97	add	$8, %rsp	/* restore stack pointer */
98
99	pop	%rcx
100	pop	%rsi
101	pop	%r15
102	pop	%r14
103	pop	%r13
104	pop	%r12
105	pop	%rbx
106
107	EMARF
108	ret
109
110/*
111	void
112	pal_efi_call_in_32bit_mode_asm(uint32_t func,
113	                           struct pal_efi_registers *efi_reg,
114	                           void *stack_contents,
115	                           size_t stack_contents_size)
116
117*/
118ENTRY(_pal_efi_call_in_32bit_mode_asm)
119	FRAME
120
121	/* save non-volatile registers */
122	push	%rbx
123	push	%r12
124	push	%r13
125	push	%r14
126	push	%r15
127
128	/* save parameters that we will need later */
129	push	%rsi
130	push	%rcx
131
132	push	%rbp	/* save %rbp and align to 16-byte boundary */
133				/* efi_reg in %rsi */
134				/* stack_contents into %rdx */
135				/* s_c_s into %rcx */
136	sub	%rcx, %rsp	/* make room for stack contents */
137
138	COPY_STACK(%rdx, %rcx, %r8)
139
140	/*
141	 * Here in long-mode, with high kernel addresses,
142	 * but with the kernel double-mapped in the bottom 4GB.
143	 * We now switch to compat mode and call into EFI.
144	 */
145	ENTER_COMPAT_MODE()
146
147	call	*%edi			/* call EFI runtime */
148
149	ENTER_64BIT_MODE()
150
151	mov	-48(%rbp), %rsi		/* load efi_reg into %esi */
152	mov	%rax, 32(%rsi)		/* save RAX back */
153
154	mov	-56(%rbp), %rcx	/* load s_c_s into %rcx */
155	add	%rcx, %rsp	/* discard stack contents */
156	pop	%rbp		/* restore full 64-bit frame pointer */
157				/* which the 32-bit EFI will have truncated */
158				/* our full %rsp will be restored by EMARF */
159	pop	%rcx
160	pop	%rsi
161	pop	%r15
162	pop	%r14
163	pop	%r13
164	pop	%r12
165	pop	%rbx
166
167	EMARF
168	ret
169
170
171
172/*
173 * void _pal_rtc_nanotime_store(
174 *		uint64_t        tsc,		// %rdi
175 *		uint64_t        nsec,		// %rsi
176 *		uint32_t        scale,		// %rdx
177 *		uint32_t        shift,		// %rcx
178 *		rtc_nanotime_t  *dst);		// %r8
179 */
180ENTRY(_pal_rtc_nanotime_store)
181	movl	RNT_GENERATION(%r8),%eax	/* get current generation */
182	movl	$0,RNT_GENERATION(%r8)		/* flag data as being updated */
183	movq	%rdi,RNT_TSC_BASE(%r8)
184	movq	%rsi,RNT_NS_BASE(%r8)
185	movl	%edx,RNT_SCALE(%r8)
186	movl	%ecx,RNT_SHIFT(%r8)
187
188	incl	%eax				/* next generation */
189	jnz	1f
190	incl	%eax				/* skip 0, which is a flag */
1911:	movl	%eax,RNT_GENERATION(%r8)	/* update generation */
192
193	ret
194
195