Annotation of sys/arch/i386/include/cpufunc.h, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cpufunc.h,v 1.13 2007/02/17 17:38:37 tom 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 _I386_CPUFUNC_H_
35: #define _I386_CPUFUNC_H_
36:
37: #ifdef _KERNEL
38:
39: /*
40: * Functions to provide access to i386-specific instructions.
41: */
42:
43: #include <sys/cdefs.h>
44: #include <sys/types.h>
45:
46: #include <machine/specialreg.h>
47:
48: static __inline void invlpg(u_int);
49: static __inline void lidt(void *);
50: static __inline void lldt(u_short);
51: static __inline void ltr(u_short);
52: static __inline void lcr0(u_int);
53: static __inline u_int rcr0(void);
54: static __inline u_int rcr2(void);
55: static __inline void lcr3(u_int);
56: static __inline u_int rcr3(void);
57: static __inline void lcr4(u_int);
58: static __inline u_int rcr4(void);
59: static __inline void tlbflush(void);
60: static __inline void tlbflushg(void);
61: static __inline void disable_intr(void);
62: static __inline void enable_intr(void);
63: static __inline u_int read_eflags(void);
64: static __inline void write_eflags(u_int);
65: static __inline void wbinvd(void);
66: static __inline void wrmsr(u_int, u_int64_t);
67: static __inline u_int64_t rdmsr(u_int);
68: static __inline void breakpoint(void);
69:
70: static __inline void
71: invlpg(u_int addr)
72: {
73: __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
74: }
75:
76: static __inline void
77: lidt(void *p)
78: {
79: __asm __volatile("lidt (%0)" : : "r" (p));
80: }
81:
82: static __inline void
83: lldt(u_short sel)
84: {
85: __asm __volatile("lldt %0" : : "r" (sel));
86: }
87:
88: static __inline void
89: ltr(u_short sel)
90: {
91: __asm __volatile("ltr %0" : : "r" (sel));
92: }
93:
94: static __inline void
95: lcr0(u_int val)
96: {
97: __asm __volatile("movl %0,%%cr0" : : "r" (val));
98: }
99:
100: static __inline u_int
101: rcr0(void)
102: {
103: u_int val;
104: __asm __volatile("movl %%cr0,%0" : "=r" (val));
105: return val;
106: }
107:
108: static __inline u_int
109: rcr2(void)
110: {
111: u_int val;
112: __asm __volatile("movl %%cr2,%0" : "=r" (val));
113: return val;
114: }
115:
116: static __inline void
117: lcr3(u_int val)
118: {
119: __asm __volatile("movl %0,%%cr3" : : "r" (val));
120: }
121:
122: static __inline u_int
123: rcr3(void)
124: {
125: u_int val;
126: __asm __volatile("movl %%cr3,%0" : "=r" (val));
127: return val;
128: }
129:
130: static __inline void
131: lcr4(u_int val)
132: {
133: __asm __volatile("movl %0,%%cr4" : : "r" (val));
134: }
135:
136: static __inline u_int
137: rcr4(void)
138: {
139: u_int val;
140: __asm __volatile("movl %%cr4,%0" : "=r" (val));
141: return val;
142: }
143:
144: static __inline void
145: tlbflush(void)
146: {
147: u_int val;
148: __asm __volatile("movl %%cr3,%0" : "=r" (val));
149: __asm __volatile("movl %0,%%cr3" : : "r" (val));
150: }
151:
152: static __inline void
153: tlbflushg(void)
154: {
155: /*
156: * Big hammer: flush all TLB entries, including ones from PTE's
157: * with the G bit set. This should only be necessary if TLB
158: * shootdown falls far behind.
159: *
160: * Intel Architecture Software Developer's Manual, Volume 3,
161: * System Programming, section 9.10, "Invalidating the
162: * Translation Lookaside Buffers (TLBS)":
163: * "The following operations invalidate all TLB entries, irrespective
164: * of the setting of the G flag:
165: * ...
166: * "(P6 family processors only): Writing to control register CR4 to
167: * modify the PSE, PGE, or PAE flag."
168: *
169: * (the alternatives not quoted above are not an option here.)
170: *
171: * If PGE is not in use, we reload CR3 for the benefit of
172: * pre-P6-family processors.
173: */
174:
175: #if defined(I686_CPU)
176: if (cpu_feature & CPUID_PGE) {
177: u_int cr4 = rcr4();
178: lcr4(cr4 & ~CR4_PGE);
179: lcr4(cr4);
180: } else
181: #endif
182: tlbflush();
183: }
184:
185: #ifdef notyet
186: void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl);
187: #endif
188:
189:
190: /* XXXX ought to be in psl.h with spl() functions */
191:
192: static __inline void
193: disable_intr(void)
194: {
195: __asm __volatile("cli");
196: }
197:
198: static __inline void
199: enable_intr(void)
200: {
201: __asm __volatile("sti");
202: }
203:
204: static __inline u_int
205: read_eflags(void)
206: {
207: u_int ef;
208:
209: __asm __volatile("pushfl; popl %0" : "=r" (ef));
210: return (ef);
211: }
212:
213: static __inline void
214: write_eflags(u_int ef)
215: {
216: __asm __volatile("pushl %0; popfl" : : "r" (ef));
217: }
218:
219: static __inline void
220: wbinvd(void)
221: {
222: __asm __volatile("wbinvd");
223: }
224:
225:
226: static __inline void
227: wrmsr(u_int msr, u_int64_t newval)
228: {
229: __asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
230: }
231:
232: static __inline u_int64_t
233: rdmsr(u_int msr)
234: {
235: u_int64_t rv;
236:
237: __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
238: return (rv);
239: }
240:
241: /*
242: * Some of the undocumented AMD64 MSRs need a 'passcode' to access.
243: *
244: * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c
245: */
246:
247: #define OPTERON_MSR_PASSCODE 0x9c5a203a
248:
249: static __inline u_int64_t
250: rdmsr_locked(u_int msr, u_int code)
251: {
252: uint64_t rv;
253: __asm volatile("rdmsr"
254: : "=A" (rv)
255: : "c" (msr), "D" (code));
256: return (rv);
257: }
258:
259: static __inline void
260: wrmsr_locked(u_int msr, u_int code, u_int64_t newval)
261: {
262: __asm volatile("wrmsr"
263: :
264: : "A" (newval), "c" (msr), "D" (code));
265: }
266:
267: /* Break into DDB/KGDB. */
268: static __inline void
269: breakpoint(void)
270: {
271: __asm __volatile("int $3");
272: }
273:
274: #ifdef I686_CPU
275: void amd64_errata(struct cpu_info *);
276: #endif
277:
278: #endif /* _KERNEL */
279: #endif /* !_I386_CPUFUNC_H_ */
CVSweb