source: mainline/arch/amd64/src/asm_utils.S@ 738ad2e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 738ad2e was 738ad2e, checked in by Ondrej Palkovsky <ondrap@…>, 19 years ago

Changed interrupt_control to preemption_control.

  • Property mode set to 100644
File size: 6.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 120
30
31#define IOFFSET_RAX 0x0
32#define IOFFSET_RBX 0x8
33#define IOFFSET_RCX 0x10
34#define IOFFSET_RDX 0x18
35#define IOFFSET_RSI 0x20
36#define IOFFSET_RDI 0x28
37#define IOFFSET_R8 0x30
38#define IOFFSET_R9 0x38
39#define IOFFSET_R10 0x40
40#define IOFFSET_R11 0x48
41#define IOFFSET_R12 0x50
42#define IOFFSET_R13 0x58
43#define IOFFSET_R14 0x60
44#define IOFFSET_R15 0x68
45#define IOFFSET_RBP 0x70
46
47# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error word
48# and 1 means interrupt with error word
49#define ERROR_WORD_INTERRUPT_LIST 0x00027D00
50
51#include <arch/pm.h>
52#include <arch/mm/page.h>
53
54.text
55.global interrupt_handlers
56.global syscall_entry
57.global panic_printf
58
59panic_printf:
60 movq $halt, (%rsp)
61 jmp printf
62
63.global memcpy
64memcpy:
65 jmp _memcpy
66
67.global cpuid
68.global has_cpuid
69.global rdtsc
70.global read_efer_flag
71.global set_efer_flag
72
73## Determine CPUID support
74#
75# Return 0 in EAX if CPUID is not support, 1 if supported.
76#
77has_cpuid:
78 pushfq # store flags
79 popq %rax # read flags
80 movq %rax,%rdx # copy flags
81 btcl $21,%edx # swap the ID bit
82 pushq %rdx
83 popfq # propagate the change into flags
84 pushfq
85 popq %rdx # read flags
86 andl $(1<<21),%eax # interested only in ID bit
87 andl $(1<<21),%edx
88 xorl %edx,%eax # 0 if not supported, 1 if supported
89 ret
90
91cpuid:
92 movq %rbx, %r10 # we have to preserve rbx across function calls
93
94 movl %edi,%eax # load the command into %eax
95
96 cpuid
97 movl %eax,0(%rsi)
98 movl %ebx,4(%rsi)
99 movl %ecx,8(%rsi)
100 movl %edx,12(%rsi)
101
102 movq %r10, %rbx
103 ret
104
105rdtsc:
106 xorq %rax,%rax
107 rdtsc
108 ret
109
110set_efer_flag:
111 movq $0xc0000080, %rcx
112 rdmsr
113 btsl %edi, %eax
114 wrmsr
115 ret
116
117read_efer_flag:
118 movq $0xc0000080, %rcx
119 rdmsr
120 ret
121
122# Push all general purpose registers on stack except %rbp, %rsp
123.macro save_all_gpr
124 movq %rax, IOFFSET_RAX(%rsp)
125 movq %rcx, IOFFSET_RCX(%rsp)
126 movq %rdx, IOFFSET_RDX(%rsp)
127 movq %rsi, IOFFSET_RSI(%rsp)
128 movq %rdi, IOFFSET_RDI(%rsp)
129 movq %r8, IOFFSET_R8(%rsp)
130 movq %r9, IOFFSET_R9(%rsp)
131 movq %r10, IOFFSET_R10(%rsp)
132 movq %r11, IOFFSET_R11(%rsp)
133#ifdef CONFIG_DEBUG_ALLREGS
134 movq %rbx, IOFFSET_RBX(%rsp)
135 movq %rbp, IOFFSET_RBP(%rsp)
136 movq %r12, IOFFSET_R12(%rsp)
137 movq %r13, IOFFSET_R13(%rsp)
138 movq %r14, IOFFSET_R14(%rsp)
139 movq %r15, IOFFSET_R15(%rsp)
140#endif
141.endm
142
143.macro restore_all_gpr
144 movq IOFFSET_RAX(%rsp), %rax
145 movq IOFFSET_RCX(%rsp), %rcx
146 movq IOFFSET_RDX(%rsp), %rdx
147 movq IOFFSET_RSI(%rsp), %rsi
148 movq IOFFSET_RDI(%rsp), %rdi
149 movq IOFFSET_R8(%rsp), %r8
150 movq IOFFSET_R9(%rsp), %r9
151 movq IOFFSET_R10(%rsp), %r10
152 movq IOFFSET_R11(%rsp), %r11
153#ifdef CONFIG_DEBUG_ALLREGS
154 movq IOFFSET_RBX(%rsp), %rbx
155 movq IOFFSET_RBP(%rsp), %rbp
156 movq IOFFSET_R12(%rsp), %r12
157 movq IOFFSET_R13(%rsp), %r13
158 movq IOFFSET_R14(%rsp), %r14
159 movq IOFFSET_R15(%rsp), %r15
160#endif
161.endm
162
163#ifdef CONFIG_DEBUG_ALLREGS
164# define INTERRUPT_ALIGN 256
165#else
166# define INTERRUPT_ALIGN 128
167#endif
168
169## Declare interrupt handlers
170#
171# Declare interrupt handlers for n interrupt
172# vectors starting at vector i.
173#
174# The handlers call exc_dispatch().
175#
176.macro handler i n
177
178 /*
179 * Choose between version with error code and version without error code.
180 * Both versions have to be of the same size. amd64 assembly is, however,
181 * a little bit tricky. For instance, subq $0x80, %rsp and subq $0x78, %rsp
182 * can result in two instructions with different op-code lengths.
183 * Therefore we align the interrupt handlers.
184 */
185
186 .iflt \i-32
187 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
188 /*
189 * Version with error word.
190 */
191 subq $IREGISTER_SPACE, %rsp
192 .else
193 /*
194 * Version without error word,
195 */
196 subq $(IREGISTER_SPACE+8), %rsp
197 .endif
198 .else
199 /*
200 * Version without error word,
201 */
202 subq $(IREGISTER_SPACE+8), %rsp
203 .endif
204
205 save_all_gpr
206
207 movq $(\i), %rdi # %rdi - first parameter
208 movq %rsp, %rsi # %rsi - pointer to istate
209 call exc_dispatch # exc_dispatch(i, istate)
210
211 restore_all_gpr
212 # $8 = Skip error word
213 addq $(IREGISTER_SPACE+8), %rsp
214 iretq
215
216 .align INTERRUPT_ALIGN
217 .if (\n-\i)-1
218 handler "(\i+1)",\n
219 .endif
220.endm
221
222.align INTERRUPT_ALIGN
223interrupt_handlers:
224h_start:
225 handler 0 IDT_ITEMS
226h_end:
227
228
229syscall_entry:
230 # Switch to hidden gs
231 swapgs
232 # %gs:0 now points to pointer to stack page
233 mov %gs:0, %r10 # We have a ptr to stack page in r10
234 addq $PAGE_SIZE-16, %r10 # We need some space to store old %sp
235
236 movq %rsp, 0(%r10) # Save old stack pointer to stack
237 movq %r10, %rsp # Change to new stack
238 pushq %rcx # Return address
239 pushq %r11 # Save flags
240
241 # Switch back to remain consistent
242 swapgs
243
244 sti
245 movq %r9, %rcx # Exchange last parameter as a third
246
247 call syscall_handler
248 cli # We will be touching stack pointer
249
250 popq %r11
251 popq %rcx
252 movq 0(%rsp), %rsp
253 sysretq
254
255
256.data
257.global interrupt_handler_size
258
259interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS
Note: See TracBrowser for help on using the repository browser.