source: mainline/kernel/arch/amd64/src/asm_utils.S@ 74bcf5e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 74bcf5e was 1f7cb3a, checked in by Jakub Jermar <jakub@…>, 16 years ago

Get rid of CONFIG_DEBUG_ALLREGS.

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