1/* $OpenBSD: cpufunc.h,v 1.34 2025/06/20 14:06:34 sf Exp $ */
2/* $NetBSD: cpufunc.h,v 1.8 1994/10/27 04:15:59 cgd Exp $ */
3
4/*
5 * Copyright (c) 1993 Charles Hannum.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles Hannum.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#ifndef _MACHINE_CPUFUNC_H_
35#define _MACHINE_CPUFUNC_H_
36
37#ifdef _KERNEL
38
39/*
40 * Functions to provide access to i386-specific instructions.
41 */
42
43#include <sys/types.h>
44
45#include <machine/specialreg.h>
46
47static __inline void invlpg(u_int);
48static __inline void lidt(void *);
49static __inline void lldt(u_short);
50static __inline void ltr(u_short);
51static __inline void lcr0(u_int);
52static __inline u_int rcr0(void);
53static __inline u_int rcr2(void);
54static __inline void lcr3(u_int);
55static __inline u_int rcr3(void);
56static __inline void lcr4(u_int);
57static __inline u_int rcr4(void);
58static __inline void tlbflush(void);
59static __inline u_int read_eflags(void);
60static __inline void write_eflags(u_int);
61static __inline void wbinvd(void);
62static __inline void clflush(u_int32_t addr);
63static __inline void mfence(void);
64static __inline void wrmsr(u_int, u_int64_t);
65static __inline u_int64_t rdmsr(u_int);
66static __inline void breakpoint(void);
67
68static __inline void
69invlpg(u_int addr)
70{
71 __asm volatile("invlpg (%0)" : : "r" (addr) : "memory");
72}
73
74static __inline void
75lidt(void *p)
76{
77 __asm volatile("lidt (%0)" : : "r" (p) : "memory");
78}
79
80static __inline void
81lldt(u_short sel)
82{
83 __asm volatile("lldt %0" : : "r" (sel));
84}
85
86static __inline void
87ltr(u_short sel)
88{
89 __asm volatile("ltr %0" : : "r" (sel));
90}
91
92static __inline void
93lcr0(u_int val)
94{
95 __asm volatile("movl %0,%%cr0" : : "r" (val));
96}
97
98static __inline u_int
99rcr0(void)
100{
101 u_int val;
102 __asm volatile("movl %%cr0,%0" : "=r" (val));
103 return val;
104}
105
106static __inline u_int
107rcr2(void)
108{
109 u_int val;
110 __asm volatile("movl %%cr2,%0" : "=r" (val));
111 return val;
112}
113
114static __inline void
115lcr3(u_int val)
116{
117 __asm volatile("movl %0,%%cr3" : : "r" (val));
118}
119
120static __inline u_int
121rcr3(void)
122{
123 u_int val;
124 __asm volatile("movl %%cr3,%0" : "=r" (val));
125 return val;
126}
127
128static __inline void
129lcr4(u_int val)
130{
131 __asm volatile("movl %0,%%cr4" : : "r" (val));
132}
133
134static __inline u_int
135rcr4(void)
136{
137 u_int val;
138 __asm volatile("movl %%cr4,%0" : "=r" (val));
139 return val;
140}
141
142static __inline void
143tlbflush(void)
144{
145 u_int val;
146 __asm volatile("movl %%cr3,%0" : "=r" (val));
147 __asm volatile("movl %0,%%cr3" : : "r" (val));
148}
149
150#ifdef notyet
151void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl);
152#endif
153
154
155/* XXXX ought to be in psl.h with spl() functions */
156
157static __inline u_int
158read_eflags(void)
159{
160 u_int ef;
161
162 __asm volatile("pushfl; popl %0" : "=r" (ef));
163 return (ef);
164}
165
166static __inline void
167write_eflags(u_int ef)
168{
169 __asm volatile("pushl %0; popfl" : : "r" (ef));
170}
171
172static inline void
173intr_enable(void)
174{
175 __asm volatile("sti");
176}
177
178static inline u_long
179intr_disable(void)
180{
181 u_long ef;
182
183 ef = read_eflags();
184 __asm volatile("cli");
185 return (ef);
186}
187
188static inline void
189intr_restore(u_long ef)
190{
191 write_eflags(ef);
192}
193
194static __inline void
195wbinvd(void)
196{
197 __asm volatile("wbinvd" : : : "memory");
198}
199
200#ifdef MULTIPROCESSOR
201int wbinvd_on_all_cpus(void);
202#else
203static inline int
204wbinvd_on_all_cpus(void)
205{
206 wbinvd();
207 return 0;
208}
209#endif
210
211static __inline void
212clflush(u_int32_t addr)
213{
214 __asm volatile("clflush %0" : "+m" (*(volatile char *)addr));
215}
216
217static __inline void
218mfence(void)
219{
220 __asm volatile("mfence" : : : "memory");
221}
222
223static __inline u_int64_t
224rdtsc(void)
225{
226 uint64_t tsc;
227
228 __asm volatile("rdtsc" : "=A" (tsc));
229 return (tsc);
230}
231
232static inline uint64_t
233rdtsc_lfence(void)
234{
235 uint64_t tsc;
236
237 __asm volatile("lfence; rdtsc" : "=A" (tsc));
238 return tsc;
239}
240
241static __inline void
242wrmsr(u_int msr, u_int64_t newval)
243{
244 __asm volatile("wrmsr" : : "A" (newval), "c" (msr));
245}
246
247static __inline u_int64_t
248rdmsr(u_int msr)
249{
250 u_int64_t rv;
251
252 __asm volatile("rdmsr" : "=A" (rv) : "c" (msr));
253 return (rv);
254}
255
256static __inline void
257monitor(const volatile void *addr, u_long extensions, u_int hints)
258{
259 __asm volatile("monitor"
260 : : "a" (addr), "c" (extensions), "d" (hints));
261}
262
263static __inline void
264mwait(u_long extensions, u_int hints)
265{
266 __asm volatile("mwait" : : "a" (hints), "c" (extensions));
267}
268
269/*
270 * Some of the undocumented AMD64 MSRs need a 'passcode' to access.
271 *
272 * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c
273 */
274
275#define OPTERON_MSR_PASSCODE 0x9c5a203a
276
277static __inline u_int64_t
278rdmsr_locked(u_int msr, u_int code)
279{
280 uint64_t rv;
281 __asm volatile("rdmsr"
282 : "=A" (rv)
283 : "c" (msr), "D" (code));
284 return (rv);
285}
286
287static __inline void
288wrmsr_locked(u_int msr, u_int code, u_int64_t newval)
289{
290 __asm volatile("wrmsr"
291 :
292 : "A" (newval), "c" (msr), "D" (code));
293}
294
295/* Break into DDB. */
296static __inline void
297breakpoint(void)
298{
299 __asm volatile("int $3");
300}
301
302void amd64_errata(struct cpu_info *);
303void cpu_ucode_setup(void);
304void cpu_ucode_apply(struct cpu_info *);
305
306struct cpu_info_full;
307void cpu_enter_pages(struct cpu_info_full *);
308
309#endif /* _KERNEL */
310#endif /* !_MACHINE_CPUFUNC_H_ */