source: mainline/kernel/arch/amd64/src/asm_utils.S@ 62baed17

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 62baed17 was a043e39, checked in by Jakub Jermar <jakub@…>, 15 years ago

Switch amd64 to use the unified panic architecture.

  • Property mode set to 100644
File size: 7.3 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 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#define IOFFSET_RBP 0x48
41
42# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error word
43# and 1 means interrupt with error word
44#define ERROR_WORD_INTERRUPT_LIST 0x00027D00
45
46#include <arch/pm.h>
47#include <arch/mm/page.h>
48
49.text
50.global interrupt_handlers
51.global syscall_entry
52
53.global cpuid
54.global has_cpuid
55.global read_efer_flag
56.global set_efer_flag
57.global memsetb
58.global memsetw
59.global memcpy
60.global memcpy_from_uspace
61.global memcpy_to_uspace
62.global memcpy_from_uspace_failover_address
63.global memcpy_to_uspace_failover_address
64
65# Wrapper for generic memsetb
66memsetb:
67 jmp _memsetb
68
69# Wrapper for generic memsetw
70memsetw:
71 jmp _memsetw
72
73#define MEMCPY_DST %rdi
74#define MEMCPY_SRC %rsi
75#define MEMCPY_SIZE %rdx
76
77/**
78 * Copy memory from/to userspace.
79 *
80 * This is almost conventional memcpy().
81 * The difference is that there is a failover part
82 * to where control is returned from a page fault if
83 * the page fault occurs during copy_from_uspace()
84 * or copy_to_uspace().
85 *
86 * @param MEMCPY_DST Destination address.
87 * @param MEMCPY_SRC Source address.
88 * @param MEMCPY_SIZE Number of bytes to copy.
89 *
90 * @retrun MEMCPY_DST on success, 0 on failure.
91 */
92memcpy:
93memcpy_from_uspace:
94memcpy_to_uspace:
95 movq MEMCPY_DST, %rax
96
97 movq MEMCPY_SIZE, %rcx
98 shrq $3, %rcx /* size / 8 */
99
100 rep movsq /* copy as much as possible word by word */
101
102 movq MEMCPY_SIZE, %rcx
103 andq $7, %rcx /* size % 8 */
104 jz 0f
105
106 rep movsb /* copy the rest byte by byte */
107
1080:
109 ret /* return MEMCPY_SRC, success */
110
111memcpy_from_uspace_failover_address:
112memcpy_to_uspace_failover_address:
113 xorq %rax, %rax /* return 0, failure */
114 ret
115
116## Determine CPUID support
117#
118# Return 0 in EAX if CPUID is not support, 1 if supported.
119#
120has_cpuid:
121 pushfq # store flags
122 popq %rax # read flags
123 movq %rax,%rdx # copy flags
124 btcl $21,%edx # swap the ID bit
125 pushq %rdx
126 popfq # propagate the change into flags
127 pushfq
128 popq %rdx # read flags
129 andl $(1<<21),%eax # interested only in ID bit
130 andl $(1<<21),%edx
131 xorl %edx,%eax # 0 if not supported, 1 if supported
132 ret
133
134cpuid:
135 movq %rbx, %r10 # we have to preserve rbx across function calls
136
137 movl %edi,%eax # load the command into %eax
138
139 cpuid
140 movl %eax,0(%rsi)
141 movl %ebx,4(%rsi)
142 movl %ecx,8(%rsi)
143 movl %edx,12(%rsi)
144
145 movq %r10, %rbx
146 ret
147
148set_efer_flag:
149 movq $0xc0000080, %rcx
150 rdmsr
151 btsl %edi, %eax
152 wrmsr
153 ret
154
155read_efer_flag:
156 movq $0xc0000080, %rcx
157 rdmsr
158 ret
159
160# Push all volatile general purpose registers on stack
161.macro save_all_gpr
162 movq %rax, IOFFSET_RAX(%rsp)
163 movq %rcx, IOFFSET_RCX(%rsp)
164 movq %rdx, IOFFSET_RDX(%rsp)
165 movq %rsi, IOFFSET_RSI(%rsp)
166 movq %rdi, IOFFSET_RDI(%rsp)
167 movq %r8, IOFFSET_R8(%rsp)
168 movq %r9, IOFFSET_R9(%rsp)
169 movq %r10, IOFFSET_R10(%rsp)
170 movq %r11, IOFFSET_R11(%rsp)
171 movq %rbp, IOFFSET_RBP(%rsp)
172.endm
173
174.macro restore_all_gpr
175 movq IOFFSET_RAX(%rsp), %rax
176 movq IOFFSET_RCX(%rsp), %rcx
177 movq IOFFSET_RDX(%rsp), %rdx
178 movq IOFFSET_RSI(%rsp), %rsi
179 movq IOFFSET_RDI(%rsp), %rdi
180 movq IOFFSET_R8(%rsp), %r8
181 movq IOFFSET_R9(%rsp), %r9
182 movq IOFFSET_R10(%rsp), %r10
183 movq IOFFSET_R11(%rsp), %r11
184 movq IOFFSET_RBP(%rsp), %rbp
185.endm
186
187#define INTERRUPT_ALIGN 128
188
189## Declare interrupt handlers
190#
191# Declare interrupt handlers for n interrupt
192# vectors starting at vector i.
193#
194# The handlers call exc_dispatch().
195#
196.macro handler i n
197
198 /*
199 * Choose between version with error code and version without error
200 * code. Both versions have to be of the same size. amd64 assembly is,
201 * however, a little bit tricky. For instance, subq $0x80, %rsp and
202 * subq $0x78, %rsp can result in two instructions with different
203 * op-code lengths.
204 * Therefore we align the interrupt handlers.
205 */
206
207 .iflt \i-32
208 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
209 /*
210 * Version with error word.
211 */
212 subq $IREGISTER_SPACE, %rsp
213 .else
214 /*
215 * Version without error word,
216 */
217 subq $(IREGISTER_SPACE+8), %rsp
218 .endif
219 .else
220 /*
221 * Version without error word,
222 */
223 subq $(IREGISTER_SPACE+8), %rsp
224 .endif
225
226 save_all_gpr
227 cld
228
229 #
230 # Stop stack traces here if we came from userspace.
231 #
232 movq %cs, %rax
233 xorq %rdx, %rdx
234 cmpq %rax, IREGISTER_SPACE+16(%rsp)
235 cmovneq %rdx, %rbp
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 pushq %rbp
290
291 xorq %rbp, %rbp # stop the stack traces here
292
293 movq %r10, %rcx # Copy the 4th argument where it is expected
294 pushq %rax
295 call syscall_handler
296 addq $8, %rsp
297
298 popq %rbp
299 popq %r11
300 popq %rcx
301
302 cli
303 swapgs
304 movq %gs:0, %rsp # Restore the user RSP
305 swapgs
306
307 sysretq
308
309.data
310.global interrupt_handler_size
311
312interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS
Note: See TracBrowser for help on using the repository browser.