source: mainline/kernel/arch/amd64/src/asm_utils.S@ 75c9852

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 75c9852 was 64bbf13, checked in by Martin Decky <martin@…>, 15 years ago

switch to C-style comments

  • 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 80
30
31#define IOFFSET_RAX 0x00
32#define IOFFSET_RCX 0x08
33#define IOFFSET_RDX 0x10
34#define IOFFSET_RSI 0x18
35#define IOFFSET_RDI 0x20
36#define IOFFSET_R8 0x28
37#define IOFFSET_R9 0x30
38#define IOFFSET_R10 0x38
39#define IOFFSET_R11 0x40
40#define IOFFSET_RBP 0x48
41
42/**
43 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
44 * has no error word and 1 means interrupt with error word
45 *
46 */
47#define ERROR_WORD_INTERRUPT_LIST 0x00027D00
48
49#include <arch/pm.h>
50#include <arch/mm/page.h>
51
52.text
53.global interrupt_handlers
54.global syscall_entry
55.global cpuid
56.global has_cpuid
57.global read_efer_flag
58.global set_efer_flag
59.global memsetb
60.global memsetw
61.global memcpy
62.global memcpy_from_uspace
63.global memcpy_to_uspace
64.global memcpy_from_uspace_failover_address
65.global memcpy_to_uspace_failover_address
66
67/* Wrapper for generic memsetb */
68memsetb:
69 jmp _memsetb
70
71/* Wrapper for generic memsetw */
72memsetw:
73 jmp _memsetw
74
75#define MEMCPY_DST %rdi
76#define MEMCPY_SRC %rsi
77#define MEMCPY_SIZE %rdx
78
79/**
80 * Copy memory from/to userspace.
81 *
82 * This is almost conventional memcpy().
83 * The difference is that there is a failover part
84 * to where control is returned from a page fault if
85 * the page fault occurs during copy_from_uspace()
86 * or copy_to_uspace().
87 *
88 * @param MEMCPY_DST Destination address.
89 * @param MEMCPY_SRC Source address.
90 * @param MEMCPY_SIZE Number of bytes to copy.
91 *
92 * @retrun MEMCPY_DST on success, 0 on failure.
93 *
94 */
95memcpy:
96memcpy_from_uspace:
97memcpy_to_uspace:
98 movq MEMCPY_DST, %rax
99
100 movq MEMCPY_SIZE, %rcx
101 shrq $3, %rcx /* size / 8 */
102
103 rep movsq /* copy as much as possible word by word */
104
105 movq MEMCPY_SIZE, %rcx
106 andq $7, %rcx /* size % 8 */
107 jz 0f
108
109 rep movsb /* copy the rest byte by byte */
110
111 0:
112 ret /* return MEMCPY_SRC, success */
113
114memcpy_from_uspace_failover_address:
115memcpy_to_uspace_failover_address:
116 xorq %rax, %rax /* return 0, failure */
117 ret
118
119/** Determine CPUID support
120*
121* @return 0 in EAX if CPUID is not support, 1 if supported.
122*
123*/
124has_cpuid:
125 /* Load RFLAGS */
126 pushfq
127 popq %rax
128 movq %rax, %rdx
129
130 /* Flip the ID bit */
131 btcl $21, %edx
132
133 /* Store RFLAGS */
134 pushq %rdx
135 popfq
136 pushfq
137
138 /* Get the ID bit again */
139 popq %rdx
140 andl $(1 << 21), %eax
141 andl $(1 << 21), %edx
142
143 /* 0 if not supported, 1 if supported */
144 xorl %edx, %eax
145 ret
146
147cpuid:
148 /* Preserve %rbx across function calls */
149 movq %rbx, %r10
150
151 /* Load the command into %eax */
152 movl %edi, %eax
153
154 cpuid
155 movl %eax, 0(%rsi)
156 movl %ebx, 4(%rsi)
157 movl %ecx, 8(%rsi)
158 movl %edx, 12(%rsi)
159
160 movq %r10, %rbx
161 ret
162
163set_efer_flag:
164 movq $0xc0000080, %rcx
165 rdmsr
166 btsl %edi, %eax
167 wrmsr
168 ret
169
170read_efer_flag:
171 movq $0xc0000080, %rcx
172 rdmsr
173 ret
174
175/** Push all volatile general purpose registers on stack
176 *
177 */
178.macro save_all_gpr
179 movq %rax, IOFFSET_RAX(%rsp)
180 movq %rcx, IOFFSET_RCX(%rsp)
181 movq %rdx, IOFFSET_RDX(%rsp)
182 movq %rsi, IOFFSET_RSI(%rsp)
183 movq %rdi, IOFFSET_RDI(%rsp)
184 movq %r8, IOFFSET_R8(%rsp)
185 movq %r9, IOFFSET_R9(%rsp)
186 movq %r10, IOFFSET_R10(%rsp)
187 movq %r11, IOFFSET_R11(%rsp)
188 movq %rbp, IOFFSET_RBP(%rsp)
189.endm
190
191.macro restore_all_gpr
192 movq IOFFSET_RAX(%rsp), %rax
193 movq IOFFSET_RCX(%rsp), %rcx
194 movq IOFFSET_RDX(%rsp), %rdx
195 movq IOFFSET_RSI(%rsp), %rsi
196 movq IOFFSET_RDI(%rsp), %rdi
197 movq IOFFSET_R8(%rsp), %r8
198 movq IOFFSET_R9(%rsp), %r9
199 movq IOFFSET_R10(%rsp), %r10
200 movq IOFFSET_R11(%rsp), %r11
201 movq IOFFSET_RBP(%rsp), %rbp
202.endm
203
204#define INTERRUPT_ALIGN 128
205
206/** Declare interrupt handlers
207 *
208 * Declare interrupt handlers for n interrupt
209 * vectors starting at vector i.
210 *
211 * The handlers call exc_dispatch().
212 *
213 */
214.macro handler i n
215
216 /*
217 * Choose between version with error code and version without error
218 * code. Both versions have to be of the same size. amd64 assembly is,
219 * however, a little bit tricky. For instance, subq $0x80, %rsp and
220 * subq $0x78, %rsp can result in two instructions with different
221 * op-code lengths.
222 * Therefore we align the interrupt handlers.
223 */
224
225 .iflt \i-32
226 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
227 /*
228 * Version with error word.
229 */
230 subq $IREGISTER_SPACE, %rsp
231 .else
232 /*
233 * Version without error word,
234 */
235 subq $(IREGISTER_SPACE + 8), %rsp
236 .endif
237 .else
238 /*
239 * Version without error word,
240 */
241 subq $(IREGISTER_SPACE + 8), %rsp
242 .endif
243
244 save_all_gpr
245 cld
246
247 /*
248 * Stop stack traces here if we came from userspace.
249 */
250 movq %cs, %rax
251 xorq %rdx, %rdx
252 cmpq %rax, IREGISTER_SPACE+16(%rsp)
253 cmovneq %rdx, %rbp
254
255 movq $(\i), %rdi /* %rdi - first argument */
256 movq %rsp, %rsi /* %rsi - pointer to istate */
257
258 /* Call exc_dispatch(i, istate) */
259 call exc_dispatch
260
261 restore_all_gpr
262
263 /* $8 = Skip error word */
264 addq $(IREGISTER_SPACE + 8), %rsp
265 iretq
266
267 .align INTERRUPT_ALIGN
268 .if (\n - \i) - 1
269 handler "(\i + 1)", \n
270 .endif
271.endm
272
273.align INTERRUPT_ALIGN
274interrupt_handlers:
275 h_start:
276 handler 0 IDT_ITEMS
277 h_end:
278
279/** Low-level syscall handler
280 *
281 * Registers on entry:
282 *
283 * @param %rcx Userspace return address.
284 * @param %r11 Userspace RLFAGS.
285 *
286 * @param %rax Syscall number.
287 * @param %rdi 1st syscall argument.
288 * @param %rsi 2nd syscall argument.
289 * @param %rdx 3rd syscall argument.
290 * @param %r10 4th syscall argument. Used instead of RCX because
291 * the SYSCALL instruction clobbers it.
292 * @param %r8 5th syscall argument.
293 * @param %r9 6th syscall argument.
294 *
295 * @return Return value is in %rax.
296 *
297 */
298syscall_entry:
299 /* Switch to hidden %gs */
300 swapgs
301
302 /*
303 * %gs:0 Scratch space for this thread's user RSP
304 * %gs:8 Address to be used as this thread's kernel RSP
305 */
306
307 movq %rsp, %gs:0 /* save this thread's user RSP */
308 movq %gs:8, %rsp /* set this thread's kernel RSP */
309
310 /* Switch back to remain consistent */
311 swapgs
312 sti
313
314 pushq %rcx
315 pushq %r11
316 pushq %rbp
317
318 xorq %rbp, %rbp /* stop the stack traces here */
319
320 /* Copy the 4th argument where it is expected */
321 movq %r10, %rcx
322 pushq %rax
323
324 call syscall_handler
325
326 addq $8, %rsp
327
328 popq %rbp
329 popq %r11
330 popq %rcx
331
332 cli
333 swapgs
334
335 /* Restore the user RSP */
336 movq %gs:0, %rsp
337 swapgs
338
339 sysretq
340
341.data
342.global interrupt_handler_size
343
344interrupt_handler_size: .quad (h_end - h_start) / IDT_ITEMS
Note: See TracBrowser for help on using the repository browser.