Fixup of some headers.
[barrelfish] / include / arch / k1om / barrelfish_kpi / asm_inlines_arch.h
1
2 /*
3  * Copyright (c) 2015, ETH Zurich.
4  * All rights reserved.
5  *
6  * This file is distributed under the terms in the attached LICENSE file.
7  * If you do not find this file, copies can be found by writing to:
8  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
9  */
10
11 #ifndef ARCH_K1OM_BARRELFISH_KPI_ASM_INLINES_H
12 #define ARCH_K1OM_BARRELFISH_KPI_ASM_INLINES_H 1
13
14 #include <machine/param.h>
15
16 #ifndef __ASSEMBLER__
17
18 #include <target/x86_64/barrelfish_kpi/registers_target.h>
19
20 #define CLOCK_PER_MS 1046008
21
22 static inline void
23 delay_ms(uint32_t ms)
24 {
25     if (ms == 0) {
26         return;
27     }
28     uint64_t num_cpu_clks = ms * CLOCK_PER_MS;
29
30     if (num_cpu_clks <= 1023) {
31         /* since delay can only go upto 1023 clocks */
32         __asm __volatile("delay %0"::"r"(num_cpu_clks));
33     } else {
34         /* break it up into 1000 clock chunks */
35         for (uint32_t tick = 1000; num_cpu_clks >= 1000; num_cpu_clks -= 1000) {
36             __asm __volatile("delay %0"::"r"(tick));
37         }
38
39         /* the remaining */
40         __asm __volatile("delay %0"::"r"(num_cpu_clks));
41     }
42     return;
43 }
44
45
46
47 /*
48  * some functions require to have the register ECX set to a specific value
49  * and will produce wrong results if the value in register ECX is out of range.
50  */
51 static inline void
52 cpuid_ext(uint32_t function,
53           uint32_t ecx_in,
54           uint32_t *eax,
55           uint32_t *ebx,
56           uint32_t *ecx,
57           uint32_t *edx)
58 {
59     // make it possible to omit certain return registers
60     uint32_t a, b, c, d;
61     if (eax == NULL) {
62         eax = &a;
63     }
64     if (ebx == NULL) {
65         ebx = &b;
66     }
67     if (ecx == NULL) {
68         ecx = &c;
69     }
70     if (edx == NULL) {
71         edx = &d;
72     }
73     __asm volatile("cpuid"
74             : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
75             : "a" (function), "c" (ecx_in)
76     );
77 }
78
79 static inline void
80 cpuid(uint32_t function,
81       uint32_t *eax,
82       uint32_t *ebx,
83       uint32_t *ecx,
84       uint32_t *edx)
85 {
86     cpuid_ext(function, 0, eax, ebx, ecx, edx);
87 }
88
89 /** \brief Atomic compare-and-swap on 128 bits
90  *
91  * If *dst == old then *dst = new, returns 0 on failure
92  *
93  * Note, dest should point to a 128bit structure that is to be overwritten
94  */
95 static inline int cmpxchg128(volatile uint64_t dest[2], uint64_t old_top, uint64_t old_bot, uint64_t new_top, uint64_t new_bot)
96 {
97     uint8_t ret;
98
99     __asm volatile (
100         "lock cmpxchg16b %1\n\t"
101         "setz %0\n\t"
102         : "=a"(ret), "=m"(*dest)//, "=d"(old_top), "=a"(old_bot)
103         : "a"(old_top), "d"(old_bot), "b"(new_top), "c"(new_bot), "m"(*dest)
104         : "memory");
105
106     return ret;
107 }
108
109 static inline void fpu_init(void)
110 {
111     __asm volatile ("fninit");
112 }
113
114 static inline void fpu_save(struct registers_fpu_x86_64 *fpustate)
115 {
116     uint8_t *regs = fpustate->registers;
117     regs += 16 - ((uintptr_t)regs % 16);
118
119     __asm volatile("fxsaveq %0" : "=m" (*regs));
120 }
121
122 static inline void fpu_restore(struct registers_fpu_x86_64 *fpustate)
123 {
124     uint8_t *regs = fpustate->registers;
125     regs += 16 - ((uintptr_t)regs % 16);
126
127     __asm volatile ("fxrstorq %0" :: "m" (*regs));
128 }
129
130 #if 0
131
132 /** \brief This code reads the cycle counter */
133 static inline uint64_t
134 rdtsc(void)
135 {
136
137     uint32_t eax, edx;
138     __asm volatile ("rdtsc" : "=a" (eax), "=d" (edx));
139     return ((uint64_t) edx << 32) | eax;
140
141     return 0;
142 }
143
144 /** \brief This code reads the cycle counter -- flushing the
145  instruction pipeline first. Throws away the processor ID information. */
146 static inline uint64_t
147 rdtscp(void)
148 {
149     /*
150      uint32_t eax, edx;
151      __asm volatile ("rdtscp" : "=a" (eax), "=d" (edx) :: "ecx");
152      return ((uint64_t)edx << 32) | eax;
153      */
154     return 0;
155 }
156
157 static inline uint64_t
158 rdpmc(uint32_t counter)
159 {
160     /*
161     uint32_t eax, edx;
162
163      __asm volatile("rdpmc"
164      : "=a" (eax), "=d" (edx)
165      : "c" (counter)
166      );
167
168     return ((uint64_t) edx << 32) | eax;
169      */
170     return 0;
171 }
172
173 static inline void
174 mfence(void)
175 {
176     // __asm volatile("mfence");
177 }
178
179 static inline void
180 sfence(void)
181 {
182     //  __asm volatile("sfence");
183 }
184
185 static inline void
186 lfence(void)
187 {
188     // __asm volatile("lfence");
189 }
190
191 static inline void
192 clflush(void *line)
193 {
194     __asm volatile("clflush %0" :: "m" (line));
195 }
196
197 #ifndef __cplusplus
198 /* flush a range of memory from the cache */
199 static inline void cache_flush_range(void *base, size_t len)
200 {
201     //mfence();
202
203     uint8_t *line = (uint8_t *)((uintptr_t)base & ~(CACHE_LINE_SIZE-1UL));
204     do {
205         clflush(line);
206         line += CACHE_LINE_SIZE;
207     }while (line < (uint8_t *)base + len);
208 }
209 #endif
210 #endif
211 #endif // __ASSEMBLER__
212
213 #endif // ARCH_K1OM_BARRELFISH_KPI_ASM_INLINES_H