cpufunc.h

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1998 The NetBSD Foundation, Inc.
00003  * All rights reserved.
00004  *
00005  * This code is derived from software contributed to The NetBSD Foundation
00006  * by Charles M. Hannum.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. All advertising materials mentioning features or use of this software
00017  *    must display the following acknowledgement:
00018  *        This product includes software developed by the NetBSD
00019  *        Foundation, Inc. and its contributors.
00020  * 4. Neither the name of The NetBSD Foundation nor the names of its
00021  *    contributors may be used to endorse or promote products derived
00022  *    from this software without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
00025  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00027  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
00028  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  * POSSIBILITY OF SUCH DAMAGE.
00035  */
00036 #ifndef __PROGRAM_CPROTO__
00037 
00038 #ifndef _I386_CPUFUNC_H_
00039 #define _I386_CPUFUNC_H_
00040 #include <sysinterf/types.h>
00041 #include <machdep/psl.h>
00042 
00043 /*
00044  * Some of these functions were borrowed from NetBSD
00045  */
00046 
00047 static __inline void 
00048 invlpg(u_int addr)
00049 { 
00050   __asm __volatile ("invlpg (%0)" : : "r" (addr) : "memory");
00051 }  
00052 
00053 static __inline void    
00054 lidt(void * base, unsigned int limit)
00055 {
00056   unsigned int  i[2];
00057         
00058   i[0] = limit<<16;
00059   i[1] = (unsigned int) base;
00060 
00061   /* lidt takes a memory location which has bits 0..15 as the limit
00062    * and 16..47 as the base of the IDT */
00063   __asm __volatile ("lidt (%0)": :"r" (((char *)i) + 2));
00064 }
00065 
00066 static __inline void
00067 lgdt(void * base, unsigned int limit)
00068 {
00069   unsigned int  i[2];
00070         
00071   i[0] = limit<<16;
00072   i[1] = (unsigned int) base;
00073 
00074   __asm __volatile ("lgdt (%0)": :"r" (((char *) i) + 2));
00075 }
00076 
00077 static __inline void
00078 lcall(u_int selector)
00079 {
00080   u_int sel[2];
00081 
00082   sel[0] = 0;
00083   sel[1] = selector;
00084 
00085   __asm __volatile ("lcall *%0": :"m" (*sel)); 
00086 }
00087 
00088 static __inline void
00089 lldt(u_short sel)
00090 {
00091   __asm __volatile ("lldt %0" : : "r" (sel));
00092 }
00093 
00094 static __inline void
00095 lcr0(u_int val)
00096 {
00097   __asm __volatile ("movl %0,%%cr0" : : "r" (val));
00098 }
00099 
00100 static __inline u_int
00101 rcr0(void)
00102 {
00103   u_int val;
00104   __asm __volatile ("movl %%cr0,%0" : "=r" (val));
00105   return val;
00106 }
00107 
00108 static __inline u_int
00109 rcr2(void)
00110 {
00111   u_int val;
00112   __asm __volatile ("movl %%cr2,%0" : "=r" (val));
00113   return val;
00114 }
00115 
00116 static __inline void
00117 lcr2(u_int val)
00118 {
00119   __asm __volatile ("movl %0,%%cr2" : : "r" (val));
00120 }
00121 
00122 
00123 static __inline void
00124 lcr3(u_int val)
00125 {
00126   __asm __volatile ("movl %0,%%cr3" : : "r" (val));
00127 }
00128 
00129 static __inline u_int
00130 rcr3(void)
00131 {
00132   u_int val;
00133   __asm __volatile ("movl %%cr3,%0" : "=r" (val));
00134   return val;
00135 }
00136 
00137 static __inline void
00138 lcr4(u_int val)
00139 {
00140   __asm __volatile ("movl %0,%%cr4" : : "r" (val));
00141 }
00142 
00143 static __inline u_int
00144 rcr4(void)
00145 {
00146   u_int val;
00147   __asm __volatile ("movl %%cr4,%0" : "=r" (val));
00148   return val;
00149 }
00150 
00151 static __inline void
00152 tlbflush(void)
00153 {
00154   u_int val;
00155   __asm __volatile ("movl %%cr3,%0" : "=r" (val));
00156   __asm __volatile ("movl %0,%%cr3" : : "r" (val));
00157 }
00158 
00159 static __inline void
00160 leax(u_int val)
00161 {
00162   __asm __volatile ("movl %0,%%eax" : : "r" (val));
00163 }
00164 
00165 static __inline void
00166 lebx(u_int val)
00167 {
00168   __asm __volatile ("movl %0,%%ebx" : : "r" (val));
00169 }
00170 
00171 static __inline void
00172 lecx(u_int val)
00173 {
00174   __asm __volatile ("movl %0,%%ecx" : : "r" (val));
00175 }
00176 
00177 static __inline u_int
00178 rebx(void)
00179 {
00180   u_int val;
00181   __asm __volatile ("movl %%ebx,%0" : "=r" (val));
00182   return val;
00183 }
00184 
00185 static __inline u_int
00186 recx(void)
00187 {
00188   u_int val;
00189   __asm __volatile ("movl %%ecx,%0" : "=r" (val));
00190   return val;
00191 }
00192 
00193 static __inline void
00194 ledx(u_int val)
00195 {
00196   __asm __volatile ("movl %0,%%edx" : : "r" (val));
00197 }
00198 
00199 static __inline void
00200 cpu_hang()
00201 {
00202   __asm __volatile ("cli;hlt");
00203 }
00204 
00205 static __inline void
00206 cpu_halt()
00207 {
00208   __asm __volatile ("hlt");
00209 }
00210 
00211 static __inline void
00212 yield()
00213 {
00214   __asm __volatile ("iret");
00215 }
00216 
00217 static __inline void
00218 disable_intr(void)
00219 {
00220   __asm __volatile ("cli");
00221 }
00222 
00223 static __inline void
00224 enable_intr(void)
00225 {
00226   __asm __volatile ("sti");
00227 }
00228 
00229 static __inline u_long
00230 read_eflags(void)
00231 {
00232   u_long        ef;
00233 
00234   __asm __volatile ("pushfl; popl %0" : "=r" (ef));
00235   return (ef);
00236 }
00237 
00242 static __inline int
00243 interruptible()
00244 {
00245   return (read_eflags() & PSL_I);
00246 }
00247 
00248 static __inline void
00249 write_eflags(u_long ef)
00250 {
00251   __asm __volatile ("pushl %0; popfl" : : "r" (ef));
00252 }
00253 
00254 static __inline u_int64_t
00255 rdmsr(u_int msr)
00256 {
00257   u_int64_t rv;
00258 
00259   __asm __volatile ("rdmsr" : "=A" (rv) : "c" (msr));
00260   return (rv);
00261 }
00262 
00263 static __inline void
00264 wrmsr(u_int msr, u_int64_t newval)
00265 {
00266   __asm __volatile ("wrmsr" : : "A" (newval), "c" (msr));
00267 }
00268 
00269 static __inline void
00270 wbinvd(void)
00271 {
00272   __asm __volatile ("wbinvd");
00273 }
00274 
00275 static __inline u_int64_t
00276 rdtsc(void)
00277 {
00278   u_int64_t rv;
00279 
00280   __asm __volatile ("rdtsc" : "=A" (rv));
00281   return (rv);
00282 }
00283 
00284 static __inline u_int64_t
00285 rdpmc(u_int pmc)
00286 {
00287   u_int64_t rv;
00288 
00289   __asm __volatile ("rdpmc" : "=A" (rv) : "c" (pmc));
00290   return (rv);
00291 }
00292 
00293 /*
00294  * xchg borrowed from linux 
00295  */
00296 #define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
00297 
00298 struct __xchg_dummy { unsigned long a[100]; };
00299 #define __xg(x) ((struct __xchg_dummy *)(x))
00300 
00301 /*
00302  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
00303  * Note 2: xchg has side effect, so that attribute volatile is necessary,
00304  * but generally the primitive is invalid, *ptr is output argument. --ANK
00305  */
00306 static __inline unsigned long 
00307 __xchg(unsigned long x, volatile void * ptr, int size)
00308 {
00309   switch (size) {
00310   case 1:
00311     __asm __volatile ("xchgb %b0,%1"
00312                       :"=q" (x)
00313                       :"m" (*__xg(ptr)), "0" (x)
00314                       :"memory");
00315     break;
00316   case 2:
00317     __asm __volatile ("xchgw %w0,%1"
00318                       :"=r" (x)
00319                       :"m" (*__xg(ptr)), "0" (x)
00320                       :"memory");
00321     break;
00322   case 4:
00323     __asm __volatile ("xchgl %0,%1"
00324                       :"=r" (x)
00325                       :"m" (*__xg(ptr)), "0" (x)
00326                       :"memory");
00327     break;
00328   }
00329   return x;
00330 }
00331 
00332 /* I/O functions borrowed from NetBSD */
00333 
00334 /*
00335  * Functions to provide access to i386 programmed I/O instructions.
00336  *
00337  * The in[bwl]() and out[bwl]() functions are split into two varieties: one to
00338  * use a small, constant, 8-bit port number, and another to use a large or
00339  * variable port number.  The former can be compiled as a smaller instruction.
00340  */
00341 #ifdef __OPTIMIZE__
00342 
00343 #define __use_immediate_port(port) \
00344         (__builtin_constant_p((port)) && (port) < 0x100)
00345 
00346 #else
00347 
00348 #define __use_immediate_port(port)      0
00349 
00350 #endif
00351 
00352 
00353 #define inb(port) \
00354         (__use_immediate_port(port) ? __inbc(port) : __inb(port))
00355 
00356 static __inline u_int8_t
00357 __inbc(int port)
00358 {
00359         u_int8_t data;
00360         __asm __volatile("inb %1,%0" : "=a" (data) : "id" (port));
00361         return data;
00362 }
00363 
00364 static __inline u_int8_t
00365 __inb(int port)
00366 {
00367         u_int8_t data;
00368         __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
00369         return data;
00370 }
00371 
00372 static __inline void
00373 insb(int port, void *addr, int cnt)
00374 {
00375         void *dummy1;
00376         int dummy2;
00377         __asm __volatile("cld\n\trepne\n\tinsb"                 :
00378                          "=D" (dummy1), "=c" (dummy2)           :
00379                          "d" (port), "0" (addr), "1" (cnt)      :
00380                          "memory");
00381 }
00382 
00383 #define inw(port) \
00384         (__use_immediate_port(port) ? __inwc(port) : __inw(port))
00385 
00386 static __inline u_int16_t
00387 __inwc(int port)
00388 {
00389         u_int16_t data;
00390         __asm __volatile("inw %1,%0" : "=a" (data) : "id" (port));
00391         return data;
00392 }
00393 
00394 static __inline u_int16_t
00395 __inw(int port)
00396 {
00397         u_int16_t data;
00398         __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
00399         return data;
00400 }
00401 
00402 static __inline void
00403 insw(int port, void *addr, int cnt)
00404 {
00405         void *dummy1;
00406         int dummy2;
00407         __asm __volatile("cld\n\trepne\n\tinsw"                 :
00408                          "=D" (dummy1), "=c" (dummy2)           :
00409                          "d" (port), "0" (addr), "1" (cnt)      :
00410                          "memory");
00411 }
00412 
00413 #define inl(port) \
00414         (__use_immediate_port(port) ? __inlc(port) : __inl(port))
00415 
00416 static __inline u_int32_t
00417 __inlc(int port)
00418 {
00419         u_int32_t data;
00420         __asm __volatile("inl %1,%0" : "=a" (data) : "id" (port));
00421         return data;
00422 }
00423 
00424 static __inline u_int32_t
00425 __inl(int port)
00426 {
00427         u_int32_t data;
00428         __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
00429         return data;
00430 }
00431 
00432 static __inline void
00433 insl(int port, void *addr, int cnt)
00434 {
00435         void *dummy1;
00436         int dummy2;
00437         __asm __volatile("cld\n\trepne\n\tinsl"                 :
00438                          "=D" (dummy1), "=c" (dummy2)           :
00439                          "d" (port), "0" (addr), "1" (cnt)      :
00440                          "memory");
00441 }
00442 
00443 #define outb(port, data) \
00444         (__use_immediate_port(port) ? __outbc(port, data) : __outb(port, data))
00445 
00446 static __inline void
00447 __outbc(int port, u_int8_t data)
00448 {
00449         __asm __volatile("outb %0,%1" : : "a" (data), "id" (port));
00450 }
00451 
00452 static __inline void
00453 __outb(int port, u_int8_t data)
00454 {
00455         __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
00456 }
00457 
00458 static __inline void
00459 outsb(int port, void *addr, int cnt)
00460 {
00461         void *dummy1;
00462         int dummy2;
00463         __asm __volatile("cld\n\trepne\n\toutsb"                :
00464                          "=S" (dummy1), "=c" (dummy2)           :
00465                          "d" (port), "0" (addr), "1" (cnt));
00466 }
00467 
00468 #define outw(port, data) \
00469         (__use_immediate_port(port) ? __outwc(port, data) : __outw(port, data))
00470 
00471 static __inline void
00472 __outwc(int port, u_int16_t data)
00473 {
00474         __asm __volatile("outw %0,%1" : : "a" (data), "id" (port));
00475 }
00476 
00477 static __inline void
00478 __outw(int port, u_int16_t data)
00479 {
00480         __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
00481 }
00482 
00483 static __inline void
00484 outsw(int port, void *addr, int cnt)
00485 {
00486         void *dummy1;
00487         int dummy2;
00488         __asm __volatile("cld\n\trepne\n\toutsw"                :
00489                          "=S" (dummy1), "=c" (dummy2)           :
00490                          "d" (port), "0" (addr), "1" (cnt));
00491 }
00492 
00493 #define outl(port, data) \
00494         (__use_immediate_port(port) ? __outlc(port, data) : __outl(port, data))
00495 
00496 static __inline void
00497 __outlc(int port, u_int32_t data)
00498 {
00499         __asm __volatile("outl %0,%1" : : "a" (data), "id" (port));
00500 }
00501 
00502 static __inline void
00503 __outl(int port, u_int32_t data)
00504 {
00505         __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
00506 }
00507 
00508 static __inline void
00509 outsl(int port, void *addr, int cnt)
00510 {
00511         void *dummy1;
00512         int dummy2;
00513         __asm __volatile("cld\n\trepne\n\toutsl"                :
00514                          "=S" (dummy1), "=c" (dummy2)           :
00515                          "d" (port), "0" (addr), "1" (cnt));
00516 }
00517 
00518 /*
00519  * debug function: in a non-ring0 program, should ioacquire(0x60)
00520  * before using it
00521  */
00522 static __inline void
00523 waitch(u_int8_t waited)
00524 {
00525   static u_int8_t       prev_code = 0xff;
00526   u_int8_t              code;
00527 
00528   while (1)
00529     {
00530       code = inb(0x60);
00531       if (code == waited && prev_code != waited)
00532         {
00533           prev_code = code;
00534           return ;
00535         }
00536       prev_code = code;
00537     }
00538 }
00539 
00540 #endif
00541 #endif /* PROGRAM_CPROTO */

Generated on Wed May 24 23:04:17 2006 for LSE/OS by  doxygen 1.4.6