xref: /openbsd-src/sys/arch/amd64/include/cpufunc.h (revision 305d28e7ca41fd4bba643076583b35933bc0756c)
1*305d28e7Sbluhm /*	$OpenBSD: cpufunc.h,v 1.43 2024/11/08 12:08:22 bluhm Exp $	*/
2f5df1827Smickey /*	$NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $	*/
3f5df1827Smickey 
4f5df1827Smickey /*-
5f5df1827Smickey  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6f5df1827Smickey  * All rights reserved.
7f5df1827Smickey  *
8f5df1827Smickey  * This code is derived from software contributed to The NetBSD Foundation
9f5df1827Smickey  * by Charles M. Hannum.
10f5df1827Smickey  *
11f5df1827Smickey  * Redistribution and use in source and binary forms, with or without
12f5df1827Smickey  * modification, are permitted provided that the following conditions
13f5df1827Smickey  * are met:
14f5df1827Smickey  * 1. Redistributions of source code must retain the above copyright
15f5df1827Smickey  *    notice, this list of conditions and the following disclaimer.
16f5df1827Smickey  * 2. Redistributions in binary form must reproduce the above copyright
17f5df1827Smickey  *    notice, this list of conditions and the following disclaimer in the
18f5df1827Smickey  *    documentation and/or other materials provided with the distribution.
19f5df1827Smickey  *
20f5df1827Smickey  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21f5df1827Smickey  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22f5df1827Smickey  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23f5df1827Smickey  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24f5df1827Smickey  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25f5df1827Smickey  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26f5df1827Smickey  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27f5df1827Smickey  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28f5df1827Smickey  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29f5df1827Smickey  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30f5df1827Smickey  * POSSIBILITY OF SUCH DAMAGE.
31f5df1827Smickey  */
32f5df1827Smickey 
332fa72412Spirofti #ifndef _MACHINE_CPUFUNC_H_
342fa72412Spirofti #define	_MACHINE_CPUFUNC_H_
35f5df1827Smickey 
36f5df1827Smickey /*
37f5df1827Smickey  * Functions to provide access to i386-specific instructions.
38f5df1827Smickey  */
39f5df1827Smickey 
40f5df1827Smickey #include <sys/types.h>
41f5df1827Smickey 
42f5df1827Smickey #include <machine/specialreg.h>
43f5df1827Smickey 
44f9b85086Sderaadt #if defined(_KERNEL) && !defined (_STANDALONE)
45f5df1827Smickey 
46f5df1827Smickey static __inline void
47f5df1827Smickey invlpg(u_int64_t addr)
48f5df1827Smickey {
492df76cc2Sguenther         __asm volatile("invlpg (%0)" : : "r" (addr) : "memory");
50f5df1827Smickey }
51f5df1827Smickey 
52f5df1827Smickey static __inline void
535845e8e5Smlarkin sidt(void *p)
545845e8e5Smlarkin {
555845e8e5Smlarkin 	__asm volatile("sidt (%0)" : : "r" (p) : "memory");
565845e8e5Smlarkin }
575845e8e5Smlarkin 
585845e8e5Smlarkin static __inline void
59f5df1827Smickey lidt(void *p)
60f5df1827Smickey {
612df76cc2Sguenther 	__asm volatile("lidt (%0)" : : "r" (p) : "memory");
62f5df1827Smickey }
63f5df1827Smickey 
64f5df1827Smickey static __inline void
655845e8e5Smlarkin sgdt(void *p)
665845e8e5Smlarkin {
675845e8e5Smlarkin 	__asm volatile("sgdt (%0)" : : "r" (p) : "memory");
685845e8e5Smlarkin }
695845e8e5Smlarkin 
705845e8e5Smlarkin static __inline void
715845e8e5Smlarkin bare_lgdt(struct region_descriptor *p)
725845e8e5Smlarkin {
735845e8e5Smlarkin 	__asm volatile("lgdt (%0)" : : "r" (p) : "memory");
745845e8e5Smlarkin }
755845e8e5Smlarkin 
765845e8e5Smlarkin static __inline void
775845e8e5Smlarkin sldt(u_short *sel)
785845e8e5Smlarkin {
795845e8e5Smlarkin 	__asm volatile("sldt (%0)" : : "r" (sel) : "memory");
805845e8e5Smlarkin }
815845e8e5Smlarkin 
825845e8e5Smlarkin static __inline void
83f5df1827Smickey lldt(u_short sel)
84f5df1827Smickey {
852df76cc2Sguenther 	__asm volatile("lldt %0" : : "r" (sel));
86f5df1827Smickey }
87f5df1827Smickey 
88f5df1827Smickey static __inline void
89f5df1827Smickey ltr(u_short sel)
90f5df1827Smickey {
912df76cc2Sguenther 	__asm volatile("ltr %0" : : "r" (sel));
92f5df1827Smickey }
93f5df1827Smickey 
94f5df1827Smickey static __inline void
95f5df1827Smickey lcr8(u_int val)
96f5df1827Smickey {
97f5df1827Smickey 	u_int64_t val64 = val;
982df76cc2Sguenther 	__asm volatile("movq %0,%%cr8" : : "r" (val64));
99f5df1827Smickey }
100f5df1827Smickey 
101f5df1827Smickey /*
102f5df1827Smickey  * Upper 32 bits are reserved anyway, so just keep this 32bits.
103f5df1827Smickey  */
104f5df1827Smickey static __inline void
105f5df1827Smickey lcr0(u_int val)
106f5df1827Smickey {
107f5df1827Smickey 	u_int64_t val64 = val;
1082df76cc2Sguenther 	__asm volatile("movq %0,%%cr0" : : "r" (val64));
109f5df1827Smickey }
110f5df1827Smickey 
111f5df1827Smickey static __inline u_int
112f5df1827Smickey rcr0(void)
113f5df1827Smickey {
114f5df1827Smickey 	u_int64_t val64;
115f5df1827Smickey 	u_int val;
1162df76cc2Sguenther 	__asm volatile("movq %%cr0,%0" : "=r" (val64));
117f5df1827Smickey 	val = val64;
118f5df1827Smickey 	return val;
119f5df1827Smickey }
120f5df1827Smickey 
121f5df1827Smickey static __inline u_int64_t
122f5df1827Smickey rcr2(void)
123f5df1827Smickey {
124f5df1827Smickey 	u_int64_t val;
1252df76cc2Sguenther 	__asm volatile("movq %%cr2,%0" : "=r" (val));
126f5df1827Smickey 	return val;
127f5df1827Smickey }
128f5df1827Smickey 
129f5df1827Smickey static __inline void
130f5df1827Smickey lcr3(u_int64_t val)
131f5df1827Smickey {
1322df76cc2Sguenther 	__asm volatile("movq %0,%%cr3" : : "r" (val));
133f5df1827Smickey }
134f5df1827Smickey 
135f5df1827Smickey static __inline u_int64_t
136f5df1827Smickey rcr3(void)
137f5df1827Smickey {
138f5df1827Smickey 	u_int64_t val;
1392df76cc2Sguenther 	__asm volatile("movq %%cr3,%0" : "=r" (val));
140f5df1827Smickey 	return val;
141f5df1827Smickey }
142f5df1827Smickey 
143f5df1827Smickey /*
144f5df1827Smickey  * Same as for cr0. Don't touch upper 32 bits.
145f5df1827Smickey  */
146f5df1827Smickey static __inline void
147f5df1827Smickey lcr4(u_int val)
148f5df1827Smickey {
149f5df1827Smickey 	u_int64_t val64 = val;
150f5df1827Smickey 
1512df76cc2Sguenther 	__asm volatile("movq %0,%%cr4" : : "r" (val64));
152f5df1827Smickey }
153f5df1827Smickey 
154f5df1827Smickey static __inline u_int
155f5df1827Smickey rcr4(void)
156f5df1827Smickey {
157f5df1827Smickey 	u_int64_t val64;
1582df76cc2Sguenther 	__asm volatile("movq %%cr4,%0" : "=r" (val64));
159c61a50a0Sderaadt 	return (u_int) val64;
160f5df1827Smickey }
161f5df1827Smickey 
162f5df1827Smickey static __inline void
163f5df1827Smickey tlbflush(void)
164f5df1827Smickey {
165f5df1827Smickey 	u_int64_t val;
1662df76cc2Sguenther 	__asm volatile("movq %%cr3,%0" : "=r" (val));
1672df76cc2Sguenther 	__asm volatile("movq %0,%%cr3" : : "r" (val));
168f5df1827Smickey }
169f5df1827Smickey 
170f95e373fSguenther static inline void
171f95e373fSguenther invpcid(uint64_t type, paddr_t pcid, paddr_t addr)
172f95e373fSguenther {
173f95e373fSguenther 	uint64_t desc[2] = { pcid, addr };
174f95e373fSguenther 	asm volatile("invpcid %0,%1" : : "m"(desc[0]), "r"(type));
175f95e373fSguenther }
176f95e373fSguenther #define INVPCID_ADDR		0
177f95e373fSguenther #define INVPCID_PCID		1
178f95e373fSguenther #define INVPCID_ALL		2
179f95e373fSguenther #define INVPCID_NON_GLOBAL	3
180f95e373fSguenther 
181f5df1827Smickey #ifdef notyet
182f5df1827Smickey void	setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl);
183f5df1827Smickey #endif
184f5df1827Smickey 
185f5df1827Smickey 
186f5df1827Smickey /* XXXX ought to be in psl.h with spl() functions */
187f5df1827Smickey 
188f5df1827Smickey static __inline u_long
189f5df1827Smickey read_rflags(void)
190f5df1827Smickey {
191f5df1827Smickey 	u_long	ef;
192f5df1827Smickey 
1932df76cc2Sguenther 	__asm volatile("pushfq; popq %0" : "=r" (ef));
194f5df1827Smickey 	return (ef);
195f5df1827Smickey }
196f5df1827Smickey 
197f5df1827Smickey static __inline void
198f5df1827Smickey write_rflags(u_long ef)
199f5df1827Smickey {
2002df76cc2Sguenther 	__asm volatile("pushq %0; popfq" : : "r" (ef));
201f5df1827Smickey }
202f5df1827Smickey 
20382ffe153Skettenis static __inline void
20482ffe153Skettenis intr_enable(void)
20582ffe153Skettenis {
2060db9c031Skettenis 	__asm volatile("sti");
20782ffe153Skettenis }
20882ffe153Skettenis 
2096950c8e2Smpi static __inline u_long
2106950c8e2Smpi intr_disable(void)
2116950c8e2Smpi {
2126950c8e2Smpi 	u_long ef;
2136950c8e2Smpi 
2146950c8e2Smpi 	ef = read_rflags();
2150db9c031Skettenis 	__asm volatile("cli");
2166950c8e2Smpi 	return (ef);
2176950c8e2Smpi }
2186950c8e2Smpi 
2196950c8e2Smpi static __inline void
2206950c8e2Smpi intr_restore(u_long ef)
2216950c8e2Smpi {
2226950c8e2Smpi 	write_rflags(ef);
2236950c8e2Smpi }
2246950c8e2Smpi 
225f5df1827Smickey static __inline u_int64_t
226f5df1827Smickey rdmsr(u_int msr)
227f5df1827Smickey {
228f5df1827Smickey 	uint32_t hi, lo;
2292df76cc2Sguenther 	__asm volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr));
230f5df1827Smickey 	return (((uint64_t)hi << 32) | (uint64_t) lo);
231f5df1827Smickey }
232f5df1827Smickey 
233e9e0c464Sderaadt static __inline int
234e9e0c464Sderaadt rdpkru(u_int ecx)
235e9e0c464Sderaadt {
236e9e0c464Sderaadt 	uint32_t edx, pkru;
237e9e0c464Sderaadt 	asm volatile("rdpkru " : "=a" (pkru), "=d" (edx) : "c" (ecx));
238e9e0c464Sderaadt 	return pkru;
239e9e0c464Sderaadt }
240e9e0c464Sderaadt 
241f5df1827Smickey static __inline void
2427d13b9d9Sguenther wrpkru(u_int ecx, uint32_t pkru)
24389e94d10Sdv {
2447d13b9d9Sguenther 	uint32_t edx = 0;
2457d13b9d9Sguenther 	asm volatile("wrpkru" : : "a" (pkru), "c" (ecx), "d" (edx));
24689e94d10Sdv }
24789e94d10Sdv 
24889e94d10Sdv static __inline void
249f5df1827Smickey wrmsr(u_int msr, u_int64_t newval)
250f5df1827Smickey {
2512df76cc2Sguenther 	__asm volatile("wrmsr" :
252f5df1827Smickey 	    : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr));
253f5df1827Smickey }
254f5df1827Smickey 
255d279ab14Stom /*
256d279ab14Stom  * Some of the undocumented AMD64 MSRs need a 'passcode' to access.
257d279ab14Stom  *
258d279ab14Stom  * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c
259d279ab14Stom  */
260d279ab14Stom 
261d279ab14Stom #define	OPTERON_MSR_PASSCODE	0x9c5a203a
262d279ab14Stom 
263d279ab14Stom static __inline u_int64_t
264d279ab14Stom rdmsr_locked(u_int msr, u_int code)
265d279ab14Stom {
266e4dc6a9fSderaadt 	uint32_t hi, lo;
2672df76cc2Sguenther 	__asm volatile("rdmsr"
268e4dc6a9fSderaadt 	    : "=d" (hi), "=a" (lo)
269d279ab14Stom 	    : "c" (msr), "D" (code));
270e4dc6a9fSderaadt 	return (((uint64_t)hi << 32) | (uint64_t) lo);
271d279ab14Stom }
272d279ab14Stom 
273d279ab14Stom static __inline void
274d279ab14Stom wrmsr_locked(u_int msr, u_int code, u_int64_t newval)
275d279ab14Stom {
2762df76cc2Sguenther 	__asm volatile("wrmsr" :
277e4dc6a9fSderaadt 	    : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr), "D" (code));
278d279ab14Stom }
279d279ab14Stom 
280f5df1827Smickey static __inline void
281f5df1827Smickey wbinvd(void)
282f5df1827Smickey {
283728dd5ccSbluhm 	__asm volatile("wbinvd" : : : "memory");
284f5df1827Smickey }
285f5df1827Smickey 
2863fb0e55cSjsg #ifdef MULTIPROCESSOR
2873fb0e55cSjsg int wbinvd_on_all_cpus(void);
288daa3eda4Sbluhm void wbinvd_on_all_cpus_acked(void);
2893fb0e55cSjsg #else
2903fb0e55cSjsg static inline int
2913fb0e55cSjsg wbinvd_on_all_cpus(void)
2923fb0e55cSjsg {
2933fb0e55cSjsg 	wbinvd();
2943fb0e55cSjsg 	return 0;
2953fb0e55cSjsg }
296*305d28e7Sbluhm 
297*305d28e7Sbluhm static inline int
298*305d28e7Sbluhm wbinvd_on_all_cpus_acked(void)
299*305d28e7Sbluhm {
300*305d28e7Sbluhm 	wbinvd();
301*305d28e7Sbluhm 	return 0;
302*305d28e7Sbluhm }
303*305d28e7Sbluhm #endif /* MULTIPROCESSOR */
3043fb0e55cSjsg 
305432a1d93Soga static __inline void
306432a1d93Soga clflush(u_int64_t addr)
307432a1d93Soga {
3082df76cc2Sguenther 	__asm volatile("clflush %0" : "+m" (*(volatile char *)addr));
309432a1d93Soga }
310432a1d93Soga 
311432a1d93Soga static __inline void
312432a1d93Soga mfence(void)
313432a1d93Soga {
3142df76cc2Sguenther 	__asm volatile("mfence" : : : "memory");
315432a1d93Soga }
316432a1d93Soga 
317f5df1827Smickey static __inline u_int64_t
318f5df1827Smickey rdtsc(void)
319f5df1827Smickey {
320f5df1827Smickey 	uint32_t hi, lo;
321f5df1827Smickey 
3222df76cc2Sguenther 	__asm volatile("rdtsc" : "=d" (hi), "=a" (lo));
323f5df1827Smickey 	return (((uint64_t)hi << 32) | (uint64_t) lo);
324f5df1827Smickey }
325f5df1827Smickey 
326f5df1827Smickey static __inline u_int64_t
327d55ef580Srobert rdtscp(void)
328d55ef580Srobert {
329d55ef580Srobert 	uint32_t hi, lo;
330d55ef580Srobert 
331d55ef580Srobert 	__asm volatile("rdtscp" : "=d" (hi), "=a" (lo) : : "ecx");
332d55ef580Srobert 	return (((uint64_t)hi << 32) | (uint64_t) lo);
333d55ef580Srobert }
334d55ef580Srobert 
335d55ef580Srobert static __inline u_int64_t
3366112a61fSkettenis rdtsc_lfence(void)
3376112a61fSkettenis {
3386112a61fSkettenis 	uint32_t hi, lo;
3396112a61fSkettenis 
3406112a61fSkettenis 	__asm volatile("lfence; rdtsc" : "=d" (hi), "=a" (lo));
3416112a61fSkettenis 	return (((uint64_t)hi << 32) | (uint64_t) lo);
3426112a61fSkettenis }
3436112a61fSkettenis 
3446112a61fSkettenis static __inline u_int64_t
345f5df1827Smickey rdpmc(u_int pmc)
346f5df1827Smickey {
347f5df1827Smickey 	uint32_t hi, lo;
348f5df1827Smickey 
3492df76cc2Sguenther 	__asm volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc));
350f5df1827Smickey 	return (((uint64_t)hi << 32) | (uint64_t) lo);
351f5df1827Smickey }
352f5df1827Smickey 
3536e1e92d4Sguenther static __inline void
3546e1e92d4Sguenther monitor(const volatile void *addr, u_long extensions, u_int hints)
3556e1e92d4Sguenther {
3566e1e92d4Sguenther 
3572df76cc2Sguenther 	__asm volatile("monitor"
3586e1e92d4Sguenther 	    : : "a" (addr), "c" (extensions), "d" (hints));
3596e1e92d4Sguenther }
3606e1e92d4Sguenther 
3616e1e92d4Sguenther static __inline void
3626e1e92d4Sguenther mwait(u_long extensions, u_int hints)
3636e1e92d4Sguenther {
3646e1e92d4Sguenther 
365a4858df8Sguenther 	__asm volatile(
366a4858df8Sguenther 		"	mwait			;"
367a4858df8Sguenther 		"	mov	$8,%%rcx	;"
368a4858df8Sguenther 		"	.align	16,0x90		;"
369a4858df8Sguenther 		"3:	call	5f		;"
370a4858df8Sguenther 		"4:	pause			;"
371a1fa3538Sguenther 		"	lfence			;"
372a4858df8Sguenther 		"	call	4b		;"
373a4858df8Sguenther 		"	.align	16,0xcc		;"
374a4858df8Sguenther 		"5:	call	7f		;"
375a4858df8Sguenther 		"6:	pause			;"
376a1fa3538Sguenther 		"	lfence			;"
377a4858df8Sguenther 		"	call	6b		;"
378a4858df8Sguenther 		"	.align	16,0xcc		;"
379a4858df8Sguenther 		"7:	loop	3b		;"
380a4858df8Sguenther 		"	add	$(16*8),%%rsp"
3819d94673fSguenther 	    : "+c" (extensions) : "a" (hints));
3826e1e92d4Sguenther }
3836e1e92d4Sguenther 
384b03cf8e0Skettenis static __inline void
385b03cf8e0Skettenis xsetbv(uint32_t reg, uint64_t mask)
386b03cf8e0Skettenis {
387b03cf8e0Skettenis 	uint32_t lo, hi;
388b03cf8e0Skettenis 
389b03cf8e0Skettenis 	lo = mask;
390b03cf8e0Skettenis 	hi = mask >> 32;
391b03cf8e0Skettenis 	__asm volatile("xsetbv" :: "c" (reg), "a" (lo), "d" (hi) : "memory");
392b03cf8e0Skettenis }
393b03cf8e0Skettenis 
394c86bb406Smlarkin static __inline uint64_t
395c86bb406Smlarkin xgetbv(uint32_t reg)
396c86bb406Smlarkin {
397c86bb406Smlarkin 	uint32_t lo, hi;
398c86bb406Smlarkin 
399c86bb406Smlarkin 	__asm volatile("xgetbv" : "=a" (lo), "=d" (hi) : "c" (reg));
400c86bb406Smlarkin 
401c86bb406Smlarkin 	return (((uint64_t)hi << 32) | (uint64_t)lo);
402c86bb406Smlarkin }
403c86bb406Smlarkin 
404368e368bSmlarkin static __inline void
405368e368bSmlarkin stgi(void)
406368e368bSmlarkin {
407368e368bSmlarkin 	__asm volatile("stgi");
408368e368bSmlarkin }
409368e368bSmlarkin 
410368e368bSmlarkin static __inline void
411368e368bSmlarkin clgi(void)
412368e368bSmlarkin {
413368e368bSmlarkin 	__asm volatile("clgi");
414368e368bSmlarkin }
415368e368bSmlarkin 
416f4c36297Smpi /* Break into DDB. */
417f5df1827Smickey static __inline void
418f5df1827Smickey breakpoint(void)
419f5df1827Smickey {
4202df76cc2Sguenther 	__asm volatile("int $3");
421f5df1827Smickey }
422f5df1827Smickey 
423d279ab14Stom void amd64_errata(struct cpu_info *);
424b4ccf14aSpatrick void cpu_ucode_setup(void);
425448c3487Spatrick void cpu_ucode_apply(struct cpu_info *);
426d279ab14Stom 
427b767b017Sguenther struct cpu_info_full;
428b767b017Sguenther void cpu_enter_pages(struct cpu_info_full *);
429b767b017Sguenther 
4306f4c4614Smlarkin int rdmsr_safe(u_int msr, uint64_t *);
4316f4c4614Smlarkin 
432f5df1827Smickey #endif /* _KERNEL */
433f5df1827Smickey 
4342fa72412Spirofti #endif /* !_MACHINE_CPUFUNC_H_ */
435