Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/include/arch/i386-percpu.h need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #ifndef __I386_PERPCU_H__
0019 #define __I386_PERCPU_H__
0020 
0021 #include "util/stringify.h"
0022 
0023 #define PER_CPU_SEG fs
0024 #define PER_CPU_DBG dr3
0025 #define PER_CPU_SEG_STR __stringify(PER_CPU_SEG)
0026 #define PER_CPU_DBG_STR __stringify(PER_CPU_DBG)
0027 
0028 #ifndef __ASSEMBLER__           /* for C only */
0029 #include "types.h"
0030 
0031 /* ************************************************** */
0032 /* API */
0033 
0034 /* Define a per-CPU variable */
0035 #define DEF_PER_CPU(type,var) PER_CPU_ATTR type var
0036 
0037 /* Define an initialization function for a per-CPU variable */
0038 #define INIT_PER_CPU(var)                               \
0039   void __##var##_ctor_func (void);                      \
0040   PER_CPU_CTOR_ATTR void (*__##var##_ctor_ptr) (void) = \
0041     __##var##_ctor_func;                                \
0042   void __##var##_ctor_func (void)
0043 
0044 /* Access macros for per-CPU variables */
0045 #define percpu_read(var) percpu_op_src ("mov", var, "m" (var))
0046 #define percpu_read64(var)                      \
0047   ({                                            \
0048     u32 _percpu_lo, _percpu_hi;                 \
0049     u64 _percpu_ret;                            \
0050     asm ("movl "__percpu_arg (1)", %0"          \
0051          : "=r" (_percpu_lo)                    \
0052          : "m" (var));                          \
0053     asm ("movl "__percpu_arg (1)", %0"          \
0054          : "=r" (_percpu_hi)                    \
0055          : "m" (((u32 *) &var)[1]));            \
0056     _percpu_ret = (((u64) _percpu_hi) << 32);   \
0057     _percpu_ret |= (u64) _percpu_lo;            \
0058     _percpu_ret;                                \
0059   })
0060 #define percpu_write(var, val) percpu_op_dest ("mov", var, val)
0061 #define percpu_write64(var, val) do {           \
0062     asm ("movl %2, "__percpu_arg (0)"\n"        \
0063          "movl %3, "__percpu_arg (1)            \
0064          : "+m" (var), "+m" (((u32 *) &var)[1]) \
0065          : "re" ((u32) val),                    \
0066            "re" ((u32) (val >> 32)));           \
0067   } while (0)
0068 
0069 /* Initialization for each CPU */
0070 extern void percpu_per_cpu_init (void);
0071 
0072 /* Get a pointer to a per-CPU variable, with explicit CPU parameter */
0073 extern u8 *percpu_virt[];
0074 #define percpu_pointer(cpu, var) ((void *) (&percpu_virt[cpu][(uint) &var]))
0075 
0076 /* ************************************************** */
0077 
0078 #define PER_CPU_ATTR __attribute__((section(".percpu")))
0079 #define PER_CPU_CTOR_ATTR __attribute__((section(".percpu.ctor")))
0080 
0081 #define __percpu_arg(x) "%%"PER_CPU_SEG_STR":%"#x
0082 #define percpu_op_dest(op, var, val)                    \
0083   do {                                                  \
0084     switch (sizeof (typeof (var))) {                    \
0085     case 1:                                             \
0086       asm (op "b %1, "__percpu_arg (0)                  \
0087            : "+m" (var) : "qi" (val));                  \
0088       break;                                            \
0089     case 2:                                             \
0090       asm (op "w %1, "__percpu_arg (0)                  \
0091            : "+m" (var) : "ri" (val));                  \
0092       break;                                            \
0093     case 4:                                             \
0094       asm (op "l %1, "__percpu_arg (0)                  \
0095            : "+m" (var) : "ri" (val));                  \
0096       break;                                            \
0097     default: panic ("percpu_op_dest: bad size");        \
0098     }                                                   \
0099   } while (0)
0100 
0101 #define percpu_op_src(op, var, constraint)      \
0102   ({                                            \
0103     typeof(var) _percpu_ret;                    \
0104     switch (sizeof (typeof (var))) {            \
0105     case 1:                                     \
0106       asm (op "b "__percpu_arg (1)", %0"        \
0107            : "=q" (_percpu_ret) : constraint);  \
0108       break;                                    \
0109     case 2:                                     \
0110       asm (op "w "__percpu_arg (1)", %0"        \
0111            : "=r" (_percpu_ret) : constraint);  \
0112       break;                                    \
0113     case 4:                                     \
0114       asm (op "l "__percpu_arg (1)", %0"        \
0115            : "=r" (_percpu_ret) : constraint);  \
0116       break;                                    \
0117     default: panic ("percpu_op_src: bad size"); \
0118     }                                           \
0119     _percpu_ret;                                \
0120   })
0121 
0122 #endif
0123 
0124 #endif
0125 
0126 /*
0127  * Local Variables:
0128  * indent-tabs-mode: nil
0129  * mode: C
0130  * c-file-style: "gnu"
0131  * c-basic-offset: 2
0132  * End:
0133  */
0134 
0135 /* vi: set et sw=2 sts=2: */