source: mainline/arch/amd64/src/asm_utils.S@ 8e0eb63

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

Hopefully final version of interrupt handlers for amd64 and ia32.
amd64 has been especially tricky to debug.
Error code detection is now done in compile time.

  • Property mode set to 100644
File size: 6.0 KB
RevLine 
[e3b9572]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
[8e0eb63]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
[e3b9572]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>
[fa2d382]52#include <arch/mm/page.h>
[e3b9572]53
54.text
55.global interrupt_handlers
[dd4d6b0]56.global syscall_entry
[e3b9572]57.global panic_printf
58
59panic_printf:
60 movq $halt, (%rsp)
61 jmp printf
62
[36b209a]63.global memcpy
64memcpy:
65 jmp _memcpy
66
67.global cpuid
[7df54df]68.global has_cpuid
69.global rdtsc
[89344d85]70.global read_efer_flag
71.global set_efer_flag
72
[7df54df]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
[d6dcdd2e]80 movq %rax,%rdx # copy flags
81 btcl $21,%edx # swap the ID bit
82 pushq %rdx
[7df54df]83 popfq # propagate the change into flags
84 pushfq
[d6dcdd2e]85 popq %rdx # read flags
[7df54df]86 andl $(1<<21),%eax # interested only in ID bit
[d6dcdd2e]87 andl $(1<<21),%edx
88 xorl %edx,%eax # 0 if not supported, 1 if supported
[7df54df]89 ret
90
[89344d85]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
[7df54df]104
105rdtsc:
106 xorq %rax,%rax
107 rdtsc
108 ret
[89344d85]109
110set_efer_flag:
111 movq $0xc0000080, %rcx
112 rdmsr
113 btsl %edi, %eax
114 wrmsr
115 ret
[7df54df]116
[89344d85]117read_efer_flag:
118 movq $0xc0000080, %rcx
119 rdmsr
120 ret
[7df54df]121
[e3b9572]122# Push all general purpose registers on stack except %rbp, %rsp
[49a39c2]123.macro save_all_gpr
124 movq %rbp, IOFFSET_RBP(%rsp)
125 movq %rax, IOFFSET_RAX(%rsp)
126 movq %rbx, IOFFSET_RBX(%rsp)
127 movq %rcx, IOFFSET_RCX(%rsp)
128 movq %rdx, IOFFSET_RDX(%rsp)
129 movq %rsi, IOFFSET_RSI(%rsp)
130 movq %rdi, IOFFSET_RDI(%rsp)
131 movq %r8, IOFFSET_R8(%rsp)
132 movq %r9, IOFFSET_R9(%rsp)
133 movq %r10, IOFFSET_R10(%rsp)
134 movq %r11, IOFFSET_R11(%rsp)
135 movq %r12, IOFFSET_R12(%rsp)
136 movq %r13, IOFFSET_R13(%rsp)
137 movq %r14, IOFFSET_R14(%rsp)
138 movq %r15, IOFFSET_R15(%rsp)
[e3b9572]139.endm
140
[49a39c2]141.macro restore_all_gpr
142 movq IOFFSET_RBP(%rsp), %rbp
143 movq IOFFSET_RAX(%rsp), %rax
144 movq IOFFSET_RBX(%rsp), %rbx
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 movq IOFFSET_R12(%rsp), %r12
154 movq IOFFSET_R13(%rsp), %r13
155 movq IOFFSET_R14(%rsp), %r14
156 movq IOFFSET_R15(%rsp), %r15
[e3b9572]157.endm
[8e0eb63]158
[e3b9572]159## Declare interrupt handlers
160#
161# Declare interrupt handlers for n interrupt
162# vectors starting at vector i.
163#
[8e0eb63]164# The handlers call exc_dispatch().
[e3b9572]165#
166.macro handler i n
167
[8e0eb63]168 /*
169 * Choose between version with error code and version without error code.
170 * Both versions have to be of the same size. amd64 assembly is, however,
171 * a little bit tricky. For instance, subq $0x80, %rsp and subq $0x78, %rsp
172 * can result in two instructions with different op-code lengths.
173 * Therefore, pay special attention to the extra NOP's that serve as
174 * a necessary fill.
175 */
176
177 .iflt \i-32
178 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
179 /*
180 * Version with error word.
181 */
182 subq $IREGISTER_SPACE, %rsp
183 nop
184 nop
185 nop
186 .else
187 /*
188 * Version without error word,
189 */
190 subq $(IREGISTER_SPACE+8), %rsp
191 .endif
192 .else
193 /*
194 * Version without error word,
195 */
196 subq $(IREGISTER_SPACE+8), %rsp
197 .endif
[e3b9572]198
[8e0eb63]199 save_all_gpr
[e3b9572]200
[8e0eb63]201 movq $(\i), %rdi # %rdi - first parameter
202 movq %rsp, %rsi # %rsi - pointer to istate
203 call exc_dispatch # exc_dispatch(i, istate)
204
[49a39c2]205 restore_all_gpr
206 # $8 = Skip error word
[8e0eb63]207 addq $(IREGISTER_SPACE+8), %rsp
[e3b9572]208 iretq
209
210 .if (\n-\i)-1
211 handler "(\i+1)",\n
212 .endif
213.endm
214
215interrupt_handlers:
216h_start:
217 handler 0 IDT_ITEMS
218h_end:
[dd4d6b0]219
[e3b9572]220
[dd4d6b0]221syscall_entry:
[37b451f7]222 # Switch to hidden gs
223 swapgs
[fa2d382]224 # %gs:0 now points to pointer to stack page
225 mov %gs:0, %r10 # We have a ptr to stack page in r10
226 addq $PAGE_SIZE-16, %r10 # We need some space to store old %sp
[37b451f7]227
228 movq %rsp, 0(%r10) # Save old stack pointer to stack
229 movq %r10, %rsp # Change to new stack
230 pushq %rcx # Return address
231 pushq %r11 # Save flags
232
233 # Switch back to remain consistent
234 swapgs
235
[6d9c49a]236 sti
[37b451f7]237 movq %r9, %rcx # Exchange last parameter as a third
[dd4d6b0]238 call syscall_handler
[6d9c49a]239 cli # We will be touching stack pointer
240
[37b451f7]241 popq %r11
242 popq %rcx
243 movq 0(%rsp), %rsp
244 sysretq
[dd4d6b0]245
[e3b9572]246.data
247.global interrupt_handler_size
248
[42744880]249interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS
Note: See TracBrowser for help on using the repository browser.