source: mainline/kernel/arch/amd64/src/asm_utils.S@ 8ccd2ea

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8ccd2ea was 296426ad, checked in by Jakub Jermar <jakub@…>, 18 years ago

Support for 6 syscalls arguments on amd64.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1#
2# Copyright (c) 2005 Ondrej Palkovsky
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8#
9# - Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# - Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14# - The name of the author may not be used to endorse or promote products
15# derived from this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28
29#define IREGISTER_SPACE 120
30
31#define IOFFSET_RAX 0x0
32#define IOFFSET_RBX 0x8
33#define IOFFSET_RCX 0x10
34#define IOFFSET_RDX 0x18
35#define IOFFSET_RSI 0x20
36#define IOFFSET_RDI 0x28
37#define IOFFSET_R8 0x30
38#define IOFFSET_R9 0x38
39#define IOFFSET_R10 0x40
40#define IOFFSET_R11 0x48
41#define IOFFSET_R12 0x50
42#define IOFFSET_R13 0x58
43#define IOFFSET_R14 0x60
44#define IOFFSET_R15 0x68
45#define IOFFSET_RBP 0x70
46
47# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error word
48# and 1 means interrupt with error word
49#define ERROR_WORD_INTERRUPT_LIST 0x00027D00
50
51#include <arch/pm.h>
52#include <arch/mm/page.h>
53
54.text
55.global interrupt_handlers
56.global syscall_entry
57.global panic_printf
58
59panic_printf:
60 movq $halt, (%rsp)
61 jmp printf
62
63.global cpuid
64.global has_cpuid
65.global get_cycle
66.global read_efer_flag
67.global set_efer_flag
68.global memcpy
69.global memcpy_from_uspace
70.global memcpy_to_uspace
71.global memcpy_from_uspace_failover_address
72.global memcpy_to_uspace_failover_address
73
74#define MEMCPY_DST %rdi
75#define MEMCPY_SRC %rsi
76#define MEMCPY_SIZE %rdx
77
78/**
79 * Copy memory from/to userspace.
80 *
81 * This is almost conventional memcpy().
82 * The difference is that there is a failover part
83 * to where control is returned from a page fault if
84 * the page fault occurs during copy_from_uspace()
85 * or copy_to_uspace().
86 *
87 * @param MEMCPY_DST Destination address.
88 * @param MEMCPY_SRC Source address.
89 * @param MEMCPY_SIZE Number of bytes to copy.
90 *
91 * @retrun MEMCPY_SRC on success, 0 on failure.
92 */
93memcpy:
94memcpy_from_uspace:
95memcpy_to_uspace:
96 movq MEMCPY_SRC, %rax
97
98 movq MEMCPY_SIZE, %rcx
99 shrq $3, %rcx /* size / 8 */
100
101 rep movsq /* copy as much as possible word by word */
102
103 movq MEMCPY_SIZE, %rcx
104 andq $7, %rcx /* size % 8 */
105 jz 0f
106
107 rep movsb /* copy the rest byte by byte */
108
1090:
110 ret /* return MEMCPY_SRC, success */
111
112memcpy_from_uspace_failover_address:
113memcpy_to_uspace_failover_address:
114 xorq %rax, %rax /* return 0, failure */
115 ret
116
117## Determine CPUID support
118#
119# Return 0 in EAX if CPUID is not support, 1 if supported.
120#
121has_cpuid:
122 pushfq # store flags
123 popq %rax # read flags
124 movq %rax,%rdx # copy flags
125 btcl $21,%edx # swap the ID bit
126 pushq %rdx
127 popfq # propagate the change into flags
128 pushfq
129 popq %rdx # read flags
130 andl $(1<<21),%eax # interested only in ID bit
131 andl $(1<<21),%edx
132 xorl %edx,%eax # 0 if not supported, 1 if supported
133 ret
134
135cpuid:
136 movq %rbx, %r10 # we have to preserve rbx across function calls
137
138 movl %edi,%eax # load the command into %eax
139
140 cpuid
141 movl %eax,0(%rsi)
142 movl %ebx,4(%rsi)
143 movl %ecx,8(%rsi)
144 movl %edx,12(%rsi)
145
146 movq %r10, %rbx
147 ret
148
149get_cycle:
150 xorq %rax,%rax
151 rdtsc
152 ret
153
154set_efer_flag:
155 movq $0xc0000080, %rcx
156 rdmsr
157 btsl %edi, %eax
158 wrmsr
159 ret
160
161read_efer_flag:
162 movq $0xc0000080, %rcx
163 rdmsr
164 ret
165
166# Push all general purpose registers on stack except %rbp, %rsp
167.macro save_all_gpr
168 movq %rax, IOFFSET_RAX(%rsp)
169 movq %rcx, IOFFSET_RCX(%rsp)
170 movq %rdx, IOFFSET_RDX(%rsp)
171 movq %rsi, IOFFSET_RSI(%rsp)
172 movq %rdi, IOFFSET_RDI(%rsp)
173 movq %r8, IOFFSET_R8(%rsp)
174 movq %r9, IOFFSET_R9(%rsp)
175 movq %r10, IOFFSET_R10(%rsp)
176 movq %r11, IOFFSET_R11(%rsp)
177#ifdef CONFIG_DEBUG_ALLREGS
178 movq %rbx, IOFFSET_RBX(%rsp)
179 movq %rbp, IOFFSET_RBP(%rsp)
180 movq %r12, IOFFSET_R12(%rsp)
181 movq %r13, IOFFSET_R13(%rsp)
182 movq %r14, IOFFSET_R14(%rsp)
183 movq %r15, IOFFSET_R15(%rsp)
184#endif
185.endm
186
187.macro restore_all_gpr
188 movq IOFFSET_RAX(%rsp), %rax
189 movq IOFFSET_RCX(%rsp), %rcx
190 movq IOFFSET_RDX(%rsp), %rdx
191 movq IOFFSET_RSI(%rsp), %rsi
192 movq IOFFSET_RDI(%rsp), %rdi
193 movq IOFFSET_R8(%rsp), %r8
194 movq IOFFSET_R9(%rsp), %r9
195 movq IOFFSET_R10(%rsp), %r10
196 movq IOFFSET_R11(%rsp), %r11
197#ifdef CONFIG_DEBUG_ALLREGS
198 movq IOFFSET_RBX(%rsp), %rbx
199 movq IOFFSET_RBP(%rsp), %rbp
200 movq IOFFSET_R12(%rsp), %r12
201 movq IOFFSET_R13(%rsp), %r13
202 movq IOFFSET_R14(%rsp), %r14
203 movq IOFFSET_R15(%rsp), %r15
204#endif
205.endm
206
207#ifdef CONFIG_DEBUG_ALLREGS
208# define INTERRUPT_ALIGN 256
209#else
210# define INTERRUPT_ALIGN 128
211#endif
212
213## Declare interrupt handlers
214#
215# Declare interrupt handlers for n interrupt
216# vectors starting at vector i.
217#
218# The handlers call exc_dispatch().
219#
220.macro handler i n
221
222 /*
223 * Choose between version with error code and version without error
224 * code. Both versions have to be of the same size. amd64 assembly is,
225 * however, a little bit tricky. For instance, subq $0x80, %rsp and
226 * subq $0x78, %rsp can result in two instructions with different
227 * op-code lengths.
228 * Therefore we align the interrupt handlers.
229 */
230
231 .iflt \i-32
232 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
233 /*
234 * Version with error word.
235 */
236 subq $IREGISTER_SPACE, %rsp
237 .else
238 /*
239 * Version without error word,
240 */
241 subq $(IREGISTER_SPACE+8), %rsp
242 .endif
243 .else
244 /*
245 * Version without error word,
246 */
247 subq $(IREGISTER_SPACE+8), %rsp
248 .endif
249
250 save_all_gpr
251
252 movq $(\i), %rdi # %rdi - first parameter
253 movq %rsp, %rsi # %rsi - pointer to istate
254 call exc_dispatch # exc_dispatch(i, istate)
255
256 restore_all_gpr
257 # $8 = Skip error word
258 addq $(IREGISTER_SPACE+8), %rsp
259 iretq
260
261 .align INTERRUPT_ALIGN
262 .if (\n-\i)-1
263 handler "(\i+1)",\n
264 .endif
265.endm
266
267.align INTERRUPT_ALIGN
268interrupt_handlers:
269h_start:
270 handler 0 IDT_ITEMS
271h_end:
272
273## Low-level syscall handler
274#
275# Registers on entry:
276#
277# @param rcx Userspace return address.
278# @param r11 Userspace RLFAGS.
279#
280# @param rax Syscall number.
281# @param rdi 1st syscall argument.
282# @param rsi 2nd syscall argument.
283# @param rdx 3rd syscall argument.
284# @param r10 4th syscall argument. Used instead of RCX because the
285# SYSCALL instruction clobbers it.
286# @param r8 5th syscall argument.
287# @param r9 6th syscall argument.
288#
289# @return Return value is in rax.
290#
291syscall_entry:
292 swapgs # Switch to hidden gs
293 #
294 # %gs:0 Scratch space for this thread's user RSP
295 # %gs:8 Address to be used as this thread's kernel RSP
296 #
297 movq %rsp, %gs:0 # Save this thread's user RSP
298 movq %gs:8, %rsp # Set this thread's kernel RSP
299 swapgs # Switch back to remain consistent
300 sti
301
302 pushq %rcx
303 pushq %r11
304
305 movq %r10, %rcx # Copy the 4th argument where it is expected
306 pushq %rax
307 call syscall_handler
308 addq $8, %rsp
309
310 popq %r11
311 popq %rcx
312
313 cli
314 swapgs
315 movq %gs:0, %rsp # Restore the user RSP
316 swapgs
317
318 sysretq
319
320.data
321.global interrupt_handler_size
322
323interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS
Note: See TracBrowser for help on using the repository browser.