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
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 %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)
[8d25b44]133#ifdef CONFIG_DEBUG_ALLREGS
134 movq %rbx, IOFFSET_RBX(%rsp)
135 movq %rbp, IOFFSET_RBP(%rsp)
[49a39c2]136 movq %r12, IOFFSET_R12(%rsp)
137 movq %r13, IOFFSET_R13(%rsp)
138 movq %r14, IOFFSET_R14(%rsp)
139 movq %r15, IOFFSET_R15(%rsp)
[8d25b44]140#endif
[e3b9572]141.endm
142
[49a39c2]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
[8d25b44]153#ifdef CONFIG_DEBUG_ALLREGS
154 movq IOFFSET_RBX(%rsp), %rbx
155 movq IOFFSET_RBP(%rsp), %rbp
[49a39c2]156 movq IOFFSET_R12(%rsp), %r12
157 movq IOFFSET_R13(%rsp), %r13
158 movq IOFFSET_R14(%rsp), %r14
159 movq IOFFSET_R15(%rsp), %r15
[8d25b44]160#endif
[e3b9572]161.endm
[8e0eb63]162
[8d25b44]163#ifdef CONFIG_DEBUG_ALLREGS
164# define INTERRUPT_ALIGN 256
165#else
166# define INTERRUPT_ALIGN 128
167#endif
168
[e3b9572]169## Declare interrupt handlers
170#
171# Declare interrupt handlers for n interrupt
172# vectors starting at vector i.
173#
[8e0eb63]174# The handlers call exc_dispatch().
[e3b9572]175#
176.macro handler i n
177
[8e0eb63]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.
[e1be3b6]183 * Therefore we align the interrupt handlers.
[8e0eb63]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
[e3b9572]204
[8e0eb63]205 save_all_gpr
[e3b9572]206
[8e0eb63]207 movq $(\i), %rdi # %rdi - first parameter
208 movq %rsp, %rsi # %rsi - pointer to istate
209 call exc_dispatch # exc_dispatch(i, istate)
210
[49a39c2]211 restore_all_gpr
212 # $8 = Skip error word
[8e0eb63]213 addq $(IREGISTER_SPACE+8), %rsp
[e3b9572]214 iretq
215
[8d25b44]216 .align INTERRUPT_ALIGN
[e3b9572]217 .if (\n-\i)-1
218 handler "(\i+1)",\n
219 .endif
220.endm
[8d25b44]221
222.align INTERRUPT_ALIGN
[e3b9572]223interrupt_handlers:
224h_start:
225 handler 0 IDT_ITEMS
226h_end:
[dd4d6b0]227
[e3b9572]228
[dd4d6b0]229syscall_entry:
[37b451f7]230 # Switch to hidden gs
231 swapgs
[fa2d382]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
[37b451f7]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
[6d9c49a]244 sti
[37b451f7]245 movq %r9, %rcx # Exchange last parameter as a third
[c7c0b89b]246
[dd4d6b0]247 call syscall_handler
[6d9c49a]248 cli # We will be touching stack pointer
249
[37b451f7]250 popq %r11
251 popq %rcx
252 movq 0(%rsp), %rsp
253 sysretq
[738ad2e]254
[dd4d6b0]255
[e3b9572]256.data
257.global interrupt_handler_size
258
[42744880]259interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS
Note: See TracBrowser for help on using the repository browser.