00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #ifndef __amd64_ASM_H__
00036 #define __amd64_ASM_H__
00037
00038 #include <arch/pm.h>
00039 #include <arch/types.h>
00040 #include <config.h>
00041
00042 extern void asm_delay_loop(__u32 t);
00043 extern void asm_fake_loop(__u32 t);
00044
00051 static inline __address get_stack_base(void)
00052 {
00053 __address v;
00054
00055 __asm__ volatile ("andq %%rsp, %0\n" : "=r" (v) : "0" (~((__u64)STACK_SIZE-1)));
00056
00057 return v;
00058 }
00059
00060 static inline void cpu_sleep(void) { __asm__ volatile ("hlt\n"); };
00061 static inline void cpu_halt(void) { __asm__ volatile ("hlt\n"); };
00062
00063
00071 static inline __u8 inb(__u16 port) { __u8 val; __asm__ volatile ("inb %w1, %b0 \n" : "=a" (val) : "d" (port) ); return val; }
00072
00080 static inline void outb(__u16 port, __u8 val) { __asm__ volatile ("outb %b0, %w1\n" : : "a" (val), "d" (port) ); }
00081
00083 static inline void swapgs(void) { __asm__ volatile("swapgs"); }
00084
00092 static inline ipl_t interrupts_enable(void) {
00093 ipl_t v;
00094 __asm__ volatile (
00095 "pushfq\n"
00096 "popq %0\n"
00097 "sti\n"
00098 : "=r" (v)
00099 );
00100 return v;
00101 }
00102
00110 static inline ipl_t interrupts_disable(void) {
00111 ipl_t v;
00112 __asm__ volatile (
00113 "pushfq\n"
00114 "popq %0\n"
00115 "cli\n"
00116 : "=r" (v)
00117 );
00118 return v;
00119 }
00120
00127 static inline void interrupts_restore(ipl_t ipl) {
00128 __asm__ volatile (
00129 "pushq %0\n"
00130 "popfq\n"
00131 : : "r" (ipl)
00132 );
00133 }
00134
00141 static inline ipl_t interrupts_read(void) {
00142 ipl_t v;
00143 __asm__ volatile (
00144 "pushfq\n"
00145 "popq %0\n"
00146 : "=r" (v)
00147 );
00148 return v;
00149 }
00150
00152 static inline void write_msr(__u32 msr, __u64 value)
00153 {
00154 __asm__ volatile (
00155 "wrmsr;" : : "c" (msr),
00156 "a" ((__u32)(value)),
00157 "d" ((__u32)(value >> 32))
00158 );
00159 }
00160
00161 static inline __native read_msr(__u32 msr)
00162 {
00163 __u32 ax, dx;
00164
00165 __asm__ volatile (
00166 "rdmsr;" : "=a"(ax), "=d"(dx) : "c" (msr)
00167 );
00168 return ((__u64)dx << 32) | ax;
00169 }
00170
00171
00176 static inline void enable_l_apic_in_msr()
00177 {
00178 __asm__ volatile (
00179 "movl $0x1b, %%ecx\n"
00180 "rdmsr\n"
00181 "orl $(1<<11),%%eax\n"
00182 "orl $(0xfee00000),%%eax\n"
00183 "wrmsr\n"
00184 :
00185 :
00186 :"%eax","%ecx","%edx"
00187 );
00188 }
00189
00190 static inline __address * get_ip()
00191 {
00192 __address *ip;
00193
00194 __asm__ volatile (
00195 "mov %%rip, %0"
00196 : "=r" (ip)
00197 );
00198 return ip;
00199 }
00200
00205 static inline void invlpg(__address addr)
00206 {
00207 __asm__ volatile ("invlpg %0\n" :: "m" (*((__native *)addr)));
00208 }
00209
00214 static inline void gdtr_load(struct ptr_16_64 *gdtr_reg)
00215 {
00216 __asm__ volatile ("lgdtq %0\n" : : "m" (*gdtr_reg));
00217 }
00218
00223 static inline void gdtr_store(struct ptr_16_64 *gdtr_reg)
00224 {
00225 __asm__ volatile ("sgdtq %0\n" : : "m" (*gdtr_reg));
00226 }
00227
00232 static inline void idtr_load(struct ptr_16_64 *idtr_reg)
00233 {
00234 __asm__ volatile ("lidtq %0\n" : : "m" (*idtr_reg));
00235 }
00236
00241 static inline void tr_load(__u16 sel)
00242 {
00243 __asm__ volatile ("ltr %0" : : "r" (sel));
00244 }
00245
00246 #define GEN_READ_REG(reg) static inline __native read_ ##reg (void) \
00247 { \
00248 __native res; \
00249 __asm__ volatile ("movq %%" #reg ", %0" : "=r" (res) ); \
00250 return res; \
00251 }
00252
00253 #define GEN_WRITE_REG(reg) static inline void write_ ##reg (__native regn) \
00254 { \
00255 __asm__ volatile ("movq %0, %%" #reg : : "r" (regn)); \
00256 }
00257
00258 GEN_READ_REG(cr0);
00259 GEN_READ_REG(cr2);
00260 GEN_READ_REG(cr3);
00261 GEN_WRITE_REG(cr3);
00262
00263 GEN_READ_REG(dr0);
00264 GEN_READ_REG(dr1);
00265 GEN_READ_REG(dr2);
00266 GEN_READ_REG(dr3);
00267 GEN_READ_REG(dr6);
00268 GEN_READ_REG(dr7);
00269
00270 GEN_WRITE_REG(dr0);
00271 GEN_WRITE_REG(dr1);
00272 GEN_WRITE_REG(dr2);
00273 GEN_WRITE_REG(dr3);
00274 GEN_WRITE_REG(dr6);
00275 GEN_WRITE_REG(dr7);
00276
00277
00278 extern size_t interrupt_handler_size;
00279 extern void interrupt_handlers(void);
00280
00281 #endif
00282