2
# Copyright (c) 2005 Ondrej Palkovsky
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions
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.
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.
29
#define IREGISTER_SPACE 72
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
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
46
#include <arch/mm/page.h>
49
.global interrupt_handlers
60
.global read_efer_flag
65
.global memcpy_from_uspace
66
.global memcpy_to_uspace
67
.global memcpy_from_uspace_failover_address
68
.global memcpy_to_uspace_failover_address
70
# Wrapper for generic memsetb
74
# Wrapper for generic memsetw
78
#define MEMCPY_DST %rdi
79
#define MEMCPY_SRC %rsi
80
#define MEMCPY_SIZE %rdx
83
* Copy memory from/to userspace.
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().
91
* @param MEMCPY_DST Destination address.
92
* @param MEMCPY_SRC Source address.
93
* @param MEMCPY_SIZE Number of bytes to copy.
95
* @retrun MEMCPY_DST on success, 0 on failure.
100
movq MEMCPY_DST, %rax
102
movq MEMCPY_SIZE, %rcx
103
shrq $3, %rcx /* size / 8 */
105
rep movsq /* copy as much as possible word by word */
107
movq MEMCPY_SIZE, %rcx
108
andq $7, %rcx /* size % 8 */
111
rep movsb /* copy the rest byte by byte */
114
ret /* return MEMCPY_SRC, success */
116
memcpy_from_uspace_failover_address:
117
memcpy_to_uspace_failover_address:
118
xorq %rax, %rax /* return 0, failure */
121
## Determine CPUID support
123
# Return 0 in EAX if CPUID is not support, 1 if supported.
127
popq %rax # read flags
128
movq %rax,%rdx # copy flags
129
btcl $21,%edx # swap the ID bit
131
popfq # propagate the change into flags
133
popq %rdx # read flags
134
andl $(1<<21),%eax # interested only in ID bit
136
xorl %edx,%eax # 0 if not supported, 1 if supported
140
movq %rbx, %r10 # we have to preserve rbx across function calls
142
movl %edi,%eax # load the command into %eax
159
movq $0xc0000080, %rcx
166
movq $0xc0000080, %rcx
170
# Push all volatile general purpose registers on stack
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)
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
195
#define INTERRUPT_ALIGN 128
197
## Declare interrupt handlers
199
# Declare interrupt handlers for n interrupt
200
# vectors starting at vector i.
202
# The handlers call exc_dispatch().
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
212
* Therefore we align the interrupt handlers.
216
.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
218
* Version with error word.
220
subq $IREGISTER_SPACE, %rsp
223
* Version without error word,
225
subq $(IREGISTER_SPACE+8), %rsp
229
* Version without error word,
231
subq $(IREGISTER_SPACE+8), %rsp
237
movq $(\i), %rdi # %rdi - first parameter
238
movq %rsp, %rsi # %rsi - pointer to istate
239
call exc_dispatch # exc_dispatch(i, istate)
242
# $8 = Skip error word
243
addq $(IREGISTER_SPACE+8), %rsp
246
.align INTERRUPT_ALIGN
252
.align INTERRUPT_ALIGN
258
## Low-level syscall handler
260
# Registers on entry:
262
# @param rcx Userspace return address.
263
# @param r11 Userspace RLFAGS.
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.
274
# @return Return value is in rax.
277
swapgs # Switch to hidden gs
279
# %gs:0 Scratch space for this thread's user RSP
280
# %gs:8 Address to be used as this thread's kernel RSP
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
290
movq %r10, %rcx # Copy the 4th argument where it is expected
300
movq %gs:0, %rsp # Restore the user RSP
306
.global interrupt_handler_size
308
interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS