source: rtems-libbsd/freebsd/sys/i386/include/machine/cpufunc.h @ 2fc413a

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2fc413a was 2fc413a, checked in by Sebastian Huber <sebastian.huber@…>, on 07/31/15 at 09:52:16

i386: Make <machine/cpufunc.h> compile clean

  • Property mode set to 100644
File size: 14.3 KB
Line 
1/*-
2 * Copyright (c) 1993 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31
32/*
33 * Functions to provide access to special i386 instructions.
34 * This in included in sys/systm.h, and that file should be
35 * used in preference to this.
36 */
37
38#ifndef _MACHINE_CPUFUNC_H_
39#define _MACHINE_CPUFUNC_H_
40
41#ifndef _SYS_CDEFS_H_
42#error this file needs sys/cdefs.h as a prerequisite
43#endif
44
45#ifdef XEN
46extern void xen_cli(void);
47extern void xen_sti(void);
48extern u_int xen_rcr2(void);
49extern void xen_load_cr3(u_int data);
50extern void xen_tlb_flush(void);
51extern void xen_invlpg(u_int addr);
52extern void write_eflags(u_int eflags);
53extern u_int read_eflags(void);
54#endif
55
56struct region_descriptor;
57
58#define readb(va)       (*(volatile uint8_t *) (va))
59#define readw(va)       (*(volatile uint16_t *) (va))
60#define readl(va)       (*(volatile uint32_t *) (va))
61
62#define writeb(va, d)   (*(volatile uint8_t *) (va) = (d))
63#define writew(va, d)   (*(volatile uint16_t *) (va) = (d))
64#define writel(va, d)   (*(volatile uint32_t *) (va) = (d))
65
66#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
67
68#ifndef __rtems__
69static __inline void
70breakpoint(void)
71{
72        __asm __volatile("int $3");
73}
74#endif
75
76static __inline u_int
77bsfl(u_int mask)
78{
79        u_int   result;
80
81        __asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
82        return (result);
83}
84
85static __inline u_int
86bsrl(u_int mask)
87{
88        u_int   result;
89
90        __asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
91        return (result);
92}
93
94static __inline void
95clflush(u_long addr)
96{
97
98        __asm __volatile("clflush %0" : : "m" (*(char *)addr));
99}
100
101static __inline void
102clts(void)
103{
104
105        __asm __volatile("clts");
106}
107
108static __inline void
109disable_intr(void)
110{
111#ifdef XEN
112        xen_cli();
113#else   
114        __asm __volatile("cli" : : : "memory");
115#endif
116}
117
118static __inline void
119do_cpuid(u_int ax, u_int *p)
120{
121        __asm __volatile("cpuid"
122                         : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
123                         :  "0" (ax));
124}
125
126static __inline void
127cpuid_count(u_int ax, u_int cx, u_int *p)
128{
129        __asm __volatile("cpuid"
130                         : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
131                         :  "0" (ax), "c" (cx));
132}
133
134static __inline void
135enable_intr(void)
136{
137#ifdef XEN
138        xen_sti();
139#else
140        __asm __volatile("sti");
141#endif
142}
143
144static __inline void
145cpu_monitor(const void *addr, u_long extensions, u_int hints)
146{
147
148        __asm __volatile("monitor"
149            : : "a" (addr), "c" (extensions), "d" (hints));
150}
151
152static __inline void
153cpu_mwait(u_long extensions, u_int hints)
154{
155
156        __asm __volatile("mwait" : : "a" (hints), "c" (extensions));
157}
158
159static __inline void
160lfence(void)
161{
162
163        __asm __volatile("lfence" : : : "memory");
164}
165
166static __inline void
167mfence(void)
168{
169
170        __asm __volatile("mfence" : : : "memory");
171}
172
173#ifdef _KERNEL
174
175#ifndef __rtems__
176#define HAVE_INLINE_FFS
177
178static __inline int
179ffs(int mask)
180{
181        /*
182         * Note that gcc-2's builtin ffs would be used if we didn't declare
183         * this inline or turn off the builtin.  The builtin is faster but
184         * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
185         * versions.
186         */
187         return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
188}
189
190#define HAVE_INLINE_FLS
191#endif /* __rtems__ */
192
193#ifndef __rtems__
194static __inline int
195fls(int mask)
196{
197        return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
198}
199#endif
200
201#endif /* _KERNEL */
202
203static __inline void
204halt(void)
205{
206        __asm __volatile("hlt");
207}
208
209static __inline u_char
210inb(u_int port)
211{
212        u_char  data;
213
214        __asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
215        return (data);
216}
217
218static __inline u_int
219inl(u_int port)
220{
221        u_int   data;
222
223        __asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
224        return (data);
225}
226
227static __inline void
228insb(u_int port, void *addr, size_t count)
229{
230        __asm __volatile("cld; rep; insb"
231                         : "+D" (addr), "+c" (count)
232                         : "d" (port)
233                         : "memory");
234}
235
236static __inline void
237insw(u_int port, void *addr, size_t count)
238{
239        __asm __volatile("cld; rep; insw"
240                         : "+D" (addr), "+c" (count)
241                         : "d" (port)
242                         : "memory");
243}
244
245static __inline void
246insl(u_int port, void *addr, size_t count)
247{
248        __asm __volatile("cld; rep; insl"
249                         : "+D" (addr), "+c" (count)
250                         : "d" (port)
251                         : "memory");
252}
253
254static __inline void
255invd(void)
256{
257        __asm __volatile("invd");
258}
259
260static __inline u_short
261inw(u_int port)
262{
263        u_short data;
264
265        __asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
266        return (data);
267}
268
269static __inline void
270outb(u_int port, u_char data)
271{
272        __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
273}
274
275static __inline void
276outl(u_int port, u_int data)
277{
278        __asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
279}
280
281static __inline void
282outsb(u_int port, const void *addr, size_t count)
283{
284        __asm __volatile("cld; rep; outsb"
285                         : "+S" (addr), "+c" (count)
286                         : "d" (port));
287}
288
289static __inline void
290outsw(u_int port, const void *addr, size_t count)
291{
292        __asm __volatile("cld; rep; outsw"
293                         : "+S" (addr), "+c" (count)
294                         : "d" (port));
295}
296
297static __inline void
298outsl(u_int port, const void *addr, size_t count)
299{
300        __asm __volatile("cld; rep; outsl"
301                         : "+S" (addr), "+c" (count)
302                         : "d" (port));
303}
304
305static __inline void
306outw(u_int port, u_short data)
307{
308        __asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
309}
310
311static __inline void
312ia32_pause(void)
313{
314        __asm __volatile("pause");
315}
316
317static __inline u_int
318#ifdef XEN
319_read_eflags(void)
320#else   
321read_eflags(void)
322#endif
323{
324        u_int   ef;
325
326        __asm __volatile("pushfl; popl %0" : "=r" (ef));
327        return (ef);
328}
329
330static __inline uint64_t
331rdmsr(u_int msr)
332{
333        uint64_t rv;
334
335        __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
336        return (rv);
337}
338
339static __inline uint64_t
340rdpmc(u_int pmc)
341{
342        uint64_t rv;
343
344        __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
345        return (rv);
346}
347
348static __inline uint64_t
349rdtsc(void)
350{
351        uint64_t rv;
352
353        __asm __volatile("rdtsc" : "=A" (rv));
354        return (rv);
355}
356
357static __inline uint32_t
358rdtsc32(void)
359{
360        uint32_t rv;
361
362        __asm __volatile("rdtsc" : "=a" (rv) : : "edx");
363        return (rv);
364}
365
366static __inline void
367wbinvd(void)
368{
369        __asm __volatile("wbinvd");
370}
371
372static __inline void
373#ifdef XEN
374_write_eflags(u_int ef)
375#else
376write_eflags(u_int ef)
377#endif
378{
379        __asm __volatile("pushl %0; popfl" : : "r" (ef));
380}
381
382static __inline void
383wrmsr(u_int msr, uint64_t newval)
384{
385        __asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
386}
387
388static __inline void
389load_cr0(u_int data)
390{
391
392        __asm __volatile("movl %0,%%cr0" : : "r" (data));
393}
394
395static __inline u_int
396rcr0(void)
397{
398        u_int   data;
399
400        __asm __volatile("movl %%cr0,%0" : "=r" (data));
401        return (data);
402}
403
404static __inline u_int
405rcr2(void)
406{
407        u_int   data;
408
409#ifdef XEN
410        return (xen_rcr2());
411#endif
412        __asm __volatile("movl %%cr2,%0" : "=r" (data));
413        return (data);
414}
415
416static __inline void
417load_cr3(u_int data)
418{
419#ifdef XEN
420        xen_load_cr3(data);
421#else
422        __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
423#endif
424}
425
426static __inline u_int
427rcr3(void)
428{
429        u_int   data;
430
431        __asm __volatile("movl %%cr3,%0" : "=r" (data));
432        return (data);
433}
434
435static __inline void
436load_cr4(u_int data)
437{
438        __asm __volatile("movl %0,%%cr4" : : "r" (data));
439}
440
441static __inline u_int
442rcr4(void)
443{
444        u_int   data;
445
446        __asm __volatile("movl %%cr4,%0" : "=r" (data));
447        return (data);
448}
449
450/*
451 * Global TLB flush (except for thise for pages marked PG_G)
452 */
453static __inline void
454invltlb(void)
455{
456#ifdef XEN
457        xen_tlb_flush();
458#else   
459        load_cr3(rcr3());
460#endif
461}
462
463/*
464 * TLB flush for an individual page (even if it has PG_G).
465 * Only works on 486+ CPUs (i386 does not have PG_G).
466 */
467static __inline void
468invlpg(u_int addr)
469{
470
471#ifdef XEN
472        xen_invlpg(addr);
473#else
474        __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
475#endif
476}
477
478static __inline u_short
479rfs(void)
480{
481        u_short sel;
482        __asm __volatile("movw %%fs,%0" : "=rm" (sel));
483        return (sel);
484}
485
486static __inline uint64_t
487rgdt(void)
488{
489        uint64_t gdtr;
490        __asm __volatile("sgdt %0" : "=m" (gdtr));
491        return (gdtr);
492}
493
494static __inline u_short
495rgs(void)
496{
497        u_short sel;
498        __asm __volatile("movw %%gs,%0" : "=rm" (sel));
499        return (sel);
500}
501
502static __inline uint64_t
503ridt(void)
504{
505        uint64_t idtr;
506        __asm __volatile("sidt %0" : "=m" (idtr));
507        return (idtr);
508}
509
510static __inline u_short
511rldt(void)
512{
513        u_short ldtr;
514        __asm __volatile("sldt %0" : "=g" (ldtr));
515        return (ldtr);
516}
517
518static __inline u_short
519rss(void)
520{
521        u_short sel;
522        __asm __volatile("movw %%ss,%0" : "=rm" (sel));
523        return (sel);
524}
525
526static __inline u_short
527rtr(void)
528{
529        u_short tr;
530        __asm __volatile("str %0" : "=g" (tr));
531        return (tr);
532}
533
534static __inline void
535load_fs(u_short sel)
536{
537        __asm __volatile("movw %0,%%fs" : : "rm" (sel));
538}
539
540static __inline void
541load_gs(u_short sel)
542{
543        __asm __volatile("movw %0,%%gs" : : "rm" (sel));
544}
545
546static __inline void
547lidt(struct region_descriptor *addr)
548{
549        __asm __volatile("lidt (%0)" : : "r" (addr));
550}
551
552static __inline void
553lldt(u_short sel)
554{
555        __asm __volatile("lldt %0" : : "r" (sel));
556}
557
558static __inline void
559ltr(u_short sel)
560{
561        __asm __volatile("ltr %0" : : "r" (sel));
562}
563
564static __inline u_int
565rdr0(void)
566{
567        u_int   data;
568        __asm __volatile("movl %%dr0,%0" : "=r" (data));
569        return (data);
570}
571
572static __inline void
573load_dr0(u_int dr0)
574{
575        __asm __volatile("movl %0,%%dr0" : : "r" (dr0));
576}
577
578static __inline u_int
579rdr1(void)
580{
581        u_int   data;
582        __asm __volatile("movl %%dr1,%0" : "=r" (data));
583        return (data);
584}
585
586static __inline void
587load_dr1(u_int dr1)
588{
589        __asm __volatile("movl %0,%%dr1" : : "r" (dr1));
590}
591
592static __inline u_int
593rdr2(void)
594{
595        u_int   data;
596        __asm __volatile("movl %%dr2,%0" : "=r" (data));
597        return (data);
598}
599
600static __inline void
601load_dr2(u_int dr2)
602{
603        __asm __volatile("movl %0,%%dr2" : : "r" (dr2));
604}
605
606static __inline u_int
607rdr3(void)
608{
609        u_int   data;
610        __asm __volatile("movl %%dr3,%0" : "=r" (data));
611        return (data);
612}
613
614static __inline void
615load_dr3(u_int dr3)
616{
617        __asm __volatile("movl %0,%%dr3" : : "r" (dr3));
618}
619
620static __inline u_int
621rdr4(void)
622{
623        u_int   data;
624        __asm __volatile("movl %%dr4,%0" : "=r" (data));
625        return (data);
626}
627
628static __inline void
629load_dr4(u_int dr4)
630{
631        __asm __volatile("movl %0,%%dr4" : : "r" (dr4));
632}
633
634static __inline u_int
635rdr5(void)
636{
637        u_int   data;
638        __asm __volatile("movl %%dr5,%0" : "=r" (data));
639        return (data);
640}
641
642static __inline void
643load_dr5(u_int dr5)
644{
645        __asm __volatile("movl %0,%%dr5" : : "r" (dr5));
646}
647
648static __inline u_int
649rdr6(void)
650{
651        u_int   data;
652        __asm __volatile("movl %%dr6,%0" : "=r" (data));
653        return (data);
654}
655
656static __inline void
657load_dr6(u_int dr6)
658{
659        __asm __volatile("movl %0,%%dr6" : : "r" (dr6));
660}
661
662static __inline u_int
663rdr7(void)
664{
665        u_int   data;
666        __asm __volatile("movl %%dr7,%0" : "=r" (data));
667        return (data);
668}
669
670static __inline void
671load_dr7(u_int dr7)
672{
673        __asm __volatile("movl %0,%%dr7" : : "r" (dr7));
674}
675
676static __inline u_char
677read_cyrix_reg(u_char reg)
678{
679        outb(0x22, reg);
680        return inb(0x23);
681}
682
683static __inline void
684write_cyrix_reg(u_char reg, u_char data)
685{
686        outb(0x22, reg);
687        outb(0x23, data);
688}
689
690#ifndef __rtems__
691static __inline register_t
692intr_disable(void)
693{
694        register_t eflags;
695
696        eflags = read_eflags();
697        disable_intr();
698        return (eflags);
699}
700
701static __inline void
702intr_restore(register_t eflags)
703{
704        write_eflags(eflags);
705}
706#endif /* __rtems__ */
707
708#else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
709
710#ifndef __rtems__
711int     breakpoint(void);
712#endif
713u_int   bsfl(u_int mask);
714u_int   bsrl(u_int mask);
715void    clflush(u_long addr);
716void    clts(void);
717void    cpuid_count(u_int ax, u_int cx, u_int *p);
718void    disable_intr(void);
719void    do_cpuid(u_int ax, u_int *p);
720void    enable_intr(void);
721void    halt(void);
722void    ia32_pause(void);
723u_char  inb(u_int port);
724u_int   inl(u_int port);
725void    insb(u_int port, void *addr, size_t count);
726void    insl(u_int port, void *addr, size_t count);
727void    insw(u_int port, void *addr, size_t count);
728register_t      intr_disable(void);
729void    intr_restore(register_t ef);
730void    invd(void);
731void    invlpg(u_int addr);
732void    invltlb(void);
733u_short inw(u_int port);
734void    lidt(struct region_descriptor *addr);
735void    lldt(u_short sel);
736void    load_cr0(u_int cr0);
737void    load_cr3(u_int cr3);
738void    load_cr4(u_int cr4);
739void    load_dr0(u_int dr0);
740void    load_dr1(u_int dr1);
741void    load_dr2(u_int dr2);
742void    load_dr3(u_int dr3);
743void    load_dr4(u_int dr4);
744void    load_dr5(u_int dr5);
745void    load_dr6(u_int dr6);
746void    load_dr7(u_int dr7);
747void    load_fs(u_short sel);
748void    load_gs(u_short sel);
749void    ltr(u_short sel);
750void    outb(u_int port, u_char data);
751void    outl(u_int port, u_int data);
752void    outsb(u_int port, const void *addr, size_t count);
753void    outsl(u_int port, const void *addr, size_t count);
754void    outsw(u_int port, const void *addr, size_t count);
755void    outw(u_int port, u_short data);
756u_int   rcr0(void);
757u_int   rcr2(void);
758u_int   rcr3(void);
759u_int   rcr4(void);
760uint64_t rdmsr(u_int msr);
761uint64_t rdpmc(u_int pmc);
762u_int   rdr0(void);
763u_int   rdr1(void);
764u_int   rdr2(void);
765u_int   rdr3(void);
766u_int   rdr4(void);
767u_int   rdr5(void);
768u_int   rdr6(void);
769u_int   rdr7(void);
770uint64_t rdtsc(void);
771u_char  read_cyrix_reg(u_char reg);
772u_int   read_eflags(void);
773u_int   rfs(void);
774uint64_t rgdt(void);
775u_int   rgs(void);
776uint64_t ridt(void);
777u_short rldt(void);
778u_short rtr(void);
779void    wbinvd(void);
780void    write_cyrix_reg(u_char reg, u_char data);
781void    write_eflags(u_int ef);
782void    wrmsr(u_int msr, uint64_t newval);
783
784#endif  /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
785
786void    reset_dbregs(void);
787
788#ifdef _KERNEL
789int     rdmsr_safe(u_int msr, uint64_t *val);
790int     wrmsr_safe(u_int msr, uint64_t newval);
791#endif
792
793#endif /* !_MACHINE_CPUFUNC_H_ */
Note: See TracBrowser for help on using the repository browser.