source: mainline/kernel/arch/amd64/include/arch/asm.h@ 8addb24a

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8addb24a was 8addb24a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Turn spin look hint into a function

  • Property mode set to 100644
File size: 9.8 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 kernel_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#include <typedefs.h>
40#include <arch/cpu.h>
41#include <trace.h>
42
43#define IO_SPACE_BOUNDARY ((void *) (64 * 1024))
44
45_NO_TRACE static inline void cpu_sleep(void)
46{
47 asm volatile (
48 "hlt\n"
49 );
50}
51
52_NO_TRACE static inline void __attribute__((noreturn)) cpu_halt(void)
53{
54 while (true) {
55 asm volatile (
56 "hlt\n"
57 );
58 }
59}
60
61_NO_TRACE static inline void cpu_spin_hint(void)
62{
63 asm volatile (
64 "pause\n"
65 );
66}
67
68/** Byte from port
69 *
70 * Get byte from port
71 *
72 * @param port Port to read from
73 * @return Value read
74 *
75 */
76_NO_TRACE static inline uint8_t pio_read_8(ioport8_t *port)
77{
78 if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
79 uint8_t val;
80
81 asm volatile (
82 "inb %w[port], %b[val]\n"
83 : [val] "=a" (val)
84 : [port] "d" (port)
85 );
86
87 return val;
88 } else
89 return (uint8_t) *port;
90}
91
92/** Word from port
93 *
94 * Get word from port
95 *
96 * @param port Port to read from
97 * @return Value read
98 *
99 */
100_NO_TRACE static inline uint16_t pio_read_16(ioport16_t *port)
101{
102 if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
103 uint16_t val;
104
105 asm volatile (
106 "inw %w[port], %w[val]\n"
107 : [val] "=a" (val)
108 : [port] "d" (port)
109 );
110
111 return val;
112 } else
113 return (uint16_t) *port;
114}
115
116/** Double word from port
117 *
118 * Get double word from port
119 *
120 * @param port Port to read from
121 * @return Value read
122 *
123 */
124_NO_TRACE static inline uint32_t pio_read_32(ioport32_t *port)
125{
126 if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
127 uint32_t val;
128
129 asm volatile (
130 "inl %w[port], %[val]\n"
131 : [val] "=a" (val)
132 : [port] "d" (port)
133 );
134
135 return val;
136 } else
137 return (uint32_t) *port;
138}
139
140/** Byte to port
141 *
142 * Output byte to port
143 *
144 * @param port Port to write to
145 * @param val Value to write
146 *
147 */
148_NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t val)
149{
150 if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
151 asm volatile (
152 "outb %b[val], %w[port]\n"
153 :: [val] "a" (val), [port] "d" (port)
154 );
155 } else
156 *port = val;
157}
158
159/** Word to port
160 *
161 * Output word to port
162 *
163 * @param port Port to write to
164 * @param val Value to write
165 *
166 */
167_NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t val)
168{
169 if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
170 asm volatile (
171 "outw %w[val], %w[port]\n"
172 :: [val] "a" (val), [port] "d" (port)
173 );
174 } else
175 *port = val;
176}
177
178/** Double word to port
179 *
180 * Output double word to port
181 *
182 * @param port Port to write to
183 * @param val Value to write
184 *
185 */
186_NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t val)
187{
188 if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
189 asm volatile (
190 "outl %[val], %w[port]\n"
191 :: [val] "a" (val), [port] "d" (port)
192 );
193 } else
194 *port = val;
195}
196
197_NO_TRACE static inline uint64_t read_rflags(void)
198{
199 uint64_t rflags;
200
201 asm volatile (
202 "pushfq\n"
203 "popq %[v]\n"
204 : [v] "=r" (rflags)
205 );
206
207 return rflags;
208}
209
210_NO_TRACE static inline void write_rflags(uint64_t rflags)
211{
212 asm volatile (
213 "pushq %[v]\n"
214 "popfq\n"
215 :: [v] "r" (rflags)
216 );
217}
218
219/** Return interrupt priority level.
220 *
221 * Return the current interrupt priority level.
222 *
223 * @return Current interrupt priority level.
224 *
225 */
226_NO_TRACE static inline ipl_t interrupts_read(void)
227{
228 return (ipl_t) read_rflags();
229}
230
231/** Enable interrupts.
232 *
233 * Enable interrupts and return the previous interrupt priority level.
234 *
235 * @return Old interrupt priority level.
236 *
237 */
238_NO_TRACE static inline ipl_t interrupts_enable(void)
239{
240 ipl_t ipl = interrupts_read();
241
242 asm volatile ("sti\n");
243
244 return ipl;
245}
246
247/** Disable interrupts.
248 *
249 * Disable interrupts and return the previous interrupt priority level.
250 *
251 * @return Old interrupt priority level.
252 *
253 */
254_NO_TRACE static inline ipl_t interrupts_disable(void)
255{
256 ipl_t ipl = interrupts_read();
257
258 asm volatile ("cli\n");
259
260 return ipl;
261}
262
263/** Restore interrupt priority level.
264 *
265 * Restore the previously save interrupt priority level.
266 *
267 * @param ipl Saved interrupt priority level.
268 *
269 */
270_NO_TRACE static inline void interrupts_restore(ipl_t ipl)
271{
272 write_rflags((uint64_t) ipl);
273}
274
275/** Check interrupts state.
276 *
277 * @return True if interrupts are disabled.
278 *
279 */
280_NO_TRACE static inline bool interrupts_disabled(void)
281{
282 return ((read_rflags() & RFLAGS_IF) == 0);
283}
284
285/** Write to MSR */
286_NO_TRACE static inline void write_msr(uint32_t msr, uint64_t value)
287{
288 asm volatile (
289 "wrmsr\n"
290 :: "c" (msr),
291 "a" ((uint32_t) (value)),
292 "d" ((uint32_t) (value >> 32))
293 );
294}
295
296_NO_TRACE static inline sysarg_t read_msr(uint32_t msr)
297{
298 uint32_t ax, dx;
299
300 asm volatile (
301 "rdmsr\n"
302 : "=a" (ax), "=d" (dx)
303 : "c" (msr)
304 );
305
306 return ((uint64_t) dx << 32) | ax;
307}
308
309/** Invalidate TLB Entry.
310 *
311 * @param addr Address on a page whose TLB entry is to be invalidated.
312 *
313 */
314_NO_TRACE static inline void invlpg(uintptr_t addr)
315{
316 asm volatile (
317 "invlpg %[addr]\n"
318 :: [addr] "m" (*((sysarg_t *) addr))
319 );
320}
321
322/** Load GDTR register from memory.
323 *
324 * @param gdtr_reg Address of memory from where to load GDTR.
325 *
326 */
327_NO_TRACE static inline void gdtr_load(ptr_16_64_t *gdtr_reg)
328{
329 asm volatile (
330 "lgdtq %[gdtr_reg]\n"
331 :: [gdtr_reg] "m" (*gdtr_reg)
332 );
333}
334
335/** Store GDTR register to memory.
336 *
337 * @param gdtr_reg Address of memory to where to load GDTR.
338 *
339 */
340_NO_TRACE static inline void gdtr_store(ptr_16_64_t *gdtr_reg)
341{
342 asm volatile (
343 "sgdtq %[gdtr_reg]\n"
344 :: [gdtr_reg] "m" (*gdtr_reg)
345 );
346}
347
348/** Load IDTR register from memory.
349 *
350 * @param idtr_reg Address of memory from where to load IDTR.
351 *
352 */
353_NO_TRACE static inline void idtr_load(ptr_16_64_t *idtr_reg)
354{
355 asm volatile (
356 "lidtq %[idtr_reg]\n"
357 :: [idtr_reg] "m" (*idtr_reg));
358}
359
360/** Load TR from descriptor table.
361 *
362 * @param sel Selector specifying descriptor of TSS segment.
363 *
364 */
365_NO_TRACE static inline void tr_load(uint16_t sel)
366{
367 asm volatile (
368 "ltr %[sel]"
369 :: [sel] "r" (sel)
370 );
371}
372
373#define GEN_READ_REG(reg) _NO_TRACE static inline sysarg_t read_ ##reg (void) \
374 { \
375 sysarg_t res; \
376 asm volatile ( \
377 "movq %%" #reg ", %[res]" \
378 : [res] "=r" (res) \
379 ); \
380 return res; \
381 }
382
383#define GEN_WRITE_REG(reg) _NO_TRACE static inline void write_ ##reg (sysarg_t regn) \
384 { \
385 asm volatile ( \
386 "movq %[regn], %%" #reg \
387 :: [regn] "r" (regn) \
388 ); \
389 }
390
391GEN_READ_REG(cr0);
392GEN_WRITE_REG(cr0);
393GEN_READ_REG(cr2);
394GEN_READ_REG(cr3);
395GEN_WRITE_REG(cr3);
396GEN_READ_REG(cr4);
397GEN_WRITE_REG(cr4);
398
399GEN_READ_REG(dr0);
400GEN_READ_REG(dr1);
401GEN_READ_REG(dr2);
402GEN_READ_REG(dr3);
403GEN_READ_REG(dr6);
404GEN_READ_REG(dr7);
405
406GEN_WRITE_REG(dr0);
407GEN_WRITE_REG(dr1);
408GEN_WRITE_REG(dr2);
409GEN_WRITE_REG(dr3);
410GEN_WRITE_REG(dr6);
411GEN_WRITE_REG(dr7);
412
413extern void asm_delay_loop(uint32_t);
414extern void asm_fake_loop(uint32_t);
415
416extern uintptr_t int_0;
417extern uintptr_t int_1;
418extern uintptr_t int_2;
419extern uintptr_t int_3;
420extern uintptr_t int_4;
421extern uintptr_t int_5;
422extern uintptr_t int_6;
423extern uintptr_t int_7;
424extern uintptr_t int_8;
425extern uintptr_t int_9;
426extern uintptr_t int_10;
427extern uintptr_t int_11;
428extern uintptr_t int_12;
429extern uintptr_t int_13;
430extern uintptr_t int_14;
431extern uintptr_t int_15;
432extern uintptr_t int_16;
433extern uintptr_t int_17;
434extern uintptr_t int_18;
435extern uintptr_t int_19;
436extern uintptr_t int_20;
437extern uintptr_t int_21;
438extern uintptr_t int_22;
439extern uintptr_t int_23;
440extern uintptr_t int_24;
441extern uintptr_t int_25;
442extern uintptr_t int_26;
443extern uintptr_t int_27;
444extern uintptr_t int_28;
445extern uintptr_t int_29;
446extern uintptr_t int_30;
447extern uintptr_t int_31;
448extern uintptr_t int_32;
449extern uintptr_t int_33;
450extern uintptr_t int_34;
451extern uintptr_t int_35;
452extern uintptr_t int_36;
453extern uintptr_t int_37;
454extern uintptr_t int_38;
455extern uintptr_t int_39;
456extern uintptr_t int_40;
457extern uintptr_t int_41;
458extern uintptr_t int_42;
459extern uintptr_t int_43;
460extern uintptr_t int_44;
461extern uintptr_t int_45;
462extern uintptr_t int_46;
463extern uintptr_t int_47;
464extern uintptr_t int_48;
465extern uintptr_t int_49;
466extern uintptr_t int_50;
467extern uintptr_t int_51;
468extern uintptr_t int_52;
469extern uintptr_t int_53;
470extern uintptr_t int_54;
471extern uintptr_t int_55;
472extern uintptr_t int_56;
473extern uintptr_t int_57;
474extern uintptr_t int_58;
475extern uintptr_t int_59;
476extern uintptr_t int_60;
477extern uintptr_t int_61;
478extern uintptr_t int_62;
479extern uintptr_t int_63;
480
481extern void enable_l_apic_in_msr(void);
482
483#endif
484
485/** @}
486 */
Note: See TracBrowser for help on using the repository browser.