Line data Source code
1 : /* $OpenBSD: cpufunc.h,v 1.30 2018/07/27 21:11:31 kettenis Exp $ */
2 : /* $NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $ */
3 :
4 : /*-
5 : * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 : * All rights reserved.
7 : *
8 : * This code is derived from software contributed to The NetBSD Foundation
9 : * by Charles M. Hannum.
10 : *
11 : * Redistribution and use in source and binary forms, with or without
12 : * modification, are permitted provided that the following conditions
13 : * are met:
14 : * 1. Redistributions of source code must retain the above copyright
15 : * notice, this list of conditions and the following disclaimer.
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in the
18 : * documentation and/or other materials provided with the distribution.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 : * POSSIBILITY OF SUCH DAMAGE.
31 : */
32 :
33 : #ifndef _MACHINE_CPUFUNC_H_
34 : #define _MACHINE_CPUFUNC_H_
35 :
36 : /*
37 : * Functions to provide access to i386-specific instructions.
38 : */
39 :
40 : #include <sys/types.h>
41 :
42 : #include <machine/specialreg.h>
43 :
44 : #if defined(_KERNEL) && !defined (_STANDALONE)
45 :
46 : extern int cpu_feature;
47 :
48 : static __inline void
49 0 : invlpg(u_int64_t addr)
50 : {
51 60 : __asm volatile("invlpg (%0)" : : "r" (addr) : "memory");
52 0 : }
53 :
54 : static __inline void
55 0 : lidt(void *p)
56 : {
57 0 : __asm volatile("lidt (%0)" : : "r" (p) : "memory");
58 0 : }
59 :
60 : static __inline void
61 0 : lldt(u_short sel)
62 : {
63 0 : __asm volatile("lldt %0" : : "r" (sel));
64 0 : }
65 :
66 : static __inline void
67 0 : ltr(u_short sel)
68 : {
69 0 : __asm volatile("ltr %0" : : "r" (sel));
70 0 : }
71 :
72 : static __inline void
73 0 : lcr8(u_int val)
74 : {
75 0 : u_int64_t val64 = val;
76 0 : __asm volatile("movq %0,%%cr8" : : "r" (val64));
77 0 : }
78 :
79 : /*
80 : * Upper 32 bits are reserved anyway, so just keep this 32bits.
81 : */
82 : static __inline void
83 0 : lcr0(u_int val)
84 : {
85 0 : u_int64_t val64 = val;
86 0 : __asm volatile("movq %0,%%cr0" : : "r" (val64));
87 0 : }
88 :
89 : static __inline u_int
90 0 : rcr0(void)
91 : {
92 : u_int64_t val64;
93 : u_int val;
94 0 : __asm volatile("movq %%cr0,%0" : "=r" (val64));
95 0 : val = val64;
96 0 : return val;
97 : }
98 :
99 : static __inline u_int64_t
100 0 : rcr2(void)
101 : {
102 : u_int64_t val;
103 0 : __asm volatile("movq %%cr2,%0" : "=r" (val));
104 0 : return val;
105 : }
106 :
107 : static __inline void
108 0 : lcr3(u_int64_t val)
109 : {
110 0 : __asm volatile("movq %0,%%cr3" : : "r" (val));
111 0 : }
112 :
113 : static __inline u_int64_t
114 0 : rcr3(void)
115 : {
116 : u_int64_t val;
117 0 : __asm volatile("movq %%cr3,%0" : "=r" (val));
118 0 : return val;
119 : }
120 :
121 : /*
122 : * Same as for cr0. Don't touch upper 32 bits.
123 : */
124 : static __inline void
125 0 : lcr4(u_int val)
126 : {
127 0 : u_int64_t val64 = val;
128 :
129 0 : __asm volatile("movq %0,%%cr4" : : "r" (val64));
130 0 : }
131 :
132 : static __inline u_int
133 0 : rcr4(void)
134 : {
135 : u_int64_t val64;
136 0 : __asm volatile("movq %%cr4,%0" : "=r" (val64));
137 0 : return (u_int) val64;
138 : }
139 :
140 : static __inline void
141 0 : tlbflush(void)
142 : {
143 : u_int64_t val;
144 0 : __asm volatile("movq %%cr3,%0" : "=r" (val));
145 0 : __asm volatile("movq %0,%%cr3" : : "r" (val));
146 0 : }
147 :
148 : #ifdef notyet
149 : void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl);
150 : #endif
151 :
152 :
153 : /* XXXX ought to be in psl.h with spl() functions */
154 :
155 : static __inline u_long
156 0 : read_rflags(void)
157 : {
158 : u_long ef;
159 :
160 0 : __asm volatile("pushfq; popq %0" : "=r" (ef));
161 0 : return (ef);
162 : }
163 :
164 : static __inline void
165 0 : write_rflags(u_long ef)
166 : {
167 0 : __asm volatile("pushq %0; popfq" : : "r" (ef));
168 0 : }
169 :
170 : static __inline void
171 0 : intr_enable(void)
172 : {
173 0 : __asm volatile("sti");
174 0 : }
175 :
176 : static __inline u_long
177 0 : intr_disable(void)
178 : {
179 : u_long ef;
180 :
181 0 : ef = read_rflags();
182 0 : __asm volatile("cli");
183 0 : return (ef);
184 : }
185 :
186 : static __inline void
187 0 : intr_restore(u_long ef)
188 : {
189 0 : write_rflags(ef);
190 0 : }
191 :
192 : static __inline u_int64_t
193 0 : rdmsr(u_int msr)
194 : {
195 : uint32_t hi, lo;
196 0 : __asm volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr));
197 0 : return (((uint64_t)hi << 32) | (uint64_t) lo);
198 : }
199 :
200 : static __inline void
201 0 : wrmsr(u_int msr, u_int64_t newval)
202 : {
203 0 : __asm volatile("wrmsr" :
204 0 : : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr));
205 0 : }
206 :
207 : /*
208 : * Some of the undocumented AMD64 MSRs need a 'passcode' to access.
209 : *
210 : * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c
211 : */
212 :
213 : #define OPTERON_MSR_PASSCODE 0x9c5a203a
214 :
215 : static __inline u_int64_t
216 0 : rdmsr_locked(u_int msr, u_int code)
217 : {
218 : uint32_t hi, lo;
219 0 : __asm volatile("rdmsr"
220 : : "=d" (hi), "=a" (lo)
221 : : "c" (msr), "D" (code));
222 0 : return (((uint64_t)hi << 32) | (uint64_t) lo);
223 : }
224 :
225 : static __inline void
226 0 : wrmsr_locked(u_int msr, u_int code, u_int64_t newval)
227 : {
228 0 : __asm volatile("wrmsr" :
229 0 : : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr), "D" (code));
230 0 : }
231 :
232 : static __inline void
233 0 : wbinvd(void)
234 : {
235 0 : __asm volatile("wbinvd");
236 0 : }
237 :
238 : static __inline void
239 0 : clflush(u_int64_t addr)
240 : {
241 0 : __asm volatile("clflush %0" : "+m" (*(volatile char *)addr));
242 0 : }
243 :
244 : static __inline void
245 0 : mfence(void)
246 : {
247 0 : __asm volatile("mfence" : : : "memory");
248 0 : }
249 :
250 : static __inline u_int64_t
251 0 : rdtsc(void)
252 : {
253 : uint32_t hi, lo;
254 :
255 0 : __asm volatile("rdtsc" : "=d" (hi), "=a" (lo));
256 0 : return (((uint64_t)hi << 32) | (uint64_t) lo);
257 : }
258 :
259 : static __inline u_int64_t
260 : rdpmc(u_int pmc)
261 : {
262 : uint32_t hi, lo;
263 :
264 : __asm volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc));
265 : return (((uint64_t)hi << 32) | (uint64_t) lo);
266 : }
267 :
268 : static __inline void
269 0 : monitor(const volatile void *addr, u_long extensions, u_int hints)
270 : {
271 :
272 0 : __asm volatile("monitor"
273 : : : "a" (addr), "c" (extensions), "d" (hints));
274 0 : }
275 :
276 : static __inline void
277 0 : mwait(u_long extensions, u_int hints)
278 : {
279 :
280 0 : __asm volatile(
281 : " mwait ;"
282 : " mov $8,%%rcx ;"
283 : " .align 16,0x90 ;"
284 : "3: call 5f ;"
285 : "4: pause ;"
286 : " lfence ;"
287 : " call 4b ;"
288 : " .align 16,0xcc ;"
289 : "5: call 7f ;"
290 : "6: pause ;"
291 : " lfence ;"
292 : " call 6b ;"
293 : " .align 16,0xcc ;"
294 : "7: loop 3b ;"
295 : " add $(16*8),%%rsp"
296 : : "+c" (extensions) : "a" (hints));
297 0 : }
298 :
299 : static __inline void
300 0 : xsetbv(uint32_t reg, uint64_t mask)
301 : {
302 : uint32_t lo, hi;
303 :
304 0 : lo = mask;
305 0 : hi = mask >> 32;
306 0 : __asm volatile("xsetbv" :: "c" (reg), "a" (lo), "d" (hi) : "memory");
307 0 : }
308 :
309 : static __inline uint64_t
310 0 : xgetbv(uint32_t reg)
311 : {
312 : uint32_t lo, hi;
313 :
314 0 : __asm volatile("xgetbv" : "=a" (lo), "=d" (hi) : "c" (reg));
315 :
316 0 : return (((uint64_t)hi << 32) | (uint64_t)lo);
317 : }
318 :
319 : static __inline void
320 0 : stgi(void)
321 : {
322 0 : __asm volatile("stgi");
323 0 : }
324 :
325 : static __inline void
326 0 : clgi(void)
327 : {
328 0 : __asm volatile("clgi");
329 0 : }
330 :
331 : /* Break into DDB. */
332 : static __inline void
333 0 : breakpoint(void)
334 : {
335 0 : __asm volatile("int $3");
336 0 : }
337 :
338 : void amd64_errata(struct cpu_info *);
339 : void cpu_ucode_setup(void);
340 : void cpu_ucode_apply(struct cpu_info *);
341 :
342 : struct cpu_info_full;
343 : void cpu_enter_pages(struct cpu_info_full *);
344 :
345 : #endif /* _KERNEL */
346 :
347 : #endif /* !_MACHINE_CPUFUNC_H_ */
|