Subversion Repositories HelenOS

Rev

Rev 3403 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
224 palkovsky 1
#
2071 jermar 2
# Copyright (c) 2005 Ondrej Palkovsky
224 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
 
4343 svoboda 29
#define IREGISTER_SPACE	72 
224 palkovsky 30
 
4343 svoboda 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
1021 jermar 40
 
224 palkovsky 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>
808 palkovsky 46
#include <arch/mm/page.h>
224 palkovsky 47
 
48
.text
49
.global interrupt_handlers
803 palkovsky 50
.global syscall_entry
224 palkovsky 51
.global panic_printf
52
 
53
panic_printf:
54
	movq $halt, (%rsp)
55
	jmp printf
56
 
252 palkovsky 57
.global cpuid
242 palkovsky 58
.global has_cpuid
2018 decky 59
.global get_cycle
251 palkovsky 60
.global read_efer_flag
61
.global set_efer_flag
3107 svoboda 62
.global memsetb
63
.global memsetw
1288 jermar 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
 
3107 svoboda 70
# Wrapper for generic memsetb
71
memsetb:
72
	jmp _memsetb
73
 
74
# Wrapper for generic memsetw
75
memsetw:
76
	jmp _memsetw
77
 
1288 jermar 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
 *
3403 svoboda 95
 * @retrun MEMCPY_DST on success, 0 on failure.
1288 jermar 96
 */
97
memcpy:
98
memcpy_from_uspace:
99
memcpy_to_uspace:
3403 svoboda 100
	movq MEMCPY_DST, %rax
1288 jermar 101
 
102
	movq MEMCPY_SIZE, %rcx
103
	shrq $3, %rcx			/* size / 8 */
251 palkovsky 104
 
1288 jermar 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
 
113
0:
114
	ret				/* return MEMCPY_SRC, success */
115
 
116
memcpy_from_uspace_failover_address:
117
memcpy_to_uspace_failover_address:
118
	xorq %rax, %rax			/* return 0, failure */
119
	ret
120
 
242 palkovsky 121
## Determine CPUID support
122
#
123
# Return 0 in EAX if CPUID is not support, 1 if supported.
124
#
125
has_cpuid:
126
	pushfq			# store flags
127
	popq %rax		# read flags
348 jermar 128
	movq %rax,%rdx		# copy flags
129
	btcl $21,%edx		# swap the ID bit
130
	pushq %rdx
242 palkovsky 131
	popfq			# propagate the change into flags
132
	pushfq
348 jermar 133
	popq %rdx		# read flags	
242 palkovsky 134
	andl $(1<<21),%eax	# interested only in ID bit
348 jermar 135
	andl $(1<<21),%edx
136
	xorl %edx,%eax		# 0 if not supported, 1 if supported
242 palkovsky 137
	ret
138
 
251 palkovsky 139
cpuid:
140
	movq %rbx, %r10  # we have to preserve rbx across function calls
242 palkovsky 141
 
251 palkovsky 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
 
2018 decky 153
get_cycle:
242 palkovsky 154
	xorq %rax,%rax
155
	rdtsc
156
	ret
251 palkovsky 157
 
158
set_efer_flag:
159
	movq $0xc0000080, %rcx
160
	rdmsr
161
	btsl %edi, %eax
162
	wrmsr
163
	ret
242 palkovsky 164
 
251 palkovsky 165
read_efer_flag:	
166
	movq $0xc0000080, %rcx
167
	rdmsr
168
	ret 		
242 palkovsky 169
 
4343 svoboda 170
# Push all volatile general purpose registers on stack
799 palkovsky 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)
224 palkovsky 181
.endm
182
 
799 palkovsky 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
224 palkovsky 193
.endm
1021 jermar 194
 
4343 svoboda 195
#define INTERRUPT_ALIGN 128
1094 palkovsky 196
 
224 palkovsky 197
## Declare interrupt handlers
198
#
199
# Declare interrupt handlers for n interrupt
200
# vectors starting at vector i.
201
#
1021 jermar 202
# The handlers call exc_dispatch().
224 palkovsky 203
#
204
.macro handler i n
205
 
1021 jermar 206
	/*
2606 jermar 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.
1121 jermar 212
	 * Therefore we align the interrupt handlers.
1021 jermar 213
	 */
224 palkovsky 214
 
1021 jermar 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	
224 palkovsky 233
 
1021 jermar 234
	save_all_gpr
2784 jermar 235
	cld
224 palkovsky 236
 
1021 jermar 237
	movq $(\i), %rdi   	# %rdi - first parameter
238
	movq %rsp, %rsi   	# %rsi - pointer to istate
239
	call exc_dispatch 	# exc_dispatch(i, istate)
240
 
799 palkovsky 241
	restore_all_gpr
242
	# $8 = Skip error word
1021 jermar 243
	addq $(IREGISTER_SPACE+8), %rsp
224 palkovsky 244
	iretq
245
 
1094 palkovsky 246
	.align INTERRUPT_ALIGN
224 palkovsky 247
	.if (\n-\i)-1
248
	handler "(\i+1)",\n
249
	.endif
250
.endm
1094 palkovsky 251
 
252
.align INTERRUPT_ALIGN
224 palkovsky 253
interrupt_handlers:
254
h_start:
255
	handler 0 IDT_ITEMS
256
h_end:
803 palkovsky 257
 
2606 jermar 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
#
803 palkovsky 276
syscall_entry:
2606 jermar 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
806 palkovsky 286
 
2606 jermar 287
	pushq %rcx
288
	pushq %r11
806 palkovsky 289
 
2606 jermar 290
	movq %r10, %rcx		# Copy the 4th argument where it is expected 
291
	pushq %rax
803 palkovsky 292
	call syscall_handler
2606 jermar 293
	addq $8, %rsp
955 palkovsky 294
 
806 palkovsky 295
	popq %r11
296
	popq %rcx
2606 jermar 297
 
298
	cli
299
	swapgs
300
	movq %gs:0, %rsp	# Restore the user RSP
301
	swapgs
302
 
806 palkovsky 303
	sysretq
2606 jermar 304
 
224 palkovsky 305
.data
306
.global interrupt_handler_size
307
 
820 jermar 308
interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS