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

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

© versus ©

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