source: mainline/kernel/arch/amd64/src/asm_utils.S@ 86018c1

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

Add amd64 specific support for kernel stack traces.

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