source: mainline/kernel/arch/amd64/include/asm.h@ 201abde

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 201abde was b3f8fb7, checked in by Martin Decky <martin@…>, 19 years ago

huge type system cleanup
remove cyclical type dependencies across multiple header files
many minor coding style fixes

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2005 Jakub Jermar
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/** @addtogroup amd64
30 * @{
31 */
32/** @file
33 */
34
35#ifndef KERN_amd64_ASM_H_
36#define KERN_amd64_ASM_H_
37
38#include <config.h>
39
40extern void asm_delay_loop(uint32_t t);
41extern void asm_fake_loop(uint32_t t);
42
43/** Return base address of current stack.
44 *
45 * Return the base address of the current stack.
46 * The stack is assumed to be STACK_SIZE bytes long.
47 * The stack must start on page boundary.
48 */
49static inline uintptr_t get_stack_base(void)
50{
51 uintptr_t v;
52
53 asm volatile ("andq %%rsp, %0\n" : "=r" (v) : "0" (~((uint64_t)STACK_SIZE-1)));
54
55 return v;
56}
57
58static inline void cpu_sleep(void) { __asm__ volatile ("hlt\n"); };
59static inline void cpu_halt(void) { __asm__ volatile ("hlt\n"); };
60
61
62/** Byte from port
63 *
64 * Get byte from port
65 *
66 * @param port Port to read from
67 * @return Value read
68 */
69static inline uint8_t inb(uint16_t port) { uint8_t val; __asm__ volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port) ); return val; }
70
71/** Byte to port
72 *
73 * Output byte to port
74 *
75 * @param port Port to write to
76 * @param val Value to write
77 */
78static inline void outb(uint16_t port, uint8_t val) { __asm__ volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port) ); }
79
80/** Swap Hidden part of GS register with visible one */
81static inline void swapgs(void) { __asm__ volatile("swapgs"); }
82
83/** Enable interrupts.
84 *
85 * Enable interrupts and return previous
86 * value of EFLAGS.
87 *
88 * @return Old interrupt priority level.
89 */
90static inline ipl_t interrupts_enable(void) {
91 ipl_t v;
92 __asm__ volatile (
93 "pushfq\n"
94 "popq %0\n"
95 "sti\n"
96 : "=r" (v)
97 );
98 return v;
99}
100
101/** Disable interrupts.
102 *
103 * Disable interrupts and return previous
104 * value of EFLAGS.
105 *
106 * @return Old interrupt priority level.
107 */
108static inline ipl_t interrupts_disable(void) {
109 ipl_t v;
110 __asm__ volatile (
111 "pushfq\n"
112 "popq %0\n"
113 "cli\n"
114 : "=r" (v)
115 );
116 return v;
117}
118
119/** Restore interrupt priority level.
120 *
121 * Restore EFLAGS.
122 *
123 * @param ipl Saved interrupt priority level.
124 */
125static inline void interrupts_restore(ipl_t ipl) {
126 __asm__ volatile (
127 "pushq %0\n"
128 "popfq\n"
129 : : "r" (ipl)
130 );
131}
132
133/** Return interrupt priority level.
134 *
135 * Return EFLAFS.
136 *
137 * @return Current interrupt priority level.
138 */
139static inline ipl_t interrupts_read(void) {
140 ipl_t v;
141 __asm__ volatile (
142 "pushfq\n"
143 "popq %0\n"
144 : "=r" (v)
145 );
146 return v;
147}
148
149/** Write to MSR */
150static inline void write_msr(uint32_t msr, uint64_t value)
151{
152 __asm__ volatile (
153 "wrmsr;" : : "c" (msr),
154 "a" ((uint32_t)(value)),
155 "d" ((uint32_t)(value >> 32))
156 );
157}
158
159static inline unative_t read_msr(uint32_t msr)
160{
161 uint32_t ax, dx;
162
163 __asm__ volatile (
164 "rdmsr;" : "=a"(ax), "=d"(dx) : "c" (msr)
165 );
166 return ((uint64_t)dx << 32) | ax;
167}
168
169
170/** Enable local APIC
171 *
172 * Enable local APIC in MSR.
173 */
174static inline void enable_l_apic_in_msr()
175{
176 __asm__ volatile (
177 "movl $0x1b, %%ecx\n"
178 "rdmsr\n"
179 "orl $(1<<11),%%eax\n"
180 "orl $(0xfee00000),%%eax\n"
181 "wrmsr\n"
182 :
183 :
184 :"%eax","%ecx","%edx"
185 );
186}
187
188static inline uintptr_t * get_ip()
189{
190 uintptr_t *ip;
191
192 __asm__ volatile (
193 "mov %%rip, %0"
194 : "=r" (ip)
195 );
196 return ip;
197}
198
199/** Invalidate TLB Entry.
200 *
201 * @param addr Address on a page whose TLB entry is to be invalidated.
202 */
203static inline void invlpg(uintptr_t addr)
204{
205 __asm__ volatile ("invlpg %0\n" :: "m" (*((unative_t *)addr)));
206}
207
208/** Load GDTR register from memory.
209 *
210 * @param gdtr_reg Address of memory from where to load GDTR.
211 */
212static inline void gdtr_load(struct ptr_16_64 *gdtr_reg)
213{
214 __asm__ volatile ("lgdtq %0\n" : : "m" (*gdtr_reg));
215}
216
217/** Store GDTR register to memory.
218 *
219 * @param gdtr_reg Address of memory to where to load GDTR.
220 */
221static inline void gdtr_store(struct ptr_16_64 *gdtr_reg)
222{
223 __asm__ volatile ("sgdtq %0\n" : : "m" (*gdtr_reg));
224}
225
226/** Load IDTR register from memory.
227 *
228 * @param idtr_reg Address of memory from where to load IDTR.
229 */
230static inline void idtr_load(struct ptr_16_64 *idtr_reg)
231{
232 __asm__ volatile ("lidtq %0\n" : : "m" (*idtr_reg));
233}
234
235/** Load TR from descriptor table.
236 *
237 * @param sel Selector specifying descriptor of TSS segment.
238 */
239static inline void tr_load(uint16_t sel)
240{
241 __asm__ volatile ("ltr %0" : : "r" (sel));
242}
243
244#define GEN_READ_REG(reg) static inline unative_t read_ ##reg (void) \
245 { \
246 unative_t res; \
247 __asm__ volatile ("movq %%" #reg ", %0" : "=r" (res) ); \
248 return res; \
249 }
250
251#define GEN_WRITE_REG(reg) static inline void write_ ##reg (unative_t regn) \
252 { \
253 __asm__ volatile ("movq %0, %%" #reg : : "r" (regn)); \
254 }
255
256GEN_READ_REG(cr0);
257GEN_READ_REG(cr2);
258GEN_READ_REG(cr3);
259GEN_WRITE_REG(cr3);
260
261GEN_READ_REG(dr0);
262GEN_READ_REG(dr1);
263GEN_READ_REG(dr2);
264GEN_READ_REG(dr3);
265GEN_READ_REG(dr6);
266GEN_READ_REG(dr7);
267
268GEN_WRITE_REG(dr0);
269GEN_WRITE_REG(dr1);
270GEN_WRITE_REG(dr2);
271GEN_WRITE_REG(dr3);
272GEN_WRITE_REG(dr6);
273GEN_WRITE_REG(dr7);
274
275extern size_t interrupt_handler_size;
276extern void interrupt_handlers(void);
277
278#endif
279
280/** @}
281 */
Note: See TracBrowser for help on using the repository browser.